aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am116
-rw-r--r--src/flash/Makefile.am23
-rw-r--r--src/flash/common.c47
-rw-r--r--src/flash/common.h48
-rw-r--r--src/flash/mflash.c1449
-rw-r--r--src/flash/mflash.h289
-rw-r--r--src/flash/nand/Makefile.am46
-rw-r--r--src/flash/nand/arm_io.c299
-rw-r--r--src/flash/nand/arm_io.h55
-rw-r--r--src/flash/nand/at91sam9.c722
-rw-r--r--src/flash/nand/core.c876
-rw-r--r--src/flash/nand/core.h232
-rw-r--r--src/flash/nand/davinci.c793
-rw-r--r--src/flash/nand/driver.c82
-rw-r--r--src/flash/nand/driver.h103
-rw-r--r--src/flash/nand/ecc.c182
-rw-r--r--src/flash/nand/ecc_kw.c174
-rw-r--r--src/flash/nand/fileio.c226
-rw-r--r--src/flash/nand/fileio.h56
-rw-r--r--src/flash/nand/imp.h38
-rw-r--r--src/flash/nand/lpc3180.c1359
-rw-r--r--src/flash/nand/lpc3180.h37
-rw-r--r--src/flash/nand/lpc32xx.c1821
-rw-r--r--src/flash/nand/lpc32xx.h36
-rw-r--r--src/flash/nand/mx3.c719
-rw-r--r--src/flash/nand/mx3.h112
-rw-r--r--src/flash/nand/mxc.c960
-rw-r--r--src/flash/nand/mxc.h168
-rw-r--r--src/flash/nand/nonce.c73
-rw-r--r--src/flash/nand/nuc910.c227
-rw-r--r--src/flash/nand/nuc910.h57
-rw-r--r--src/flash/nand/orion.c161
-rw-r--r--src/flash/nand/s3c2410.c116
-rw-r--r--src/flash/nand/s3c2412.c75
-rw-r--r--src/flash/nand/s3c2440.c166
-rw-r--r--src/flash/nand/s3c2443.c75
-rw-r--r--src/flash/nand/s3c24xx.c117
-rw-r--r--src/flash/nand/s3c24xx.h78
-rw-r--r--src/flash/nand/s3c24xx_regs.h129
-rw-r--r--src/flash/nand/s3c6400.c72
-rw-r--r--src/flash/nand/tcl.c626
-rw-r--r--src/flash/nor/Makefile.am70
-rw-r--r--src/flash/nor/aduc702x.c404
-rw-r--r--src/flash/nor/aducm360.c582
-rw-r--r--src/flash/nor/ambiqmicro.c904
-rw-r--r--src/flash/nor/at91sam3.c3774
-rw-r--r--src/flash/nor/at91sam4.c2678
-rw-r--r--src/flash/nor/at91sam4l.c707
-rw-r--r--src/flash/nor/at91sam7.c1203
-rw-r--r--src/flash/nor/at91samd.c1124
-rw-r--r--src/flash/nor/atsamv.c739
-rw-r--r--src/flash/nor/avrf.c489
-rw-r--r--src/flash/nor/cfi.c3131
-rw-r--r--src/flash/nor/cfi.h163
-rw-r--r--src/flash/nor/core.c797
-rw-r--r--src/flash/nor/core.h232
-rw-r--r--src/flash/nor/driver.h224
-rw-r--r--src/flash/nor/drivers.c133
-rw-r--r--src/flash/nor/dsp5680xx_flash.c270
-rw-r--r--src/flash/nor/efm32.c1069
-rw-r--r--src/flash/nor/em357.c939
-rw-r--r--src/flash/nor/faux.c140
-rw-r--r--src/flash/nor/fespi.c1127
-rw-r--r--src/flash/nor/fm3.c1000
-rw-r--r--src/flash/nor/fm4.c722
-rw-r--r--src/flash/nor/imp.h49
-rw-r--r--src/flash/nor/jtagspi.c413
-rw-r--r--src/flash/nor/kinetis.c2423
-rw-r--r--src/flash/nor/kinetis_ke.c1314
-rw-r--r--src/flash/nor/lpc2000.c1573
-rw-r--r--src/flash/nor/lpc288x.c436
-rw-r--r--src/flash/nor/lpc2900.c1601
-rw-r--r--src/flash/nor/lpcspifi.c945
-rw-r--r--src/flash/nor/mdr.c635
-rw-r--r--src/flash/nor/mrvlqspi.c958
-rw-r--r--src/flash/nor/niietcm4.c1744
-rw-r--r--src/flash/nor/non_cfi.c560
-rw-r--r--src/flash/nor/non_cfi.h36
-rw-r--r--src/flash/nor/nrf51.c1334
-rw-r--r--src/flash/nor/numicro.c1883
-rw-r--r--src/flash/nor/ocl.c343
-rw-r--r--src/flash/nor/ocl.h39
-rw-r--r--src/flash/nor/pic32mx.c984
-rw-r--r--src/flash/nor/psoc4.c812
-rw-r--r--src/flash/nor/sim3x.c1126
-rw-r--r--src/flash/nor/spi.c83
-rw-r--r--src/flash/nor/spi.h61
-rw-r--r--src/flash/nor/stellaris.c1455
-rw-r--r--src/flash/nor/stm32f1x.c1650
-rw-r--r--src/flash/nor/stm32f2x.c1463
-rw-r--r--src/flash/nor/stm32l4x.c930
-rw-r--r--src/flash/nor/stm32lx.c1421
-rw-r--r--src/flash/nor/stmsmi.c657
-rw-r--r--src/flash/nor/str7x.c815
-rw-r--r--src/flash/nor/str9x.c682
-rw-r--r--src/flash/nor/str9xpec.c1210
-rw-r--r--src/flash/nor/tcl.c1146
-rw-r--r--src/flash/nor/tms470.c1189
-rw-r--r--src/flash/nor/virtual.c233
-rw-r--r--src/flash/nor/xmc1xxx.c549
-rw-r--r--src/flash/nor/xmc4xxx.c1444
-rw-r--r--src/flash/startup.tcl110
-rw-r--r--src/hello.c112
-rw-r--r--src/hello.h29
-rw-r--r--src/helper/Makefile.am56
-rwxr-xr-xsrc/helper/bin2char.sh14
-rw-r--r--src/helper/binarybuffer.c418
-rw-r--r--src/helper/binarybuffer.h241
-rw-r--r--src/helper/command.c1466
-rw-r--r--src/helper/command.h418
-rw-r--r--src/helper/configuration.c170
-rw-r--r--src/helper/configuration.h43
-rw-r--r--src/helper/fileio.c269
-rw-r--r--src/helper/fileio.h69
-rw-r--r--src/helper/ioutil.c534
-rw-r--r--src/helper/ioutil.h25
-rw-r--r--src/helper/ioutil_stubs.c28
-rw-r--r--src/helper/jep106.c44
-rw-r--r--src/helper/jep106.h32
-rw-r--r--src/helper/jep106.inc1119
-rw-r--r--src/helper/jim-nvp.c341
-rw-r--r--src/helper/jim-nvp.h329
-rw-r--r--src/helper/list.h737
-rw-r--r--src/helper/log.c467
-rw-r--r--src/helper/log.h142
-rw-r--r--src/helper/options.c230
-rw-r--r--src/helper/replacements.c318
-rw-r--r--src/helper/replacements.h283
-rw-r--r--src/helper/startup.tcl66
-rw-r--r--src/helper/system.h89
-rw-r--r--src/helper/time_support.c89
-rw-r--r--src/helper/time_support.h60
-rw-r--r--src/helper/time_support_common.c41
-rw-r--r--src/helper/types.h340
-rwxr-xr-xsrc/helper/update_jep106.pl35
-rw-r--r--src/helper/util.c59
-rw-r--r--src/helper/util.h25
-rw-r--r--src/jtag/Makefile.am86
-rw-r--r--src/jtag/adapter.c535
-rw-r--r--src/jtag/aice/Makefile.am27
-rw-r--r--src/jtag/aice/aice_interface.c507
-rw-r--r--src/jtag/aice/aice_interface.h35
-rw-r--r--src/jtag/aice/aice_pipe.c893
-rw-r--r--src/jtag/aice/aice_pipe.h31
-rw-r--r--src/jtag/aice/aice_port.c45
-rw-r--r--src/jtag/aice/aice_port.h237
-rw-r--r--src/jtag/aice/aice_transport.c385
-rw-r--r--src/jtag/aice/aice_transport.h24
-rw-r--r--src/jtag/aice/aice_usb.c4123
-rw-r--r--src/jtag/aice/aice_usb.h132
-rw-r--r--src/jtag/commands.c253
-rw-r--r--src/jtag/commands.h176
-rw-r--r--src/jtag/core.c1966
-rw-r--r--src/jtag/driver.h26
-rw-r--r--src/jtag/drivers/Makefile.am173
-rw-r--r--src/jtag/drivers/Makefile.rlink71
-rw-r--r--src/jtag/drivers/OpenULINK/Makefile87
-rw-r--r--src/jtag/drivers/OpenULINK/README34
-rw-r--r--src/jtag/drivers/OpenULINK/include/common.h24
-rw-r--r--src/jtag/drivers/OpenULINK/include/delay.h32
-rw-r--r--src/jtag/drivers/OpenULINK/include/io.h122
-rw-r--r--src/jtag/drivers/OpenULINK/include/jtag.h46
-rw-r--r--src/jtag/drivers/OpenULINK/include/main.h24
-rw-r--r--src/jtag/drivers/OpenULINK/include/msgtypes.h189
-rw-r--r--src/jtag/drivers/OpenULINK/include/protocol.h30
-rw-r--r--src/jtag/drivers/OpenULINK/include/reg_ezusb.h741
-rw-r--r--src/jtag/drivers/OpenULINK/include/usb.h265
-rw-r--r--src/jtag/drivers/OpenULINK/src/USBJmpTb.a5181
-rw-r--r--src/jtag/drivers/OpenULINK/src/delay.c49
-rw-r--r--src/jtag/drivers/OpenULINK/src/jtag.c721
-rw-r--r--src/jtag/drivers/OpenULINK/src/main.c89
-rw-r--r--src/jtag/drivers/OpenULINK/src/protocol.c238
-rw-r--r--src/jtag/drivers/OpenULINK/src/usb.c562
-rw-r--r--src/jtag/drivers/OpenULINK/ulink_firmware.hex347
-rw-r--r--src/jtag/drivers/amt_jtagaccel.c605
-rw-r--r--src/jtag/drivers/arm-jtag-ew.c793
-rw-r--r--src/jtag/drivers/at91rm9200.c266
-rw-r--r--src/jtag/drivers/bcm2835gpio.c531
-rw-r--r--src/jtag/drivers/bitbang.c548
-rw-r--r--src/jtag/drivers/bitbang.h48
-rw-r--r--src/jtag/drivers/bitq.c315
-rw-r--r--src/jtag/drivers/bitq.h45
-rw-r--r--src/jtag/drivers/buspirate.c1126
-rw-r--r--src/jtag/drivers/cmsis_dap_usb.c1630
-rw-r--r--src/jtag/drivers/driver.c421
-rw-r--r--src/jtag/drivers/dummy.c160
-rw-r--r--src/jtag/drivers/ep93xx.c212
-rw-r--r--src/jtag/drivers/ft2232.c4308
-rw-r--r--src/jtag/drivers/ftd2xx_common.h55
-rw-r--r--src/jtag/drivers/ftdi.c1297
-rw-r--r--src/jtag/drivers/gw16012.c543
-rw-r--r--src/jtag/drivers/jlink.c1979
-rw-r--r--src/jtag/drivers/jtag_vpi.c466
m---------src/jtag/drivers/libjaylink0
-rw-r--r--src/jtag/drivers/libusb0_common.c188
-rw-r--r--src/jtag/drivers/libusb0_common.h73
-rw-r--r--src/jtag/drivers/libusb1_common.c248
-rw-r--r--src/jtag/drivers/libusb1_common.h80
-rw-r--r--src/jtag/drivers/libusb_common.h27
-rw-r--r--src/jtag/drivers/minidriver_imp.h41
-rw-r--r--src/jtag/drivers/mpsse.c930
-rw-r--r--src/jtag/drivers/mpsse.h78
-rw-r--r--src/jtag/drivers/opendous.c825
-rw-r--r--src/jtag/drivers/openjtag.c843
-rw-r--r--src/jtag/drivers/osbdm.c699
-rw-r--r--src/jtag/drivers/parport.c518
-rw-r--r--src/jtag/drivers/presto.c794
-rw-r--r--src/jtag/drivers/remote_bitbang.c280
-rw-r--r--src/jtag/drivers/rlink.c1683
-rw-r--r--src/jtag/drivers/rlink.h32
-rw-r--r--src/jtag/drivers/rlink_call.m4483
-rw-r--r--src/jtag/drivers/rlink_dtc_cmd.h76
-rw-r--r--src/jtag/drivers/rlink_ep1_cmd.h60
-rw-r--r--src/jtag/drivers/rlink_init.m472
-rw-r--r--src/jtag/drivers/rlink_speed_table.c101
-rw-r--r--src/jtag/drivers/rlink_st7.h117
-rw-r--r--src/jtag/drivers/stlink_usb.c1890
-rw-r--r--src/jtag/drivers/sysfsgpio.c681
-rw-r--r--src/jtag/drivers/ti_icdi_usb.c782
-rw-r--r--src/jtag/drivers/ulink.c2316
-rw-r--r--src/jtag/drivers/usb_blaster/Makefile.am24
-rw-r--r--src/jtag/drivers/usb_blaster/README.CheapClone71
-rw-r--r--src/jtag/drivers/usb_blaster/ublast2_access_libusb.c253
-rw-r--r--src/jtag/drivers/usb_blaster/ublast_access.h74
-rw-r--r--src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c180
-rw-r--r--src/jtag/drivers/usb_blaster/ublast_access_ftdi.c138
-rw-r--r--src/jtag/drivers/usb_blaster/usb_blaster.c1079
-rw-r--r--src/jtag/drivers/usb_common.c54
-rw-r--r--src/jtag/drivers/usb_common.h26
-rw-r--r--src/jtag/drivers/usbprog.c619
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c95
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c78
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c63
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c156
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c553
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h237
-rw-r--r--src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h161
-rw-r--r--src/jtag/drivers/versaloon/versaloon.c359
-rw-r--r--src/jtag/drivers/versaloon/versaloon.h112
-rw-r--r--src/jtag/drivers/versaloon/versaloon_include.h102
-rw-r--r--src/jtag/drivers/versaloon/versaloon_internal.h110
-rw-r--r--src/jtag/drivers/vsllink.c975
-rw-r--r--src/jtag/hla/Makefile.am23
-rw-r--r--src/jtag/hla/hla_interface.c347
-rw-r--r--src/jtag/hla/hla_interface.h68
-rw-r--r--src/jtag/hla/hla_layout.c90
-rw-r--r--src/jtag/hla/hla_layout.h128
-rw-r--r--src/jtag/hla/hla_tcl.c157
-rw-r--r--src/jtag/hla/hla_tcl.h28
-rw-r--r--src/jtag/hla/hla_transport.c235
-rw-r--r--src/jtag/hla/hla_transport.h32
-rw-r--r--src/jtag/interface.c468
-rw-r--r--src/jtag/interface.h335
-rw-r--r--src/jtag/interfaces.c238
-rw-r--r--src/jtag/interfaces.h44
-rw-r--r--src/jtag/jtag.h649
-rw-r--r--src/jtag/minidriver.h90
-rw-r--r--src/jtag/minidriver/minidriver_imp.h30
-rw-r--r--src/jtag/minidummy/jtag_minidriver.h21
-rw-r--r--src/jtag/minidummy/minidummy.c169
-rw-r--r--src/jtag/startup.tcl163
-rw-r--r--src/jtag/swd.h216
-rw-r--r--src/jtag/tcl.c1387
-rw-r--r--src/jtag/tcl.h37
-rw-r--r--src/jtag/zy1000/jtag_minidriver.h182
-rw-r--r--src/jtag/zy1000/zy1000.c1252
-rw-r--r--src/main.c40
-rw-r--r--src/openocd.c351
-rw-r--r--src/openocd.h32
-rw-r--r--src/pld/Makefile.am8
-rw-r--r--src/pld/pld.c239
-rw-r--r--src/pld/pld.h52
-rw-r--r--src/pld/virtex2.c250
-rw-r--r--src/pld/virtex2.h29
-rw-r--r--src/pld/xilinx_bit.c128
-rw-r--r--src/pld/xilinx_bit.h34
-rw-r--r--src/rtos/ChibiOS.c547
-rw-r--r--src/rtos/FreeRTOS.c555
-rw-r--r--src/rtos/Makefile.am32
-rw-r--r--src/rtos/ThreadX.c617
-rw-r--r--src/rtos/eCos.c392
-rw-r--r--src/rtos/embKernel.c342
-rw-r--r--src/rtos/linux.c1594
-rw-r--r--src/rtos/linux_header.h37
-rw-r--r--src/rtos/mqx.c561
-rw-r--r--src/rtos/riscv_debug.c280
-rw-r--r--src/rtos/riscv_debug.h9
-rw-r--r--src/rtos/rtos.c549
-rw-r--r--src/rtos/rtos.h111
-rw-r--r--src/rtos/rtos_chibios_stackings.c83
-rw-r--r--src/rtos/rtos_chibios_stackings.h31
-rw-r--r--src/rtos/rtos_ecos_stackings.c51
-rw-r--r--src/rtos/rtos_ecos_stackings.h28
-rw-r--r--src/rtos/rtos_embkernel_stackings.c55
-rw-r--r--src/rtos/rtos_embkernel_stackings.h30
-rw-r--r--src/rtos/rtos_mqx_stackings.c80
-rw-r--r--src/rtos/rtos_mqx_stackings.h30
-rw-r--r--src/rtos/rtos_standard_stackings.c270
-rw-r--r--src/rtos/rtos_standard_stackings.h40
-rw-r--r--src/server/Makefile.am23
-rw-r--r--src/server/gdb_server.c3197
-rw-r--r--src/server/gdb_server.h51
-rw-r--r--src/server/server.c751
-rw-r--r--src/server/server.h112
-rw-r--r--src/server/server_stubs.c30
-rw-r--r--src/server/startup.tcl10
-rw-r--r--src/server/tcl_server.c361
-rw-r--r--src/server/tcl_server.h26
-rw-r--r--src/server/telnet_server.c682
-rw-r--r--src/server/telnet_server.h70
-rw-r--r--src/svf/Makefile.am8
-rw-r--r--src/svf/svf.c1578
-rw-r--r--src/svf/svf.h47
-rw-r--r--src/target/Makefile.am219
-rw-r--r--src/target/adi_v5_jtag.c756
-rw-r--r--src/target/adi_v5_swd.c451
-rw-r--r--src/target/algorithm.c52
-rw-r--r--src/target/algorithm.h50
-rw-r--r--src/target/arm.h243
-rw-r--r--src/target/arm11.c1382
-rw-r--r--src/target/arm11.h114
-rw-r--r--src/target/arm11_dbgtap.c1195
-rw-r--r--src/target/arm11_dbgtap.h83
-rw-r--r--src/target/arm720t.c587
-rw-r--r--src/target/arm720t.h41
-rw-r--r--src/target/arm7_9_common.c2903
-rw-r--r--src/target/arm7_9_common.h195
-rw-r--r--src/target/arm7tdmi.c721
-rw-r--r--src/target/arm7tdmi.h32
-rw-r--r--src/target/arm920t.c1720
-rw-r--r--src/target/arm920t.h71
-rw-r--r--src/target/arm926ejs.c832
-rw-r--r--src/target/arm926ejs.h55
-rw-r--r--src/target/arm946e.c784
-rw-r--r--src/target/arm946e.h51
-rw-r--r--src/target/arm966e.c282
-rw-r--r--src/target/arm966e.h48
-rw-r--r--src/target/arm9tdmi.c923
-rw-r--r--src/target/arm9tdmi.h56
-rw-r--r--src/target/arm_adi_v5.c1700
-rw-r--r--src/target/arm_adi_v5.h507
-rw-r--r--src/target/arm_disassembler.c4465
-rw-r--r--src/target/arm_disassembler.h204
-rw-r--r--src/target/arm_dpm.c1042
-rw-r--r--src/target/arm_dpm.h201
-rw-r--r--src/target/arm_jtag.c94
-rw-r--r--src/target/arm_jtag.h78
-rw-r--r--src/target/arm_opcodes.h313
-rw-r--r--src/target/arm_semihosting.c556
-rw-r--r--src/target/arm_semihosting.h24
-rw-r--r--src/target/arm_simulator.c722
-rw-r--r--src/target/arm_simulator.h39
-rw-r--r--src/target/armv4_5.c1612
-rw-r--r--src/target/armv4_5.h49
-rw-r--r--src/target/armv4_5_cache.c102
-rw-r--r--src/target/armv4_5_cache.h55
-rw-r--r--src/target/armv4_5_mmu.c169
-rw-r--r--src/target/armv4_5_mmu.h56
-rw-r--r--src/target/armv7a.c769
-rw-r--r--src/target/armv7a.h187
-rw-r--r--src/target/armv7a_cache.c610
-rw-r--r--src/target/armv7a_cache.h46
-rw-r--r--src/target/armv7a_cache_l2x.c378
-rw-r--r--src/target/armv7a_cache_l2x.h158
-rw-r--r--src/target/armv7m.c829
-rw-r--r--src/target/armv7m.h234
-rw-r--r--src/target/armv7m_trace.c351
-rw-r--r--src/target/armv7m_trace.h91
-rw-r--r--src/target/avr32_ap7k.c624
-rw-r--r--src/target/avr32_ap7k.h43
-rw-r--r--src/target/avr32_jtag.c376
-rw-r--r--src/target/avr32_jtag.h103
-rw-r--r--src/target/avr32_mem.c317
-rw-r--r--src/target/avr32_mem.h35
-rw-r--r--src/target/avr32_regs.c114
-rw-r--r--src/target/avr32_regs.h44
-rw-r--r--src/target/avrt.c223
-rw-r--r--src/target/avrt.h37
-rw-r--r--src/target/breakpoints.c519
-rw-r--r--src/target/breakpoints.h76
-rw-r--r--src/target/cortex_a.c3591
-rw-r--r--src/target/cortex_a.h117
-rw-r--r--src/target/cortex_m.c2429
-rw-r--r--src/target/cortex_m.h214
-rw-r--r--src/target/dsp563xx.c2339
-rw-r--r--src/target/dsp563xx.h73
-rw-r--r--src/target/dsp563xx_once.c293
-rw-r--r--src/target/dsp563xx_once.h89
-rw-r--r--src/target/dsp5680xx.c2297
-rw-r--r--src/target/dsp5680xx.h382
-rw-r--r--src/target/embeddedice.c648
-rw-r--r--src/target/embeddedice.h128
-rw-r--r--src/target/etb.c703
-rw-r--r--src/target/etb.h58
-rw-r--r--src/target/etm.c2115
-rw-r--r--src/target/etm.h224
-rw-r--r--src/target/etm_dummy.c106
-rw-r--r--src/target/etm_dummy.h26
-rw-r--r--src/target/fa526.c387
-rw-r--r--src/target/feroceon.c769
-rw-r--r--src/target/hla_target.c815
-rw-r--r--src/target/image.c1044
-rw-r--r--src/target/image.h110
-rw-r--r--src/target/lakemont.c1125
-rw-r--r--src/target/lakemont.h106
-rw-r--r--src/target/ls1_sap.c243
-rw-r--r--src/target/mips32.c952
-rw-r--r--src/target/mips32.h252
-rw-r--r--src/target/mips32_dmaacc.c462
-rw-r--r--src/target/mips32_dmaacc.h41
-rw-r--r--src/target/mips32_pracc.c1117
-rw-r--r--src/target/mips32_pracc.h102
-rw-r--r--src/target/mips_ejtag.c480
-rw-r--r--src/target/mips_ejtag.h235
-rw-r--r--src/target/mips_m4k.c1437
-rw-r--r--src/target/mips_m4k.h46
-rw-r--r--src/target/nds32.c2628
-rw-r--r--src/target/nds32.h457
-rw-r--r--src/target/nds32_aice.c158
-rw-r--r--src/target/nds32_aice.h161
-rw-r--r--src/target/nds32_cmd.c1126
-rw-r--r--src/target/nds32_cmd.h26
-rw-r--r--src/target/nds32_disassembler.c3858
-rw-r--r--src/target/nds32_disassembler.h56
-rw-r--r--src/target/nds32_edm.h115
-rw-r--r--src/target/nds32_insn.h78
-rw-r--r--src/target/nds32_reg.c380
-rw-r--r--src/target/nds32_reg.h325
-rw-r--r--src/target/nds32_tlb.c78
-rw-r--r--src/target/nds32_tlb.h47
-rw-r--r--src/target/nds32_v2.c785
-rw-r--r--src/target/nds32_v2.h42
-rw-r--r--src/target/nds32_v3.c521
-rw-r--r--src/target/nds32_v3.h45
-rw-r--r--src/target/nds32_v3_common.c675
-rw-r--r--src/target/nds32_v3_common.h61
-rw-r--r--src/target/nds32_v3m.c506
-rw-r--r--src/target/nds32_v3m.h51
-rw-r--r--src/target/oocd_trace.c417
-rw-r--r--src/target/oocd_trace.h53
-rw-r--r--src/target/openrisc/Makefile.am18
-rw-r--r--src/target/openrisc/jsp_server.c245
-rw-r--r--src/target/openrisc/jsp_server.h17
-rw-r--r--src/target/openrisc/or1k.c1462
-rw-r--r--src/target/openrisc/or1k.h158
-rw-r--r--src/target/openrisc/or1k_du.h78
-rw-r--r--src/target/openrisc/or1k_du_adv.c1098
-rw-r--r--src/target/openrisc/or1k_tap.h42
-rw-r--r--src/target/openrisc/or1k_tap_mohor.c63
-rw-r--r--src/target/openrisc/or1k_tap_vjtag.c309
-rw-r--r--src/target/openrisc/or1k_tap_xilinx_bscan.c63
-rw-r--r--src/target/quark_d20xx.c115
-rw-r--r--src/target/quark_x10xx.c98
-rw-r--r--src/target/register.c113
-rw-r--r--src/target/register.h167
-rw-r--r--src/target/riscv/asm.h36
-rw-r--r--src/target/riscv/debug_defines.h1501
-rw-r--r--src/target/riscv/encoding.h1313
-rw-r--r--src/target/riscv/gdb_regs.h25
-rw-r--r--src/target/riscv/opcodes.h279
-rw-r--r--src/target/riscv/riscv-011.c2603
-rw-r--r--src/target/riscv/riscv-013.c1634
-rw-r--r--src/target/riscv/riscv.c1007
-rw-r--r--src/target/riscv/riscv.h177
-rw-r--r--src/target/smp.c97
-rw-r--r--src/target/smp.h29
-rw-r--r--src/target/startup.tcl210
-rw-r--r--src/target/target.c6228
-rw-r--r--src/target/target.h686
-rw-r--r--src/target/target_request.c315
-rw-r--r--src/target/target_request.h55
-rw-r--r--src/target/target_type.h280
-rw-r--r--src/target/testee.c73
-rw-r--r--src/target/trace.c175
-rw-r--r--src/target/trace.h59
-rw-r--r--src/target/x86_32_common.c1497
-rw-r--r--src/target/x86_32_common.h330
-rw-r--r--src/target/xscale.c3728
-rw-r--r--src/target/xscale.h188
-rwxr-xr-xsrc/target/xscale/build.sh7
-rw-r--r--src/target/xscale/debug_handler.S716
-rwxr-xr-xsrc/target/xscale/debug_handler.binbin1592 -> 0 bytes
-rw-r--r--src/target/xscale/debug_handler.cmd49
-rw-r--r--src/target/xscale/protocol.h68
-rw-r--r--src/transport/Makefile.am11
-rw-r--r--src/transport/transport.c380
-rw-r--r--src/transport/transport.h93
-rw-r--r--src/xsvf/Makefile.am8
-rw-r--r--src/xsvf/xsvf.c1113
-rw-r--r--src/xsvf/xsvf.h29
490 files changed, 0 insertions, 246964 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 26e02d0..0000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,116 +0,0 @@
-include $(top_srcdir)/common.mk
-
-SUBDIRS = \
- jtag \
- helper \
- target \
- transport \
- flash \
- svf \
- xsvf \
- pld \
- server \
- rtos
-
-noinst_LTLIBRARIES = libopenocd.la
-bin_PROGRAMS = openocd
-
-MAINFILE = main.c
-
-openocd_SOURCES = $(MAINFILE)
-openocd_LDADD = libopenocd.la
-
-if INTERNAL_JIMTCL
-openocd_LDADD += $(top_builddir)/jimtcl/libjim.a
-else
-openocd_LDADD += -ljim
-endif
-
-if ULINK
-openocd_LDADD += -lm
-endif
-
-libopenocd_la_SOURCES = \
- hello.c \
- openocd.c
-
-noinst_HEADERS = \
- hello.h \
- openocd.h
-
-libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\"
-
-# banner output includes RELSTR appended to $VERSION from the configure script
-# guess-rev.sh returns either a repository version ID or "-snapshot"
-if RELEASE
-libopenocd_la_CPPFLAGS += -DRELSTR=\"\"
-libopenocd_la_CPPFLAGS += -DGITVERSION=\"\"
-else
-libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\"
-libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\"
-endif
-
-# add default CPPFLAGS
-libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS)
-
-# the library search path.
-libopenocd_la_LDFLAGS = $(all_libraries)
-
-if IS_MINGW
-MINGWLDADD = -lws2_32
-else
-MINGWLDADD =
-endif
-
-libopenocd_la_LIBADD = \
- $(top_builddir)/src/xsvf/libxsvf.la \
- $(top_builddir)/src/svf/libsvf.la \
- $(top_builddir)/src/pld/libpld.la \
- $(top_builddir)/src/jtag/libjtag.la \
- $(top_builddir)/src/transport/libtransport.la \
- $(top_builddir)/src/flash/libflash.la \
- $(top_builddir)/src/target/libtarget.la \
- $(top_builddir)/src/server/libserver.la \
- $(top_builddir)/src/rtos/librtos.la \
- $(top_builddir)/src/helper/libhelper.la \
- $(LIBFTDI_LIBS) $(MINGWLDADD) \
- $(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS)
-
-STARTUP_TCL_SRCS = \
- $(srcdir)/helper/startup.tcl \
- $(srcdir)/jtag/startup.tcl \
- $(srcdir)/target/startup.tcl \
- $(srcdir)/flash/startup.tcl \
- $(srcdir)/server/startup.tcl
-
-EXTRA_DIST = $(STARTUP_TCL_SRCS)
-
-BUILT_SOURCES = startup_tcl.inc
-
-startup.tcl: $(STARTUP_TCL_SRCS)
- cat $^ > $@
-
-BIN2C = $(top_srcdir)/src/helper/bin2char.sh
-
-# Convert .tcl to c-array
-startup_tcl.inc: startup.tcl $(BIN2C)
- $(BIN2C) < $< > $@ || { rm -f $@; false; }
-
-# add generated files to make clean list
-CLEANFILES = startup.tcl startup_tcl.inc
-
-# we do not want generated file in the dist
-dist-hook:
- rm -f $(distdir)/startup_tcl.inc
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
-
-# The "quick" target builds executables & reinstalls the executables
-# Primary use: developer types to quicken the edit/compile/debug
-# cycle. by not requiring a "full build and full install". Note the
-# assumption is: You are only rebuilding the EXE.... and everything
-# else is/was previously installed.
-#
-# use at your own risk
-quick: all install-binPROGRAMS
-
diff --git a/src/flash/Makefile.am b/src/flash/Makefile.am
deleted file mode 100644
index ece4018..0000000
--- a/src/flash/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-include $(top_srcdir)/common.mk
-
-SUBDIRS = \
- nor \
- nand
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libflash.la
-libflash_la_SOURCES = \
- common.c \
- mflash.c
-
-libflash_la_LIBADD = \
- $(top_builddir)/src/flash/nor/libocdflashnor.la \
- $(top_builddir)/src/flash/nand/libocdflashnand.la
-
-noinst_HEADERS = \
- common.h \
- mflash.h
-
-EXTRA_DIST = startup.tcl
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/flash/common.c b/src/flash/common.c
deleted file mode 100644
index 3e25511..0000000
--- a/src/flash/common.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "common.h"
-#include <helper/log.h>
-
-unsigned get_flash_name_index(const char *name)
-{
- const char *name_index = strrchr(name, '.');
- if (NULL == name_index)
- return 0;
- if (name_index[1] < '0' || name_index[1] > '9')
- return ~0U;
- unsigned requested;
- int retval = parse_uint(name_index + 1, &requested);
- /* detect parsing error by forcing past end of bank list */
- return (ERROR_OK == retval) ? requested : ~0U;
-}
-
-bool flash_driver_name_matches(const char *name, const char *expected)
-{
- unsigned blen = strlen(name);
- /* only match up to the length of the driver name... */
- if (strncmp(name, expected, blen) != 0)
- return false;
-
- /* ...then check that name terminates at this spot. */
- return expected[blen] == '.' || expected[blen] == '\0';
-}
diff --git a/src/flash/common.h b/src/flash/common.h
deleted file mode 100644
index ce26fcc..0000000
--- a/src/flash/common.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_COMMON_H
-#define OPENOCD_FLASH_COMMON_H
-
-#include <helper/log.h>
-
-/**
- * Parses the optional '.index' portion of a flash bank identifier.
- * @param name The desired driver name, passed by the user.
- * @returns The parsed index request, or 0 if not present. If the
- * name provides a suffix but it does not parse as an unsigned integer,
- * the routine returns ~0U. This will prevent further matching.
- */
-unsigned get_flash_name_index(const char *name);
-/**
- * Attempt to match the @c expected name with the @c name of a driver.
- * @param name The name of the driver (from the bank's device structure).
- * @param expected The expected driver name, passed by the user.
- */
-bool flash_driver_name_matches(const char *name, const char *expected);
-
-#define ERROR_FLASH_BANK_INVALID (-900)
-#define ERROR_FLASH_SECTOR_INVALID (-901)
-#define ERROR_FLASH_OPERATION_FAILED (-902)
-#define ERROR_FLASH_DST_OUT_OF_BANK (-903)
-#define ERROR_FLASH_DST_BREAKS_ALIGNMENT (-904)
-#define ERROR_FLASH_BUSY (-905)
-#define ERROR_FLASH_SECTOR_NOT_ERASED (-906)
-#define ERROR_FLASH_BANK_NOT_PROBED (-907)
-#define ERROR_FLASH_OPER_UNSUPPORTED (-908)
-
-#endif /* OPENOCD_FLASH_COMMON_H */
diff --git a/src/flash/mflash.c b/src/flash/mflash.c
deleted file mode 100644
index b699955..0000000
--- a/src/flash/mflash.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007-2008 by unsik Kim <donari75@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mflash.h"
-#include <target/target.h>
-#include <helper/time_support.h>
-#include <helper/fileio.h>
-#include <helper/log.h>
-
-static int s3c2440_set_gpio_to_output(struct mflash_gpio_num gpio);
-static int s3c2440_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val);
-static int pxa270_set_gpio_to_output(struct mflash_gpio_num gpio);
-static int pxa270_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val);
-
-static struct mflash_bank *mflash_bank;
-
-static struct mflash_gpio_drv pxa270_gpio = {
- .name = "pxa270",
- .set_gpio_to_output = pxa270_set_gpio_to_output,
- .set_gpio_output_val = pxa270_set_gpio_output_val
-};
-
-static struct mflash_gpio_drv s3c2440_gpio = {
- .name = "s3c2440",
- .set_gpio_to_output = s3c2440_set_gpio_to_output,
- .set_gpio_output_val = s3c2440_set_gpio_output_val
-};
-
-static struct mflash_gpio_drv *mflash_gpio[] = {
- &pxa270_gpio,
- &s3c2440_gpio,
- NULL
-};
-
-#define PXA270_GAFR0_L 0x40E00054
-#define PXA270_GAFR3_U 0x40E00070
-#define PXA270_GAFR3_U_RESERVED_BITS 0xfffc0000u
-#define PXA270_GPDR0 0x40E0000C
-#define PXA270_GPDR3 0x40E0010C
-#define PXA270_GPDR3_RESERVED_BITS 0xfe000000u
-#define PXA270_GPSR0 0x40E00018
-#define PXA270_GPCR0 0x40E00024
-
-static int pxa270_set_gpio_to_output(struct mflash_gpio_num gpio)
-{
- uint32_t addr, value, mask;
- struct target *target = mflash_bank->target;
- int ret;
-
- /* remove alternate function. */
- mask = 0x3u << (gpio.num & 0xF)*2;
-
- addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4;
-
- ret = target_read_u32(target, addr, &value);
- if (ret != ERROR_OK)
- return ret;
-
- value &= ~mask;
- if (addr == PXA270_GAFR3_U)
- value &= ~PXA270_GAFR3_U_RESERVED_BITS;
-
- ret = target_write_u32(target, addr, value);
- if (ret != ERROR_OK)
- return ret;
-
- /* set direction to output */
- mask = 0x1u << (gpio.num & 0x1F);
-
- addr = PXA270_GPDR0 + (gpio.num >> 5) * 4;
-
- ret = target_read_u32(target, addr, &value);
- if (ret != ERROR_OK)
- return ret;
-
- value |= mask;
- if (addr == PXA270_GPDR3)
- value &= ~PXA270_GPDR3_RESERVED_BITS;
-
- ret = target_write_u32(target, addr, value);
- return ret;
-}
-
-static int pxa270_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val)
-{
- uint32_t addr, value, mask;
- struct target *target = mflash_bank->target;
- int ret;
-
- mask = 0x1u << (gpio.num & 0x1F);
-
- if (val)
- addr = PXA270_GPSR0 + (gpio.num >> 5) * 4;
- else
- addr = PXA270_GPCR0 + (gpio.num >> 5) * 4;
-
- ret = target_read_u32(target, addr, &value);
- if (ret != ERROR_OK)
- return ret;
-
- value |= mask;
-
- ret = target_write_u32(target, addr, value);
-
- return ret;
-}
-
-#define S3C2440_GPACON 0x56000000
-#define S3C2440_GPADAT 0x56000004
-#define S3C2440_GPJCON 0x560000d0
-#define S3C2440_GPJDAT 0x560000d4
-
-static int s3c2440_set_gpio_to_output(struct mflash_gpio_num gpio)
-{
- uint32_t data, mask, gpio_con;
- struct target *target = mflash_bank->target;
- int ret;
-
- if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h')
- gpio_con = S3C2440_GPACON + (gpio.port[0] - 'a') * 0x10;
- else if (gpio.port[0] == 'j')
- gpio_con = S3C2440_GPJCON;
- else {
- LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- ret = target_read_u32(target, gpio_con, &data);
-
- if (ret == ERROR_OK) {
- if (gpio.port[0] == 'a') {
- mask = 1 << gpio.num;
- data &= ~mask;
- } else {
- mask = 3 << gpio.num * 2;
- data &= ~mask;
- data |= (1 << gpio.num * 2);
- }
-
- ret = target_write_u32(target, gpio_con, data);
- }
- return ret;
-}
-
-static int s3c2440_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val)
-{
- uint32_t data, mask, gpio_dat;
- struct target *target = mflash_bank->target;
- int ret;
-
- if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h')
- gpio_dat = S3C2440_GPADAT + (gpio.port[0] - 'a') * 0x10;
- else if (gpio.port[0] == 'j')
- gpio_dat = S3C2440_GPJDAT;
- else {
- LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- ret = target_read_u32(target, gpio_dat, &data);
-
- if (ret == ERROR_OK) {
- mask = 1 << gpio.num;
- if (val)
- data |= mask;
- else
- data &= ~mask;
-
- ret = target_write_u32(target, gpio_dat, data);
- }
- return ret;
-}
-
-static int mg_hdrst(uint8_t level)
-{
- return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level);
-}
-
-static int mg_init_gpio(void)
-{
- int ret;
- struct mflash_gpio_drv *gpio_drv = mflash_bank->gpio_drv;
-
- ret = gpio_drv->set_gpio_to_output(mflash_bank->rst_pin);
- if (ret != ERROR_OK)
- return ret;
-
- ret = gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1);
-
- return ret;
-}
-
-static int mg_dsk_wait(mg_io_type_wait wait_local, uint32_t time_var)
-{
- uint8_t status, error;
- struct target *target = mflash_bank->target;
- uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
- int ret;
- long long t = 0;
-
- struct duration bench;
- duration_start(&bench);
-
- while (time_var) {
-
- ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
- if (ret != ERROR_OK)
- return ret;
-
- if (status & mg_io_rbit_status_busy) {
- if (wait_local == mg_io_wait_bsy)
- return ERROR_OK;
- } else {
- switch (wait_local) {
- case mg_io_wait_not_bsy:
- return ERROR_OK;
- case mg_io_wait_rdy_noerr:
- if (status & mg_io_rbit_status_ready)
- return ERROR_OK;
- break;
- case mg_io_wait_drq_noerr:
- if (status & mg_io_rbit_status_data_req)
- return ERROR_OK;
- break;
- default:
- break;
- }
-
- /* Now we check the error condition! */
- if (status & mg_io_rbit_status_error) {
- ret = target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_ERROR("mflash: io error 0x%02x", error);
-
- return ERROR_MG_IO;
- }
-
- switch (wait_local) {
- case mg_io_wait_rdy:
- if (status & mg_io_rbit_status_ready)
- return ERROR_OK;
-
- case mg_io_wait_drq:
- if (status & mg_io_rbit_status_data_req)
- return ERROR_OK;
-
- default:
- break;
- }
- }
-
- ret = duration_measure(&bench);
- if (ERROR_OK == ret)
- t = duration_elapsed(&bench) * 1000.0;
- else
- LOG_ERROR("mflash: duration measurement failed: %d", ret);
-
- if (t > time_var)
- break;
- }
-
- LOG_ERROR("mflash: timeout occured");
- return ERROR_MG_TIMEOUT;
-}
-
-static int mg_dsk_srst(uint8_t on)
-{
- struct target *target = mflash_bank->target;
- uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
- uint8_t value;
- int ret;
-
- ret = target_read_u8(target, mg_task_reg + MG_REG_DRV_CTRL, &value);
- if (ret != ERROR_OK)
- return ret;
-
- if (on)
- value |= (mg_io_rbit_devc_srst);
- else
- value &= ~mg_io_rbit_devc_srst;
-
- ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_CTRL, value);
- return ret;
-}
-
-static int mg_dsk_io_cmd(uint32_t sect_num, uint32_t cnt, uint8_t cmd)
-{
- struct target *target = mflash_bank->target;
- uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
- uint8_t value;
- int ret;
-
- ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL);
- if (ret != ERROR_OK)
- return ret;
-
- value = mg_io_rval_dev_drv_master | mg_io_rval_dev_lba_mode | ((sect_num >> 24) & 0xf);
-
- ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_HEAD, value);
- ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, (uint8_t)cnt);
- ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_NUM, (uint8_t)sect_num);
- ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_LOW, (uint8_t)(sect_num >> 8));
- ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_HIGH, (uint8_t)(sect_num >> 16));
-
- if (ret != ERROR_OK)
- return ret;
-
- return target_write_u8(target, mg_task_reg + MG_REG_COMMAND, cmd);
-}
-
-static int mg_dsk_drv_info(void)
-{
- struct target *target = mflash_bank->target;
- uint32_t mg_buff = mflash_bank->base + MG_BUFFER_OFFSET;
- int ret;
-
- ret = mg_dsk_io_cmd(0, 1, mg_io_cmd_identify);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_INFO("mflash: read drive info");
-
- if (!mflash_bank->drv_info)
- mflash_bank->drv_info = malloc(sizeof(struct mg_drv_info));
-
- ret = target_read_memory(target, mg_buff, 2,
- sizeof(mg_io_type_drv_info) >> 1,
- (uint8_t *)&mflash_bank->drv_info->drv_id);
- if (ret != ERROR_OK)
- return ret;
-
- mflash_bank->drv_info->tot_sects =
- (uint32_t)(mflash_bank->drv_info->drv_id.total_user_addressable_sectors_hi << 16)
- + mflash_bank->drv_info->drv_id.total_user_addressable_sectors_lo;
-
- return target_write_u8(target,
- mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND,
- mg_io_cmd_confirm_read);
-}
-
-static int mg_mflash_rst(void)
-{
- int ret;
-
- ret = mg_init_gpio();
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_hdrst(0);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_hdrst(1);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_dsk_srst(1);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_dsk_srst(0);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_INFO("mflash: reset ok");
-
- return ERROR_OK;
-}
-
-static int mg_mflash_probe(void)
-{
- int ret = mg_mflash_rst();
- if (ret != ERROR_OK)
- return ret;
-
- return mg_dsk_drv_info();
-}
-
-COMMAND_HANDLER(mg_probe_cmd)
-{
- int ret;
-
- ret = mg_mflash_probe();
-
- if (ret == ERROR_OK) {
- command_print(CMD_CTX,
- "mflash (total %" PRIu32 " sectors) found at 0x%8.8" PRIx32 "",
- mflash_bank->drv_info->tot_sects,
- mflash_bank->base);
- }
-
- return ret;
-}
-
-static int mg_mflash_do_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
-{
- uint32_t i, address;
- int ret;
- struct target *target = mflash_bank->target;
- uint8_t *buff_ptr = buff;
-
- ret = mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read);
- if (ret != ERROR_OK)
- return ret;
-
- address = mflash_bank->base + MG_BUFFER_OFFSET;
-
- struct duration bench;
- duration_start(&bench);
-
- for (i = 0; i < sect_cnt; i++) {
- ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
- if (ret != ERROR_OK)
- return ret;
-
- ret = target_read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
- if (ret != ERROR_OK)
- return ret;
-
- buff_ptr += MG_MFLASH_SECTOR_SIZE;
-
- ret = target_write_u8(target,
- mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND,
- mg_io_cmd_confirm_read);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector read", sect_num + i,
- (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
-
- ret = duration_measure(&bench);
- if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
- LOG_INFO("mflash: read %" PRIu32 "'th sectors", sect_num + i);
- duration_start(&bench);
- }
- }
-
- return mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
-}
-
-static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
-{
- uint32_t quotient, residue, i;
- uint8_t *buff_ptr = buff;
- int ret = ERROR_OK;
-
- quotient = sect_cnt >> 8;
- residue = sect_cnt % 256;
-
- for (i = 0; i < quotient; i++) {
- LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p",
- sect_num, buff_ptr);
- ret = mg_mflash_do_read_sects(buff_ptr, sect_num, 256);
- if (ret != ERROR_OK)
- return ret;
-
- sect_num += 256;
- buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
- }
-
- if (residue) {
- LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %p",
- sect_num, buff_ptr);
- return mg_mflash_do_read_sects(buff_ptr, sect_num, residue);
- }
-
- return ret;
-}
-
-static int mg_mflash_do_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt,
- uint8_t cmd)
-{
- uint32_t i, address;
- int ret;
- struct target *target = mflash_bank->target;
- uint8_t *buff_ptr = buff;
-
- ret = mg_dsk_io_cmd(sect_num, sect_cnt, cmd);
- if (ret != ERROR_OK)
- return ret;
-
- address = mflash_bank->base + MG_BUFFER_OFFSET;
-
- struct duration bench;
- duration_start(&bench);
-
- for (i = 0; i < sect_cnt; i++) {
- ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
- if (ret != ERROR_OK)
- return ret;
-
- ret = target_write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
- if (ret != ERROR_OK)
- return ret;
-
- buff_ptr += MG_MFLASH_SECTOR_SIZE;
-
- ret = target_write_u8(target,
- mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND,
- mg_io_cmd_confirm_write);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector write", sect_num + i,
- (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
-
- ret = duration_measure(&bench);
- if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
- LOG_INFO("mflash: wrote %" PRIu32 "'th sectors", sect_num + i);
- duration_start(&bench);
- }
- }
-
- if (cmd == mg_io_cmd_write)
- ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
- else
- ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_LONG);
-
- return ret;
-}
-
-static int mg_mflash_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
-{
- uint32_t quotient, residue, i;
- uint8_t *buff_ptr = buff;
- int ret = ERROR_OK;
-
- quotient = sect_cnt >> 8;
- residue = sect_cnt % 256;
-
- for (i = 0; i < quotient; i++) {
- LOG_DEBUG("mflash: sect num : %" PRIu32 "buff : %p", sect_num,
- buff_ptr);
- ret = mg_mflash_do_write_sects(buff_ptr, sect_num, 256, mg_io_cmd_write);
- if (ret != ERROR_OK)
- return ret;
-
- sect_num += 256;
- buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
- }
-
- if (residue) {
- LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p", sect_num,
- buff_ptr);
- return mg_mflash_do_write_sects(buff_ptr, sect_num, residue, mg_io_cmd_write);
- }
-
- return ret;
-}
-
-static int mg_mflash_read(uint32_t addr, uint8_t *buff, uint32_t len)
-{
- uint8_t *buff_ptr = buff;
- uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
- uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
- int ret = ERROR_OK;
-
- cnt = 0;
- cur_addr = addr;
- end_addr = addr + len;
-
- if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
-
- next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
- sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
- ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
- if (ret != ERROR_OK)
- return ret;
-
- if (end_addr < next_sec_addr) {
- memcpy(buff_ptr,
- sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
- end_addr - cur_addr);
- LOG_DEBUG(
- "mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "",
- end_addr - cur_addr,
- cur_addr);
- cur_addr = end_addr;
- } else {
- memcpy(buff_ptr,
- sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
- next_sec_addr - cur_addr);
- LOG_DEBUG(
- "mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "",
- next_sec_addr - cur_addr,
- cur_addr);
- buff_ptr += (next_sec_addr - cur_addr);
- cur_addr = next_sec_addr;
- }
- }
-
- if (cur_addr < end_addr) {
-
- sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
- next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
-
- while (next_sec_addr <= end_addr) {
- cnt++;
- next_sec_addr += MG_MFLASH_SECTOR_SIZE;
- }
-
- if (cnt) {
- ret = mg_mflash_read_sects(buff_ptr, sect_num, cnt);
- if (ret != ERROR_OK)
- return ret;
- }
-
- buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
- cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
-
- if (cur_addr < end_addr) {
-
- sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
- ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
- if (ret != ERROR_OK)
- return ret;
-
- memcpy(buff_ptr, sect_buff, end_addr - cur_addr);
- LOG_DEBUG("mflash: copies %u byte", (unsigned)(end_addr - cur_addr));
- }
- }
-
- return ret;
-}
-
-static int mg_mflash_write(uint32_t addr, uint8_t *buff, uint32_t len)
-{
- uint8_t *buff_ptr = buff;
- uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
- uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
- int ret = ERROR_OK;
-
- cnt = 0;
- cur_addr = addr;
- end_addr = addr + len;
-
- if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
-
- next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
- sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
- ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
- if (ret != ERROR_OK)
- return ret;
-
- if (end_addr < next_sec_addr) {
- memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
- buff_ptr,
- end_addr - cur_addr);
- LOG_DEBUG(
- "mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "",
- end_addr - cur_addr,
- cur_addr);
- cur_addr = end_addr;
- } else {
- memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
- buff_ptr,
- next_sec_addr - cur_addr);
- LOG_DEBUG(
- "mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "",
- next_sec_addr - cur_addr,
- cur_addr);
- buff_ptr += (next_sec_addr - cur_addr);
- cur_addr = next_sec_addr;
- }
-
- ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
- if (ret != ERROR_OK)
- return ret;
- }
-
- if (cur_addr < end_addr) {
-
- sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
- next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
-
- while (next_sec_addr <= end_addr) {
- cnt++;
- next_sec_addr += MG_MFLASH_SECTOR_SIZE;
- }
-
- if (cnt) {
- ret = mg_mflash_write_sects(buff_ptr, sect_num, cnt);
- if (ret != ERROR_OK)
- return ret;
- }
-
- buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
- cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
-
- if (cur_addr < end_addr) {
-
- sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
- ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
- if (ret != ERROR_OK)
- return ret;
-
- memcpy(sect_buff, buff_ptr, end_addr - cur_addr);
- LOG_DEBUG("mflash: copies %" PRIu32 " byte", end_addr - cur_addr);
- ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
- }
- }
-
- return ret;
-}
-
-COMMAND_HANDLER(mg_write_cmd)
-{
- uint32_t address, cnt, res, i;
- uint8_t *buffer;
- struct fileio *fileio;
- int ret;
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
-
- ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
- if (ret != ERROR_OK)
- return ret;
-
- size_t filesize;
- buffer = malloc(MG_FILEIO_CHUNK);
- if (!buffer) {
- fileio_close(fileio);
- return ERROR_FAIL;
- }
- int retval = fileio_size(fileio, &filesize);
- if (retval != ERROR_OK) {
- fileio_close(fileio);
- free(buffer);
- return retval;
- }
-
- cnt = filesize / MG_FILEIO_CHUNK;
- res = filesize % MG_FILEIO_CHUNK;
-
- struct duration bench;
- duration_start(&bench);
-
- size_t buf_cnt;
- for (i = 0; i < cnt; i++) {
- ret = fileio_read(fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt);
- if (ret != ERROR_OK)
- goto mg_write_cmd_err;
- ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK);
- if (ret != ERROR_OK)
- goto mg_write_cmd_err;
- address += MG_FILEIO_CHUNK;
- }
-
- if (res) {
- ret = fileio_read(fileio, res, buffer, &buf_cnt);
- if (ret != ERROR_OK)
- goto mg_write_cmd_err;
- ret = mg_mflash_write(address, buffer, res);
- if (ret != ERROR_OK)
- goto mg_write_cmd_err;
- }
-
- if (duration_measure(&bench) == ERROR_OK) {
- command_print(CMD_CTX, "wrote %zu bytes from file %s "
- "in %fs (%0.3f kB/s)", filesize, CMD_ARGV[1],
- duration_elapsed(&bench), duration_kbps(&bench, filesize));
- }
-
- free(buffer);
- fileio_close(fileio);
-
- return ERROR_OK;
-
-mg_write_cmd_err:
- free(buffer);
- fileio_close(fileio);
-
- return ret;
-}
-
-COMMAND_HANDLER(mg_dump_cmd)
-{
- uint32_t address, size, cnt, res, i;
- uint8_t *buffer;
- struct fileio *fileio;
- int ret;
-
- if (CMD_ARGC != 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], size);
-
- ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
- if (ret != ERROR_OK)
- return ret;
-
- buffer = malloc(MG_FILEIO_CHUNK);
- if (!buffer) {
- fileio_close(fileio);
- return ERROR_FAIL;
- }
-
- cnt = size / MG_FILEIO_CHUNK;
- res = size % MG_FILEIO_CHUNK;
-
- struct duration bench;
- duration_start(&bench);
-
- size_t size_written;
- for (i = 0; i < cnt; i++) {
- ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK);
- if (ret != ERROR_OK)
- goto mg_dump_cmd_err;
- ret = fileio_write(fileio, MG_FILEIO_CHUNK, buffer, &size_written);
- if (ret != ERROR_OK)
- goto mg_dump_cmd_err;
- address += MG_FILEIO_CHUNK;
- }
-
- if (res) {
- ret = mg_mflash_read(address, buffer, res);
- if (ret != ERROR_OK)
- goto mg_dump_cmd_err;
- ret = fileio_write(fileio, res, buffer, &size_written);
- if (ret != ERROR_OK)
- goto mg_dump_cmd_err;
- }
-
- if (duration_measure(&bench) == ERROR_OK) {
- command_print(CMD_CTX, "dump image (address 0x%8.8" PRIx32 " "
- "size %" PRIu32 ") to file %s in %fs (%0.3f kB/s)",
- address, size, CMD_ARGV[1],
- duration_elapsed(&bench), duration_kbps(&bench, size));
- }
-
- free(buffer);
- fileio_close(fileio);
-
- return ERROR_OK;
-
-mg_dump_cmd_err:
- free(buffer);
- fileio_close(fileio);
-
- return ret;
-}
-
-static int mg_set_feature(mg_feature_id feature, mg_feature_val config)
-{
- struct target *target = mflash_bank->target;
- uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
- int ret;
-
- ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL);
- if (ret != ERROR_OK)
- return ret;
-
- ret = target_write_u8(target, mg_task_reg + MG_REG_FEATURE, feature);
- ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, config);
- ret |= target_write_u8(target, mg_task_reg + MG_REG_COMMAND,
- mg_io_cmd_set_feature);
-
- return ret;
-}
-
-static int mg_is_valid_pll(double XIN, int N, double CLK_OUT, int NO)
-{
- double v1 = XIN / N;
- double v2 = CLK_OUT * NO;
-
- if (v1 < 1000000 || v1 > 15000000 || v2 < 100000000 || v2 > 500000000)
- return ERROR_MG_INVALID_PLL;
-
- return ERROR_OK;
-}
-
-static int mg_pll_get_M(unsigned short feedback_div)
-{
- int i, M;
-
- for (i = 1, M = 0; i < 512; i <<= 1, feedback_div >>= 1)
- M += (feedback_div & 1) * i;
-
- return M + 2;
-}
-
-static int mg_pll_get_N(unsigned char input_div)
-{
- int i, N;
-
- for (i = 1, N = 0; i < 32; i <<= 1, input_div >>= 1)
- N += (input_div & 1) * i;
-
- return N + 2;
-}
-
-static int mg_pll_get_NO(unsigned char output_div)
-{
- int i, NO;
-
- for (i = 0, NO = 1; i < 2; ++i, output_div >>= 1)
- if (output_div & 1)
- NO = NO << 1;
-
- return NO;
-}
-
-static double mg_do_calc_pll(double XIN, mg_pll_t *p_pll_val, int is_approximate)
-{
- unsigned short i;
- unsigned char j, k;
- int M, N, NO;
- double CLK_OUT;
- double DIV = 1;
- double ROUND = 0;
-
- if (is_approximate) {
- DIV = 1000000;
- ROUND = 500000;
- }
-
- for (i = 0; i < MG_PLL_MAX_FEEDBACKDIV_VAL; ++i) {
- M = mg_pll_get_M(i);
-
- for (j = 0; j < MG_PLL_MAX_INPUTDIV_VAL; ++j) {
- N = mg_pll_get_N(j);
-
- for (k = 0; k < MG_PLL_MAX_OUTPUTDIV_VAL; ++k) {
- NO = mg_pll_get_NO(k);
-
- CLK_OUT = XIN * ((double)M / N) / NO;
-
- if ((int)((CLK_OUT + ROUND) / DIV)
- == (int)(MG_PLL_CLK_OUT / DIV)) {
- if (mg_is_valid_pll(XIN, N, CLK_OUT, NO) == ERROR_OK) {
- p_pll_val->lock_cyc =
- (int)(XIN * MG_PLL_STD_LOCKCYCLE /
- MG_PLL_STD_INPUTCLK);
- p_pll_val->feedback_div = i;
- p_pll_val->input_div = j;
- p_pll_val->output_div = k;
-
- return CLK_OUT;
- }
- }
- }
- }
- }
-
- return 0;
-}
-
-static double mg_calc_pll(double XIN, mg_pll_t *p_pll_val)
-{
- double CLK_OUT;
-
- CLK_OUT = mg_do_calc_pll(XIN, p_pll_val, 0);
-
- if (!CLK_OUT)
- return mg_do_calc_pll(XIN, p_pll_val, 1);
- else
- return CLK_OUT;
-}
-
-static int mg_verify_interface(void)
-{
- uint16_t buff[MG_MFLASH_SECTOR_SIZE >> 1];
- uint16_t i, j;
- uint32_t address = mflash_bank->base + MG_BUFFER_OFFSET;
- struct target *target = mflash_bank->target;
- int ret;
-
- for (j = 0; j < 10; j++) {
- for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++)
- buff[i] = i;
-
- ret = target_write_memory(target, address, 2,
- MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
- if (ret != ERROR_OK)
- return ret;
-
- memset(buff, 0xff, MG_MFLASH_SECTOR_SIZE);
-
- ret = target_read_memory(target, address, 2,
- MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
- if (ret != ERROR_OK)
- return ret;
-
- for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) {
- if (buff[i] != i) {
- LOG_ERROR("mflash: verify interface fail");
- return ERROR_MG_INTERFACE;
- }
- }
- }
-
- LOG_INFO("mflash: verify interface ok");
- return ret;
-}
-
-static const char g_strSEG_SerialNum[20] = {
- 'G', 'm', 'n', 'i', '-', 'e', 'e', 'S', 'g', 'a', 'e', 'l',
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
-};
-
-static const char g_strSEG_FWRev[8] = {
- 'F', 'X', 'L', 'T', '2', 'v', '0', '.'
-};
-
-static const char g_strSEG_ModelNum[40] = {
- 'F', 'X', 'A', 'L', 'H', 'S', '2', 0x20, '0', '0', 's', '7',
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
-};
-
-static void mg_gen_ataid(mg_io_type_drv_info *pSegIdDrvInfo)
-{
- /* b15 is ATA device(0) , b7 is Removable Media Device */
- pSegIdDrvInfo->general_configuration = 0x045A;
- /* 128MB : Cylinder=> 977 , Heads=> 8 , Sectors=> 32
- * 256MB : Cylinder=> 980 , Heads=> 16 , Sectors=> 32
- * 384MB : Cylinder=> 745 , Heads=> 16 , Sectors=> 63
- */
- pSegIdDrvInfo->number_of_cylinders = 0x02E9;
- pSegIdDrvInfo->reserved1 = 0x0;
- pSegIdDrvInfo->number_of_heads = 0x10;
- pSegIdDrvInfo->unformatted_bytes_per_track = 0x0;
- pSegIdDrvInfo->unformatted_bytes_per_sector = 0x0;
- pSegIdDrvInfo->sectors_per_track = 0x3F;
- pSegIdDrvInfo->vendor_unique1[0] = 0x000B;
- pSegIdDrvInfo->vendor_unique1[1] = 0x7570;
- pSegIdDrvInfo->vendor_unique1[2] = 0x8888;
-
- memcpy(pSegIdDrvInfo->serial_number, g_strSEG_SerialNum, 20);
- /* 0x2 : dual buffer */
- pSegIdDrvInfo->buffer_type = 0x2;
- /* buffer size : 2KB */
- pSegIdDrvInfo->buffer_sector_size = 0x800;
- pSegIdDrvInfo->number_of_ecc_bytes = 0;
-
- memcpy(pSegIdDrvInfo->firmware_revision, g_strSEG_FWRev, 8);
-
- memcpy(pSegIdDrvInfo->model_number, g_strSEG_ModelNum, 40);
-
- pSegIdDrvInfo->maximum_block_transfer = 0x4;
- pSegIdDrvInfo->vendor_unique2 = 0x0;
- pSegIdDrvInfo->dword_io = 0x00;
- /* b11 : IORDY support(PIO Mode 4), b10 : Disable/Enbale IORDY
- * b9 : LBA support, b8 : DMA mode support
- */
- pSegIdDrvInfo->capabilities = 0x1 << 9;
-
- pSegIdDrvInfo->reserved2 = 0x4000;
- pSegIdDrvInfo->vendor_unique3 = 0x00;
- /* PIOMode-2 support */
- pSegIdDrvInfo->pio_cycle_timing_mode = 0x02;
- pSegIdDrvInfo->vendor_unique4 = 0x00;
- /* MultiWord-2 support */
- pSegIdDrvInfo->dma_cycle_timing_mode = 0x00;
- /* b1 : word64~70 is valid
- * b0 : word54~58 are valid and reflect the current numofcyls,heads,sectors
- * b2 : If device supports Ultra DMA , set to one to vaildate word88
- */
- pSegIdDrvInfo->translation_fields_valid = (0x1 << 1) | (0x1 << 0);
- pSegIdDrvInfo->number_of_current_cylinders = 0x02E9;
- pSegIdDrvInfo->number_of_current_heads = 0x10;
- pSegIdDrvInfo->current_sectors_per_track = 0x3F;
- pSegIdDrvInfo->current_sector_capacity_lo = 0x7570;
- pSegIdDrvInfo->current_sector_capacity_hi = 0x000B;
-
- pSegIdDrvInfo->multi_sector_count = 0x04;
- /* b8 : Multiple secotr setting valid , b[7:0] num of secotrs per block */
- pSegIdDrvInfo->multi_sector_setting_valid = 0x01;
- pSegIdDrvInfo->total_user_addressable_sectors_lo = 0x7570;
- pSegIdDrvInfo->total_user_addressable_sectors_hi = 0x000B;
- pSegIdDrvInfo->single_dma_modes_supported = 0x00;
- pSegIdDrvInfo->single_dma_transfer_active = 0x00;
- /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
- pSegIdDrvInfo->multi_dma_modes_supported = (0x1 << 0);
- /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
- pSegIdDrvInfo->multi_dma_transfer_active = (0x1 << 0);
- /* b0 : PIO Mode-3 support, b1 : PIO Mode-4 support */
- pSegIdDrvInfo->adv_pio_mode = 0x00;
- /* 480(0x1E0)nsec for Multi-word DMA mode0
- * 150(0x96) nsec for Multi-word DMA mode1
- * 120(0x78) nsec for Multi-word DMA mode2
- */
- pSegIdDrvInfo->min_dma_cyc = 0x1E0;
- pSegIdDrvInfo->recommend_dma_cyc = 0x1E0;
- pSegIdDrvInfo->min_pio_cyc_no_iordy = 0x1E0;
- pSegIdDrvInfo->min_pio_cyc_with_iordy = 0x1E0;
- memset(pSegIdDrvInfo->reserved3, 0x00, 22);
- /* b7 : ATA/ATAPI-7 ,b6 : ATA/ATAPI-6 ,b5 : ATA/ATAPI-5,b4 : ATA/ATAPI-4 */
- pSegIdDrvInfo->major_ver_num = 0x7E;
- /* 0x1C : ATA/ATAPI-6 T13 1532D revision1 */
- pSegIdDrvInfo->minor_ver_num = 0x19;
- /* NOP/READ BUFFER/WRITE BUFFER/Power management feature set support */
- pSegIdDrvInfo->feature_cmd_set_suprt0 = 0x7068;
- /* Features/command set is valid/Advanced Pwr management/CFA feature set
- * not support
- */
- pSegIdDrvInfo->feature_cmd_set_suprt1 = 0x400C;
- pSegIdDrvInfo->feature_cmd_set_suprt2 = 0x4000;
- /* READ/WRITE BUFFER/PWR Management enable */
- pSegIdDrvInfo->feature_cmd_set_en0 = 0x7000;
- /* CFA feature is disabled / Advancde power management disable */
- pSegIdDrvInfo->feature_cmd_set_en1 = 0x0;
- pSegIdDrvInfo->feature_cmd_set_en2 = 0x4000;
- pSegIdDrvInfo->reserved4 = 0x0;
- /* 0x1 * 2minutes */
- pSegIdDrvInfo->req_time_for_security_er_done = 0x19;
- pSegIdDrvInfo->req_time_for_enhan_security_er_done = 0x19;
- /* Advanced power management level 1 */
- pSegIdDrvInfo->adv_pwr_mgm_lvl_val = 0x0;
- pSegIdDrvInfo->reserved5 = 0x0;
- memset(pSegIdDrvInfo->reserved6, 0x00, 68);
- /* Security mode feature is disabled */
- pSegIdDrvInfo->security_stas = 0x0;
- memset(pSegIdDrvInfo->vendor_uniq_bytes, 0x00, 62);
- /* CFA power mode 1 support in maximum 200mA */
- pSegIdDrvInfo->cfa_pwr_mode = 0x0100;
- memset(pSegIdDrvInfo->reserved7, 0x00, 190);
-}
-
-static int mg_storage_config(void)
-{
- uint8_t buff[512];
- int ret;
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
- if (ret != ERROR_OK)
- return ret;
-
- mg_gen_ataid((mg_io_type_drv_info *)(void *)buff);
-
- ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_INFO("mflash: storage config ok");
- return ret;
-}
-
-static int mg_boot_config(void)
-{
- uint8_t buff[512];
- int ret;
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
- if (ret != ERROR_OK)
- return ret;
-
- memset(buff, 0xff, 512);
-
- buff[0] = mg_op_mode_snd; /* operation mode */
- buff[1] = MG_UNLOCK_OTP_AREA;
- buff[2] = 4; /* boot size */
- *((uint32_t *)(void *)(buff + 4)) = 0; /* XIP size */
-
- ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_INFO("mflash: boot config ok");
- return ret;
-}
-
-static int mg_set_pll(mg_pll_t *pll)
-{
- uint8_t buff[512];
- int ret;
-
- memset(buff, 0xff, 512);
- /* PLL Lock cycle and Feedback 9bit Divider */
- memcpy(buff, &pll->lock_cyc, sizeof(uint32_t));
- memcpy(buff + 4, &pll->feedback_div, sizeof(uint16_t));
- buff[6] = pll->input_div; /* PLL Input 5bit Divider */
- buff[7] = pll->output_div; /* PLL Output Divider */
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_wr_pll);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_INFO("mflash: set pll ok");
- return ret;
-}
-
-static int mg_erase_nand(void)
-{
- int ret;
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_mflash_do_write_sects(NULL, 0, 0, mg_vcmd_purge_nand);
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_INFO("mflash: erase nand ok");
- return ret;
-}
-
-COMMAND_HANDLER(mg_config_cmd)
-{
- double fin, fout;
- mg_pll_t pll;
- int ret;
-
- ret = mg_verify_interface();
- if (ret != ERROR_OK)
- return ret;
-
- ret = mg_mflash_rst();
- if (ret != ERROR_OK)
- return ret;
-
- switch (CMD_ARGC) {
- case 2:
- if (!strcmp(CMD_ARGV[1], "boot"))
- return mg_boot_config();
- else if (!strcmp(CMD_ARGV[1], "storage"))
- return mg_storage_config();
- else
- return ERROR_COMMAND_NOTFOUND;
- break;
- case 3:
- if (!strcmp(CMD_ARGV[1], "pll")) {
- unsigned long freq;
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], freq);
- fin = freq;
-
- if (fin > MG_PLL_CLK_OUT) {
- LOG_ERROR("mflash: input freq. is too large");
- return ERROR_MG_INVALID_OSC;
- }
-
- fout = mg_calc_pll(fin, &pll);
-
- if (!fout) {
- LOG_ERROR("mflash: cannot generate valid pll");
- return ERROR_MG_INVALID_PLL;
- }
-
- LOG_INFO("mflash: Fout=%" PRIu32 " Hz, feedback=%u,"
- "indiv=%u, outdiv=%u, lock=%u",
- (uint32_t)fout, pll.feedback_div,
- pll.input_div, pll.output_div,
- pll.lock_cyc);
-
- ret = mg_erase_nand();
- if (ret != ERROR_OK)
- return ret;
-
- return mg_set_pll(&pll);
- } else
- return ERROR_COMMAND_NOTFOUND;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-}
-
-static const struct command_registration mflash_exec_command_handlers[] = {
- {
- .name = "probe",
- .handler = mg_probe_cmd,
- .mode = COMMAND_EXEC,
- .help = "Detect bank configuration information",
- },
- {
- .name = "write",
- .handler = mg_write_cmd,
- .mode = COMMAND_EXEC,
- /* FIXME bank_num is unused */
- .usage = "bank_num filename address",
- .help = "Write binary file at the specified address.",
- },
- {
- .name = "dump",
- .handler = mg_dump_cmd,
- .mode = COMMAND_EXEC,
- /* FIXME bank_num is unused */
- .usage = "bank_num filename address size",
- .help = "Write specified number of bytes from a binary file "
- "to the specified, address.",
- },
- {
- .name = "config",
- .handler = mg_config_cmd,
- .mode = COMMAND_EXEC,
- .help = "Configure MFLASH options.",
- .usage = "('boot'|'storage'|'pll' frequency)",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int mflash_init_drivers(struct command_context *cmd_ctx)
-{
- if (!mflash_bank)
- return ERROR_OK;
- return register_commands(cmd_ctx, NULL, mflash_exec_command_handlers);
-}
-
-COMMAND_HANDLER(handle_mflash_init_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- static bool mflash_initialized;
- if (mflash_initialized) {
- LOG_INFO("'mflash init' has already been called");
- return ERROR_OK;
- }
- mflash_initialized = true;
-
- LOG_DEBUG("Initializing mflash devices...");
- return mflash_init_drivers(CMD_CTX);
-}
-
-COMMAND_HANDLER(mg_bank_cmd)
-{
- struct target *target;
- int i;
-
- if (CMD_ARGC < 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_target(CMD_ARGV[3]);
- if (target == NULL) {
- LOG_ERROR("target '%s' not defined", CMD_ARGV[3]);
- return ERROR_FAIL;
- }
-
- mflash_bank = calloc(sizeof(struct mflash_bank), 1);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mflash_bank->base);
- /** @todo Verify how this parsing should work, then document it. */
- char *str;
- mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
- if (*str)
- mflash_bank->rst_pin.port[0] = (uint16_t)
- tolower((unsigned)str[0]);
-
- mflash_bank->target = target;
-
- for (i = 0; mflash_gpio[i]; i++) {
- if (!strcmp(mflash_gpio[i]->name, CMD_ARGV[0]))
- mflash_bank->gpio_drv = mflash_gpio[i];
- }
-
- if (!mflash_bank->gpio_drv) {
- LOG_ERROR("%s is unsupported soc", CMD_ARGV[0]);
- return ERROR_MG_UNSUPPORTED_SOC;
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration mflash_config_command_handlers[] = {
- {
- .name = "bank",
- .handler = mg_bank_cmd,
- .mode = COMMAND_CONFIG,
- .help = "configure a mflash device bank",
- .usage = "soc_type base_addr pin_id target",
- },
- {
- .name = "init",
- .mode = COMMAND_CONFIG,
- .handler = handle_mflash_init_command,
- .help = "initialize mflash devices",
- .usage = ""
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration mflash_command_handler[] = {
- {
- .name = "mflash",
- .mode = COMMAND_ANY,
- .help = "mflash command group",
- .usage = "",
- .chain = mflash_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-int mflash_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, mflash_command_handler);
-}
diff --git a/src/flash/mflash.h b/src/flash/mflash.h
deleted file mode 100644
index 18da403..0000000
--- a/src/flash/mflash.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007-2008 by unsik Kim <donari75@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_MFLASH_H
-#define OPENOCD_FLASH_MFLASH_H
-
-struct command_context;
-
-typedef unsigned long mg_io_uint32;
-typedef unsigned short mg_io_uint16;
-typedef unsigned char mg_io_uint8;
-
-struct mflash_gpio_num {
- char port[2];
- signed short num;
-};
-
-struct mflash_gpio_drv {
- const char *name;
- int (*set_gpio_to_output)(struct mflash_gpio_num gpio);
- int (*set_gpio_output_val)(struct mflash_gpio_num gpio, uint8_t val);
-};
-
-typedef struct _mg_io_type_drv_info {
-
- mg_io_uint16 general_configuration; /* 00 */
- mg_io_uint16 number_of_cylinders; /* 01 */
- mg_io_uint16 reserved1; /* 02 */
- mg_io_uint16 number_of_heads; /* 03 */
- mg_io_uint16 unformatted_bytes_per_track; /* 04 */
- mg_io_uint16 unformatted_bytes_per_sector; /* 05 */
- mg_io_uint16 sectors_per_track; /* 06 */
- mg_io_uint16 vendor_unique1[3]; /* 07/08/09 */
-
- mg_io_uint8 serial_number[20]; /* 10~19 */
-
- mg_io_uint16 buffer_type; /* 20 */
- mg_io_uint16 buffer_sector_size; /* 21 */
- mg_io_uint16 number_of_ecc_bytes; /* 22 */
-
- mg_io_uint8 firmware_revision[8]; /* 23~26 */
- mg_io_uint8 model_number[40]; /* 27 */
-
- mg_io_uint8 maximum_block_transfer; /* 47 low byte */
- mg_io_uint8 vendor_unique2; /* 47 high byte */
- mg_io_uint16 dword_io; /* 48 */
-
- mg_io_uint16 capabilities; /* 49 */
- mg_io_uint16 reserved2; /* 50 */
-
- mg_io_uint8 vendor_unique3; /* 51 low byte */
- mg_io_uint8 pio_cycle_timing_mode; /* 51 high byte */
- mg_io_uint8 vendor_unique4; /* 52 low byte */
- mg_io_uint8 dma_cycle_timing_mode; /* 52 high byte */
- mg_io_uint16 translation_fields_valid; /* 53 (low bit) */
- mg_io_uint16 number_of_current_cylinders; /* 54 */
- mg_io_uint16 number_of_current_heads; /* 55 */
- mg_io_uint16 current_sectors_per_track; /* 56 */
- mg_io_uint16 current_sector_capacity_lo; /* 57 & 58 */
- mg_io_uint16 current_sector_capacity_hi; /* 57 & 58 */
- mg_io_uint8 multi_sector_count; /* 59 low */
- mg_io_uint8 multi_sector_setting_valid; /* 59 high (low bit) */
-
- mg_io_uint16 total_user_addressable_sectors_lo; /* 60 & 61 */
- mg_io_uint16 total_user_addressable_sectors_hi; /* 60 & 61 */
-
- mg_io_uint8 single_dma_modes_supported; /* 62 low byte */
- mg_io_uint8 single_dma_transfer_active; /* 62 high byte */
- mg_io_uint8 multi_dma_modes_supported; /* 63 low byte */
- mg_io_uint8 multi_dma_transfer_active; /* 63 high byte */
- mg_io_uint16 adv_pio_mode;
- mg_io_uint16 min_dma_cyc;
- mg_io_uint16 recommend_dma_cyc;
- mg_io_uint16 min_pio_cyc_no_iordy;
- mg_io_uint16 min_pio_cyc_with_iordy;
- mg_io_uint8 reserved3[22];
- mg_io_uint16 major_ver_num;
- mg_io_uint16 minor_ver_num;
- mg_io_uint16 feature_cmd_set_suprt0;
- mg_io_uint16 feature_cmd_set_suprt1;
- mg_io_uint16 feature_cmd_set_suprt2;
- mg_io_uint16 feature_cmd_set_en0;
- mg_io_uint16 feature_cmd_set_en1;
- mg_io_uint16 feature_cmd_set_en2;
- mg_io_uint16 reserved4;
- mg_io_uint16 req_time_for_security_er_done;
- mg_io_uint16 req_time_for_enhan_security_er_done;
- mg_io_uint16 adv_pwr_mgm_lvl_val;
- mg_io_uint16 reserved5;
- mg_io_uint16 re_of_hw_rst;
- mg_io_uint8 reserved6[68];
- mg_io_uint16 security_stas;
- mg_io_uint8 vendor_uniq_bytes[62];
- mg_io_uint16 cfa_pwr_mode;
- mg_io_uint8 reserved7[186];
-
- mg_io_uint16 scts_per_secure_data_unit;
- mg_io_uint16 integrity_word;
-
-} mg_io_type_drv_info;
-
-typedef struct _mg_pll_t {
- unsigned int lock_cyc;
- unsigned short feedback_div; /* 9bit divider */
- unsigned char input_div; /* 5bit divider */
- unsigned char output_div; /* 2bit divider */
-} mg_pll_t;
-
-struct mg_drv_info {
- mg_io_type_drv_info drv_id;
- uint32_t tot_sects;
-};
-
-struct mflash_bank {
- uint32_t base;
-
- struct mflash_gpio_num rst_pin;
-
- struct mflash_gpio_drv *gpio_drv;
- struct target *target;
- struct mg_drv_info *drv_info;
-};
-
-int mflash_register_commands(struct command_context *cmd_ctx);
-
-#define MG_MFLASH_SECTOR_SIZE (0x200) /* 512Bytes = 2^9 */
-#define MG_MFLASH_SECTOR_SIZE_MASK (0x200-1)
-#define MG_MFLASH_SECTOR_SIZE_SHIFT (9)
-
-#define MG_BUFFER_OFFSET 0x8000
-#define MG_REG_OFFSET 0xC000
-#define MG_REG_FEATURE 0x2 /* write case */
-#define MG_REG_ERROR 0x2 /* read case */
-#define MG_REG_SECT_CNT 0x4
-#define MG_REG_SECT_NUM 0x6
-#define MG_REG_CYL_LOW 0x8
-#define MG_REG_CYL_HIGH 0xA
-#define MG_REG_DRV_HEAD 0xC
-#define MG_REG_COMMAND 0xE /* write case */
-#define MG_REG_STATUS 0xE /* read case */
-#define MG_REG_DRV_CTRL 0x10
-#define MG_REG_BURST_CTRL 0x12
-
-#define MG_OEM_DISK_WAIT_TIME_LONG 15000 /* msec */
-#define MG_OEM_DISK_WAIT_TIME_NORMAL 3000 /* msec */
-#define MG_OEM_DISK_WAIT_TIME_SHORT 1000 /* msec */
-
-#define MG_PLL_CLK_OUT 66000000.0 /* 66Mhz */
-#define MG_PLL_MAX_FEEDBACKDIV_VAL 512
-#define MG_PLL_MAX_INPUTDIV_VAL 32
-#define MG_PLL_MAX_OUTPUTDIV_VAL 4
-
-#define MG_PLL_STD_INPUTCLK 12000000.0 /* 12Mhz */
-#define MG_PLL_STD_LOCKCYCLE 10000
-
-#define MG_UNLOCK_OTP_AREA 0xFF
-
-#define MG_FILEIO_CHUNK 1048576
-
-#define ERROR_MG_IO (-1600)
-#define ERROR_MG_TIMEOUT (-1601)
-#define ERROR_MG_INVALID_PLL (-1603)
-#define ERROR_MG_INTERFACE (-1604)
-#define ERROR_MG_INVALID_OSC (-1605)
-#define ERROR_MG_UNSUPPORTED_SOC (-1606)
-
-typedef enum _mg_io_type_wait {
-
- mg_io_wait_bsy = 1,
- mg_io_wait_not_bsy = 2,
- mg_io_wait_rdy = 3,
- mg_io_wait_drq = 4, /* wait for data request */
- mg_io_wait_drq_noerr = 5, /* wait for DRQ but ignore the error status bit */
- mg_io_wait_rdy_noerr = 6 /* wait for ready, but ignore error status bit */
-
-} mg_io_type_wait;
-
-/*= "Status Register" bit masks. */
-typedef enum _mg_io_type_rbit_status {
-
- mg_io_rbit_status_error = 0x01, /* error bit in status register */
- mg_io_rbit_status_corrected_error = 0x04, /* corrected error in status register */
- mg_io_rbit_status_data_req = 0x08, /* data request bit in status register */
- mg_io_rbit_status_seek_done = 0x10, /* DSC - Drive Seek Complete */
- mg_io_rbit_status_write_fault = 0x20, /* DWF - Drive Write Fault */
- mg_io_rbit_status_ready = 0x40,
- mg_io_rbit_status_busy = 0x80
-
-} mg_io_type_rbit_status;
-
-/*= "Error Register" bit masks. */
-typedef enum _mg_io_type_rbit_error {
-
- mg_io_rbit_err_general = 0x01,
- mg_io_rbit_err_aborted = 0x04,
- mg_io_rbit_err_bad_sect_num = 0x10,
- mg_io_rbit_err_uncorrectable = 0x40,
- mg_io_rbit_err_bad_block = 0x80
-
-} mg_io_type_rbit_error;
-
-/* = "Device Control Register" bit. */
-typedef enum _mg_io_type_rbit_devc {
-
- mg_io_rbit_devc_intr = 0x02, /* interrupt enable bit (1:disable, 0:enable) */
- mg_io_rbit_devc_srst = 0x04 /* softwrae reset bit (1:assert, 0:de-assert) */
-
-} mg_io_type_rbit_devc;
-
-/* "Drive Select/Head Register" values. */
-typedef enum _mg_io_type_rval_dev {
-
- mg_io_rval_dev_must_be_on = 0x80, /* These 1 bits are always on */
- mg_io_rval_dev_drv_master = (0x00 | mg_io_rval_dev_must_be_on), /* Master */
- mg_io_rval_dev_drv_slave0 = (0x10 | mg_io_rval_dev_must_be_on), /* Slave0 */
- mg_io_rval_dev_drv_slave1 = (0x20 | mg_io_rval_dev_must_be_on), /* Slave1 */
- mg_io_rval_dev_drv_slave2 = (0x30 | mg_io_rval_dev_must_be_on), /* Slave2 */
- mg_io_rval_dev_lba_mode = (0x40 | mg_io_rval_dev_must_be_on)
-
-} mg_io_type_rval_dev;
-
-typedef enum _mg_io_type_cmd {
- mg_io_cmd_read = 0x20,
- mg_io_cmd_write = 0x30,
-
- mg_io_cmd_setmul = 0xC6,
- mg_io_cmd_readmul = 0xC4,
- mg_io_cmd_writemul = 0xC5,
-
- mg_io_cmd_idle = 0x97, /* 0xE3 */
- mg_io_cmd_idle_immediate = 0x95, /* 0xE1 */
-
- mg_io_cmd_setsleep = 0x99, /* 0xE6 */
- mg_io_cmd_stdby = 0x96, /* 0xE2 */
- mg_io_cmd_stdby_immediate = 0x94, /* 0xE0 */
-
- mg_io_cmd_identify = 0xEC,
- mg_io_cmd_set_feature = 0xEF,
-
- mg_io_cmd_confirm_write = 0x3C,
- mg_io_cmd_confirm_read = 0x40,
- mg_io_cmd_wakeup = 0xC3
-
-} mg_io_type_cmd;
-
-typedef enum _mg_feature_id {
- mg_feature_id_transmode = 0x3
-} mg_feature_id;
-
-typedef enum _mg_feature_val {
- mg_feature_val_trans_default = 0x0,
- mg_feature_val_trans_vcmd = 0x3,
- mg_feature_val_trand_vcmds = 0x2
-} mg_feature_val;
-
-typedef enum _mg_vcmd {
- mg_vcmd_update_xipinfo = 0xFA, /* FWPATCH commmand through IOM I/O */
- mg_vcmd_verify_fwpatch = 0xFB, /* FWPATCH commmand through IOM I/O */
- mg_vcmd_update_stgdrvinfo = 0xFC, /* IOM identificatin info program command */
- mg_vcmd_prep_fwpatch = 0xFD, /* FWPATCH commmand through IOM I/O */
- mg_vcmd_exe_fwpatch = 0xFE, /* FWPATCH commmand through IOM I/O */
- mg_vcmd_wr_pll = 0x8B,
- mg_vcmd_purge_nand = 0x8C, /* Only for Seagle */
- mg_vcmd_lock_otp = 0x8D,
- mg_vcmd_rd_otp = 0x8E,
- mg_vcmd_wr_otp = 0x8F
-} mg_vcmd;
-
-typedef enum _mg_opmode {
- mg_op_mode_xip = 1, /* TRUE XIP */
- mg_op_mode_snd = 2, /* BOOT + Storage */
- mg_op_mode_stg = 0 /* Only Storage */
-} mg_opmode;
-
-#endif /* OPENOCD_FLASH_MFLASH_H */
diff --git a/src/flash/nand/Makefile.am b/src/flash/nand/Makefile.am
deleted file mode 100644
index 2ddd096..0000000
--- a/src/flash/nand/Makefile.am
+++ /dev/null
@@ -1,46 +0,0 @@
-include $(top_srcdir)/common.mk
-
-noinst_LTLIBRARIES = libocdflashnand.la
-
-libocdflashnand_la_SOURCES = \
- ecc.c \
- ecc_kw.c \
- core.c \
- fileio.c \
- tcl.c \
- arm_io.c \
- $(NAND_DRIVERS) \
- driver.c
-
-NAND_DRIVERS = \
- nonce.c \
- davinci.c \
- lpc3180.c \
- lpc32xx.c \
- mxc.c \
- mx3.c \
- orion.c \
- s3c24xx.c \
- s3c2410.c \
- s3c2412.c \
- s3c2440.c \
- s3c2443.c \
- s3c6400.c \
- at91sam9.c \
- nuc910.c
-
-noinst_HEADERS = \
- arm_io.h \
- core.h \
- driver.h \
- fileio.h \
- imp.h \
- lpc3180.h \
- lpc32xx.h \
- mxc.h \
- mx3.h \
- s3c24xx.h \
- s3c24xx_regs.h \
- nuc910.h
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/flash/nand/arm_io.c b/src/flash/nand/arm_io.c
deleted file mode 100644
index e319f95..0000000
--- a/src/flash/nand/arm_io.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2009 by Marvell Semiconductors, Inc.
- * Written by Nicolas Pitre <nico at marvell.com>
- *
- * Copyright (C) 2009 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "core.h"
-#include "arm_io.h"
-#include <helper/binarybuffer.h>
-#include <target/arm.h>
-#include <target/armv7m.h>
-#include <target/algorithm.h>
-
-/**
- * Copies code to a working area. This will allocate room for the code plus the
- * additional amount requested if the working area pointer is null.
- *
- * @param target Pointer to the target to copy code to
- * @param code Pointer to the code area to be copied
- * @param code_size Size of the code being copied
- * @param additional Size of the additional area to be allocated in addition to
- * code
- * @param area Pointer to a pointer to a working area to copy code to
- * @return Success or failure of the operation
- */
-static int arm_code_to_working_area(struct target *target,
- const uint32_t *code, unsigned code_size,
- unsigned additional, struct working_area **area)
-{
- uint8_t code_buf[code_size];
- int retval;
- unsigned size = code_size + additional;
-
- /* REVISIT this assumes size doesn't ever change.
- * That's usually correct; but there are boards with
- * both large and small page chips, where it won't be...
- */
-
- /* make sure we have a working area */
- if (NULL == *area) {
- retval = target_alloc_working_area(target, size, area);
- if (retval != ERROR_OK) {
- LOG_DEBUG("%s: no %d byte buffer", __func__, (int) size);
- return ERROR_NAND_NO_BUFFER;
- }
- }
-
- /* buffer code in target endianness */
- target_buffer_set_u32_array(target, code_buf, code_size / 4, code);
-
- /* copy code to work area */
- retval = target_write_memory(target, (*area)->address,
- 4, code_size / 4, code_buf);
-
- return retval;
-}
-
-/**
- * ARM-specific bulk write from buffer to address of 8-bit wide NAND.
- * For now this supports ARMv4,ARMv5 and ARMv7-M cores.
- *
- * Enhancements to target_run_algorithm() could enable:
- * - ARMv6 and ARMv7 cores in ARM mode
- *
- * Different code fragments could handle:
- * - 16-bit wide data (needs different setup)
- *
- * @param nand Pointer to the arm_nand_data struct that defines the I/O
- * @param data Pointer to the data to be copied to flash
- * @param size Size of the data being copied
- * @return Success or failure of the operation
- */
-int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
-{
- struct target *target = nand->target;
- struct arm_algorithm armv4_5_algo;
- struct armv7m_algorithm armv7m_algo;
- void *arm_algo;
- struct arm *arm = target->arch_info;
- struct reg_param reg_params[3];
- uint32_t target_buf;
- uint32_t exit_var = 0;
- int retval;
-
- /* Inputs:
- * r0 NAND data address (byte wide)
- * r1 buffer address
- * r2 buffer length
- */
- static const uint32_t code_armv4_5[] = {
- 0xe4d13001, /* s: ldrb r3, [r1], #1 */
- 0xe5c03000, /* strb r3, [r0] */
- 0xe2522001, /* subs r2, r2, #1 */
- 0x1afffffb, /* bne s */
-
- /* exit: ARMv4 needs hardware breakpoint */
- 0xe1200070, /* e: bkpt #0 */
- };
-
- /* Inputs:
- * r0 NAND data address (byte wide)
- * r1 buffer address
- * r2 buffer length
- *
- * see contrib/loaders/flash/armv7m_io.s for src
- */
- static const uint32_t code_armv7m[] = {
- 0x3b01f811,
- 0x3a017003,
- 0xaffaf47f,
- 0xbf00be00,
- };
-
- int target_code_size = 0;
- const uint32_t *target_code_src = NULL;
-
- /* set up algorithm */
- if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
- arm_algo = &armv7m_algo;
- target_code_size = sizeof(code_armv7m);
- target_code_src = code_armv7m;
- } else {
- armv4_5_algo.common_magic = ARM_COMMON_MAGIC;
- armv4_5_algo.core_mode = ARM_MODE_SVC;
- armv4_5_algo.core_state = ARM_STATE_ARM;
- arm_algo = &armv4_5_algo;
- target_code_size = sizeof(code_armv4_5);
- target_code_src = code_armv4_5;
- }
-
- if (nand->op != ARM_NAND_WRITE || !nand->copy_area) {
- retval = arm_code_to_working_area(target, target_code_src, target_code_size,
- nand->chunk_size, &nand->copy_area);
- if (retval != ERROR_OK)
- return retval;
- }
-
- nand->op = ARM_NAND_WRITE;
-
- /* copy data to work area */
- target_buf = nand->copy_area->address + target_code_size;
- retval = target_write_buffer(target, target_buf, size, data);
- if (retval != ERROR_OK)
- return retval;
-
- /* set up parameters */
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN);
- init_reg_param(&reg_params[1], "r1", 32, PARAM_IN);
- init_reg_param(&reg_params[2], "r2", 32, PARAM_IN);
-
- buf_set_u32(reg_params[0].value, 0, 32, nand->data);
- buf_set_u32(reg_params[1].value, 0, 32, target_buf);
- buf_set_u32(reg_params[2].value, 0, 32, size);
-
- /* armv4 must exit using a hardware breakpoint */
- if (arm->is_armv4)
- exit_var = nand->copy_area->address + target_code_size - 4;
-
- /* use alg to write data from work area to NAND chip */
- retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- nand->copy_area->address, exit_var, 1000, arm_algo);
- if (retval != ERROR_OK)
- LOG_ERROR("error executing hosted NAND write");
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- return retval;
-}
-
-/**
- * Uses an on-chip algorithm for an ARM device to read from a NAND device and
- * store the data into the host machine's memory.
- *
- * @param nand Pointer to the arm_nand_data struct that defines the I/O
- * @param data Pointer to the data buffer to store the read data
- * @param size Amount of data to be stored to the buffer.
- * @return Success or failure of the operation
- */
-int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size)
-{
- struct target *target = nand->target;
- struct arm_algorithm armv4_5_algo;
- struct armv7m_algorithm armv7m_algo;
- void *arm_algo;
- struct arm *arm = target->arch_info;
- struct reg_param reg_params[3];
- uint32_t target_buf;
- uint32_t exit_var = 0;
- int retval;
-
- /* Inputs:
- * r0 buffer address
- * r1 NAND data address (byte wide)
- * r2 buffer length
- */
- static const uint32_t code_armv4_5[] = {
- 0xe5d13000, /* s: ldrb r3, [r1] */
- 0xe4c03001, /* strb r3, [r0], #1 */
- 0xe2522001, /* subs r2, r2, #1 */
- 0x1afffffb, /* bne s */
-
- /* exit: ARMv4 needs hardware breakpoint */
- 0xe1200070, /* e: bkpt #0 */
- };
-
- /* Inputs:
- * r0 buffer address
- * r1 NAND data address (byte wide)
- * r2 buffer length
- *
- * see contrib/loaders/flash/armv7m_io.s for src
- */
- static const uint32_t code_armv7m[] = {
- 0xf800780b,
- 0x3a013b01,
- 0xaffaf47f,
- 0xbf00be00,
- };
-
- int target_code_size = 0;
- const uint32_t *target_code_src = NULL;
-
- /* set up algorithm */
- if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
- arm_algo = &armv7m_algo;
- target_code_size = sizeof(code_armv7m);
- target_code_src = code_armv7m;
- } else {
- armv4_5_algo.common_magic = ARM_COMMON_MAGIC;
- armv4_5_algo.core_mode = ARM_MODE_SVC;
- armv4_5_algo.core_state = ARM_STATE_ARM;
- arm_algo = &armv4_5_algo;
- target_code_size = sizeof(code_armv4_5);
- target_code_src = code_armv4_5;
- }
-
- /* create the copy area if not yet available */
- if (nand->op != ARM_NAND_READ || !nand->copy_area) {
- retval = arm_code_to_working_area(target, target_code_src, target_code_size,
- nand->chunk_size, &nand->copy_area);
- if (retval != ERROR_OK)
- return retval;
- }
-
- nand->op = ARM_NAND_READ;
- target_buf = nand->copy_area->address + target_code_size;
-
- /* set up parameters */
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN);
- init_reg_param(&reg_params[1], "r1", 32, PARAM_IN);
- init_reg_param(&reg_params[2], "r2", 32, PARAM_IN);
-
- buf_set_u32(reg_params[0].value, 0, 32, target_buf);
- buf_set_u32(reg_params[1].value, 0, 32, nand->data);
- buf_set_u32(reg_params[2].value, 0, 32, size);
-
- /* armv4 must exit using a hardware breakpoint */
- if (arm->is_armv4)
- exit_var = nand->copy_area->address + target_code_size - 4;
-
- /* use alg to write data from NAND chip to work area */
- retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- nand->copy_area->address, exit_var, 1000, arm_algo);
- if (retval != ERROR_OK)
- LOG_ERROR("error executing hosted NAND read");
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- /* read from work area to the host's memory */
- retval = target_read_buffer(target, target_buf, size, data);
-
- return retval;
-}
diff --git a/src/flash/nand/arm_io.h b/src/flash/nand/arm_io.h
deleted file mode 100644
index 8bb3114..0000000
--- a/src/flash/nand/arm_io.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef OPENOCD_FLASH_NAND_ARM_IO_H
-#define OPENOCD_FLASH_NAND_ARM_IO_H
-
-/**
- * Available operational states the arm_nand_data struct can be in.
- */
-enum arm_nand_op {
- ARM_NAND_NONE, /**< No operation performed. */
- ARM_NAND_READ, /**< Read operation performed. */
- ARM_NAND_WRITE, /**< Write operation performed. */
-};
-
-/**
- * The arm_nand_data struct is used for defining NAND I/O operations on an ARM
- * core.
- */
-struct arm_nand_data {
- /** Target is proxy for some ARM core. */
- struct target *target;
-
- /** The copy area holds code loop and data for I/O operations. */
- struct working_area *copy_area;
-
- /** The chunk size is the page size or ECC chunk. */
- unsigned chunk_size;
-
- /** Where data is read from or written to. */
- uint32_t data;
-
- /** Last operation executed using this struct. */
- enum arm_nand_op op;
-
- /* currently implicit: data width == 8 bits (not 16) */
-};
-
-int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size);
-int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size);
-
-#endif /* OPENOCD_FLASH_NAND_ARM_IO_H */
diff --git a/src/flash/nand/at91sam9.c b/src/flash/nand/at91sam9.c
deleted file mode 100644
index 0af12b2..0000000
--- a/src/flash/nand/at91sam9.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * Copyright (C) 2009 by Dean Glazeski
- * dnglaze@gmail.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <target/arm.h>
-#include <helper/log.h>
-#include "imp.h"
-#include "arm_io.h"
-
-#define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */
-#define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */
-#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */
-#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */
-#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */
-#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */
-#define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */
-
-/**
- * Representation of a pin on an AT91SAM9 chip.
- */
-struct at91sam9_pin {
- /** Address of the PIO controller. */
- uint32_t pioc;
-
- /** Pin number. */
- uint32_t num;
-};
-
-/**
- * Private data for the controller that is stored in the NAND device structure.
- */
-struct at91sam9_nand {
- /** Address of the ECC controller for NAND. */
- uint32_t ecc;
-
- /** Address data is written to. */
- uint32_t data;
-
- /** Address commands are written to. */
- uint32_t cmd;
-
- /** Address addresses are written to. */
- uint32_t addr;
-
- /** I/O structure for hosted reads/writes. */
- struct arm_nand_data io;
-
- /** Pin representing the ready/~busy line. */
- struct at91sam9_pin busy;
-
- /** Pin representing the chip enable. */
- struct at91sam9_pin ce;
-};
-
-/**
- * Checks if the target is halted and prints an error message if it isn't.
- *
- * @param target Target to be checked.
- * @param label String label for where function is called from.
- * @return True if the target is halted.
- */
-static int at91sam9_halted(struct target *target, const char *label)
-{
- if (target->state == TARGET_HALTED)
- return true;
-
- LOG_ERROR("Target must be halted to use NAND controller (%s)", label);
- return false;
-}
-
-/**
- * Initialize the AT91SAM9 NAND controller.
- *
- * @param nand NAND device the controller is attached to.
- * @return Success or failure of initialization.
- */
-static int at91sam9_init(struct nand_device *nand)
-{
- struct target *target = nand->target;
-
- if (!at91sam9_halted(target, "init"))
- return ERROR_NAND_OPERATION_FAILED;
-
- return ERROR_OK;
-}
-
-/**
- * Enable NAND device attached to a controller.
- *
- * @param info NAND controller information for controlling NAND device.
- * @return Success or failure of the enabling.
- */
-static int at91sam9_enable(struct nand_device *nand)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- return target_write_u32(target, info->ce.pioc + AT91C_PIOx_CODR, 1 << info->ce.num);
-}
-
-/**
- * Disable NAND device attached to a controller.
- *
- * @param info NAND controller information for controlling NAND device.
- * @return Success or failure of the disabling.
- */
-static int at91sam9_disable(struct nand_device *nand)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- return target_write_u32(target, info->ce.pioc + AT91C_PIOx_SODR, 1 << info->ce.num);
-}
-
-/**
- * Send a command to the NAND device.
- *
- * @param nand NAND device to write the command to.
- * @param command Command to be written.
- * @return Success or failure of writing the command.
- */
-static int at91sam9_command(struct nand_device *nand, uint8_t command)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!at91sam9_halted(target, "command"))
- return ERROR_NAND_OPERATION_FAILED;
-
- at91sam9_enable(nand);
-
- return target_write_u8(target, info->cmd, command);
-}
-
-/**
- * Reset the AT91SAM9 NAND controller.
- *
- * @param nand NAND device to be reset.
- * @return Success or failure of reset.
- */
-static int at91sam9_reset(struct nand_device *nand)
-{
- if (!at91sam9_halted(nand->target, "reset"))
- return ERROR_NAND_OPERATION_FAILED;
-
- return at91sam9_disable(nand);
-}
-
-/**
- * Send an address to the NAND device attached to an AT91SAM9 NAND controller.
- *
- * @param nand NAND device to send the address to.
- * @param address Address to be sent.
- * @return Success or failure of sending the address.
- */
-static int at91sam9_address(struct nand_device *nand, uint8_t address)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!at91sam9_halted(nand->target, "address"))
- return ERROR_NAND_OPERATION_FAILED;
-
- return target_write_u8(target, info->addr, address);
-}
-
-/**
- * Read data directly from the NAND device attached to an AT91SAM9 NAND
- * controller.
- *
- * @param nand NAND device to read from.
- * @param data Pointer to where the data should be put.
- * @return Success or failure of reading the data.
- */
-static int at91sam9_read_data(struct nand_device *nand, void *data)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!at91sam9_halted(nand->target, "read data"))
- return ERROR_NAND_OPERATION_FAILED;
-
- return target_read_u8(target, info->data, data);
-}
-
-/**
- * Write data directly to the NAND device attached to an AT91SAM9 NAND
- * controller.
- *
- * @param nand NAND device to be written to.
- * @param data Data to be written.
- * @return Success or failure of the data write.
- */
-static int at91sam9_write_data(struct nand_device *nand, uint16_t data)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!at91sam9_halted(target, "write data"))
- return ERROR_NAND_OPERATION_FAILED;
-
- return target_write_u8(target, info->data, data);
-}
-
-/**
- * Determine if the NAND device is ready by looking at the ready/~busy pin.
- *
- * @param nand NAND device to check.
- * @param timeout Time in milliseconds to wait for NAND to be ready.
- * @return True if the NAND is ready in the timeout period.
- */
-static int at91sam9_nand_ready(struct nand_device *nand, int timeout)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t status;
-
- if (!at91sam9_halted(target, "nand ready"))
- return 0;
-
- do {
- target_read_u32(target, info->busy.pioc + AT91C_PIOx_PDSR, &status);
-
- if (status & (1 << info->busy.num))
- return 1;
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-/**
- * Read a block of data from the NAND device attached to an AT91SAM9. This
- * utilizes the ARM hosted NAND read function.
- *
- * @param nand NAND device to read from.
- * @param data Pointer to where the read data should be placed.
- * @param size Size of the data being read.
- * @return Success or failure of the hosted read.
- */
-static int at91sam9_read_block_data(struct nand_device *nand, uint8_t *data, int size)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct arm_nand_data *io = &info->io;
- int status;
-
- if (!at91sam9_halted(nand->target, "read block"))
- return ERROR_NAND_OPERATION_FAILED;
-
- io->chunk_size = nand->page_size;
- status = arm_nandread(io, data, size);
-
- return status;
-}
-
-/**
- * Write a block of data to a NAND device attached to an AT91SAM9. This uses
- * the ARM hosted write function to write the data.
- *
- * @param nand NAND device to write to.
- * @param data Data to be written to device.
- * @param size Size of the data being written.
- * @return Success or failure of the hosted write.
- */
-static int at91sam9_write_block_data(struct nand_device *nand, uint8_t *data, int size)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct arm_nand_data *io = &info->io;
- int status;
-
- if (!at91sam9_halted(nand->target, "write block"))
- return ERROR_NAND_OPERATION_FAILED;
-
- io->chunk_size = nand->page_size;
- status = arm_nandwrite(io, data, size);
-
- return status;
-}
-
-/**
- * Initialize the ECC controller on the AT91SAM9.
- *
- * @param target Target to configure ECC on.
- * @param info NAND controller information for where the ECC is.
- * @return Success or failure of initialization.
- */
-static int at91sam9_ecc_init(struct target *target, struct at91sam9_nand *info)
-{
- if (!info->ecc) {
- LOG_ERROR("ECC controller address must be set when not reading raw NAND data");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* reset ECC parity registers */
- return target_write_u32(target, info->ecc + AT91C_ECCx_CR, 1);
-}
-
-/**
- * Initialize an area for the OOB based on whether a user is requesting the OOB
- * data. This determines the size of the OOB and allocates the space in case
- * the user has not requested the OOB data.
- *
- * @param nand NAND device we are creating an OOB for.
- * @param oob Pointer to the user supplied OOB area.
- * @param size Size of the OOB.
- * @return Pointer to an area to store OOB data.
- */
-static uint8_t *at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size)
-{
- if (!oob) {
- /* user doesn't want OOB, allocate it */
- if (nand->page_size == 512)
- *size = 16;
- else if (nand->page_size == 2048)
- *size = 64;
-
- oob = malloc(*size);
- if (!oob) {
- LOG_ERROR("Unable to allocate space for OOB");
- return NULL;
- }
-
- memset(oob, 0xFF, *size);
- }
-
- return oob;
-}
-
-/**
- * Reads a page from an AT91SAM9 NAND controller and verifies using 1-bit ECC
- * controller on chip. This makes an attempt to correct any errors that are
- * encountered while reading the page of data.
- *
- * @param nand NAND device to read from
- * @param page Page to be read.
- * @param data Pointer to where data should be read to.
- * @param data_size Size of the data to be read.
- * @param oob Pointer to where OOB data should be read to.
- * @param oob_size Size of the OOB data to be read.
- * @return Success or failure of reading the NAND page.
- */
-static int at91sam9_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- int retval;
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- uint8_t *oob_data;
- uint32_t status;
-
- retval = at91sam9_ecc_init(target, info);
- if (ERROR_OK != retval)
- return retval;
-
- retval = nand_page_command(nand, page, NAND_CMD_READ0, !data);
- if (ERROR_OK != retval)
- return retval;
-
- if (data) {
- retval = nand_read_data_page(nand, data, data_size);
- if (ERROR_OK != retval)
- return retval;
- }
-
- oob_data = at91sam9_oob_init(nand, oob, &oob_size);
- retval = nand_read_data_page(nand, oob_data, oob_size);
- if (ERROR_OK == retval && data) {
- target_read_u32(target, info->ecc + AT91C_ECCx_SR, &status);
- if (status & 1) {
- LOG_ERROR("Error detected!");
- if (status & 4)
- LOG_ERROR("Multiple errors encountered; unrecoverable!");
- else {
- /* attempt recovery */
- uint32_t parity;
-
- target_read_u32(target,
- info->ecc + AT91C_ECCx_PR,
- &parity);
- uint32_t word = (parity & 0x0000FFF0) >> 4;
- uint32_t bit = parity & 0x0F;
-
- data[word] ^= (0x1) << bit;
- LOG_INFO("Data word %d, bit %d corrected.",
- (unsigned) word,
- (unsigned) bit);
- }
- }
-
- if (status & 2) {
- /* we could write back correct ECC data */
- LOG_ERROR("Error in ECC bytes detected");
- }
- }
-
- if (!oob) {
- /* if it wasn't asked for, free it */
- free(oob_data);
- }
-
- return retval;
-}
-
-/**
- * Write a page of data including 1-bit ECC information to a NAND device
- * attached to an AT91SAM9 controller. If there is OOB data to be written,
- * this will ignore the computed ECC from the ECC controller.
- *
- * @param nand NAND device to write to.
- * @param page Page to write.
- * @param data Pointer to data being written.
- * @param data_size Size of the data being written.
- * @param oob Pointer to OOB data being written.
- * @param oob_size Size of the OOB data.
- * @return Success or failure of the page write.
- */
-static int at91sam9_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- struct at91sam9_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
- uint8_t *oob_data = oob;
- uint32_t parity, nparity;
-
- retval = at91sam9_ecc_init(target, info);
- if (ERROR_OK != retval)
- return retval;
-
- retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
- if (ERROR_OK != retval)
- return retval;
-
- if (data) {
- retval = nand_write_data_page(nand, data, data_size);
- if (ERROR_OK != retval) {
- LOG_ERROR("Unable to write data to NAND device");
- return retval;
- }
- }
-
- oob_data = at91sam9_oob_init(nand, oob, &oob_size);
-
- if (!oob) {
- /* no OOB given, so read in the ECC parity from the ECC controller */
- target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity);
- target_read_u32(target, info->ecc + AT91C_ECCx_NPR, &nparity);
-
- oob_data[0] = (uint8_t) parity;
- oob_data[1] = (uint8_t) (parity >> 8);
- oob_data[2] = (uint8_t) nparity;
- oob_data[3] = (uint8_t) (nparity >> 8);
- }
-
- retval = nand_write_data_page(nand, oob_data, oob_size);
-
- if (!oob)
- free(oob_data);
-
- if (ERROR_OK != retval) {
- LOG_ERROR("Unable to write OOB data to NAND");
- return retval;
- }
-
- retval = nand_write_finish(nand);
-
- return retval;
-}
-
-/**
- * Handle the initial NAND device command for AT91SAM9 controllers. This
- * initializes much of the controller information struct to be ready for future
- * reads and writes.
- */
-NAND_DEVICE_COMMAND_HANDLER(at91sam9_nand_device_command)
-{
- unsigned long chip = 0, ecc = 0;
- struct at91sam9_nand *info = NULL;
-
- LOG_DEBUG("AT91SAM9 NAND Device Command");
-
- if (CMD_ARGC < 3 || CMD_ARGC > 4) {
- LOG_ERROR("parameters: %s target chip_addr", CMD_ARGV[0]);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
- if (chip == 0) {
- LOG_ERROR("invalid NAND chip address: %s", CMD_ARGV[2]);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (CMD_ARGC == 4) {
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[3], ecc);
- if (ecc == 0) {
- LOG_ERROR("invalid ECC controller address: %s", CMD_ARGV[3]);
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- info = calloc(1, sizeof(*info));
- if (!info) {
- LOG_ERROR("unable to allocate space for controller private data");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- info->data = chip;
- info->cmd = chip | (1 << 22);
- info->addr = chip | (1 << 21);
- info->ecc = ecc;
-
- nand->controller_priv = info;
- info->io.target = nand->target;
- info->io.data = info->data;
- info->io.op = ARM_NAND_NONE;
-
- return ERROR_OK;
-}
-
-/**
- * Handle the AT91SAM9 CLE command for specifying the address line to use for
- * writing commands to a NAND device.
- */
-COMMAND_HANDLER(handle_at91sam9_cle_command)
-{
- struct nand_device *nand = NULL;
- struct at91sam9_nand *info = NULL;
- unsigned num, address_line;
-
- if (CMD_ARGC != 2) {
- command_print(CMD_CTX, "incorrect number of arguments for 'at91sam9 cle' command");
- return ERROR_OK;
- }
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
- nand = get_nand_device_by_num(num);
- if (!nand) {
- command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- info = nand->controller_priv;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], address_line);
- info->cmd = info->data | (1 << address_line);
-
- return ERROR_OK;
-}
-
-/**
- * Handle the AT91SAM9 ALE command for specifying the address line to use for
- * writing addresses to the NAND device.
- */
-COMMAND_HANDLER(handle_at91sam9_ale_command)
-{
- struct nand_device *nand = NULL;
- struct at91sam9_nand *info = NULL;
- unsigned num, address_line;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
- nand = get_nand_device_by_num(num);
- if (!nand) {
- command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- info = nand->controller_priv;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], address_line);
- info->addr = info->data | (1 << address_line);
-
- return ERROR_OK;
-}
-
-/**
- * Handle the AT91SAM9 RDY/~BUSY command for specifying the pin that watches the
- * RDY/~BUSY line from the NAND device.
- */
-COMMAND_HANDLER(handle_at91sam9_rdy_busy_command)
-{
- struct nand_device *nand = NULL;
- struct at91sam9_nand *info = NULL;
- unsigned num, base_pioc, pin_num;
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
- nand = get_nand_device_by_num(num);
- if (!nand) {
- command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- info = nand->controller_priv;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], base_pioc);
- info->busy.pioc = base_pioc;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], pin_num);
- info->busy.num = pin_num;
-
- return ERROR_OK;
-}
-
-/**
- * Handle the AT91SAM9 CE command for specifying the pin that is used to enable
- * or disable the NAND device.
- */
-COMMAND_HANDLER(handle_at91sam9_ce_command)
-{
- struct nand_device *nand = NULL;
- struct at91sam9_nand *info = NULL;
- unsigned num, base_pioc, pin_num;
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
- nand = get_nand_device_by_num(num);
- if (!nand) {
- command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- info = nand->controller_priv;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], base_pioc);
- info->ce.pioc = base_pioc;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], pin_num);
- info->ce.num = pin_num;
-
- return ERROR_OK;
-}
-
-static const struct command_registration at91sam9_sub_command_handlers[] = {
- {
- .name = "cle",
- .handler = handle_at91sam9_cle_command,
- .mode = COMMAND_CONFIG,
- .help = "set command latch enable address line (default is 22)",
- .usage = "bank_id address_line",
- },
- {
- .name = "ale",
- .handler = handle_at91sam9_ale_command,
- .mode = COMMAND_CONFIG,
- .help = "set address latch enable address line (default is 21)",
- .usage = "bank_id address_line",
- },
- {
- .name = "rdy_busy",
- .handler = handle_at91sam9_rdy_busy_command,
- .mode = COMMAND_CONFIG,
- .help = "set the GPIO input pin connected to "
- "the RDY/~BUSY signal (no default)",
- .usage = "bank_id pio_base_addr pin_num",
- },
- {
- .name = "ce",
- .handler = handle_at91sam9_ce_command,
- .mode = COMMAND_CONFIG,
- .help = "set the GPIO output pin connected to "
- "the chip enable signal (no default)",
- .usage = "bank_id pio_base_addr pin_num",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration at91sam9_command_handler[] = {
- {
- .name = "at91sam9",
- .mode = COMMAND_ANY,
- .help = "AT91SAM9 NAND flash controller commands",
- .usage = "",
- .chain = at91sam9_sub_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/**
- * Structure representing the AT91SAM9 NAND controller.
- */
-struct nand_flash_controller at91sam9_nand_controller = {
- .name = "at91sam9",
- .nand_device_command = at91sam9_nand_device_command,
- .commands = at91sam9_command_handler,
- .init = at91sam9_init,
- .command = at91sam9_command,
- .reset = at91sam9_reset,
- .address = at91sam9_address,
- .read_data = at91sam9_read_data,
- .write_data = at91sam9_write_data,
- .nand_ready = at91sam9_nand_ready,
- .read_block_data = at91sam9_read_block_data,
- .write_block_data = at91sam9_write_block_data,
- .read_page = at91sam9_read_page,
- .write_page = at91sam9_write_page,
-};
diff --git a/src/flash/nand/core.c b/src/flash/nand/core.c
deleted file mode 100644
index 7428d22..0000000
--- a/src/flash/nand/core.c
+++ /dev/null
@@ -1,876 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * Partially based on drivers/mtd/nand_ids.c from Linux. *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-
-/* configured NAND devices and NAND Flash command handler */
-struct nand_device *nand_devices;
-
-void nand_device_add(struct nand_device *c)
-{
- if (nand_devices) {
- struct nand_device *p = nand_devices;
- while (p && p->next)
- p = p->next;
- p->next = c;
- } else
- nand_devices = c;
-}
-
-
-/* Chip ID list
- *
- * Manufacturer, ID code, pagesize, chipsize in MegaByte, eraseblock size,
- * options, name
- *
- * Pagesize; 0, 256, 512
- * 0 get this information from the extended chip ID
- * 256 256 Byte page size
- * 512 512 Byte page size
- */
-static struct nand_info nand_flash_ids[] = {
- /* Vendor Specific Entries */
- { NAND_MFR_SAMSUNG, 0xD5, 8192, 2048, 0x100000, LP_OPTIONS,
- "K9GAG08 2GB NAND 3.3V x8 MLC 2b/cell"},
- { NAND_MFR_SAMSUNG, 0xD7, 8192, 4096, 0x100000, LP_OPTIONS,
- "K9LBG08 4GB NAND 3.3V x8 MLC 2b/cell"},
-
- /* start "museum" IDs */
- { 0x0, 0x6e, 256, 1, 0x1000, 0, "NAND 1MiB 5V 8-bit"},
- { 0x0, 0x64, 256, 2, 0x1000, 0, "NAND 2MiB 5V 8-bit"},
- { 0x0, 0x6b, 512, 4, 0x2000, 0, "NAND 4MiB 5V 8-bit"},
- { 0x0, 0xe8, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
- { 0x0, 0xec, 256, 1, 0x1000, 0, "NAND 1MiB 3.3V 8-bit"},
- { 0x0, 0xea, 256, 2, 0x1000, 0, "NAND 2MiB 3.3V 8-bit"},
- { 0x0, 0xd5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
- { 0x0, 0xe3, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
- { 0x0, 0xe5, 512, 4, 0x2000, 0, "NAND 4MiB 3.3V 8-bit"},
- { 0x0, 0xd6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
-
- { 0x0, 0x39, 512, 8, 0x2000, 0, "NAND 8MiB 1.8V 8-bit"},
- { 0x0, 0xe6, 512, 8, 0x2000, 0, "NAND 8MiB 3.3V 8-bit"},
- { 0x0, 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 1.8V 16-bit"},
- { 0x0, 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16, "NAND 8MiB 3.3V 16-bit"},
- /* end "museum" IDs */
-
- { 0x0, 0x33, 512, 16, 0x4000, 0, "NAND 16MiB 1.8V 8-bit"},
- { 0x0, 0x73, 512, 16, 0x4000, 0, "NAND 16MiB 3.3V 8-bit"},
- { 0x0, 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 1.8V 16-bit"},
- { 0x0, 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16, "NAND 16MiB 3.3V 16-bit"},
-
- { 0x0, 0x35, 512, 32, 0x4000, 0, "NAND 32MiB 1.8V 8-bit"},
- { 0x0, 0x75, 512, 32, 0x4000, 0, "NAND 32MiB 3.3V 8-bit"},
- { 0x0, 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 1.8V 16-bit"},
- { 0x0, 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16, "NAND 32MiB 3.3V 16-bit"},
-
- { 0x0, 0x36, 512, 64, 0x4000, 0, "NAND 64MiB 1.8V 8-bit"},
- { 0x0, 0x76, 512, 64, 0x4000, 0, "NAND 64MiB 3.3V 8-bit"},
- { 0x0, 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 1.8V 16-bit"},
- { 0x0, 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16, "NAND 64MiB 3.3V 16-bit"},
-
- { 0x0, 0x78, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
- { 0x0, 0x39, 512, 128, 0x4000, 0, "NAND 128MiB 1.8V 8-bit"},
- { 0x0, 0x79, 512, 128, 0x4000, 0, "NAND 128MiB 3.3V 8-bit"},
- { 0x0, 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
- { 0x0, 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 1.8V 16-bit"},
- { 0x0, 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
- { 0x0, 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16, "NAND 128MiB 3.3V 16-bit"},
-
- { 0x0, 0x71, 512, 256, 0x4000, 0, "NAND 256MiB 3.3V 8-bit"},
-
- { 0x0, 0xA2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 1.8V 8-bit"},
- { 0x0, 0xF2, 0, 64, 0, LP_OPTIONS, "NAND 64MiB 3.3V 8-bit"},
- { 0x0, 0xB2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 1.8V 16-bit"},
- { 0x0, 0xC2, 0, 64, 0, LP_OPTIONS16, "NAND 64MiB 3.3V 16-bit"},
-
- { 0x0, 0xA1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 1.8V 8-bit"},
- { 0x0, 0xF1, 0, 128, 0, LP_OPTIONS, "NAND 128MiB 3.3V 8-bit"},
- { 0x0, 0xB1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 1.8V 16-bit"},
- { 0x0, 0xC1, 0, 128, 0, LP_OPTIONS16, "NAND 128MiB 3.3V 16-bit"},
-
- { 0x0, 0xAA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 1.8V 8-bit"},
- { 0x0, 0xDA, 0, 256, 0, LP_OPTIONS, "NAND 256MiB 3.3V 8-bit"},
- { 0x0, 0xBA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 1.8V 16-bit"},
- { 0x0, 0xCA, 0, 256, 0, LP_OPTIONS16, "NAND 256MiB 3.3V 16-bit"},
-
- { 0x0, 0xAC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 1.8V 8-bit"},
- { 0x0, 0xDC, 0, 512, 0, LP_OPTIONS, "NAND 512MiB 3.3V 8-bit"},
- { 0x0, 0xBC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 1.8V 16-bit"},
- { 0x0, 0xCC, 0, 512, 0, LP_OPTIONS16, "NAND 512MiB 3.3V 16-bit"},
-
- { 0x0, 0xA3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 1.8V 8-bit"},
- { 0x0, 0xD3, 0, 1024, 0, LP_OPTIONS, "NAND 1GiB 3.3V 8-bit"},
- { 0x0, 0xB3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 1.8V 16-bit"},
- { 0x0, 0xC3, 0, 1024, 0, LP_OPTIONS16, "NAND 1GiB 3.3V 16-bit"},
-
- { 0x0, 0xA5, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 1.8V 8-bit"},
- { 0x0, 0xD5, 0, 8192, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
- { 0x0, 0xB5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 1.8V 16-bit"},
- { 0x0, 0xC5, 0, 2048, 0, LP_OPTIONS16, "NAND 2GiB 3.3V 16-bit"},
-
- { 0x0, 0x48, 0, 2048, 0, LP_OPTIONS, "NAND 2GiB 3.3V 8-bit"},
-
- {0, 0, 0, 0, 0, 0, NULL}
-};
-
-/* Manufacturer ID list
- */
-static struct nand_manufacturer nand_manuf_ids[] = {
- {0x0, "unknown"},
- {NAND_MFR_TOSHIBA, "Toshiba"},
- {NAND_MFR_SAMSUNG, "Samsung"},
- {NAND_MFR_FUJITSU, "Fujitsu"},
- {NAND_MFR_NATIONAL, "National"},
- {NAND_MFR_RENESAS, "Renesas"},
- {NAND_MFR_STMICRO, "ST Micro"},
- {NAND_MFR_HYNIX, "Hynix"},
- {NAND_MFR_MICRON, "Micron"},
- {0x0, NULL},
-};
-
-/*
- * Define default oob placement schemes for large and small page devices
- */
-
-#if 0
-static struct nand_ecclayout nand_oob_8 = {
- .eccbytes = 3,
- .eccpos = {0, 1, 2},
- .oobfree = {
- {.offset = 3,
- .length = 2},
- {.offset = 6,
- .length = 2}
- }
-};
-#endif
-
-/**
- * Returns the flash bank specified by @a name, which matches the
- * driver name and a suffix (option) specify the driver-specific
- * bank number. The suffix consists of the '.' and the driver-specific
- * bank number: when two davinci banks are defined, then 'davinci.1' refers
- * to the second (e.g. DM355EVM).
- */
-static struct nand_device *get_nand_device_by_name(const char *name)
-{
- unsigned requested = get_flash_name_index(name);
- unsigned found = 0;
-
- struct nand_device *nand;
- for (nand = nand_devices; NULL != nand; nand = nand->next) {
- if (strcmp(nand->name, name) == 0)
- return nand;
- if (!flash_driver_name_matches(nand->controller->name, name))
- continue;
- if (++found < requested)
- continue;
- return nand;
- }
- return NULL;
-}
-
-struct nand_device *get_nand_device_by_num(int num)
-{
- struct nand_device *p;
- int i = 0;
-
- for (p = nand_devices; p; p = p->next) {
- if (i++ == num)
- return p;
- }
-
- return NULL;
-}
-
-COMMAND_HELPER(nand_command_get_device, unsigned name_index,
- struct nand_device **nand)
-{
- const char *str = CMD_ARGV[name_index];
- *nand = get_nand_device_by_name(str);
- if (*nand)
- return ERROR_OK;
-
- unsigned num;
- COMMAND_PARSE_NUMBER(uint, str, num);
- *nand = get_nand_device_by_num(num);
- if (!*nand) {
- command_print(CMD_CTX, "NAND flash device '%s' not found", str);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return ERROR_OK;
-}
-
-int nand_build_bbt(struct nand_device *nand, int first, int last)
-{
- uint32_t page;
- int i;
- int pages_per_block = (nand->erase_size / nand->page_size);
- uint8_t oob[6];
- int ret;
-
- if ((first < 0) || (first >= nand->num_blocks))
- first = 0;
-
- if ((last >= nand->num_blocks) || (last == -1))
- last = nand->num_blocks - 1;
-
- page = first * pages_per_block;
- for (i = first; i <= last; i++) {
- ret = nand_read_page(nand, page, NULL, 0, oob, 6);
- if (ret != ERROR_OK)
- return ret;
-
- if (((nand->device->options & NAND_BUSWIDTH_16) && ((oob[0] & oob[1]) != 0xff))
- || (((nand->page_size == 512) && (oob[5] != 0xff)) ||
- ((nand->page_size == 2048) && (oob[0] != 0xff)))) {
- LOG_WARNING("bad block: %i", i);
- nand->blocks[i].is_bad = 1;
- } else
- nand->blocks[i].is_bad = 0;
-
- page += pages_per_block;
- }
-
- return ERROR_OK;
-}
-
-int nand_read_status(struct nand_device *nand, uint8_t *status)
-{
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
-
- /* Send read status command */
- nand->controller->command(nand, NAND_CMD_STATUS);
-
- alive_sleep(1);
-
- /* read status */
- if (nand->device->options & NAND_BUSWIDTH_16) {
- uint16_t data;
- nand->controller->read_data(nand, &data);
- *status = data & 0xff;
- } else
- nand->controller->read_data(nand, status);
-
- return ERROR_OK;
-}
-
-static int nand_poll_ready(struct nand_device *nand, int timeout)
-{
- uint8_t status;
-
- nand->controller->command(nand, NAND_CMD_STATUS);
- do {
- if (nand->device->options & NAND_BUSWIDTH_16) {
- uint16_t data;
- nand->controller->read_data(nand, &data);
- status = data & 0xff;
- } else
- nand->controller->read_data(nand, &status);
- if (status & NAND_STATUS_READY)
- break;
- alive_sleep(1);
- } while (timeout--);
-
- return (status & NAND_STATUS_READY) != 0;
-}
-
-int nand_probe(struct nand_device *nand)
-{
- uint8_t manufacturer_id, device_id;
- uint8_t id_buff[6];
- int retval;
- int i;
-
- /* clear device data */
- nand->device = NULL;
- nand->manufacturer = NULL;
-
- /* clear device parameters */
- nand->bus_width = 0;
- nand->address_cycles = 0;
- nand->page_size = 0;
- nand->erase_size = 0;
-
- /* initialize controller (device parameters are zero, use controller default) */
- retval = nand->controller->init(nand);
- if (retval != ERROR_OK) {
- switch (retval) {
- case ERROR_NAND_OPERATION_FAILED:
- LOG_DEBUG("controller initialization failed");
- return ERROR_NAND_OPERATION_FAILED;
- case ERROR_NAND_OPERATION_NOT_SUPPORTED:
- LOG_ERROR(
- "BUG: controller reported that it doesn't support default parameters");
- return ERROR_NAND_OPERATION_FAILED;
- default:
- LOG_ERROR("BUG: unknown controller initialization failure");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- nand->controller->command(nand, NAND_CMD_RESET);
- nand->controller->reset(nand);
-
- nand->controller->command(nand, NAND_CMD_READID);
- nand->controller->address(nand, 0x0);
-
- if (nand->bus_width == 8) {
- nand->controller->read_data(nand, &manufacturer_id);
- nand->controller->read_data(nand, &device_id);
- } else {
- uint16_t data_buf;
- nand->controller->read_data(nand, &data_buf);
- manufacturer_id = data_buf & 0xff;
- nand->controller->read_data(nand, &data_buf);
- device_id = data_buf & 0xff;
- }
-
- for (i = 0; nand_flash_ids[i].name; i++) {
- if (nand_flash_ids[i].id == device_id &&
- (nand_flash_ids[i].mfr_id == manufacturer_id ||
- nand_flash_ids[i].mfr_id == 0)) {
- nand->device = &nand_flash_ids[i];
- break;
- }
- }
-
- for (i = 0; nand_manuf_ids[i].name; i++) {
- if (nand_manuf_ids[i].id == manufacturer_id) {
- nand->manufacturer = &nand_manuf_ids[i];
- break;
- }
- }
-
- if (!nand->manufacturer) {
- nand->manufacturer = &nand_manuf_ids[0];
- nand->manufacturer->id = manufacturer_id;
- }
-
- if (!nand->device) {
- LOG_ERROR(
- "unknown NAND flash device found, manufacturer id: 0x%2.2x device id: 0x%2.2x",
- manufacturer_id,
- device_id);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_DEBUG("found %s (%s)", nand->device->name, nand->manufacturer->name);
-
- /* initialize device parameters */
-
- /* bus width */
- if (nand->device->options & NAND_BUSWIDTH_16)
- nand->bus_width = 16;
- else
- nand->bus_width = 8;
-
- /* Do we need extended device probe information? */
- if (nand->device->page_size == 0 ||
- nand->device->erase_size == 0) {
- if (nand->bus_width == 8) {
- nand->controller->read_data(nand, id_buff + 3);
- nand->controller->read_data(nand, id_buff + 4);
- nand->controller->read_data(nand, id_buff + 5);
- } else {
- uint16_t data_buf;
-
- nand->controller->read_data(nand, &data_buf);
- id_buff[3] = data_buf;
-
- nand->controller->read_data(nand, &data_buf);
- id_buff[4] = data_buf;
-
- nand->controller->read_data(nand, &data_buf);
- id_buff[5] = data_buf >> 8;
- }
- }
-
- /* page size */
- if (nand->device->page_size == 0)
- nand->page_size = 1 << (10 + (id_buff[4] & 3));
- else if (nand->device->page_size == 256) {
- LOG_ERROR("NAND flashes with 256 byte pagesize are not supported");
- return ERROR_NAND_OPERATION_FAILED;
- } else
- nand->page_size = nand->device->page_size;
-
- /* number of address cycles */
- if (nand->page_size <= 512) {
- /* small page devices */
- if (nand->device->chip_size <= 32)
- nand->address_cycles = 3;
- else if (nand->device->chip_size <= 8*1024)
- nand->address_cycles = 4;
- else {
- LOG_ERROR("BUG: small page NAND device with more than 8 GiB encountered");
- nand->address_cycles = 5;
- }
- } else {
- /* large page devices */
- if (nand->device->chip_size <= 128)
- nand->address_cycles = 4;
- else if (nand->device->chip_size <= 32*1024)
- nand->address_cycles = 5;
- else {
- LOG_ERROR("BUG: large page NAND device with more than 32 GiB encountered");
- nand->address_cycles = 6;
- }
- }
-
- /* erase size */
- if (nand->device->erase_size == 0) {
- switch ((id_buff[4] >> 4) & 3) {
- case 0:
- nand->erase_size = 64 << 10;
- break;
- case 1:
- nand->erase_size = 128 << 10;
- break;
- case 2:
- nand->erase_size = 256 << 10;
- break;
- case 3:
- nand->erase_size = 512 << 10;
- break;
- }
- } else
- nand->erase_size = nand->device->erase_size;
-
- /* initialize controller, but leave parameters at the controllers default */
- retval = nand->controller->init(nand);
- if (retval != ERROR_OK) {
- switch (retval) {
- case ERROR_NAND_OPERATION_FAILED:
- LOG_DEBUG("controller initialization failed");
- return ERROR_NAND_OPERATION_FAILED;
- case ERROR_NAND_OPERATION_NOT_SUPPORTED:
- LOG_ERROR(
- "controller doesn't support requested parameters (buswidth: %i, address cycles: %i, page size: %i)",
- nand->bus_width,
- nand->address_cycles,
- nand->page_size);
- return ERROR_NAND_OPERATION_FAILED;
- default:
- LOG_ERROR("BUG: unknown controller initialization failure");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- nand->num_blocks = (nand->device->chip_size * 1024) / (nand->erase_size / 1024);
- nand->blocks = malloc(sizeof(struct nand_block) * nand->num_blocks);
-
- for (i = 0; i < nand->num_blocks; i++) {
- nand->blocks[i].size = nand->erase_size;
- nand->blocks[i].offset = i * nand->erase_size;
- nand->blocks[i].is_erased = -1;
- nand->blocks[i].is_bad = -1;
- }
-
- return ERROR_OK;
-}
-
-int nand_erase(struct nand_device *nand, int first_block, int last_block)
-{
- int i;
- uint32_t page;
- uint8_t status;
- int retval;
-
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
-
- if ((first_block < 0) || (last_block >= nand->num_blocks))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* make sure we know if a block is bad before erasing it */
- for (i = first_block; i <= last_block; i++) {
- if (nand->blocks[i].is_bad == -1) {
- nand_build_bbt(nand, i, last_block);
- break;
- }
- }
-
- for (i = first_block; i <= last_block; i++) {
- /* Send erase setup command */
- nand->controller->command(nand, NAND_CMD_ERASE1);
-
- page = i * (nand->erase_size / nand->page_size);
-
- /* Send page address */
- if (nand->page_size <= 512) {
- /* row */
- nand->controller->address(nand, page & 0xff);
- nand->controller->address(nand, (page >> 8) & 0xff);
-
- /* 3rd cycle only on devices with more than 32 MiB */
- if (nand->address_cycles >= 4)
- nand->controller->address(nand, (page >> 16) & 0xff);
-
- /* 4th cycle only on devices with more than 8 GiB */
- if (nand->address_cycles >= 5)
- nand->controller->address(nand, (page >> 24) & 0xff);
- } else {
- /* row */
- nand->controller->address(nand, page & 0xff);
- nand->controller->address(nand, (page >> 8) & 0xff);
-
- /* 3rd cycle only on devices with more than 128 MiB */
- if (nand->address_cycles >= 5)
- nand->controller->address(nand, (page >> 16) & 0xff);
- }
-
- /* Send erase confirm command */
- nand->controller->command(nand, NAND_CMD_ERASE2);
-
- retval = nand->controller->nand_ready ?
- nand->controller->nand_ready(nand, 1000) :
- nand_poll_ready(nand, 1000);
- if (!retval) {
- LOG_ERROR("timeout waiting for NAND flash block erase to complete");
- return ERROR_NAND_OPERATION_TIMEOUT;
- }
-
- retval = nand_read_status(nand, &status);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read status");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & 0x1) {
- LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x",
- (nand->blocks[i].is_bad == 1)
- ? "bad " : "",
- i, status);
- /* continue; other blocks might still be erasable */
- }
-
- nand->blocks[i].is_erased = 1;
- }
-
- return ERROR_OK;
-}
-
-#if 0
-static int nand_read_plain(struct nand_device *nand,
- uint32_t address,
- uint8_t *data,
- uint32_t data_size)
-{
- uint8_t *page;
-
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
-
- if (address % nand->page_size) {
- LOG_ERROR("reads need to be page aligned");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- page = malloc(nand->page_size);
-
- while (data_size > 0) {
- uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
- uint32_t page_address;
-
-
- page_address = address / nand->page_size;
-
- nand_read_page(nand, page_address, page, nand->page_size, NULL, 0);
-
- memcpy(data, page, thisrun_size);
-
- address += thisrun_size;
- data += thisrun_size;
- data_size -= thisrun_size;
- }
-
- free(page);
-
- return ERROR_OK;
-}
-
-static int nand_write_plain(struct nand_device *nand,
- uint32_t address,
- uint8_t *data,
- uint32_t data_size)
-{
- uint8_t *page;
-
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
-
- if (address % nand->page_size) {
- LOG_ERROR("writes need to be page aligned");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- page = malloc(nand->page_size);
-
- while (data_size > 0) {
- uint32_t thisrun_size = (data_size > nand->page_size) ? nand->page_size : data_size;
- uint32_t page_address;
-
- memset(page, 0xff, nand->page_size);
- memcpy(page, data, thisrun_size);
-
- page_address = address / nand->page_size;
-
- nand_write_page(nand, page_address, page, nand->page_size, NULL, 0);
-
- address += thisrun_size;
- data += thisrun_size;
- data_size -= thisrun_size;
- }
-
- free(page);
-
- return ERROR_OK;
-}
-#endif
-
-int nand_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- uint32_t block;
-
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
-
- block = page / (nand->erase_size / nand->page_size);
- if (nand->blocks[block].is_erased == 1)
- nand->blocks[block].is_erased = 0;
-
- if (nand->use_raw || nand->controller->write_page == NULL)
- return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
- else
- return nand->controller->write_page(nand, page, data, data_size, oob, oob_size);
-}
-
-int nand_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
-
- if (nand->use_raw || nand->controller->read_page == NULL)
- return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
- else
- return nand->controller->read_page(nand, page, data, data_size, oob, oob_size);
-}
-
-int nand_page_command(struct nand_device *nand, uint32_t page,
- uint8_t cmd, bool oob_only)
-{
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
-
- if (oob_only && NAND_CMD_READ0 == cmd && nand->page_size <= 512)
- cmd = NAND_CMD_READOOB;
-
- nand->controller->command(nand, cmd);
-
- if (nand->page_size <= 512) {
- /* small page device */
-
- /* column (always 0, we start at the beginning of a page/OOB area) */
- nand->controller->address(nand, 0x0);
-
- /* row */
- nand->controller->address(nand, page & 0xff);
- nand->controller->address(nand, (page >> 8) & 0xff);
-
- /* 4th cycle only on devices with more than 32 MiB */
- if (nand->address_cycles >= 4)
- nand->controller->address(nand, (page >> 16) & 0xff);
-
- /* 5th cycle only on devices with more than 8 GiB */
- if (nand->address_cycles >= 5)
- nand->controller->address(nand, (page >> 24) & 0xff);
- } else {
- /* large page device */
-
- /* column (0 when we start at the beginning of a page,
- * or 2048 for the beginning of OOB area)
- */
- nand->controller->address(nand, 0x0);
- if (oob_only)
- nand->controller->address(nand, 0x8);
- else
- nand->controller->address(nand, 0x0);
-
- /* row */
- nand->controller->address(nand, page & 0xff);
- nand->controller->address(nand, (page >> 8) & 0xff);
-
- /* 5th cycle only on devices with more than 128 MiB */
- if (nand->address_cycles >= 5)
- nand->controller->address(nand, (page >> 16) & 0xff);
-
- /* large page devices need a start command if reading */
- if (NAND_CMD_READ0 == cmd)
- nand->controller->command(nand, NAND_CMD_READSTART);
- }
-
- if (nand->controller->nand_ready) {
- if (!nand->controller->nand_ready(nand, 100))
- return ERROR_NAND_OPERATION_TIMEOUT;
- } else {
- /* nand_poll_read() cannot be used during nand read */
- alive_sleep(1);
- }
-
- return ERROR_OK;
-}
-
-int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size)
-{
- int retval = ERROR_NAND_NO_BUFFER;
-
- if (nand->controller->read_block_data != NULL)
- retval = (nand->controller->read_block_data)(nand, data, size);
-
- if (ERROR_NAND_NO_BUFFER == retval) {
- uint32_t i;
- int incr = (nand->device->options & NAND_BUSWIDTH_16) ? 2 : 1;
-
- retval = ERROR_OK;
- for (i = 0; retval == ERROR_OK && i < size; i += incr) {
- retval = nand->controller->read_data(nand, data);
- data += incr;
- }
- }
-
- return retval;
-}
-
-int nand_read_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- int retval;
-
- retval = nand_page_command(nand, page, NAND_CMD_READ0, !data);
- if (ERROR_OK != retval)
- return retval;
-
- if (data)
- nand_read_data_page(nand, data, data_size);
-
- if (oob)
- nand_read_data_page(nand, oob, oob_size);
-
- return ERROR_OK;
-}
-
-int nand_write_data_page(struct nand_device *nand, uint8_t *data, uint32_t size)
-{
- int retval = ERROR_NAND_NO_BUFFER;
-
- if (nand->controller->write_block_data != NULL)
- retval = (nand->controller->write_block_data)(nand, data, size);
-
- if (ERROR_NAND_NO_BUFFER == retval) {
- bool is16bit = nand->device->options & NAND_BUSWIDTH_16;
- uint32_t incr = is16bit ? 2 : 1;
- uint16_t write_data;
- uint32_t i;
-
- for (i = 0; i < size; i += incr) {
- if (is16bit)
- write_data = le_to_h_u16(data);
- else
- write_data = *data;
-
- retval = nand->controller->write_data(nand, write_data);
- if (ERROR_OK != retval)
- break;
-
- data += incr;
- }
- }
-
- return retval;
-}
-
-int nand_write_finish(struct nand_device *nand)
-{
- int retval;
- uint8_t status;
-
- nand->controller->command(nand, NAND_CMD_PAGEPROG);
-
- retval = nand->controller->nand_ready ?
- nand->controller->nand_ready(nand, 100) :
- nand_poll_ready(nand, 100);
- if (!retval)
- return ERROR_NAND_OPERATION_TIMEOUT;
-
- retval = nand_read_status(nand, &status);
- if (ERROR_OK != retval) {
- LOG_ERROR("couldn't read status");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & NAND_STATUS_FAIL) {
- LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
- status);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-int nand_write_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- int retval;
-
- retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
- if (ERROR_OK != retval)
- return retval;
-
- if (data) {
- retval = nand_write_data_page(nand, data, data_size);
- if (ERROR_OK != retval) {
- LOG_ERROR("Unable to write data to NAND device");
- return retval;
- }
- }
-
- if (oob) {
- retval = nand_write_data_page(nand, oob, oob_size);
- if (ERROR_OK != retval) {
- LOG_ERROR("Unable to write OOB data to NAND device");
- return retval;
- }
- }
-
- return nand_write_finish(nand);
-}
diff --git a/src/flash/nand/core.h b/src/flash/nand/core.h
deleted file mode 100644
index 5bf9fb3..0000000
--- a/src/flash/nand/core.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * Partially based on linux/include/linux/mtd/nand.h *
- * Copyright (C) 2000 David Woodhouse <dwmw2@mvhi.com> *
- * Copyright (C) 2000 Steven J. Hill <sjhill@realitydiluted.com> *
- * Copyright (C) 2000 Thomas Gleixner <tglx@linutronix.de> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_CORE_H
-#define OPENOCD_FLASH_NAND_CORE_H
-
-#include <flash/common.h>
-
-/**
- * Representation of a single NAND block in a NAND device.
- */
-struct nand_block {
- /** Offset to the block. */
- uint32_t offset;
-
- /** Size of the block. */
- uint32_t size;
-
- /** True if the block has been erased. */
- int is_erased;
-
- /** True if the block is bad. */
- int is_bad;
-};
-
-struct nand_oobfree {
- int offset;
- int length;
-};
-
-struct nand_ecclayout {
- int eccbytes;
- int eccpos[64];
- int oobavail;
- struct nand_oobfree oobfree[2];
-};
-
-struct nand_device {
- const char *name;
- struct target *target;
- struct nand_flash_controller *controller;
- void *controller_priv;
- struct nand_manufacturer *manufacturer;
- struct nand_info *device;
- int bus_width;
- int address_cycles;
- int page_size;
- int erase_size;
- bool use_raw;
- int num_blocks;
- struct nand_block *blocks;
- struct nand_device *next;
-};
-
-/* NAND Flash Manufacturer ID Codes
- */
-enum {
- NAND_MFR_TOSHIBA = 0x98,
- NAND_MFR_SAMSUNG = 0xec,
- NAND_MFR_FUJITSU = 0x04,
- NAND_MFR_NATIONAL = 0x8f,
- NAND_MFR_RENESAS = 0x07,
- NAND_MFR_STMICRO = 0x20,
- NAND_MFR_HYNIX = 0xad,
- NAND_MFR_MICRON = 0x2c,
-};
-
-struct nand_manufacturer {
- int id;
- const char *name;
-};
-
-struct nand_info {
- int mfr_id;
- int id;
- int page_size;
- int chip_size;
- int erase_size;
- int options;
- const char *name;
-};
-
-/* Option constants for bizarre disfunctionality and real features
- */
-enum {
- /* Chip can not auto increment pages */
- NAND_NO_AUTOINCR = 0x00000001,
-
- /* Buswitdh is 16 bit */
- NAND_BUSWIDTH_16 = 0x00000002,
-
- /* Device supports partial programming without padding */
- NAND_NO_PADDING = 0x00000004,
-
- /* Chip has cache program function */
- NAND_CACHEPRG = 0x00000008,
-
- /* Chip has copy back function */
- NAND_COPYBACK = 0x00000010,
-
- /* AND Chip which has 4 banks and a confusing page / block
- * assignment. See Renesas datasheet for further information */
- NAND_IS_AND = 0x00000020,
-
- /* Chip has a array of 4 pages which can be read without
- * additional ready /busy waits */
- NAND_4PAGE_ARRAY = 0x00000040,
-
- /* Chip requires that BBT is periodically rewritten to prevent
- * bits from adjacent blocks from 'leaking' in altering data.
- * This happens with the Renesas AG-AND chips, possibly others. */
- BBT_AUTO_REFRESH = 0x00000080,
-
- /* Chip does not require ready check on read. True
- * for all large page devices, as they do not support
- * autoincrement.*/
- NAND_NO_READRDY = 0x00000100,
-
- /* Options valid for Samsung large page devices */
- NAND_SAMSUNG_LP_OPTIONS = (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK),
-
- /* Options for new chips with large page size. The pagesize and the
- * erasesize is determined from the extended id bytes
- */
- LP_OPTIONS = (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR),
- LP_OPTIONS16 = (LP_OPTIONS | NAND_BUSWIDTH_16),
-};
-
-enum {
- /* Standard NAND flash commands */
- NAND_CMD_READ0 = 0x0,
- NAND_CMD_READ1 = 0x1,
- NAND_CMD_RNDOUT = 0x5,
- NAND_CMD_PAGEPROG = 0x10,
- NAND_CMD_READOOB = 0x50,
- NAND_CMD_ERASE1 = 0x60,
- NAND_CMD_STATUS = 0x70,
- NAND_CMD_STATUS_MULTI = 0x71,
- NAND_CMD_SEQIN = 0x80,
- NAND_CMD_RNDIN = 0x85,
- NAND_CMD_READID = 0x90,
- NAND_CMD_ERASE2 = 0xd0,
- NAND_CMD_RESET = 0xff,
-
- /* Extended commands for large page devices */
- NAND_CMD_READSTART = 0x30,
- NAND_CMD_RNDOUTSTART = 0xE0,
- NAND_CMD_CACHEDPROG = 0x15,
-};
-
-/* Status bits */
-enum {
- NAND_STATUS_FAIL = 0x01,
- NAND_STATUS_FAIL_N1 = 0x02,
- NAND_STATUS_TRUE_READY = 0x20,
- NAND_STATUS_READY = 0x40,
- NAND_STATUS_WP = 0x80,
-};
-
-/* OOB (spare) data formats */
-enum oob_formats {
- NAND_OOB_NONE = 0x0, /* no OOB data at all */
- NAND_OOB_RAW = 0x1, /* raw OOB data (16 bytes for 512b page sizes, 64 bytes for
- *2048b page sizes) */
- NAND_OOB_ONLY = 0x2, /* only OOB data */
- NAND_OOB_SW_ECC = 0x10, /* when writing, use SW ECC (as opposed to no ECC) */
- NAND_OOB_HW_ECC = 0x20, /* when writing, use HW ECC (as opposed to no ECC) */
- NAND_OOB_SW_ECC_KW = 0x40, /* when writing, use Marvell's Kirkwood bootrom format */
- NAND_OOB_JFFS2 = 0x100, /* when writing, use JFFS2 OOB layout */
- NAND_OOB_YAFFS2 = 0x100,/* when writing, use YAFFS2 OOB layout */
-};
-
-
-struct nand_device *get_nand_device_by_num(int num);
-
-int nand_page_command(struct nand_device *nand, uint32_t page,
- uint8_t cmd, bool oob_only);
-
-int nand_read_data_page(struct nand_device *nand, uint8_t *data, uint32_t size);
-int nand_write_data_page(struct nand_device *nand,
- uint8_t *data, uint32_t size);
-
-int nand_write_finish(struct nand_device *nand);
-
-int nand_read_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
-int nand_write_page_raw(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
-
-int nand_read_status(struct nand_device *nand, uint8_t *status);
-
-int nand_calculate_ecc(struct nand_device *nand,
- const uint8_t *dat, uint8_t *ecc_code);
-int nand_calculate_ecc_kw(struct nand_device *nand,
- const uint8_t *dat, uint8_t *ecc_code);
-
-int nand_register_commands(struct command_context *cmd_ctx);
-
-/** helper for parsing a nand device command argument string */
-COMMAND_HELPER(nand_command_get_device, unsigned name_index,
- struct nand_device **nand);
-
-
-#define ERROR_NAND_DEVICE_INVALID (-1100)
-#define ERROR_NAND_OPERATION_FAILED (-1101)
-#define ERROR_NAND_OPERATION_TIMEOUT (-1102)
-#define ERROR_NAND_OPERATION_NOT_SUPPORTED (-1103)
-#define ERROR_NAND_DEVICE_NOT_PROBED (-1104)
-#define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105)
-#define ERROR_NAND_NO_BUFFER (-1106)
-
-#endif /* OPENOCD_FLASH_NAND_CORE_H */
diff --git a/src/flash/nand/davinci.c b/src/flash/nand/davinci.c
deleted file mode 100644
index 17e6f68..0000000
--- a/src/flash/nand/davinci.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by David Brownell *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * DaVinci family NAND controller support for OpenOCD.
- *
- * This driver uses hardware ECC (1-bit or 4-bit) unless
- * the chip is accessed in "raw" mode.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "arm_io.h"
-#include <target/target.h>
-
-enum ecc {
- HWECC1, /* all controllers support 1-bit ECC */
- HWECC4, /* newer chips also have 4-bit ECC hardware */
- HWECC4_INFIX, /* avoid this layout, except maybe for boot code */
-};
-
-struct davinci_nand {
- uint8_t chipsel; /* chipselect 0..3 == CS2..CS5 */
- uint8_t eccmode;
-
- /* Async EMIF controller base */
- uint32_t aemif;
-
- /* NAND chip addresses */
- uint32_t data; /* without CLE or ALE */
- uint32_t cmd; /* with CLE */
- uint32_t addr; /* with ALE */
-
- /* write acceleration */
- struct arm_nand_data io;
-
- /* page i/o for the relevant flavor of hardware ECC */
- int (*read_page)(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
- int (*write_page)(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size);
-};
-
-#define NANDFCR 0x60 /* flash control register */
-#define NANDFSR 0x64 /* flash status register */
-#define NANDFECC 0x70 /* 1-bit ECC data, CS0, 1st of 4 */
-#define NAND4BITECCLOAD 0xbc /* 4-bit ECC, load saved values */
-#define NAND4BITECC 0xc0 /* 4-bit ECC data, 1st of 4 */
-#define NANDERRADDR 0xd0 /* 4-bit ECC err addr, 1st of 2 */
-#define NANDERRVAL 0xd8 /* 4-bit ECC err value, 1st of 2 */
-
-static int halted(struct target *target, const char *label)
-{
- if (target->state == TARGET_HALTED)
- return true;
-
- LOG_ERROR("Target must be halted to use NAND controller (%s)", label);
- return false;
-}
-
-static int davinci_init(struct nand_device *nand)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t nandfcr;
-
- if (!halted(target, "init"))
- return ERROR_NAND_OPERATION_FAILED;
-
- /* We require something else to have configured AEMIF to talk
- * to NAND chip in this range (including timings and width).
- */
- target_read_u32(target, info->aemif + NANDFCR, &nandfcr);
- if (!(nandfcr & (1 << info->chipsel))) {
- LOG_ERROR("chip address %08" PRIx32 " not NAND-enabled?", info->data);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* REVISIT verify: AxCR must be in 8-bit mode, since that's all we
- * tested. 16 bit support should work too; but not with 4-bit ECC.
- */
-
- return ERROR_OK;
-}
-
-static int davinci_reset(struct nand_device *nand)
-{
- return ERROR_OK;
-}
-
-static int davinci_nand_ready(struct nand_device *nand, int timeout)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t nandfsr;
-
- /* NOTE: return code is zero/error, else success; not ERROR_* */
-
- if (!halted(target, "ready"))
- return 0;
-
- do {
- target_read_u32(target, info->aemif + NANDFSR, &nandfsr);
-
- if (nandfsr & 0x01)
- return 1;
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-static int davinci_command(struct nand_device *nand, uint8_t command)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!halted(target, "command"))
- return ERROR_NAND_OPERATION_FAILED;
-
- target_write_u8(target, info->cmd, command);
- return ERROR_OK;
-}
-
-static int davinci_address(struct nand_device *nand, uint8_t address)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!halted(target, "address"))
- return ERROR_NAND_OPERATION_FAILED;
-
- target_write_u8(target, info->addr, address);
- return ERROR_OK;
-}
-
-static int davinci_write_data(struct nand_device *nand, uint16_t data)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!halted(target, "write_data"))
- return ERROR_NAND_OPERATION_FAILED;
-
- target_write_u8(target, info->data, data);
- return ERROR_OK;
-}
-
-static int davinci_read_data(struct nand_device *nand, void *data)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (!halted(target, "read_data"))
- return ERROR_NAND_OPERATION_FAILED;
-
- target_read_u8(target, info->data, data);
- return ERROR_OK;
-}
-
-/* REVISIT a bit of native code should let block reads be MUCH faster */
-
-static int davinci_read_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t nfdata = info->data;
- uint32_t tmp;
-
- if (!halted(target, "read_block"))
- return ERROR_NAND_OPERATION_FAILED;
-
- while (data_size >= 4) {
- target_read_u32(target, nfdata, &tmp);
-
- data[0] = tmp;
- data[1] = tmp >> 8;
- data[2] = tmp >> 16;
- data[3] = tmp >> 24;
-
- data_size -= 4;
- data += 4;
- }
-
- while (data_size > 0) {
- target_read_u8(target, nfdata, data);
-
- data_size -= 1;
- data += 1;
- }
-
- return ERROR_OK;
-}
-
-static int davinci_write_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t nfdata = info->data;
- uint32_t tmp;
- int status;
-
- if (!halted(target, "write_block"))
- return ERROR_NAND_OPERATION_FAILED;
-
- /* try the fast way first */
- status = arm_nandwrite(&info->io, data, data_size);
- if (status != ERROR_NAND_NO_BUFFER)
- return status;
-
- /* else do it slowly */
- while (data_size >= 4) {
- tmp = le_to_h_u32(data);
- target_write_u32(target, nfdata, tmp);
-
- data_size -= 4;
- data += 4;
- }
-
- while (data_size > 0) {
- target_write_u8(target, nfdata, *data);
-
- data_size -= 1;
- data += 1;
- }
-
- return ERROR_OK;
-}
-
-static int davinci_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- struct davinci_nand *info = nand->controller_priv;
- uint8_t *ooballoc = NULL;
- int status;
-
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
- if (!halted(nand->target, "write_page"))
- return ERROR_NAND_OPERATION_FAILED;
-
- /* Always write both data and OOB ... we are not "raw" I/O! */
- if (!data) {
- LOG_ERROR("Missing NAND data; try 'nand raw_access enable'");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* If we're not given OOB, write 0xff where we don't write ECC codes. */
- switch (nand->page_size) {
- case 512:
- oob_size = 16;
- break;
- case 2048:
- oob_size = 64;
- break;
- case 4096:
- oob_size = 128;
- break;
- default:
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (!oob) {
- ooballoc = malloc(oob_size);
- if (!ooballoc)
- return ERROR_NAND_OPERATION_FAILED;
- oob = ooballoc;
- memset(oob, 0x0ff, oob_size);
- }
-
- /* REVISIT avoid wasting SRAM: unless nand->use_raw is set,
- * use 512 byte chunks. Read side support will often want
- * to include oob_size ...
- */
- info->io.chunk_size = nand->page_size;
-
- status = info->write_page(nand, page, data, data_size, oob, oob_size);
- free(ooballoc);
- return status;
-}
-
-static int davinci_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- struct davinci_nand *info = nand->controller_priv;
-
- if (!nand->device)
- return ERROR_NAND_DEVICE_NOT_PROBED;
- if (!halted(nand->target, "read_page"))
- return ERROR_NAND_OPERATION_FAILED;
-
- return info->read_page(nand, page, data, data_size, oob, oob_size);
-}
-
-static void davinci_write_pagecmd(struct nand_device *nand, uint8_t cmd, uint32_t page)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- int page3 = nand->address_cycles - (nand->page_size == 512);
-
- /* write command ({page,otp}x{read,program} */
- target_write_u8(target, info->cmd, cmd);
-
- /* column address (beginning-of-page) */
- target_write_u8(target, info->addr, 0);
- if (nand->page_size > 512)
- target_write_u8(target, info->addr, 0);
-
- /* page address */
- target_write_u8(target, info->addr, page);
- target_write_u8(target, info->addr, page >> 8);
- if (page3)
- target_write_u8(target, info->addr, page >> 16);
- if (page3 == 2)
- target_write_u8(target, info->addr, page >> 24);
-}
-
-static int davinci_seek_column(struct nand_device *nand, uint16_t column)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
-
- /* Random read, we must have issued a page read already */
- target_write_u8(target, info->cmd, NAND_CMD_RNDOUT);
-
- target_write_u8(target, info->addr, column);
-
- if (nand->page_size > 512) {
- target_write_u8(target, info->addr, column >> 8);
- target_write_u8(target, info->cmd, NAND_CMD_RNDOUTSTART);
- }
-
- if (!davinci_nand_ready(nand, 100))
- return ERROR_NAND_OPERATION_TIMEOUT;
-
- return ERROR_OK;
-}
-
-static int davinci_writepage_tail(struct nand_device *nand,
- uint8_t *oob, uint32_t oob_size)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- uint8_t status;
-
- if (oob_size)
- davinci_write_block_data(nand, oob, oob_size);
-
- /* non-cachemode page program */
- target_write_u8(target, info->cmd, NAND_CMD_PAGEPROG);
-
- if (!davinci_nand_ready(nand, 100))
- return ERROR_NAND_OPERATION_TIMEOUT;
-
- if (nand_read_status(nand, &status) != ERROR_OK) {
- LOG_ERROR("couldn't read status");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & NAND_STATUS_FAIL) {
- LOG_ERROR("write operation failed, status: 0x%02x", status);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-/*
- * All DaVinci family chips support 1-bit ECC on a per-chipselect basis.
- */
-static int davinci_write_page_ecc1(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- unsigned oob_offset;
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- const uint32_t fcr_addr = info->aemif + NANDFCR;
- const uint32_t ecc1_addr = info->aemif + NANDFECC + (4 * info->chipsel);
- uint32_t fcr, ecc1;
-
- /* Write contiguous ECC bytes starting at specified offset.
- * NOTE: Linux reserves twice as many bytes as we need; and
- * for 16-bit OOB, those extra bytes are discontiguous.
- */
- switch (nand->page_size) {
- case 512:
- oob_offset = 0;
- break;
- case 2048:
- oob_offset = 40;
- break;
- default:
- oob_offset = 80;
- break;
- }
-
- davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
-
- /* scrub any old ECC state */
- target_read_u32(target, ecc1_addr, &ecc1);
-
- target_read_u32(target, fcr_addr, &fcr);
- fcr |= 1 << (8 + info->chipsel);
-
- do {
- /* set "start csX 1bit ecc" bit */
- target_write_u32(target, fcr_addr, fcr);
-
- /* write 512 bytes */
- davinci_write_block_data(nand, data, 512);
- data += 512;
- data_size -= 512;
-
- /* read the ecc, pack to 3 bytes, and invert so the ecc
- * in an erased block is correct
- */
- target_read_u32(target, ecc1_addr, &ecc1);
- ecc1 = (ecc1 & 0x0fff) | ((ecc1 & 0x0fff0000) >> 4);
- ecc1 = ~ecc1;
-
- /* save correct ECC code into oob data */
- oob[oob_offset++] = (uint8_t)(ecc1);
- oob[oob_offset++] = (uint8_t)(ecc1 >> 8);
- oob[oob_offset++] = (uint8_t)(ecc1 >> 16);
-
- } while (data_size);
-
- /* write OOB into spare area */
- return davinci_writepage_tail(nand, oob, oob_size);
-}
-
-/*
- * Preferred "new style" ECC layout for use with 4-bit ECC. This somewhat
- * slows down large page reads done with error correction (since the OOB
- * is read first, so its ECC data can be used incrementally), but the
- * manufacturer bad block markers are safe. Contrast: old "infix" style.
- */
-static int davinci_write_page_ecc4(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- static const uint8_t ecc512[] = {
- 0, 1, 2, 3, 4, /* 5== mfr badblock */
- 6, 7, /* 8..12 for BBT or JFFS2 */ 13, 14, 15,
- };
- static const uint8_t ecc2048[] = {
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- };
- static const uint8_t ecc4096[] = {
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
- 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
- 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- };
-
- struct davinci_nand *info = nand->controller_priv;
- const uint8_t *l;
- struct target *target = nand->target;
- const uint32_t fcr_addr = info->aemif + NANDFCR;
- const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
- uint32_t fcr, ecc4;
-
- /* Use the same ECC layout Linux uses. For small page chips
- * it's a bit cramped.
- *
- * NOTE: at this writing, 4KB pages have issues in Linux
- * because they need more than 64 bytes of ECC data, which
- * the standard ECC logic can't handle.
- */
- switch (nand->page_size) {
- case 512:
- l = ecc512;
- break;
- case 2048:
- l = ecc2048;
- break;
- default:
- l = ecc4096;
- break;
- }
-
- davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
-
- /* scrub any old ECC state */
- target_read_u32(target, info->aemif + NANDERRVAL, &ecc4);
-
- target_read_u32(target, fcr_addr, &fcr);
- fcr &= ~(0x03 << 4);
- fcr |= (1 << 12) | (info->chipsel << 4);
-
- do {
- uint32_t raw_ecc[4], *p;
- int i;
-
- /* start 4bit ecc on csX */
- target_write_u32(target, fcr_addr, fcr);
-
- /* write 512 bytes */
- davinci_write_block_data(nand, data, 512);
- data += 512;
- data_size -= 512;
-
- /* read the ecc, then save it into 10 bytes in the oob */
- for (i = 0; i < 4; i++) {
- target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]);
- raw_ecc[i] &= 0x03ff03ff;
- }
- for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
- oob[*l++] = p[0] & 0xff;
- oob[*l++] = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
- oob[*l++] = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
- oob[*l++] = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
- oob[*l++] = (p[1] >> 18) & 0xff;
- }
-
- } while (data_size);
-
- /* write OOB into spare area */
- return davinci_writepage_tail(nand, oob, oob_size);
-}
-
-/*
- * "Infix" OOB ... like Linux ECC_HW_SYNDROME. Avoided because it trashes
- * manufacturer bad block markers, except on small page chips. Once you
- * write to a page using this scheme, you need specialized code to update
- * it (code which ignores now-invalid bad block markers).
- *
- * This is needed *only* to support older firmware. Older ROM Boot Loaders
- * need it to read their second stage loader (UBL) into SRAM, but from then
- * on the whole system can use the cleaner non-infix layouts. Systems with
- * older second stage loaders (ABL/U-Boot, etc) or other system software
- * (MVL 4.x/5.x kernels, filesystems, etc) may need it more generally.
- */
-static int davinci_write_page_ecc4infix(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- struct davinci_nand *info = nand->controller_priv;
- struct target *target = nand->target;
- const uint32_t fcr_addr = info->aemif + NANDFCR;
- const uint32_t ecc4_addr = info->aemif + NAND4BITECC;
- uint32_t fcr, ecc4;
-
- davinci_write_pagecmd(nand, NAND_CMD_SEQIN, page);
-
- /* scrub any old ECC state */
- target_read_u32(target, info->aemif + NANDERRVAL, &ecc4);
-
- target_read_u32(target, fcr_addr, &fcr);
- fcr &= ~(0x03 << 4);
- fcr |= (1 << 12) | (info->chipsel << 4);
-
- do {
- uint32_t raw_ecc[4], *p;
- uint8_t *l;
- int i;
-
- /* start 4bit ecc on csX */
- target_write_u32(target, fcr_addr, fcr);
-
- /* write 512 bytes */
- davinci_write_block_data(nand, data, 512);
- data += 512;
- data_size -= 512;
-
- /* read the ecc */
- for (i = 0; i < 4; i++) {
- target_read_u32(target, ecc4_addr + 4 * i, &raw_ecc[i]);
- raw_ecc[i] &= 0x03ff03ff;
- }
-
- /* skip 6 bytes of prepad, then pack 10 packed ecc bytes */
- for (i = 0, l = oob + 6, p = raw_ecc; i < 2; i++, p += 2) {
- *l++ = p[0] & 0xff;
- *l++ = ((p[0] >> 8) & 0x03) | ((p[0] >> 14) & 0xfc);
- *l++ = ((p[0] >> 22) & 0x0f) | ((p[1] << 4) & 0xf0);
- *l++ = ((p[1] >> 4) & 0x3f) | ((p[1] >> 10) & 0xc0);
- *l++ = (p[1] >> 18) & 0xff;
- }
-
- /* write this "out-of-band" data -- infix */
- davinci_write_block_data(nand, oob, 16);
- oob += 16;
- oob_size -= 16;
-
- } while (data_size);
-
- /* the last data and OOB writes included the spare area */
- return davinci_writepage_tail(nand, NULL, 0);
-}
-
-static int davinci_read_page_ecc4infix(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
-{
- int read_size;
- int want_col, at_col;
- int ret;
-
- davinci_write_pagecmd(nand, NAND_CMD_READ0, page);
-
- /* large page devices need a start command */
- if (nand->page_size > 512)
- davinci_command(nand, NAND_CMD_READSTART);
-
- if (!davinci_nand_ready(nand, 100))
- return ERROR_NAND_OPERATION_TIMEOUT;
-
- /* NOTE: not bothering to compute and use ECC data for now */
-
- want_col = 0;
- at_col = 0;
- while ((data && data_size) || (oob && oob_size)) {
-
- if (data && data_size) {
- if (want_col != at_col) {
- /* Reads are slow, so seek past them when we can */
- ret = davinci_seek_column(nand, want_col);
- if (ret != ERROR_OK)
- return ret;
- at_col = want_col;
- }
- /* read 512 bytes or data_size, whichever is smaller*/
- read_size = data_size > 512 ? 512 : data_size;
- davinci_read_block_data(nand, data, read_size);
- data += read_size;
- data_size -= read_size;
- at_col += read_size;
- }
- want_col += 512;
-
- if (oob && oob_size) {
- if (want_col != at_col) {
- ret = davinci_seek_column(nand, want_col);
- if (ret != ERROR_OK)
- return ret;
- at_col = want_col;
- }
- /* read this "out-of-band" data -- infix */
- read_size = oob_size > 16 ? 16 : oob_size;
- davinci_read_block_data(nand, oob, read_size);
- oob += read_size;
- oob_size -= read_size;
- at_col += read_size;
- }
- want_col += 16;
- }
- return ERROR_OK;
-}
-
-NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
-{
- struct davinci_nand *info;
- unsigned long chip, aemif;
- enum ecc eccmode;
- int chipsel;
-
- /* arguments:
- * - "davinci"
- * - target
- * - nand chip address
- * - ecc mode
- * - aemif address
- * Plus someday, optionally, ALE and CLE masks.
- */
- if (CMD_ARGC < 5)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip);
- if (chip == 0) {
- LOG_ERROR("Invalid NAND chip address %s", CMD_ARGV[2]);
- goto fail;
- }
-
- if (strcmp(CMD_ARGV[3], "hwecc1") == 0)
- eccmode = HWECC1;
- else if (strcmp(CMD_ARGV[3], "hwecc4") == 0)
- eccmode = HWECC4;
- else if (strcmp(CMD_ARGV[3], "hwecc4_infix") == 0)
- eccmode = HWECC4_INFIX;
- else {
- LOG_ERROR("Invalid ecc mode %s", CMD_ARGV[3]);
- goto fail;
- }
-
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[4], aemif);
- if (aemif == 0) {
- LOG_ERROR("Invalid AEMIF controller address %s", CMD_ARGV[4]);
- goto fail;
- }
-
- /* REVISIT what we'd *like* to do is look up valid ranges using
- * target-specific declarations, and not even need to pass the
- * AEMIF controller address.
- */
- if (aemif == 0x01e00000 /* dm6446, dm357 */
- || aemif == 0x01e10000 /* dm335, dm355 */
- || aemif == 0x01d10000 /* dm365 */
- ) {
- if (chip < 0x02000000 || chip >= 0x0a000000) {
- LOG_ERROR("NAND address %08lx out of range?", chip);
- goto fail;
- }
- chipsel = (chip - 0x02000000) >> 25;
- } else {
- LOG_ERROR("unrecognized AEMIF controller address %08lx", aemif);
- goto fail;
- }
-
- info = calloc(1, sizeof *info);
- if (info == NULL)
- goto fail;
-
- info->eccmode = eccmode;
- info->chipsel = chipsel;
- info->aemif = aemif;
- info->data = chip;
- info->cmd = chip | 0x10;
- info->addr = chip | 0x08;
-
- nand->controller_priv = info;
-
- info->io.target = nand->target;
- info->io.data = info->data;
- info->io.op = ARM_NAND_NONE;
-
- /* NOTE: for now we don't do any error correction on read.
- * Nothing else in OpenOCD currently corrects read errors,
- * and in any case it's *writing* that we care most about.
- */
- info->read_page = nand_read_page_raw;
-
- switch (eccmode) {
- case HWECC1:
- /* ECC_HW, 1-bit corrections, 3 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc1;
- break;
- case HWECC4:
- /* ECC_HW, 4-bit corrections, 10 bytes ECC per 512 data bytes */
- info->write_page = davinci_write_page_ecc4;
- break;
- case HWECC4_INFIX:
- /* Same 4-bit ECC HW, with problematic page/ecc layout */
- info->read_page = davinci_read_page_ecc4infix;
- info->write_page = davinci_write_page_ecc4infix;
- break;
- }
-
- return ERROR_OK;
-
-fail:
- return ERROR_NAND_OPERATION_FAILED;
-}
-
-struct nand_flash_controller davinci_nand_controller = {
- .name = "davinci",
- .usage = "chip_addr hwecc_mode aemif_addr",
- .nand_device_command = davinci_nand_device_command,
- .init = davinci_init,
- .reset = davinci_reset,
- .command = davinci_command,
- .address = davinci_address,
- .write_data = davinci_write_data,
- .read_data = davinci_read_data,
- .write_page = davinci_write_page,
- .read_page = davinci_read_page,
- .write_block_data = davinci_write_block_data,
- .read_block_data = davinci_read_block_data,
- .nand_ready = davinci_nand_ready,
-};
diff --git a/src/flash/nand/driver.c b/src/flash/nand/driver.c
deleted file mode 100644
index f766560..0000000
--- a/src/flash/nand/driver.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "core.h"
-#include "driver.h"
-
-/* NAND flash controller
- */
-extern struct nand_flash_controller nonce_nand_controller;
-extern struct nand_flash_controller davinci_nand_controller;
-extern struct nand_flash_controller lpc3180_nand_controller;
-extern struct nand_flash_controller lpc32xx_nand_controller;
-extern struct nand_flash_controller orion_nand_controller;
-extern struct nand_flash_controller s3c2410_nand_controller;
-extern struct nand_flash_controller s3c2412_nand_controller;
-extern struct nand_flash_controller s3c2440_nand_controller;
-extern struct nand_flash_controller s3c2443_nand_controller;
-extern struct nand_flash_controller s3c6400_nand_controller;
-extern struct nand_flash_controller mxc_nand_flash_controller;
-extern struct nand_flash_controller imx31_nand_flash_controller;
-extern struct nand_flash_controller at91sam9_nand_controller;
-extern struct nand_flash_controller nuc910_nand_controller;
-
-/* extern struct nand_flash_controller boundary_scan_nand_controller; */
-
-static struct nand_flash_controller *nand_flash_controllers[] = {
- &nonce_nand_controller,
- &davinci_nand_controller,
- &lpc3180_nand_controller,
- &lpc32xx_nand_controller,
- &orion_nand_controller,
- &s3c2410_nand_controller,
- &s3c2412_nand_controller,
- &s3c2440_nand_controller,
- &s3c2443_nand_controller,
- &s3c6400_nand_controller,
- &mxc_nand_flash_controller,
- &imx31_nand_flash_controller,
- &at91sam9_nand_controller,
- &nuc910_nand_controller,
-/* &boundary_scan_nand_controller, */
- NULL
-};
-
-struct nand_flash_controller *nand_driver_find_by_name(const char *name)
-{
- for (unsigned i = 0; nand_flash_controllers[i]; i++) {
- struct nand_flash_controller *controller = nand_flash_controllers[i];
- if (strcmp(name, controller->name) == 0)
- return controller;
- }
- return NULL;
-}
-int nand_driver_walk(nand_driver_walker_t f, void *x)
-{
- for (unsigned i = 0; nand_flash_controllers[i]; i++) {
- int retval = (*f)(nand_flash_controllers[i], x);
- if (ERROR_OK != retval)
- return retval;
- }
- return ERROR_OK;
-}
diff --git a/src/flash/nand/driver.h b/src/flash/nand/driver.h
deleted file mode 100644
index 2182a77..0000000
--- a/src/flash/nand/driver.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_DRIVER_H
-#define OPENOCD_FLASH_NAND_DRIVER_H
-
-struct nand_device;
-
-#define __NAND_DEVICE_COMMAND(name) \
- COMMAND_HELPER(name, struct nand_device *nand)
-
-/**
- * Interface for NAND flash controllers. Not all of these functions are
- * required for full functionality of the NAND driver, but better performance
- * can be achieved by implementing each function.
- */
-struct nand_flash_controller {
- /** Driver name that is used to select it from configuration files. */
- const char *name;
-
- /** Usage of flash command registration. */
- const char *usage;
-
- const struct command_registration *commands;
-
- /** NAND device command called when driver is instantiated during configuration. */
- __NAND_DEVICE_COMMAND((*nand_device_command));
-
- /** Initialize the NAND device. */
- int (*init)(struct nand_device *nand);
-
- /** Reset the NAND device. */
- int (*reset)(struct nand_device *nand);
-
- /** Issue a command to the NAND device. */
- int (*command)(struct nand_device *nand, uint8_t command);
-
- /** Write an address to the NAND device. */
- int (*address)(struct nand_device *nand, uint8_t address);
-
- /** Write word of data to the NAND device. */
- int (*write_data)(struct nand_device *nand, uint16_t data);
-
- /** Read word of data from the NAND device. */
- int (*read_data)(struct nand_device *nand, void *data);
-
- /** Write a block of data to the NAND device. */
- int (*write_block_data)(struct nand_device *nand, uint8_t *data, int size);
-
- /** Read a block of data from the NAND device. */
- int (*read_block_data)(struct nand_device *nand, uint8_t *data, int size);
-
- /** Write a page to the NAND device. */
- int (*write_page)(struct nand_device *nand, uint32_t page, uint8_t *data,
- uint32_t data_size, uint8_t *oob, uint32_t oob_size);
-
- /** Read a page from the NAND device. */
- int (*read_page)(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size);
-
- /** Check if the NAND device is ready for more instructions with timeout. */
- int (*nand_ready)(struct nand_device *nand, int timeout);
-};
-
-#define NAND_DEVICE_COMMAND_HANDLER(name) static __NAND_DEVICE_COMMAND(name)
-
-/**
- * Find a NAND flash controller by name.
- * @param name Identifies the NAND controller to find.
- * @returns The nand_flash_controller named @c name, or NULL if not found.
- */
-struct nand_flash_controller *nand_driver_find_by_name(const char *name);
-
-/** Signature for callback functions passed to nand_driver_walk */
-typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *);
-/**
- * Walk the list of drivers, encapsulating the data structure type.
- * Application state/context can be passed through the @c x pointer.
- * @param f The callback function to invoke for each function.
- * @param x For use as private data storate, passed directly to @c f.
- * @returns ERROR_OK if successful, or the non-zero return value of @c f.
- * This allows a walker to terminate the loop early.
- */
-int nand_driver_walk(nand_driver_walker_t f, void *x);
-
-#endif /* OPENOCD_FLASH_NAND_DRIVER_H */
diff --git a/src/flash/nand/ecc.c b/src/flash/nand/ecc.c
deleted file mode 100644
index 25b2eb1..0000000
--- a/src/flash/nand/ecc.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * This file contains an ECC algorithm from Toshiba that allows for detection
- * and correction of 1-bit errors in a 256 byte block of data.
- *
- * [ Extracted from the initial code found in some early Linux versions.
- * The current Linux code is bigger while being faster, but this is of
- * no real benefit when the bottleneck largely remains the JTAG link. ]
- *
- * Copyright (C) 2000-2004 Steven J. Hill (sjhill at realitydiluted.com)
- * Toshiba America Electronics Components, Inc.
- *
- * Copyright (C) 2006 Thomas Gleixner <tglx at linutronix.de>
- *
- * This file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 or (at your option) any
- * later version.
- *
- * This file is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, if other files instantiate templates or use
- * macros or inline functions from these files, or you compile these
- * files and link them with other works to produce a work based on these
- * files, these files do not by themselves cause the resulting work to be
- * covered by the GNU General Public License. However the source code for
- * these files must still be made available in accordance with section (3)
- * of the GNU General Public License.
- *
- * This exception does not invalidate any other reasons why a work based on
- * this file might be covered by the GNU General Public License.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "core.h"
-
-/*
- * Pre-calculated 256-way 1 byte column parity
- */
-static const uint8_t nand_ecc_precalc_table[] = {
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
- 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
- 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
- 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
- 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
- 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
- 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
- 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
-};
-
-/*
- * nand_calculate_ecc - Calculate 3-byte ECC for 256-byte block
- */
-int nand_calculate_ecc(struct nand_device *nand, const uint8_t *dat, uint8_t *ecc_code)
-{
- uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
- int i;
-
- /* Initialize variables */
- reg1 = reg2 = reg3 = 0;
-
- /* Build up column parity */
- for (i = 0; i < 256; i++) {
- /* Get CP0 - CP5 from table */
- idx = nand_ecc_precalc_table[*dat++];
- reg1 ^= (idx & 0x3f);
-
- /* All bit XOR = 1 ? */
- if (idx & 0x40) {
- reg3 ^= (uint8_t) i;
- reg2 ^= ~((uint8_t) i);
- }
- }
-
- /* Create non-inverted ECC code from line parity */
- tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */
- tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
- tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
- tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
- tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
- tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
- tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
- tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
-
- tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */
- tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
- tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
- tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
- tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
- tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
- tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
- tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
-
- /* Calculate final ECC code */
-#ifdef NAND_ECC_SMC
- ecc_code[0] = ~tmp2;
- ecc_code[1] = ~tmp1;
-#else
- ecc_code[0] = ~tmp1;
- ecc_code[1] = ~tmp2;
-#endif
- ecc_code[2] = ((~reg1) << 2) | 0x03;
-
- return 0;
-}
-
-static inline int countbits(uint32_t b)
-{
- int res = 0;
-
- for (; b; b >>= 1)
- res += b & 0x01;
- return res;
-}
-
-/**
- * nand_correct_data - Detect and correct a 1 bit error for 256 byte block
- */
-int nand_correct_data(struct nand_device *nand, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- uint8_t s0, s1, s2;
-
-#ifdef NAND_ECC_SMC
- s0 = calc_ecc[0] ^ read_ecc[0];
- s1 = calc_ecc[1] ^ read_ecc[1];
- s2 = calc_ecc[2] ^ read_ecc[2];
-#else
- s1 = calc_ecc[0] ^ read_ecc[0];
- s0 = calc_ecc[1] ^ read_ecc[1];
- s2 = calc_ecc[2] ^ read_ecc[2];
-#endif
- if ((s0 | s1 | s2) == 0)
- return 0;
-
- /* Check for a single bit error */
- if (((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
- ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
- ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
-
- uint32_t byteoffs, bitnum;
-
- byteoffs = (s1 << 0) & 0x80;
- byteoffs |= (s1 << 1) & 0x40;
- byteoffs |= (s1 << 2) & 0x20;
- byteoffs |= (s1 << 3) & 0x10;
-
- byteoffs |= (s0 >> 4) & 0x08;
- byteoffs |= (s0 >> 3) & 0x04;
- byteoffs |= (s0 >> 2) & 0x02;
- byteoffs |= (s0 >> 1) & 0x01;
-
- bitnum = (s2 >> 5) & 0x04;
- bitnum |= (s2 >> 4) & 0x02;
- bitnum |= (s2 >> 3) & 0x01;
-
- dat[byteoffs] ^= (1 << bitnum);
-
- return 1;
- }
-
- if (countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 << 16)) == 1)
- return 1;
-
- return -1;
-}
diff --git a/src/flash/nand/ecc_kw.c b/src/flash/nand/ecc_kw.c
deleted file mode 100644
index fb3481d..0000000
--- a/src/flash/nand/ecc_kw.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Reed-Solomon ECC handling for the Marvell Kirkwood SOC
- * Copyright (C) 2009 Marvell Semiconductor, Inc.
- *
- * Authors: Lennert Buytenhek <buytenh@wantstofly.org>
- * Nicolas Pitre <nico@fluxnic.net>
- *
- * This file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 or (at your option) any
- * later version.
- *
- * This file is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "core.h"
-
-/*****************************************************************************
- * Arithmetic in GF(2^10) ("F") modulo x^10 + x^3 + 1.
- *
- * For multiplication, a discrete log/exponent table is used, with
- * primitive element x (F is a primitive field, so x is primitive).
- */
-#define MODPOLY 0x409 /* x^10 + x^3 + 1 in binary */
-
-/*
- * Maps an integer a [0..1022] to a polynomial b = gf_exp[a] in
- * GF(2^10) mod x^10 + x^3 + 1 such that b = x ^ a. There's two
- * identical copies of this array back-to-back so that we can save
- * the mod 1023 operation when doing a GF multiplication.
- */
-static uint16_t gf_exp[1023 + 1023];
-
-/*
- * Maps a polynomial b in GF(2^10) mod x^10 + x^3 + 1 to an index
- * a = gf_log[b] in [0..1022] such that b = x ^ a.
- */
-static uint16_t gf_log[1024];
-
-static void gf_build_log_exp_table(void)
-{
- int i;
- int p_i;
-
- /*
- * p_i = x ^ i
- *
- * Initialise to 1 for i = 0.
- */
- p_i = 1;
-
- for (i = 0; i < 1023; i++) {
- gf_exp[i] = p_i;
- gf_exp[i + 1023] = p_i;
- gf_log[p_i] = i;
-
- /*
- * p_i = p_i * x
- */
- p_i <<= 1;
- if (p_i & (1 << 10))
- p_i ^= MODPOLY;
- }
-}
-
-
-/*****************************************************************************
- * Reed-Solomon code
- *
- * This implements a (1023,1015) Reed-Solomon ECC code over GF(2^10)
- * mod x^10 + x^3 + 1, shortened to (520,512). The ECC data consists
- * of 8 10-bit symbols, or 10 8-bit bytes.
- *
- * Given 512 bytes of data, computes 10 bytes of ECC.
- *
- * This is done by converting the 512 bytes to 512 10-bit symbols
- * (elements of F), interpreting those symbols as a polynomial in F[X]
- * by taking symbol 0 as the coefficient of X^8 and symbol 511 as the
- * coefficient of X^519, and calculating the residue of that polynomial
- * divided by the generator polynomial, which gives us the 8 ECC symbols
- * as the remainder. Finally, we convert the 8 10-bit ECC symbols to 10
- * 8-bit bytes.
- *
- * The generator polynomial is hardcoded, as that is faster, but it
- * can be computed by taking the primitive element a = x (in F), and
- * constructing a polynomial in F[X] with roots a, a^2, a^3, ..., a^8
- * by multiplying the minimal polynomials for those roots (which are
- * just 'x - a^i' for each i).
- *
- * Note: due to unfortunate circumstances, the bootrom in the Kirkwood SOC
- * expects the ECC to be computed backward, i.e. from the last byte down
- * to the first one.
- */
-int nand_calculate_ecc_kw(struct nand_device *nand, const uint8_t *data, uint8_t *ecc)
-{
- unsigned int r7, r6, r5, r4, r3, r2, r1, r0;
- int i;
- static int tables_initialized;
-
- if (!tables_initialized) {
- gf_build_log_exp_table();
- tables_initialized = 1;
- }
-
- /*
- * Load bytes 504..511 of the data into r.
- */
- r0 = data[504];
- r1 = data[505];
- r2 = data[506];
- r3 = data[507];
- r4 = data[508];
- r5 = data[509];
- r6 = data[510];
- r7 = data[511];
-
- /*
- * Shift bytes 503..0 (in that order) into r0, followed
- * by eight zero bytes, while reducing the polynomial by the
- * generator polynomial in every step.
- */
- for (i = 503; i >= -8; i--) {
- unsigned int d;
-
- d = 0;
- if (i >= 0)
- d = data[i];
-
- if (r7) {
- uint16_t *t = gf_exp + gf_log[r7];
-
- r7 = r6 ^ t[0x21c];
- r6 = r5 ^ t[0x181];
- r5 = r4 ^ t[0x18e];
- r4 = r3 ^ t[0x25f];
- r3 = r2 ^ t[0x197];
- r2 = r1 ^ t[0x193];
- r1 = r0 ^ t[0x237];
- r0 = d ^ t[0x024];
- } else {
- r7 = r6;
- r6 = r5;
- r5 = r4;
- r4 = r3;
- r3 = r2;
- r2 = r1;
- r1 = r0;
- r0 = d;
- }
- }
-
- ecc[0] = r0;
- ecc[1] = (r0 >> 8) | (r1 << 2);
- ecc[2] = (r1 >> 6) | (r2 << 4);
- ecc[3] = (r2 >> 4) | (r3 << 6);
- ecc[4] = (r3 >> 2);
- ecc[5] = r4;
- ecc[6] = (r4 >> 8) | (r5 << 2);
- ecc[7] = (r5 >> 6) | (r6 << 4);
- ecc[8] = (r6 >> 4) | (r7 << 6);
- ecc[9] = (r7 >> 2);
-
- return 0;
-}
diff --git a/src/flash/nand/fileio.c b/src/flash/nand/fileio.c
deleted file mode 100644
index 64c32c0..0000000
--- a/src/flash/nand/fileio.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * Partially based on drivers/mtd/nand_ids.c from Linux. *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "core.h"
-#include "fileio.h"
-
-static struct nand_ecclayout nand_oob_16 = {
- .eccbytes = 6,
- .eccpos = {0, 1, 2, 3, 6, 7},
- .oobfree = {
- {.offset = 8,
- .length = 8}
- }
-};
-
-static struct nand_ecclayout nand_oob_64 = {
- .eccbytes = 24,
- .eccpos = {
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63
- },
- .oobfree = {
- {.offset = 2,
- .length = 38}
- }
-};
-
-void nand_fileio_init(struct nand_fileio_state *state)
-{
- memset(state, 0, sizeof(*state));
- state->oob_format = NAND_OOB_NONE;
-}
-
-int nand_fileio_start(struct command_context *cmd_ctx,
- struct nand_device *nand, const char *filename, int filemode,
- struct nand_fileio_state *state)
-{
- if (state->address % nand->page_size) {
- command_print(cmd_ctx, "only page-aligned addresses are supported");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- duration_start(&state->bench);
-
- if (NULL != filename) {
- int retval = fileio_open(&state->fileio, filename, filemode, FILEIO_BINARY);
- if (ERROR_OK != retval) {
- const char *msg = (FILEIO_READ == filemode) ? "read" : "write";
- command_print(cmd_ctx, "failed to open '%s' for %s access",
- filename, msg);
- return retval;
- }
- state->file_opened = true;
- }
-
- if (!(state->oob_format & NAND_OOB_ONLY)) {
- state->page_size = nand->page_size;
- state->page = malloc(nand->page_size);
- }
-
- if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) {
- if (nand->page_size == 512) {
- state->oob_size = 16;
- state->eccpos = nand_oob_16.eccpos;
- } else if (nand->page_size == 2048) {
- state->oob_size = 64;
- state->eccpos = nand_oob_64.eccpos;
- }
- state->oob = malloc(state->oob_size);
- }
-
- return ERROR_OK;
-}
-int nand_fileio_cleanup(struct nand_fileio_state *state)
-{
- if (state->file_opened)
- fileio_close(state->fileio);
-
- if (state->oob) {
- free(state->oob);
- state->oob = NULL;
- }
- if (state->page) {
- free(state->page);
- state->page = NULL;
- }
- return ERROR_OK;
-}
-int nand_fileio_finish(struct nand_fileio_state *state)
-{
- nand_fileio_cleanup(state);
- return duration_measure(&state->bench);
-}
-
-COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
- struct nand_device **dev, enum fileio_access filemode,
- bool need_size, bool sw_ecc)
-{
- nand_fileio_init(state);
-
- unsigned minargs = need_size ? 4 : 3;
- if (CMD_ARGC < minargs)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct nand_device *nand;
- int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &nand);
- if (ERROR_OK != retval)
- return retval;
-
- if (NULL == nand->device) {
- command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
- return ERROR_NAND_DEVICE_NOT_PROBED;
- }
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], state->address);
- if (need_size) {
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], state->size);
- if (state->size % nand->page_size) {
- command_print(CMD_CTX, "only page-aligned sizes are supported");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- if (CMD_ARGC > minargs) {
- for (unsigned i = minargs; i < CMD_ARGC; i++) {
- if (!strcmp(CMD_ARGV[i], "oob_raw"))
- state->oob_format |= NAND_OOB_RAW;
- else if (!strcmp(CMD_ARGV[i], "oob_only"))
- state->oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY;
- else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc"))
- state->oob_format |= NAND_OOB_SW_ECC;
- else if (sw_ecc && !strcmp(CMD_ARGV[i], "oob_softecc_kw"))
- state->oob_format |= NAND_OOB_SW_ECC_KW;
- else {
- command_print(CMD_CTX, "unknown option: %s", CMD_ARGV[i]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
- }
-
- retval = nand_fileio_start(CMD_CTX, nand, CMD_ARGV[1], filemode, state);
- if (ERROR_OK != retval)
- return retval;
-
- if (!need_size) {
- size_t filesize;
- retval = fileio_size(state->fileio, &filesize);
- if (retval != ERROR_OK)
- return retval;
- state->size = filesize;
- }
-
- *dev = nand;
-
- return ERROR_OK;
-}
-
-/**
- * @returns If no error occurred, returns number of bytes consumed;
- * otherwise, returns a negative error code.)
- */
-int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s)
-{
- size_t total_read = 0;
- size_t one_read;
-
- if (NULL != s->page) {
- fileio_read(s->fileio, s->page_size, s->page, &one_read);
- if (one_read < s->page_size)
- memset(s->page + one_read, 0xff, s->page_size - one_read);
- total_read += one_read;
- }
-
- if (s->oob_format & NAND_OOB_SW_ECC) {
- uint8_t ecc[3];
- memset(s->oob, 0xff, s->oob_size);
- for (uint32_t i = 0, j = 0; i < s->page_size; i += 256) {
- nand_calculate_ecc(nand, s->page + i, ecc);
- s->oob[s->eccpos[j++]] = ecc[0];
- s->oob[s->eccpos[j++]] = ecc[1];
- s->oob[s->eccpos[j++]] = ecc[2];
- }
- } else if (s->oob_format & NAND_OOB_SW_ECC_KW) {
- /*
- * In this case eccpos is not used as
- * the ECC data is always stored contigously
- * at the end of the OOB area. It consists
- * of 10 bytes per 512-byte data block.
- */
- uint8_t *ecc = s->oob + s->oob_size - s->page_size / 512 * 10;
- memset(s->oob, 0xff, s->oob_size);
- for (uint32_t i = 0; i < s->page_size; i += 512) {
- nand_calculate_ecc_kw(nand, s->page + i, ecc);
- ecc += 10;
- }
- } else if (NULL != s->oob) {
- fileio_read(s->fileio, s->oob_size, s->oob, &one_read);
- if (one_read < s->oob_size)
- memset(s->oob + one_read, 0xff, s->oob_size - one_read);
- total_read += one_read;
- }
- return total_read;
-}
diff --git a/src/flash/nand/fileio.h b/src/flash/nand/fileio.h
deleted file mode 100644
index af6c766..0000000
--- a/src/flash/nand/fileio.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_FILEIO_H
-#define OPENOCD_FLASH_NAND_FILEIO_H
-
-#include <helper/time_support.h>
-#include <helper/fileio.h>
-
-struct nand_fileio_state {
- uint32_t address;
- uint32_t size;
-
- uint8_t *page;
- uint32_t page_size;
-
- enum oob_formats oob_format;
- uint8_t *oob;
- uint32_t oob_size;
-
- const int *eccpos;
-
- bool file_opened;
- struct fileio *fileio;
-
- struct duration bench;
-};
-
-void nand_fileio_init(struct nand_fileio_state *state);
-int nand_fileio_start(struct command_context *cmd_ctx,
- struct nand_device *nand, const char *filename, int filemode,
- struct nand_fileio_state *state);
-int nand_fileio_cleanup(struct nand_fileio_state *state);
-int nand_fileio_finish(struct nand_fileio_state *state);
-
-COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state,
- struct nand_device **dev, enum fileio_access filemode,
- bool need_size, bool sw_ecc);
-
-int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s);
-
-#endif /* OPENOCD_FLASH_NAND_FILEIO_H */
diff --git a/src/flash/nand/imp.h b/src/flash/nand/imp.h
deleted file mode 100644
index c8a4ed9..0000000
--- a/src/flash/nand/imp.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_IMP_H
-#define OPENOCD_FLASH_NAND_IMP_H
-
-#include "core.h"
-#include "driver.h"
-
-void nand_device_add(struct nand_device *c);
-
-int nand_write_page(struct nand_device *nand,
- uint32_t page, uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size);
-
-int nand_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size);
-
-int nand_probe(struct nand_device *nand);
-int nand_erase(struct nand_device *nand, int first_block, int last_block);
-int nand_build_bbt(struct nand_device *nand, int first, int last);
-
-#endif /* OPENOCD_FLASH_NAND_IMP_H */
diff --git a/src/flash/nand/lpc3180.c b/src/flash/nand/lpc3180.c
deleted file mode 100644
index d15fdce..0000000
--- a/src/flash/nand/lpc3180.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- *
- * Copyright (C) 2010 richard vegh <vegh.ricsi@gmail.com> *
- * Copyright (C) 2010 Oyvind Harboe <oyvind.harboe@zylin.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "lpc3180.h"
-#include <target/target.h>
-
-static int lpc3180_reset(struct nand_device *nand);
-static int lpc3180_controller_ready(struct nand_device *nand, int timeout);
-static int lpc3180_tc_ready(struct nand_device *nand, int timeout);
-
-#define ECC_OFFS 0x120
-#define SPARE_OFFS 0x140
-#define DATA_OFFS 0x200
-
-/* nand device lpc3180 <target#> <oscillator_frequency>
- */
-NAND_DEVICE_COMMAND_HANDLER(lpc3180_nand_device_command)
-{
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t osc_freq;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
-
- struct lpc3180_nand_controller *lpc3180_info;
- lpc3180_info = malloc(sizeof(struct lpc3180_nand_controller));
- nand->controller_priv = lpc3180_info;
-
- lpc3180_info->osc_freq = osc_freq;
-
- if ((lpc3180_info->osc_freq < 1000) || (lpc3180_info->osc_freq > 20000))
- LOG_WARNING(
- "LPC3180 oscillator frequency should be between 1000 and 20000 kHz, was %i",
- lpc3180_info->osc_freq);
- lpc3180_info->selected_controller = LPC3180_NO_CONTROLLER;
- lpc3180_info->sw_write_protection = 0;
- lpc3180_info->sw_wp_lower_bound = 0x0;
- lpc3180_info->sw_wp_upper_bound = 0x0;
-
- return ERROR_OK;
-}
-
-static int lpc3180_pll(int fclkin, uint32_t pll_ctrl)
-{
- int bypass = (pll_ctrl & 0x8000) >> 15;
- int direct = (pll_ctrl & 0x4000) >> 14;
- int feedback = (pll_ctrl & 0x2000) >> 13;
- int p = (1 << ((pll_ctrl & 0x1800) >> 11) * 2);
- int n = ((pll_ctrl & 0x0600) >> 9) + 1;
- int m = ((pll_ctrl & 0x01fe) >> 1) + 1;
- int lock = (pll_ctrl & 0x1);
-
- if (!lock)
- LOG_WARNING("PLL is not locked");
-
- if (!bypass && direct) /* direct mode */
- return (m * fclkin) / n;
-
- if (bypass && !direct) /* bypass mode */
- return fclkin / (2 * p);
-
- if (bypass & direct) /* direct bypass mode */
- return fclkin;
-
- if (feedback) /* integer mode */
- return m * (fclkin / n);
- else /* non-integer mode */
- return (m / (2 * p)) * (fclkin / n);
-}
-
-static float lpc3180_cycle_time(struct nand_device *nand)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl;
- int sysclk;
- int hclk;
- int hclk_pll;
- float cycle;
-
- /* calculate timings */
-
- /* determine current SYSCLK (13'MHz or main oscillator) */
- target_read_u32(target, 0x40004050, &sysclk_ctrl);
-
- if ((sysclk_ctrl & 1) == 0)
- sysclk = lpc3180_info->osc_freq;
- else
- sysclk = 13000;
-
- /* determine selected HCLK source */
- target_read_u32(target, 0x40004044, &pwr_ctrl);
-
- if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
- hclk = sysclk;
- else {
- target_read_u32(target, 0x40004058, &hclkpll_ctrl);
- hclk_pll = lpc3180_pll(sysclk, hclkpll_ctrl);
-
- target_read_u32(target, 0x40004040, &hclkdiv_ctrl);
-
- if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
- hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
- else /* HCLK uses HCLK_PLL */
- hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
- }
-
- LOG_DEBUG("LPC3180 HCLK currently clocked at %i kHz", hclk);
-
- cycle = (1.0 / hclk) * 1000000.0;
-
- return cycle;
-}
-
-static int lpc3180_init(struct nand_device *nand)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
- int bus_width = nand->bus_width ? : 8;
- int address_cycles = nand->address_cycles ? : 3;
- int page_size = nand->page_size ? : 512;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* sanitize arguments */
- if ((bus_width != 8) && (bus_width != 16)) {
- LOG_ERROR("LPC3180 only supports 8 or 16 bit bus width, not %i", bus_width);
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- /* The LPC3180 only brings out 8 bit NAND data bus, but the controller
- * would support 16 bit, too, so we just warn about this for now
- */
- if (bus_width == 16)
- LOG_WARNING("LPC3180 only supports 8 bit bus width");
-
- /* inform calling code about selected bus width */
- nand->bus_width = bus_width;
-
- if ((address_cycles != 3) && (address_cycles != 4)) {
- LOG_ERROR("LPC3180 only supports 3 or 4 address cycles, not %i", address_cycles);
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- if ((page_size != 512) && (page_size != 2048)) {
- LOG_ERROR("LPC3180 only supports 512 or 2048 byte pages, not %i", page_size);
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- /* select MLC controller if none is currently selected */
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_DEBUG("no LPC3180 NAND flash controller selected, using default 'mlc'");
- lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- uint32_t mlc_icr_value = 0x0;
- float cycle;
- int twp, twh, trp, treh, trhz, trbwb, tcea;
-
- /* FLASHCLK_CTRL = 0x22 (enable clock for MLC flash controller) */
- target_write_u32(target, 0x400040c8, 0x22);
-
- /* MLC_CEH = 0x0 (Force nCE assert) */
- target_write_u32(target, 0x200b804c, 0x0);
-
- /* MLC_LOCK = 0xa25e (unlock protected registers) */
- target_write_u32(target, 0x200b8044, 0xa25e);
-
- /* MLC_ICR = configuration */
- if (lpc3180_info->sw_write_protection)
- mlc_icr_value |= 0x8;
- if (page_size == 2048)
- mlc_icr_value |= 0x4;
- if (address_cycles == 4)
- mlc_icr_value |= 0x2;
- if (bus_width == 16)
- mlc_icr_value |= 0x1;
- target_write_u32(target, 0x200b8030, mlc_icr_value);
-
- /* calculate NAND controller timings */
- cycle = lpc3180_cycle_time(nand);
-
- twp = ((40 / cycle) + 1);
- twh = ((20 / cycle) + 1);
- trp = ((30 / cycle) + 1);
- treh = ((15 / cycle) + 1);
- trhz = ((30 / cycle) + 1);
- trbwb = ((100 / cycle) + 1);
- tcea = ((45 / cycle) + 1);
-
- /* MLC_LOCK = 0xa25e (unlock protected registers) */
- target_write_u32(target, 0x200b8044, 0xa25e);
-
- /* MLC_TIME_REG */
- target_write_u32(target, 0x200b8034, (twp & 0xf) | ((twh & 0xf) << 4) |
- ((trp & 0xf) << 8) | ((treh & 0xf) << 12) | ((trhz & 0x7) << 16) |
- ((trbwb & 0x1f) << 19) | ((tcea & 0x3) << 24));
-
- lpc3180_reset(nand);
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- float cycle;
- int r_setup, r_hold, r_width, r_rdy;
- int w_setup, w_hold, w_width, w_rdy;
-
- /* FLASHCLK_CTRL = 0x05 (enable clock for SLC flash controller) */
- target_write_u32(target, 0x400040c8, 0x05);
-
- /* after reset set other registers of SLC so reset calling is here at the begining*/
- lpc3180_reset(nand);
-
- /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst enabled,
- *DMA read from SLC, WIDTH = bus_width) */
- target_write_u32(target, 0x20020014, 0x3e | (bus_width == 16) ? 1 : 0);
-
- /* SLC_IEN = 3 (INT_RDY_EN = 1) ,(INT_TC_STAT = 1) */
- target_write_u32(target, 0x20020020, 0x03);
-
- /* DMA configuration
- * DMACLK_CTRL = 0x01 (enable clock for DMA controller) */
- target_write_u32(target, 0x400040e8, 0x01);
- /* DMACConfig = DMA enabled*/
- target_write_u32(target, 0x31000030, 0x01);
-
-
- /* calculate NAND controller timings */
- cycle = lpc3180_cycle_time(nand);
-
- r_setup = w_setup = 0;
- r_hold = w_hold = 10 / cycle;
- r_width = 30 / cycle;
- w_width = 40 / cycle;
- r_rdy = w_rdy = 100 / cycle;
-
- /* SLC_TAC: SLC timing arcs register */
- target_write_u32(target, 0x2002002c, (r_setup & 0xf) | ((r_hold & 0xf) << 4) |
- ((r_width & 0xf) << 8) | ((r_rdy & 0xf) << 12) | ((w_setup & 0xf) << 16) |
- ((w_hold & 0xf) << 20) | ((w_width & 0xf) << 24) | ((w_rdy & 0xf) << 28));
-
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_reset(struct nand_device *nand)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- /* MLC_CMD = 0xff (reset controller and NAND device) */
- target_write_u32(target, 0x200b8000, 0xff);
-
- if (!lpc3180_controller_ready(nand, 100)) {
- LOG_ERROR("LPC3180 NAND controller timed out after reset");
- return ERROR_NAND_OPERATION_TIMEOUT;
- }
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- /* SLC_CTRL = 0x6 (ECC_CLEAR, SW_RESET) */
- target_write_u32(target, 0x20020010, 0x6);
-
- if (!lpc3180_controller_ready(nand, 100)) {
- LOG_ERROR("LPC3180 NAND controller timed out after reset");
- return ERROR_NAND_OPERATION_TIMEOUT;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_command(struct nand_device *nand, uint8_t command)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- /* MLC_CMD = command */
- target_write_u32(target, 0x200b8000, command);
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- /* SLC_CMD = command */
- target_write_u32(target, 0x20020008, command);
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_address(struct nand_device *nand, uint8_t address)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- /* MLC_ADDR = address */
- target_write_u32(target, 0x200b8004, address);
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- /* SLC_ADDR = address */
- target_write_u32(target, 0x20020004, address);
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_write_data(struct nand_device *nand, uint16_t data)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- /* MLC_DATA = data */
- target_write_u32(target, 0x200b0000, data);
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- /* SLC_DATA = data */
- target_write_u32(target, 0x20020000, data);
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_read_data(struct nand_device *nand, void *data)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- /* data = MLC_DATA, use sized access */
- if (nand->bus_width == 8) {
- uint8_t *data8 = data;
- target_read_u8(target, 0x200b0000, data8);
- } else if (nand->bus_width == 16) {
- uint16_t *data16 = data;
- target_read_u16(target, 0x200b0000, data16);
- } else {
- LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
- return ERROR_NAND_OPERATION_FAILED;
- }
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- uint32_t data32;
-
- /* data = SLC_DATA, must use 32-bit access */
- target_read_u32(target, 0x20020000, &data32);
-
- if (nand->bus_width == 8) {
- uint8_t *data8 = data;
- *data8 = data32 & 0xff;
- } else if (nand->bus_width == 16) {
- uint16_t *data16 = data;
- *data16 = data32 & 0xffff;
- } else {
- LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_write_page(struct nand_device *nand,
- uint32_t page,
- uint8_t *data,
- uint32_t data_size,
- uint8_t *oob,
- uint32_t oob_size)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
- uint8_t status;
- uint8_t *page_buffer;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- uint8_t *oob_buffer;
- int quarter, num_quarters;
-
- if (!data && oob) {
- LOG_ERROR("LPC3180 MLC controller can't write OOB data only");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- if (oob && (oob_size > 24)) {
- LOG_ERROR("LPC3180 MLC controller can't write more "
- "than 6 bytes for each quarter's OOB data");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- if (data_size > (uint32_t)nand->page_size) {
- LOG_ERROR("data size exceeds page size");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- /* MLC_CMD = sequential input */
- target_write_u32(target, 0x200b8000, NAND_CMD_SEQIN);
-
- page_buffer = malloc(512);
- oob_buffer = malloc(6);
-
- if (nand->page_size == 512) {
- /* MLC_ADDR = 0x0 (one column cycle) */
- target_write_u32(target, 0x200b8004, 0x0);
-
- /* MLC_ADDR = row */
- target_write_u32(target, 0x200b8004, page & 0xff);
- target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
-
- if (nand->address_cycles == 4)
- target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
- } else {
- /* MLC_ADDR = 0x0 (two column cycles) */
- target_write_u32(target, 0x200b8004, 0x0);
- target_write_u32(target, 0x200b8004, 0x0);
-
- /* MLC_ADDR = row */
- target_write_u32(target, 0x200b8004, page & 0xff);
- target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
- }
-
- /* when using the MLC controller, we have to treat a large page device
- * as being made out of four quarters, each the size of a small page device
- */
- num_quarters = (nand->page_size == 2048) ? 4 : 1;
-
- for (quarter = 0; quarter < num_quarters; quarter++) {
- int thisrun_data_size = (data_size > 512) ? 512 : data_size;
- int thisrun_oob_size = (oob_size > 6) ? 6 : oob_size;
-
- memset(page_buffer, 0xff, 512);
- if (data) {
- memcpy(page_buffer, data, thisrun_data_size);
- data_size -= thisrun_data_size;
- data += thisrun_data_size;
- }
-
- memset(oob_buffer, 0xff, 6);
- if (oob) {
- memcpy(oob_buffer, oob, thisrun_oob_size);
- oob_size -= thisrun_oob_size;
- oob += thisrun_oob_size;
- }
-
- /* write MLC_ECC_ENC_REG to start encode cycle */
- target_write_u32(target, 0x200b8008, 0x0);
-
- target_write_memory(target, 0x200a8000,
- 4, 128, page_buffer);
- target_write_memory(target, 0x200a8000,
- 1, 6, oob_buffer);
-
- /* write MLC_ECC_AUTO_ENC_REG to start auto encode */
- target_write_u32(target, 0x200b8010, 0x0);
-
- if (!lpc3180_controller_ready(nand, 1000)) {
- LOG_ERROR("timeout while waiting for completion of auto encode cycle");
- free(page_buffer);
- free(oob_buffer);
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- /* MLC_CMD = auto program command */
- target_write_u32(target, 0x200b8000, NAND_CMD_PAGEPROG);
-
- retval = nand_read_status(nand, &status);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read status");
- free(page_buffer);
- free(oob_buffer);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & NAND_STATUS_FAIL) {
- LOG_ERROR("write operation didn't pass, status: 0x%2.2x", status);
- free(page_buffer);
- free(oob_buffer);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- free(page_buffer);
- free(oob_buffer);
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
-
- /**********************************************************************
- * Write both SLC NAND flash page main area and spare area.
- * Small page -
- * ------------------------------------------
- * | 512 bytes main | 16 bytes spare |
- * ------------------------------------------
- * Large page -
- * ------------------------------------------
- * | 2048 bytes main | 64 bytes spare |
- * ------------------------------------------
- * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
- * data is written to the 3rd word of the spare area. The ECC
- * generated for the 2nd 256-byte data is written to the 4th word
- * of the spare area. The ECC generated for the 3rd 256-byte data is
- * written to the 7th word of the spare area. The ECC generated
- * for the 4th 256-byte data is written to the 8th word of the
- * spare area and so on.
- *
- **********************************************************************/
-
- int i = 0, target_mem_base;
- uint8_t *ecc_flash_buffer;
- struct working_area *pworking_area;
-
- if (lpc3180_info->is_bulk) {
-
- if (!data && oob) {
- /*if oob only mode is active original method is used as SLC
- *controller hangs during DMA interworking. Anyway the code supports
- *the oob only mode below. */
- return nand_write_page_raw(nand,
- page,
- data,
- data_size,
- oob,
- oob_size);
- }
- retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
- if (ERROR_OK != retval)
- return retval;
-
- /* allocate a working area */
- if (target->working_area_size < (uint32_t) nand->page_size + 0x200) {
- LOG_ERROR("Reserve at least 0x%x physical target working area",
- nand->page_size + 0x200);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target->working_area_phys%4) {
- LOG_ERROR(
- "Reserve the physical target working area at word boundary");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target_alloc_working_area(target, target->working_area_size,
- &pworking_area) != ERROR_OK) {
- LOG_ERROR("no working area specified, can't read LPC internal flash");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- target_mem_base = target->working_area_phys;
-
- if (nand->page_size == 2048)
- page_buffer = malloc(2048);
- else
- page_buffer = malloc(512);
-
- ecc_flash_buffer = malloc(64);
-
- /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst
- *enabled, DMA write to SLC, WIDTH = bus_width) */
- target_write_u32(target, 0x20020014, 0x3c);
-
- if (data && !oob) {
- /* set DMA LLI-s in target memory and in DMA*/
- for (i = 0; i < nand->page_size/0x100; i++) {
-
- int tmp;
- /* -------LLI for 256 byte block---------
- * DMACC0SrcAddr = SRAM */
- target_write_u32(target,
- target_mem_base+0+i*32,
- target_mem_base+DATA_OFFS+i*256);
- if (i == 0)
- target_write_u32(target,
- 0x31000100,
- target_mem_base+DATA_OFFS);
- /* DMACCxDestAddr = SLC_DMA_DATA */
- target_write_u32(target, target_mem_base+4+i*32, 0x20020038);
- if (i == 0)
- target_write_u32(target, 0x31000104, 0x20020038);
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
- target_write_u32(target, target_mem_base+8+i*32, tmp);
- if (i == 0)
- target_write_u32(target, 0x31000108, tmp);
- /* DMACCxControl = TransferSize =64, Source burst size =16,
- * Destination burst size = 16, Source transfer width = 32 bit,
- * Destination transfer width = 32 bit, Source AHB master select = M0,
- * Destination AHB master select = M0, Source increment = 1,
- * Destination increment = 0, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,
- target_mem_base+12+i*32,
- 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 |
- 0<<27 | 0<<31);
- if (i == 0)
- target_write_u32(target,
- 0x3100010c,
- 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 |
- 0<<27 | 0<<31);
-
- /* -------LLI for 3 byte ECC---------
- * DMACC0SrcAddr = SLC_ECC*/
- target_write_u32(target, target_mem_base+16+i*32, 0x20020034);
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target,
- target_mem_base+20+i*32,
- target_mem_base+SPARE_OFFS+8+16*(i>>1)+(i%2)*4);
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
- target_write_u32(target, target_mem_base+24+i*32, tmp);
- /* DMACCxControl = TransferSize =1, Source burst size =4,
- * Destination burst size = 4, Source transfer width = 32 bit,
- * Destination transfer width = 32 bit, Source AHB master select = M0,
- * Destination AHB master select = M0, Source increment = 0,
- * Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,
- target_mem_base+28+i*32,
- 0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
- 31);
- }
- } else if (data && oob) {
- /* -------LLI for 512 or 2048 bytes page---------
- * DMACC0SrcAddr = SRAM */
- target_write_u32(target, target_mem_base, target_mem_base+DATA_OFFS);
- target_write_u32(target, 0x31000100, target_mem_base+DATA_OFFS);
- /* DMACCxDestAddr = SLC_DMA_DATA */
- target_write_u32(target, target_mem_base+4, 0x20020038);
- target_write_u32(target, 0x31000104, 0x20020038);
- /* DMACCxLLI = next element */
- target_write_u32(target,
- target_mem_base+8,
- (target_mem_base+32)&0xfffffffc);
- target_write_u32(target, 0x31000108,
- (target_mem_base+32)&0xfffffffc);
- /* DMACCxControl = TransferSize =512 or 128, Source burst size =16,
- * Destination burst size = 16, Source transfer width = 32 bit,
- * Destination transfer width = 32 bit, Source AHB master select = M0,
- * Destination AHB master select = M0, Source increment = 1,
- * Destination increment = 0, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,
- target_mem_base+12,
- (nand->page_size ==
- 2048 ? 512 : 128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 |
- 1<<26 | 0<<27 | 0<<31);
- target_write_u32(target,
- 0x3100010c,
- (nand->page_size ==
- 2048 ? 512 : 128) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 |
- 1<<26 | 0<<27 | 0<<31);
- i = 1;
- } else if (!data && oob)
- i = 0;
-
- /* -------LLI for spare area---------
- * DMACC0SrcAddr = SRAM*/
- target_write_u32(target, target_mem_base+0+i*32, target_mem_base+SPARE_OFFS);
- if (i == 0)
- target_write_u32(target, 0x31000100, target_mem_base+SPARE_OFFS);
- /* DMACCxDestAddr = SLC_DMA_DATA */
- target_write_u32(target, target_mem_base+4+i*32, 0x20020038);
- if (i == 0)
- target_write_u32(target, 0x31000104, 0x20020038);
- /* DMACCxLLI = next element = NULL */
- target_write_u32(target, target_mem_base+8+i*32, 0);
- if (i == 0)
- target_write_u32(target, 0x31000108, 0);
- /* DMACCxControl = TransferSize =16 for large page or 4 for small page,
- * Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
- * Destination transfer width = 32 bit, Source AHB master select = M0,
- * Destination AHB master select = M0, Source increment = 1,
- * Destination increment = 0, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,
- target_mem_base+12+i*32,
- (nand->page_size ==
- 2048 ? 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 1<<26 |
- 0<<27 | 0<<31);
- if (i == 0)
- target_write_u32(target, 0x3100010c,
- (nand->page_size == 2048 ?
- 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 |
- 0<<25 | 1<<26 | 0<<27 | 0<<31);
-
- memset(ecc_flash_buffer, 0xff, 64);
- if (oob)
- memcpy(ecc_flash_buffer, oob, oob_size);
- target_write_memory(target,
- target_mem_base+SPARE_OFFS,
- 4,
- 16,
- ecc_flash_buffer);
-
- if (data) {
- memset(page_buffer, 0xff, nand->page_size == 2048 ? 2048 : 512);
- memcpy(page_buffer, data, data_size);
- target_write_memory(target,
- target_mem_base+DATA_OFFS,
- 4,
- nand->page_size == 2048 ? 512 : 128,
- page_buffer);
- }
-
- free(page_buffer);
- free(ecc_flash_buffer);
-
- /* Enable DMA after channel set up !
- LLI only works when DMA is the flow controller!
- */
- /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC),
- *FlowCntrl = 2 (Pher -> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
- target_write_u32(target,
- 0x31000110,
- 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
-
- /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
- target_write_u32(target, 0x20020010, 0x3);
-
- /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
- target_write_u32(target, 0x20020028, 2);
-
- /* SLC_TC */
- if (!data && oob)
- target_write_u32(target, 0x20020030,
- (nand->page_size == 2048 ? 0x10 : 0x04));
- else
- target_write_u32(target, 0x20020030,
- (nand->page_size == 2048 ? 0x840 : 0x210));
-
- nand_write_finish(nand);
-
- if (!lpc3180_tc_ready(nand, 1000)) {
- LOG_ERROR("timeout while waiting for completion of DMA");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_free_working_area(target, pworking_area);
-
- LOG_INFO("Page = 0x%" PRIx32 " was written.", page);
-
- } else
- return nand_write_page_raw(nand, page, data, data_size, oob, oob_size);
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_read_page(struct nand_device *nand,
- uint32_t page,
- uint8_t *data,
- uint32_t data_size,
- uint8_t *oob,
- uint32_t oob_size)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
- uint8_t *page_buffer;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC3180 NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- uint8_t *oob_buffer;
- uint32_t page_bytes_done = 0;
- uint32_t oob_bytes_done = 0;
- uint32_t mlc_isr;
-
-#if 0
- if (oob && (oob_size > 6)) {
- LOG_ERROR("LPC3180 MLC controller can't read more than 6 bytes of OOB data");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-#endif
-
- if (data_size > (uint32_t)nand->page_size) {
- LOG_ERROR("data size exceeds page size");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- if (nand->page_size == 2048) {
- page_buffer = malloc(2048);
- oob_buffer = malloc(64);
- } else {
- page_buffer = malloc(512);
- oob_buffer = malloc(16);
- }
-
- if (!data && oob) {
- /* MLC_CMD = Read OOB
- * we can use the READOOB command on both small and large page devices,
- * as the controller translates the 0x50 command to a 0x0 with appropriate
- * positioning of the serial buffer read pointer
- */
- target_write_u32(target, 0x200b8000, NAND_CMD_READOOB);
- } else {
- /* MLC_CMD = Read0 */
- target_write_u32(target, 0x200b8000, NAND_CMD_READ0);
- }
-
- if (nand->page_size == 512) {
- /* small page device
- * MLC_ADDR = 0x0 (one column cycle) */
- target_write_u32(target, 0x200b8004, 0x0);
-
- /* MLC_ADDR = row */
- target_write_u32(target, 0x200b8004, page & 0xff);
- target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
-
- if (nand->address_cycles == 4)
- target_write_u32(target, 0x200b8004, (page >> 16) & 0xff);
- } else {
- /* large page device
- * MLC_ADDR = 0x0 (two column cycles) */
- target_write_u32(target, 0x200b8004, 0x0);
- target_write_u32(target, 0x200b8004, 0x0);
-
- /* MLC_ADDR = row */
- target_write_u32(target, 0x200b8004, page & 0xff);
- target_write_u32(target, 0x200b8004, (page >> 8) & 0xff);
-
- /* MLC_CMD = Read Start */
- target_write_u32(target, 0x200b8000, NAND_CMD_READSTART);
- }
-
- while (page_bytes_done < (uint32_t)nand->page_size) {
- /* MLC_ECC_AUTO_DEC_REG = dummy */
- target_write_u32(target, 0x200b8014, 0xaa55aa55);
-
- if (!lpc3180_controller_ready(nand, 1000)) {
- LOG_ERROR("timeout while waiting for completion of auto decode cycle");
- free(page_buffer);
- free(oob_buffer);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_read_u32(target, 0x200b8048, &mlc_isr);
-
- if (mlc_isr & 0x8) {
- if (mlc_isr & 0x40) {
- LOG_ERROR("uncorrectable error detected: 0x%2.2x",
- (unsigned)mlc_isr);
- free(page_buffer);
- free(oob_buffer);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_WARNING("%i symbol error detected and corrected",
- ((int)(((mlc_isr & 0x30) >> 4) + 1)));
- }
-
- if (data)
- target_read_memory(target,
- 0x200a8000,
- 4,
- 128,
- page_buffer + page_bytes_done);
-
- if (oob)
- target_read_memory(target,
- 0x200a8000,
- 4,
- 4,
- oob_buffer + oob_bytes_done);
-
- page_bytes_done += 512;
- oob_bytes_done += 16;
- }
-
- if (data)
- memcpy(data, page_buffer, data_size);
-
- if (oob)
- memcpy(oob, oob_buffer, oob_size);
-
- free(page_buffer);
- free(oob_buffer);
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
-
- /**********************************************************************
- * Read both SLC NAND flash page main area and spare area.
- * Small page -
- * ------------------------------------------
- * | 512 bytes main | 16 bytes spare |
- * ------------------------------------------
- * Large page -
- * ------------------------------------------
- * | 2048 bytes main | 64 bytes spare |
- * ------------------------------------------
- * If DMA & ECC enabled, then the ECC generated for the 1st 256-byte
- * data is compared with the 3rd word of the spare area. The ECC
- * generated for the 2nd 256-byte data is compared with the 4th word
- * of the spare area. The ECC generated for the 3rd 256-byte data is
- * compared with the 7th word of the spare area. The ECC generated
- * for the 4th 256-byte data is compared with the 8th word of the
- * spare area and so on.
- *
- **********************************************************************/
-
- int retval, i, target_mem_base;
- uint8_t *ecc_hw_buffer;
- uint8_t *ecc_flash_buffer;
- struct working_area *pworking_area;
-
- if (lpc3180_info->is_bulk) {
-
- /* read always the data and also oob areas*/
-
- retval = nand_page_command(nand, page, NAND_CMD_READ0, 0);
- if (ERROR_OK != retval)
- return retval;
-
- /* allocate a working area */
- if (target->working_area_size < (uint32_t) nand->page_size + 0x200) {
- LOG_ERROR("Reserve at least 0x%x physical target working area",
- nand->page_size + 0x200);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target->working_area_phys%4) {
- LOG_ERROR(
- "Reserve the physical target working area at word boundary");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (target_alloc_working_area(target, target->working_area_size,
- &pworking_area) != ERROR_OK) {
- LOG_ERROR("no working area specified, can't read LPC internal flash");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- target_mem_base = target->working_area_phys;
-
- if (nand->page_size == 2048)
- page_buffer = malloc(2048);
- else
- page_buffer = malloc(512);
-
- ecc_hw_buffer = malloc(32);
- ecc_flash_buffer = malloc(64);
-
- /* SLC_CFG = 0x (Force nCE assert, DMA ECC enabled, ECC enabled, DMA burst
- *enabled, DMA read from SLC, WIDTH = bus_width) */
- target_write_u32(target, 0x20020014, 0x3e);
-
- /* set DMA LLI-s in target memory and in DMA*/
- for (i = 0; i < nand->page_size/0x100; i++) {
- int tmp;
- /* -------LLI for 256 byte block---------
- * DMACC0SrcAddr = SLC_DMA_DATA*/
- target_write_u32(target, target_mem_base+0+i*32, 0x20020038);
- if (i == 0)
- target_write_u32(target, 0x31000100, 0x20020038);
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target,
- target_mem_base+4+i*32,
- target_mem_base+DATA_OFFS+i*256);
- if (i == 0)
- target_write_u32(target,
- 0x31000104,
- target_mem_base+DATA_OFFS);
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(1+i*2)*16)&0xfffffffc;
- target_write_u32(target, target_mem_base+8+i*32, tmp);
- if (i == 0)
- target_write_u32(target, 0x31000108, tmp);
- /* DMACCxControl = TransferSize =64, Source burst size =16,
- * Destination burst size = 16, Source transfer width = 32 bit,
- * Destination transfer width = 32 bit, Source AHB master select = M0,
- * Destination AHB master select = M0, Source increment = 0,
- * Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,
- target_mem_base+12+i*32,
- 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
- 31);
- if (i == 0)
- target_write_u32(target,
- 0x3100010c,
- 0x40 | 3<<12 | 3<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
- 31);
-
- /* -------LLI for 3 byte ECC---------
- * DMACC0SrcAddr = SLC_ECC*/
- target_write_u32(target, target_mem_base+16+i*32, 0x20020034);
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target,
- target_mem_base+20+i*32,
- target_mem_base+ECC_OFFS+i*4);
- /* DMACCxLLI = next element */
- tmp = (target_mem_base+(2+i*2)*16)&0xfffffffc;
- target_write_u32(target, target_mem_base+24+i*32, tmp);
- /* DMACCxControl = TransferSize =1, Source burst size =4,
- * Destination burst size = 4, Source transfer width = 32 bit,
- * Destination transfer width = 32 bit, Source AHB master select = M0,
- * Destination AHB master select = M0, Source increment = 0,
- * Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,
- target_mem_base+28+i*32,
- 0x01 | 1<<12 | 1<<15 | 2<<18 | 2<<21 | 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<
- 31);
- }
-
- /* -------LLI for spare area---------
- * DMACC0SrcAddr = SLC_DMA_DATA*/
- target_write_u32(target, target_mem_base+0+i*32, 0x20020038);
- /* DMACCxDestAddr = SRAM */
- target_write_u32(target, target_mem_base+4+i*32, target_mem_base+SPARE_OFFS);
- /* DMACCxLLI = next element = NULL */
- target_write_u32(target, target_mem_base+8+i*32, 0);
- /* DMACCxControl = TransferSize =16 for large page or 4 for small page,
- * Source burst size =16, Destination burst size = 16, Source transfer width = 32 bit,
- * Destination transfer width = 32 bit, Source AHB master select = M0,
- * Destination AHB master select = M0, Source increment = 0,
- * Destination increment = 1, Terminal count interrupt enable bit = 0*/
- target_write_u32(target,
- target_mem_base + 12 + i * 32,
- (nand->page_size == 2048 ? 0x10 : 0x04) | 3<<12 | 3<<15 | 2<<18 | 2<<21 |
- 0<<24 | 0<<25 | 0<<26 | 1<<27 | 0<<31);
-
- /* Enable DMA after channel set up !
- LLI only works when DMA is the flow controller!
- */
- /* DMACCxConfig= E=1, SrcPeripheral = 1 (SLC), DestPeripheral = 1 (SLC),
- *FlowCntrl = 2 (Pher-> Mem, DMA), IE = 0, ITC = 0, L= 0, H=0*/
- target_write_u32(target,
- 0x31000110,
- 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14 | 0<<15 | 0<<16 | 0<<18);
-
- /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
- target_write_u32(target, 0x20020010, 0x3);
-
- /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
- target_write_u32(target, 0x20020028, 2);
-
- /* SLC_TC */
- target_write_u32(target, 0x20020030,
- (nand->page_size == 2048 ? 0x840 : 0x210));
-
- if (!lpc3180_tc_ready(nand, 1000)) {
- LOG_ERROR("timeout while waiting for completion of DMA");
- free(page_buffer);
- free(ecc_hw_buffer);
- free(ecc_flash_buffer);
- target_free_working_area(target, pworking_area);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (data) {
- target_read_memory(target,
- target_mem_base+DATA_OFFS,
- 4,
- nand->page_size == 2048 ? 512 : 128,
- page_buffer);
- memcpy(data, page_buffer, data_size);
-
- LOG_INFO("Page = 0x%" PRIx32 " was read.", page);
-
- /* check hw generated ECC for each 256 bytes block with the saved
- *ECC in flash spare area*/
- int idx = nand->page_size/0x200;
- target_read_memory(target,
- target_mem_base+SPARE_OFFS,
- 4,
- 16,
- ecc_flash_buffer);
- target_read_memory(target,
- target_mem_base+ECC_OFFS,
- 4,
- 8,
- ecc_hw_buffer);
- for (i = 0; i < idx; i++) {
- if ((0x00ffffff & *(uint32_t *)(void *)(ecc_hw_buffer+i*8)) !=
- (0x00ffffff & *(uint32_t *)(void *)(ecc_flash_buffer+8+i*16)))
- LOG_WARNING(
- "ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,
- i * 2 + 1, page);
- if ((0x00ffffff & *(uint32_t *)(void *)(ecc_hw_buffer+4+i*8)) !=
- (0x00ffffff & *(uint32_t *)(void *)(ecc_flash_buffer+12+i*16)))
- LOG_WARNING(
- "ECC mismatch at 256 bytes size block= %d at page= 0x%" PRIx32,
- i * 2 + 2, page);
- }
- }
-
- if (oob)
- memcpy(oob, ecc_flash_buffer, oob_size);
-
- free(page_buffer);
- free(ecc_hw_buffer);
- free(ecc_flash_buffer);
-
- target_free_working_area(target, pworking_area);
-
- } else
- return nand_read_page_raw(nand, page, data, data_size, oob, oob_size);
- }
-
- return ERROR_OK;
-}
-
-static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_DEBUG("lpc3180_controller_ready count start=%d", timeout);
-
- do {
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- uint8_t status;
-
- /* Read MLC_ISR, wait for controller to become ready */
- target_read_u8(target, 0x200b8048, &status);
-
- if (status & 2) {
- LOG_DEBUG("lpc3180_controller_ready count=%d",
- timeout);
- return 1;
- }
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- uint32_t status;
-
- /* Read SLC_STAT and check READY bit */
- target_read_u32(target, 0x20020018, &status);
-
- if (status & 1) {
- LOG_DEBUG("lpc3180_controller_ready count=%d",
- timeout);
- return 1;
- }
- }
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_DEBUG("lpc3180_nand_ready count start=%d", timeout);
-
- do {
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) {
- uint8_t status = 0x0;
-
- /* Read MLC_ISR, wait for NAND flash device to become ready */
- target_read_u8(target, 0x200b8048, &status);
-
- if (status & 1) {
- LOG_DEBUG("lpc3180_nand_ready count end=%d",
- timeout);
- return 1;
- }
- } else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- uint32_t status = 0x0;
-
- /* Read SLC_STAT and check READY bit */
- target_read_u32(target, 0x20020018, &status);
-
- if (status & 1) {
- LOG_DEBUG("lpc3180_nand_ready count end=%d",
- timeout);
- return 1;
- }
- }
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-static int lpc3180_tc_ready(struct nand_device *nand, int timeout)
-{
- struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC3180 NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_DEBUG("lpc3180_tc_ready count start=%d",
- timeout);
-
- do {
- if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) {
- uint32_t status = 0x0;
- /* Read SLC_INT_STAT and check INT_TC_STAT bit */
- target_read_u32(target, 0x2002001c, &status);
-
- if (status & 2) {
- LOG_DEBUG("lpc3180_tc_ready count=%d",
- timeout);
- return 1;
- }
- }
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-COMMAND_HANDLER(handle_lpc3180_select_command)
-{
- struct lpc3180_nand_controller *lpc3180_info = NULL;
- char *selected[] = {
- "no", "mlc", "slc"
- };
-
- if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned num;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
- struct nand_device *nand = get_nand_device_by_num(num);
- if (!nand) {
- command_print(CMD_CTX, "nand device '#%s' is out of bounds", CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- lpc3180_info = nand->controller_priv;
-
- if (CMD_ARGC >= 2) {
- if (strcmp(CMD_ARGV[1], "mlc") == 0)
- lpc3180_info->selected_controller = LPC3180_MLC_CONTROLLER;
- else if (strcmp(CMD_ARGV[1], "slc") == 0) {
- lpc3180_info->selected_controller = LPC3180_SLC_CONTROLLER;
- if (CMD_ARGC == 3 && strcmp(CMD_ARGV[2], "bulk") == 0)
- lpc3180_info->is_bulk = 1;
- else
- lpc3180_info->is_bulk = 0;
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
- command_print(CMD_CTX, "%s controller selected",
- selected[lpc3180_info->selected_controller]);
- else
- command_print(CMD_CTX,
- lpc3180_info->is_bulk ? "%s controller selected bulk mode is available" :
- "%s controller selected bulk mode is not available",
- selected[lpc3180_info->selected_controller]);
-
- return ERROR_OK;
-}
-
-static const struct command_registration lpc3180_exec_command_handlers[] = {
- {
- .name = "select",
- .handler = handle_lpc3180_select_command,
- .mode = COMMAND_EXEC,
- .help =
- "select MLC or SLC controller (default is MLC), SLC can be set to bulk mode",
- .usage = "bank_id ['mlc'|'slc' ['bulk'] ]",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration lpc3180_command_handler[] = {
- {
- .name = "lpc3180",
- .mode = COMMAND_ANY,
- .help = "LPC3180 NAND flash controller commands",
- .usage = "",
- .chain = lpc3180_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct nand_flash_controller lpc3180_nand_controller = {
- .name = "lpc3180",
- .commands = lpc3180_command_handler,
- .nand_device_command = lpc3180_nand_device_command,
- .init = lpc3180_init,
- .reset = lpc3180_reset,
- .command = lpc3180_command,
- .address = lpc3180_address,
- .write_data = lpc3180_write_data,
- .read_data = lpc3180_read_data,
- .write_page = lpc3180_write_page,
- .read_page = lpc3180_read_page,
- .nand_ready = lpc3180_nand_ready,
-};
diff --git a/src/flash/nand/lpc3180.h b/src/flash/nand/lpc3180.h
deleted file mode 100644
index c02ee5b..0000000
--- a/src/flash/nand/lpc3180.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_LPC3180_H
-#define OPENOCD_FLASH_NAND_LPC3180_H
-
-enum lpc3180_selected_controller {
- LPC3180_NO_CONTROLLER,
- LPC3180_MLC_CONTROLLER,
- LPC3180_SLC_CONTROLLER,
-};
-
-struct lpc3180_nand_controller {
- int osc_freq;
- enum lpc3180_selected_controller selected_controller;
- int is_bulk;
- int sw_write_protection;
- uint32_t sw_wp_lower_bound;
- uint32_t sw_wp_upper_bound;
-};
-
-#endif /* OPENOCD_FLASH_NAND_LPC3180_H */
diff --git a/src/flash/nand/lpc32xx.c b/src/flash/nand/lpc32xx.c
deleted file mode 100644
index 1ed16df..0000000
--- a/src/flash/nand/lpc32xx.c
+++ /dev/null
@@ -1,1821 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2011 Bjarne Steinsbo <bsteinsbo@gmail.com> *
- * Copyright (C) 2010 richard vegh <vegh.ricsi@gmail.com> *
- * Copyright (C) 2010 Oyvind Harboe <oyvind.harboe@zylin.com> *
- * *
- * Based on a combination of the lpc3180 driver and code from *
- * uboot-2009.03-lpc32xx by Kevin Wells. *
- * Any bugs are mine. --BSt *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "lpc32xx.h"
-#include <target/target.h>
-
-static int lpc32xx_reset(struct nand_device *nand);
-static int lpc32xx_controller_ready(struct nand_device *nand, int timeout);
-static int lpc32xx_tc_ready(struct nand_device *nand, int timeout);
-extern int nand_correct_data(struct nand_device *nand, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc);
-
-/* These are offset with the working area in IRAM when using DMA to
- * read/write data to the SLC controller.
- * - DMA descriptors will be put at start of working area,
- * - Hardware generated ECC will be stored at ECC_OFFS
- * - OOB wil be read/written from/to SPARE_OFFS
- * - Actual page data will be read from/to DATA_OFFS
- * There are unused holes between the used areas.
- */
-#define ECC_OFFS 0x120
-#define SPARE_OFFS 0x140
-#define DATA_OFFS 0x200
-
-static const int sp_ooblayout[] = {
- 10, 11, 12, 13, 14, 15
-};
-static const int lp_ooblayout[] = {
- 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63
-};
-
-typedef struct {
- volatile uint32_t dma_src;
- volatile uint32_t dma_dest;
- volatile uint32_t next_lli;
- volatile uint32_t next_ctrl;
-} dmac_ll_t;
-
-static dmac_ll_t dmalist[(2048/256) * 2 + 1];
-
-/* nand device lpc32xx <target#> <oscillator_frequency>
- */
-NAND_DEVICE_COMMAND_HANDLER(lpc32xx_nand_device_command)
-{
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t osc_freq;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], osc_freq);
-
- struct lpc32xx_nand_controller *lpc32xx_info;
- lpc32xx_info = malloc(sizeof(struct lpc32xx_nand_controller));
- nand->controller_priv = lpc32xx_info;
-
- lpc32xx_info->osc_freq = osc_freq;
-
- if ((lpc32xx_info->osc_freq < 1000) || (lpc32xx_info->osc_freq > 20000))
- LOG_WARNING("LPC32xx oscillator frequency should be between "
- "1000 and 20000 kHz, was %i",
- lpc32xx_info->osc_freq);
-
- lpc32xx_info->selected_controller = LPC32xx_NO_CONTROLLER;
- lpc32xx_info->sw_write_protection = 0;
- lpc32xx_info->sw_wp_lower_bound = 0x0;
- lpc32xx_info->sw_wp_upper_bound = 0x0;
-
- return ERROR_OK;
-}
-
-static int lpc32xx_pll(int fclkin, uint32_t pll_ctrl)
-{
- int bypass = (pll_ctrl & 0x8000) >> 15;
- int direct = (pll_ctrl & 0x4000) >> 14;
- int feedback = (pll_ctrl & 0x2000) >> 13;
- int p = (1 << ((pll_ctrl & 0x1800) >> 11) * 2);
- int n = ((pll_ctrl & 0x0600) >> 9) + 1;
- int m = ((pll_ctrl & 0x01fe) >> 1) + 1;
- int lock = (pll_ctrl & 0x1);
-
- if (!lock)
- LOG_WARNING("PLL is not locked");
-
- if (!bypass && direct) /* direct mode */
- return (m * fclkin) / n;
-
- if (bypass && !direct) /* bypass mode */
- return fclkin / (2 * p);
-
- if (bypass & direct) /* direct bypass mode */
- return fclkin;
-
- if (feedback) /* integer mode */
- return m * (fclkin / n);
- else /* non-integer mode */
- return (m / (2 * p)) * (fclkin / n);
-}
-
-static float lpc32xx_cycle_time(struct nand_device *nand)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t sysclk_ctrl, pwr_ctrl, hclkdiv_ctrl, hclkpll_ctrl;
- int sysclk;
- int hclk;
- int hclk_pll;
- float cycle;
- int retval;
-
- /* calculate timings */
-
- /* determine current SYSCLK (13'MHz or main oscillator) */
- retval = target_read_u32(target, 0x40004050, &sysclk_ctrl);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read SYSCLK_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if ((sysclk_ctrl & 1) == 0)
- sysclk = lpc32xx_info->osc_freq;
- else
- sysclk = 13000;
-
- /* determine selected HCLK source */
- retval = target_read_u32(target, 0x40004044, &pwr_ctrl);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read HCLK_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if ((pwr_ctrl & (1 << 2)) == 0) /* DIRECT RUN mode */
- hclk = sysclk;
- else {
- retval = target_read_u32(target, 0x40004058, &hclkpll_ctrl);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read HCLKPLL_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
- hclk_pll = lpc32xx_pll(sysclk, hclkpll_ctrl);
-
- retval = target_read_u32(target, 0x40004040, &hclkdiv_ctrl);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read CLKDIV_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (pwr_ctrl & (1 << 10)) /* ARM_CLK and HCLK use PERIPH_CLK */
- hclk = hclk_pll / (((hclkdiv_ctrl & 0x7c) >> 2) + 1);
- else /* HCLK uses HCLK_PLL */
- hclk = hclk_pll / (1 << (hclkdiv_ctrl & 0x3));
- }
-
- LOG_DEBUG("LPC32xx HCLK currently clocked at %i kHz", hclk);
-
- cycle = (1.0 / hclk) * 1000000.0;
-
- return cycle;
-}
-
-static int lpc32xx_init(struct nand_device *nand)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int bus_width = nand->bus_width ? : 8;
- int address_cycles = nand->address_cycles ? : 3;
- int page_size = nand->page_size ? : 512;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* sanitize arguments */
- if (bus_width != 8) {
- LOG_ERROR("LPC32xx doesn't support %i", bus_width);
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- /* inform calling code about selected bus width */
- nand->bus_width = bus_width;
-
- if ((address_cycles < 3) || (address_cycles > 5)) {
- LOG_ERROR("LPC32xx driver doesn't support %i address cycles", address_cycles);
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- if ((page_size != 512) && (page_size != 2048)) {
- LOG_ERROR("LPC32xx doesn't support page size %i", page_size);
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- /* select MLC controller if none is currently selected */
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_DEBUG("no LPC32xx NAND flash controller selected, "
- "using default 'slc'");
- lpc32xx_info->selected_controller = LPC32xx_SLC_CONTROLLER;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- uint32_t mlc_icr_value = 0x0;
- float cycle;
- int twp, twh, trp, treh, trhz, trbwb, tcea;
-
- /* FLASHCLK_CTRL = 0x22 (enable clk for MLC) */
- retval = target_write_u32(target, 0x400040c8, 0x22);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set FLASHCLK_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_CEH = 0x0 (Force nCE assert) */
- retval = target_write_u32(target, 0x200b804c, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_CEH");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_LOCK = 0xa25e (unlock protected registers) */
- retval = target_write_u32(target, 0x200b8044, 0xa25e);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_LOCK");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_ICR = configuration */
- if (lpc32xx_info->sw_write_protection)
- mlc_icr_value |= 0x8;
- if (page_size == 2048)
- mlc_icr_value |= 0x4;
- if (address_cycles == 4)
- mlc_icr_value |= 0x2;
- if (bus_width == 16)
- mlc_icr_value |= 0x1;
- retval = target_write_u32(target, 0x200b8030, mlc_icr_value);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ICR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* calculate NAND controller timings */
- cycle = lpc32xx_cycle_time(nand);
-
- twp = ((40 / cycle) + 1);
- twh = ((20 / cycle) + 1);
- trp = ((30 / cycle) + 1);
- treh = ((15 / cycle) + 1);
- trhz = ((30 / cycle) + 1);
- trbwb = ((100 / cycle) + 1);
- tcea = ((45 / cycle) + 1);
-
- /* MLC_LOCK = 0xa25e (unlock protected registers) */
- retval = target_write_u32(target, 0x200b8044, 0xa25e);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_LOCK");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_TIME_REG */
- retval = target_write_u32(target, 0x200b8034,
- (twp & 0xf)
- | ((twh & 0xf) << 4)
- | ((trp & 0xf) << 8)
- | ((treh & 0xf) << 12)
- | ((trhz & 0x7) << 16)
- | ((trbwb & 0x1f) << 19)
- | ((tcea & 0x3) << 24));
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_TIME_REG");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- retval = lpc32xx_reset(nand);
- if (ERROR_OK != retval)
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- float cycle;
- int r_setup, r_hold, r_width, r_rdy;
- int w_setup, w_hold, w_width, w_rdy;
-
- /* FLASHCLK_CTRL = 0x05 (enable clk for SLC) */
- retval = target_write_u32(target, 0x400040c8, 0x05);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set FLASHCLK_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* after reset set other registers of SLC,
- * so reset calling is here at the begining
- */
- retval = lpc32xx_reset(nand);
- if (ERROR_OK != retval)
- return ERROR_NAND_OPERATION_FAILED;
-
- /* SLC_CFG =
- Force nCE assert,
- DMA ECC enabled,
- ECC enabled,
- DMA burst enabled,
- DMA read from SLC,
- WIDTH = bus_width)
- */
- retval = target_write_u32(target, 0x20020014,
- 0x3e | (bus_width == 16) ? 1 : 0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_CFG");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* SLC_IEN = 3 (INT_RDY_EN = 1) ,(INT_TC_STAT = 1) */
- retval = target_write_u32(target, 0x20020020, 0x03);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_IEN");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* DMA configuration */
-
- /* DMACLK_CTRL = 0x01 (enable clock for DMA controller) */
- retval = target_write_u32(target, 0x400040e8, 0x01);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set DMACLK_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* DMACConfig = DMA enabled*/
- retval = target_write_u32(target, 0x31000030, 0x01);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set DMACConfig");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* calculate NAND controller timings */
- cycle = lpc32xx_cycle_time(nand);
-
- r_setup = w_setup = 0;
- r_hold = w_hold = 10 / cycle;
- r_width = 30 / cycle;
- w_width = 40 / cycle;
- r_rdy = w_rdy = 100 / cycle;
-
- /* SLC_TAC: SLC timing arcs register */
- retval = target_write_u32(target, 0x2002002c,
- (r_setup & 0xf)
- | ((r_hold & 0xf) << 4)
- | ((r_width & 0xf) << 8)
- | ((r_rdy & 0xf) << 12)
- | ((w_setup & 0xf) << 16)
- | ((w_hold & 0xf) << 20)
- | ((w_width & 0xf) << 24)
- | ((w_rdy & 0xf) << 28));
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_TAC");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc32xx_reset(struct nand_device *nand)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC32xx NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- /* MLC_CMD = 0xff (reset controller and NAND device) */
- retval = target_write_u32(target, 0x200b8000, 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_CMD");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (!lpc32xx_controller_ready(nand, 100)) {
- LOG_ERROR("LPC32xx MLC NAND controller timed out "
- "after reset");
- return ERROR_NAND_OPERATION_TIMEOUT;
- }
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- /* SLC_CTRL = 0x6 (ECC_CLEAR, SW_RESET) */
- retval = target_write_u32(target, 0x20020010, 0x6);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_CTRL");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (!lpc32xx_controller_ready(nand, 100)) {
- LOG_ERROR("LPC32xx SLC NAND controller timed out "
- "after reset");
- return ERROR_NAND_OPERATION_TIMEOUT;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc32xx_command(struct nand_device *nand, uint8_t command)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC32xx NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- /* MLC_CMD = command */
- retval = target_write_u32(target, 0x200b8000, command);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_CMD");
- return ERROR_NAND_OPERATION_FAILED;
- }
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- /* SLC_CMD = command */
- retval = target_write_u32(target, 0x20020008, command);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_CMD");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc32xx_address(struct nand_device *nand, uint8_t address)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC32xx NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- /* MLC_ADDR = address */
- retval = target_write_u32(target, 0x200b8004, address);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- /* SLC_ADDR = address */
- retval = target_write_u32(target, 0x20020004, address);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc32xx_write_data(struct nand_device *nand, uint16_t data)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use "
- "LPC32xx NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC32xx NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- /* MLC_DATA = data */
- retval = target_write_u32(target, 0x200b0000, data);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_DATA");
- return ERROR_NAND_OPERATION_FAILED;
- }
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- /* SLC_DATA = data */
- retval = target_write_u32(target, 0x20020000, data);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_DATA");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc32xx_read_data(struct nand_device *nand, void *data)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC32xx NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- /* data = MLC_DATA, use sized access */
- if (nand->bus_width == 8) {
- uint8_t *data8 = data;
- retval = target_read_u8(target, 0x200b0000, data8);
- } else {
- LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read MLC_DATA");
- return ERROR_NAND_OPERATION_FAILED;
- }
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- uint32_t data32;
-
- /* data = SLC_DATA, must use 32-bit access */
- retval = target_read_u32(target, 0x20020000, &data32);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read SLC_DATA");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (nand->bus_width == 8) {
- uint8_t *data8 = data;
- *data8 = data32 & 0xff;
- } else {
- LOG_ERROR("BUG: bus_width neither 8 nor 16 bit");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc32xx_write_page_mlc(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- struct target *target = nand->target;
- int retval;
- uint8_t status;
- static uint8_t page_buffer[512];
- static uint8_t oob_buffer[6];
- int quarter, num_quarters;
-
- /* MLC_CMD = sequential input */
- retval = target_write_u32(target, 0x200b8000, NAND_CMD_SEQIN);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_CMD");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (nand->page_size == 512) {
- /* MLC_ADDR = 0x0 (one column cycle) */
- retval = target_write_u32(target, 0x200b8004, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_ADDR = row */
- retval = target_write_u32(target, 0x200b8004, page & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (nand->address_cycles == 4) {
- retval = target_write_u32(target, 0x200b8004,
- (page >> 16) & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
- } else {
- /* MLC_ADDR = 0x0 (two column cycles) */
- retval = target_write_u32(target, 0x200b8004, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- retval = target_write_u32(target, 0x200b8004, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_ADDR = row */
- retval = target_write_u32(target, 0x200b8004, page & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- /* when using the MLC controller, we have to treat a large page device
- * as being made out of four quarters, each the size of a small page
- * device
- */
- num_quarters = (nand->page_size == 2048) ? 4 : 1;
-
- for (quarter = 0; quarter < num_quarters; quarter++) {
- int thisrun_data_size = (data_size > 512) ? 512 : data_size;
- int thisrun_oob_size = (oob_size > 6) ? 6 : oob_size;
-
- memset(page_buffer, 0xff, 512);
- if (data) {
- memcpy(page_buffer, data, thisrun_data_size);
- data_size -= thisrun_data_size;
- data += thisrun_data_size;
- }
-
- memset(oob_buffer, 0xff, 6);
- if (oob) {
- memcpy(oob_buffer, oob, thisrun_oob_size);
- oob_size -= thisrun_oob_size;
- oob += thisrun_oob_size;
- }
-
- /* write MLC_ECC_ENC_REG to start encode cycle */
- retval = target_write_u32(target, 0x200b8008, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ECC_ENC_REG");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- retval = target_write_memory(target, 0x200a8000,
- 4, 128, page_buffer);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_BUF (data)");
- return ERROR_NAND_OPERATION_FAILED;
- }
- retval = target_write_memory(target, 0x200a8000,
- 1, 6, oob_buffer);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_BUF (oob)");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* write MLC_ECC_AUTO_ENC_REG to start auto encode */
- retval = target_write_u32(target, 0x200b8010, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ECC_AUTO_ENC_REG");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (!lpc32xx_controller_ready(nand, 1000)) {
- LOG_ERROR("timeout while waiting for "
- "completion of auto encode cycle");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- /* MLC_CMD = auto program command */
- retval = target_write_u32(target, 0x200b8000, NAND_CMD_PAGEPROG);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_CMD");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- retval = nand_read_status(nand, &status);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read status");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & NAND_STATUS_FAIL) {
- LOG_ERROR("write operation didn't pass, status: 0x%2.2x",
- status);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-/* SLC controller in !raw mode will use target cpu to read/write nand from/to
- * target internal memory. The transfer to/from flash is done by DMA. This
- * function sets up the dma linked list in host memory for later transfer to
- * target.
- */
-static int lpc32xx_make_dma_list(uint32_t target_mem_base, uint32_t page_size,
- int do_read)
-{
- uint32_t i, dmasrc, ctrl, ecc_ctrl, oob_ctrl, dmadst;
-
- /* DMACCxControl =
- TransferSize =64,
- Source burst size =16,
- Destination burst size = 16,
- Source transfer width = 32 bit,
- Destination transfer width = 32 bit,
- Source AHB master select = M0,
- Destination AHB master select = M0,
- Source increment = 0, // set later
- Destination increment = 0, // set later
- Terminal count interrupt enable bit = 0 // set on last
- */ /*
- * Write Operation Sequence for Small Block NAND
- * ----------------------------------------------------------
- * 1. X'fer 256 bytes of data from Memory to Flash.
- * 2. Copy generated ECC data from Register to Spare Area
- * 3. X'fer next 256 bytes of data from Memory to Flash.
- * 4. Copy generated ECC data from Register to Spare Area.
- * 5. X'fer 16 byets of Spare area from Memory to Flash.
- * Read Operation Sequence for Small Block NAND
- * ----------------------------------------------------------
- * 1. X'fer 256 bytes of data from Flash to Memory.
- * 2. Copy generated ECC data from Register to ECC calc Buffer.
- * 3. X'fer next 256 bytes of data from Flash to Memory.
- * 4. Copy generated ECC data from Register to ECC calc Buffer.
- * 5. X'fer 16 bytes of Spare area from Flash to Memory.
- * Write Operation Sequence for Large Block NAND
- * ----------------------------------------------------------
- * 1. Steps(1-4) of Write Operations repeate for four times
- * which generates 16 DMA descriptors to X'fer 2048 bytes of
- * data & 32 bytes of ECC data.
- * 2. X'fer 64 bytes of Spare area from Memory to Flash.
- * Read Operation Sequence for Large Block NAND
- * ----------------------------------------------------------
- * 1. Steps(1-4) of Read Operations repeate for four times
- * which generates 16 DMA descriptors to X'fer 2048 bytes of
- * data & 32 bytes of ECC data.
- * 2. X'fer 64 bytes of Spare area from Flash to Memory.
- */
-
- ctrl = (0x40 | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
- | 0 << 25 | 0 << 26 | 0 << 27 | 0 << 31);
-
- /* DMACCxControl =
- TransferSize =1,
- Source burst size =4,
- Destination burst size = 4,
- Source transfer width = 32 bit,
- Destination transfer width = 32 bit,
- Source AHB master select = M0,
- Destination AHB master select = M0,
- Source increment = 0,
- Destination increment = 1,
- Terminal count interrupt enable bit = 0
- */
- ecc_ctrl = 0x01 | 1 << 12 | 1 << 15 | 2 << 18 | 2 << 21 | 0 << 24
- | 0 << 25 | 0 << 26 | 1 << 27 | 0 << 31;
-
- /* DMACCxControl =
- TransferSize =16 for lp or 4 for sp,
- Source burst size =16,
- Destination burst size = 16,
- Source transfer width = 32 bit,
- Destination transfer width = 32 bit,
- Source AHB master select = M0,
- Destination AHB master select = M0,
- Source increment = 0, // set later
- Destination increment = 0, // set later
- Terminal count interrupt enable bit = 1 // set on last
- */
- oob_ctrl = (page_size == 2048 ? 0x10 : 0x04)
- | 3 << 12 | 3 << 15 | 2 << 18 | 2 << 21 | 0 << 24
- | 0 << 25 | 0 << 26 | 0 << 27 | 1 << 31;
- if (do_read) {
- ctrl |= 1 << 27;/* Destination increment = 1 */
- oob_ctrl |= 1 << 27; /* Destination increment = 1 */
- dmasrc = 0x20020038; /* SLC_DMA_DATA */
- dmadst = target_mem_base + DATA_OFFS;
- } else {
- ctrl |= 1 << 26;/* Source increment = 1 */
- oob_ctrl |= 1 << 26; /* Source increment = 1 */
- dmasrc = target_mem_base + DATA_OFFS;
- dmadst = 0x20020038; /* SLC_DMA_DATA */
- }
- /*
- * Write Operation Sequence for Small Block NAND
- * ----------------------------------------------------------
- * 1. X'fer 256 bytes of data from Memory to Flash.
- * 2. Copy generated ECC data from Register to Spare Area
- * 3. X'fer next 256 bytes of data from Memory to Flash.
- * 4. Copy generated ECC data from Register to Spare Area.
- * 5. X'fer 16 byets of Spare area from Memory to Flash.
- * Read Operation Sequence for Small Block NAND
- * ----------------------------------------------------------
- * 1. X'fer 256 bytes of data from Flash to Memory.
- * 2. Copy generated ECC data from Register to ECC calc Buffer.
- * 3. X'fer next 256 bytes of data from Flash to Memory.
- * 4. Copy generated ECC data from Register to ECC calc Buffer.
- * 5. X'fer 16 bytes of Spare area from Flash to Memory.
- * Write Operation Sequence for Large Block NAND
- * ----------------------------------------------------------
- * 1. Steps(1-4) of Write Operations repeate for four times
- * which generates 16 DMA descriptors to X'fer 2048 bytes of
- * data & 32 bytes of ECC data.
- * 2. X'fer 64 bytes of Spare area from Memory to Flash.
- * Read Operation Sequence for Large Block NAND
- * ----------------------------------------------------------
- * 1. Steps(1-4) of Read Operations repeate for four times
- * which generates 16 DMA descriptors to X'fer 2048 bytes of
- * data & 32 bytes of ECC data.
- * 2. X'fer 64 bytes of Spare area from Flash to Memory.
- */
- for (i = 0; i < page_size/0x100; i++) {
- dmalist[i*2].dma_src = (do_read ? dmasrc : (dmasrc + i * 256));
- dmalist[i*2].dma_dest = (do_read ? (dmadst + i * 256) : dmadst);
- dmalist[i*2].next_lli =
- target_mem_base + (i*2 + 1) * sizeof(dmac_ll_t);
- dmalist[i*2].next_ctrl = ctrl;
-
- dmalist[(i*2) + 1].dma_src = 0x20020034;/* SLC_ECC */
- dmalist[(i*2) + 1].dma_dest =
- target_mem_base + ECC_OFFS + i * 4;
- dmalist[(i*2) + 1].next_lli =
- target_mem_base + (i*2 + 2) * sizeof(dmac_ll_t);
- dmalist[(i*2) + 1].next_ctrl = ecc_ctrl;
-
- }
- if (do_read)
- dmadst = target_mem_base + SPARE_OFFS;
- else {
- dmasrc = target_mem_base + SPARE_OFFS;
- dmalist[(i*2) - 1].next_lli = 0;/* last link = null on write */
- dmalist[(i*2) - 1].next_ctrl |= (1 << 31); /* Set TC enable */
- }
- dmalist[i*2].dma_src = dmasrc;
- dmalist[i*2].dma_dest = dmadst;
- dmalist[i*2].next_lli = 0;
- dmalist[i*2].next_ctrl = oob_ctrl;
-
- return i * 2 + 1; /* Number of descriptors */
-}
-
-static int lpc32xx_start_slc_dma(struct nand_device *nand, uint32_t count,
- int do_wait)
-{
- struct target *target = nand->target;
- int retval;
-
- /* DMACIntTCClear = ch0 */
- retval = target_write_u32(target, 0x31000008, 1);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set DMACIntTCClear");
- return retval;
- }
-
- /* DMACIntErrClear = ch0 */
- retval = target_write_u32(target, 0x31000010, 1);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set DMACIntErrClear");
- return retval;
- }
-
- /* DMACCxConfig=
- E=1,
- SrcPeripheral = 1 (SLC),
- DestPeripheral = 1 (SLC),
- FlowCntrl = 2 (Pher -> Mem, DMA),
- IE = 0,
- ITC = 0,
- L= 0,
- H=0
- */
- retval = target_write_u32(target, 0x31000110,
- 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
- | 0<<15 | 0<<16 | 0<<18);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set DMACC0Config");
- return retval;
- }
-
- /* SLC_CTRL = 3 (START DMA), ECC_CLEAR */
- retval = target_write_u32(target, 0x20020010, 0x3);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set SLC_CTRL");
- return retval;
- }
-
- /* SLC_ICR = 2, INT_TC_CLR, clear pending TC*/
- retval = target_write_u32(target, 0x20020028, 2);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set SLC_ICR");
- return retval;
- }
-
- /* SLC_TC */
- retval = target_write_u32(target, 0x20020030, count);
- if (ERROR_OK != retval) {
- LOG_ERROR("lpc32xx_start_slc_dma: Could not set SLC_TC");
- return retval;
- }
-
- /* Wait finish */
- if (do_wait && !lpc32xx_tc_ready(nand, 100)) {
- LOG_ERROR("timeout while waiting for completion of DMA");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- return retval;
-}
-
-static int lpc32xx_dma_ready(struct nand_device *nand, int timeout)
-{
- struct target *target = nand->target;
-
- LOG_DEBUG("lpc32xx_dma_ready count start=%d", timeout);
-
- do {
- uint32_t tc_stat;
- uint32_t err_stat;
- int retval;
-
- /* Read DMACRawIntTCStat */
- retval = target_read_u32(target, 0x31000014, &tc_stat);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not read DMACRawIntTCStat");
- return 0;
- }
- /* Read DMACRawIntErrStat */
- retval = target_read_u32(target, 0x31000018, &err_stat);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not read DMACRawIntErrStat");
- return 0;
- }
- if ((tc_stat | err_stat) & 1) {
- LOG_DEBUG("lpc32xx_dma_ready count=%d",
- timeout);
- if (err_stat & 1) {
- LOG_ERROR("lpc32xx_dma_ready "
- "DMA error, aborted");
- return 0;
- } else
- return 1;
- }
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-static uint32_t slc_ecc_copy_to_buffer(uint8_t *spare,
- const uint32_t *ecc, int count)
-{
- int i;
- for (i = 0; i < (count * 3); i += 3) {
- uint32_t ce = ecc[i/3];
- ce = ~(ce << 2) & 0xFFFFFF;
- spare[i+2] = (uint8_t)(ce & 0xFF); ce >>= 8;
- spare[i+1] = (uint8_t)(ce & 0xFF); ce >>= 8;
- spare[i] = (uint8_t)(ce & 0xFF);
- }
- return 0;
-}
-
-static void lpc32xx_dump_oob(uint8_t *oob, uint32_t oob_size)
-{
- int addr = 0;
- while (oob_size > 0) {
- LOG_DEBUG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", addr,
- oob[0], oob[1], oob[2], oob[3],
- oob[4], oob[5], oob[6], oob[7]);
- oob += 8;
- addr += 8;
- oob_size -= 8;
- }
-}
-
-static int lpc32xx_write_page_slc(struct nand_device *nand,
- struct working_area *pworking_area,
- uint32_t page, uint8_t *data,
- uint32_t data_size, uint8_t *oob,
- uint32_t oob_size)
-{
- struct target *target = nand->target;
- int retval;
- uint32_t target_mem_base;
-
- LOG_DEBUG("SLC write page %" PRIx32 " data=%d, oob=%d, "
- "data_size=%" PRIu32 ", oob_size=%" PRIu32,
- page, data != 0, oob != 0, data_size, oob_size);
-
- target_mem_base = pworking_area->address;
- /*
- * Skip writting page which has all 0xFF data as this will
- * generate 0x0 value.
- */
- if (data && !oob) {
- uint32_t i, all_ff = 1;
- for (i = 0; i < data_size; i++)
- if (data[i] != 0xFF) {
- all_ff = 0;
- break;
- }
- if (all_ff)
- return ERROR_OK;
- }
- /* Make the dma descriptors in local memory */
- int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 0);
- /* Write them to target.
- XXX: Assumes host and target have same byte sex.
- */
- retval = target_write_memory(target, target_mem_base, 4,
- nll * sizeof(dmac_ll_t) / 4,
- (uint8_t *)dmalist);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not write DMA descriptors to IRAM");
- return retval;
- }
-
- retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data);
- if (ERROR_OK != retval) {
- LOG_ERROR("NAND_CMD_SEQIN failed");
- return retval;
- }
-
- /* SLC_CFG =
- Force nCE assert,
- DMA ECC enabled,
- ECC enabled,
- DMA burst enabled,
- DMA write to SLC,
- WIDTH = bus_width
- */
- retval = target_write_u32(target, 0x20020014, 0x3c);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set SLC_CFG");
- return retval;
- }
- if (data) {
- /* Write data to target */
- static uint8_t fdata[2048];
- memset(fdata, 0xFF, nand->page_size);
- memcpy(fdata, data, data_size);
- retval = target_write_memory(target,
- target_mem_base + DATA_OFFS,
- 4, nand->page_size/4, fdata);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not write data to IRAM");
- return retval;
- }
-
- /* Write first decriptor to DMA controller */
- retval = target_write_memory(target, 0x31000100, 4,
- sizeof(dmac_ll_t) / 4,
- (uint8_t *)dmalist);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not write DMA descriptor to DMAC");
- return retval;
- }
-
- /* Start xfer of data from iram to flash using DMA */
- int tot_size = nand->page_size;
- tot_size += tot_size == 2048 ? 64 : 16;
- retval = lpc32xx_start_slc_dma(nand, tot_size, 0);
- if (ERROR_OK != retval) {
- LOG_ERROR("DMA failed");
- return retval;
- }
-
- /* Wait for DMA to finish. SLC is not finished at this stage */
- if (!lpc32xx_dma_ready(nand, 100)) {
- LOG_ERROR("Data DMA failed during write");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- } /* data xfer */
-
- /* Copy OOB to iram */
- static uint8_t foob[64];
- int foob_size = nand->page_size == 2048 ? 64 : 16;
- memset(foob, 0xFF, foob_size);
- if (oob) /* Raw mode */
- memcpy(foob, oob, oob_size);
- else {
- /* Get HW generated ECC, made while writing data */
- int ecc_count = nand->page_size == 2048 ? 8 : 2;
- static uint32_t hw_ecc[8];
- retval = target_read_memory(target, target_mem_base + ECC_OFFS,
- 4, ecc_count, (uint8_t *)hw_ecc);
- if (ERROR_OK != retval) {
- LOG_ERROR("Reading hw generated ECC from IRAM failed");
- return retval;
- }
- /* Copy to oob, at correct offsets */
- static uint8_t ecc[24];
- slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count);
- const int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout;
- int i;
- for (i = 0; i < ecc_count * 3; i++)
- foob[layout[i]] = ecc[i];
- lpc32xx_dump_oob(foob, foob_size);
- }
- retval = target_write_memory(target, target_mem_base + SPARE_OFFS, 4,
- foob_size / 4, foob);
- if (ERROR_OK != retval) {
- LOG_ERROR("Writing OOB to IRAM failed");
- return retval;
- }
-
- /* Write OOB decriptor to DMA controller */
- retval = target_write_memory(target, 0x31000100, 4,
- sizeof(dmac_ll_t) / 4,
- (uint8_t *)(&dmalist[nll-1]));
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not write OOB DMA descriptor to DMAC");
- return retval;
- }
- if (data) {
- /* Only restart DMA with last descriptor,
- * don't setup SLC again */
-
- /* DMACIntTCClear = ch0 */
- retval = target_write_u32(target, 0x31000008, 1);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set DMACIntTCClear");
- return retval;
- }
- /* DMACCxConfig=
- * E=1,
- * SrcPeripheral = 1 (SLC),
- * DestPeripheral = 1 (SLC),
- * FlowCntrl = 2 (Pher -> Mem, DMA),
- * IE = 0,
- * ITC = 0,
- * L= 0,
- * H=0
- */
- retval = target_write_u32(target, 0x31000110,
- 1 | 1<<1 | 1<<6 | 2<<11 | 0<<14
- | 0<<15 | 0<<16 | 0<<18);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not set DMACC0Config");
- return retval;
- }
- /* Wait finish */
- if (!lpc32xx_tc_ready(nand, 100)) {
- LOG_ERROR("timeout while waiting for "
- "completion of DMA");
- return ERROR_NAND_OPERATION_FAILED;
- }
- } else {
- /* Start xfer of data from iram to flash using DMA */
- retval = lpc32xx_start_slc_dma(nand, foob_size, 1);
- if (ERROR_OK != retval) {
- LOG_ERROR("DMA OOB failed");
- return retval;
- }
- }
-
- /* Let NAND start actual writing */
- retval = nand_write_finish(nand);
- if (ERROR_OK != retval) {
- LOG_ERROR("nand_write_finish failed");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int lpc32xx_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval = ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC32xx NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- if (!data && oob) {
- LOG_ERROR("LPC32xx MLC controller can't write "
- "OOB data only");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- if (oob && (oob_size > 24)) {
- LOG_ERROR("LPC32xx MLC controller can't write more "
- "than 6 bytes for each quarter's OOB data");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- if (data_size > (uint32_t)nand->page_size) {
- LOG_ERROR("data size exceeds page size");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- retval = lpc32xx_write_page_mlc(nand, page, data, data_size,
- oob, oob_size);
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- struct working_area *pworking_area;
- if (!data && oob) {
- /*
- * if oob only mode is active original method is used
- * as SLC controller hangs during DMA interworking. (?)
- * Anyway the code supports the oob only mode below.
- */
- return nand_write_page_raw(nand, page, data,
- data_size, oob, oob_size);
- }
- retval = target_alloc_working_area(target,
- nand->page_size + DATA_OFFS,
- &pworking_area);
- if (retval != ERROR_OK) {
- LOG_ERROR("Can't allocate working area in "
- "LPC internal RAM");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- retval = lpc32xx_write_page_slc(nand, pworking_area, page,
- data, data_size, oob, oob_size);
- target_free_working_area(target, pworking_area);
- }
-
- return retval;
-}
-
-static int lpc32xx_read_page_mlc(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- struct target *target = nand->target;
- static uint8_t page_buffer[2048];
- static uint8_t oob_buffer[64];
- uint32_t page_bytes_done = 0;
- uint32_t oob_bytes_done = 0;
- uint32_t mlc_isr;
- int retval;
-
- if (!data && oob) {
- /* MLC_CMD = Read OOB
- * we can use the READOOB command on both small and large page
- * devices, as the controller translates the 0x50 command to
- * a 0x0 with appropriate positioning of the serial buffer
- * read pointer
- */
- retval = target_write_u32(target, 0x200b8000, NAND_CMD_READOOB);
- } else {
- /* MLC_CMD = Read0 */
- retval = target_write_u32(target, 0x200b8000, NAND_CMD_READ0);
- }
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_CMD");
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (nand->page_size == 512) {
- /* small page device
- * MLC_ADDR = 0x0 (one column cycle) */
- retval = target_write_u32(target, 0x200b8004, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_ADDR = row */
- retval = target_write_u32(target, 0x200b8004, page & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (nand->address_cycles == 4) {
- retval = target_write_u32(target, 0x200b8004,
- (page >> 16) & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
- } else {
- /* large page device
- * MLC_ADDR = 0x0 (two column cycles) */
- retval = target_write_u32(target, 0x200b8004, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- retval = target_write_u32(target, 0x200b8004, 0x0);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_ADDR = row */
- retval = target_write_u32(target, 0x200b8004, page & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
- retval = target_write_u32(target, 0x200b8004,
- (page >> 8) & 0xff);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ADDR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /* MLC_CMD = Read Start */
- retval = target_write_u32(target, 0x200b8000,
- NAND_CMD_READSTART);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_CMD");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- while (page_bytes_done < (uint32_t)nand->page_size) {
- /* MLC_ECC_AUTO_DEC_REG = dummy */
- retval = target_write_u32(target, 0x200b8014, 0xaa55aa55);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_ECC_AUTO_DEC_REG");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (!lpc32xx_controller_ready(nand, 1000)) {
- LOG_ERROR("timeout while waiting for "
- "completion of auto decode cycle");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- retval = target_read_u32(target, 0x200b8048, &mlc_isr);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read MLC_ISR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (mlc_isr & 0x8) {
- if (mlc_isr & 0x40) {
- LOG_ERROR("uncorrectable error detected: "
- "0x%2.2x", (unsigned)mlc_isr);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_WARNING("%i symbol error detected and corrected",
- ((int)(((mlc_isr & 0x30) >> 4) + 1)));
- }
-
- if (data) {
- retval = target_read_memory(target, 0x200a8000, 4, 128,
- page_buffer + page_bytes_done);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read MLC_BUF (data)");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- if (oob) {
- retval = target_read_memory(target, 0x200a8000, 4, 4,
- oob_buffer + oob_bytes_done);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read MLC_BUF (oob)");
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
-
- page_bytes_done += 512;
- oob_bytes_done += 16;
- }
-
- if (data)
- memcpy(data, page_buffer, data_size);
-
- if (oob)
- memcpy(oob, oob_buffer, oob_size);
-
- return ERROR_OK;
-}
-
-static int lpc32xx_read_page_slc(struct nand_device *nand,
- struct working_area *pworking_area,
- uint32_t page, uint8_t *data,
- uint32_t data_size, uint8_t *oob,
- uint32_t oob_size)
-{
- struct target *target = nand->target;
- int retval;
- uint32_t target_mem_base;
-
- LOG_DEBUG("SLC read page %" PRIx32 " data=%" PRIu32 ", oob=%" PRIu32,
- page, data_size, oob_size);
-
- target_mem_base = pworking_area->address;
-
- /* Make the dma descriptors in local memory */
- int nll = lpc32xx_make_dma_list(target_mem_base, nand->page_size, 1);
- /* Write them to target.
- XXX: Assumes host and target have same byte sex.
- */
- retval = target_write_memory(target, target_mem_base, 4,
- nll * sizeof(dmac_ll_t) / 4,
- (uint8_t *)dmalist);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not write DMA descriptors to IRAM");
- return retval;
- }
-
- retval = nand_page_command(nand, page, NAND_CMD_READ0, 0);
- if (ERROR_OK != retval) {
- LOG_ERROR("lpc32xx_read_page_slc: NAND_CMD_READ0 failed");
- return retval;
- }
-
- /* SLC_CFG =
- Force nCE assert,
- DMA ECC enabled,
- ECC enabled,
- DMA burst enabled,
- DMA read from SLC,
- WIDTH = bus_width
- */
- retval = target_write_u32(target, 0x20020014, 0x3e);
- if (ERROR_OK != retval) {
- LOG_ERROR("lpc32xx_read_page_slc: Could not set SLC_CFG");
- return retval;
- }
-
- /* Write first decriptor to DMA controller */
- retval = target_write_memory(target, 0x31000100, 4,
- sizeof(dmac_ll_t) / 4, (uint8_t *)dmalist);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not write DMA descriptor to DMAC");
- return retval;
- }
-
- /* Start xfer of data from flash to iram using DMA */
- int tot_size = nand->page_size;
- tot_size += nand->page_size == 2048 ? 64 : 16;
- retval = lpc32xx_start_slc_dma(nand, tot_size, 1);
- if (ERROR_OK != retval) {
- LOG_ERROR("lpc32xx_read_page_slc: DMA read failed");
- return retval;
- }
-
- /* Copy data from iram */
- if (data) {
- retval = target_read_memory(target, target_mem_base + DATA_OFFS,
- 4, data_size/4, data);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not read data from IRAM");
- return retval;
- }
- }
- if (oob) {
- /* No error correction, just return data as read from flash */
- retval = target_read_memory(target,
- target_mem_base + SPARE_OFFS, 4,
- oob_size/4, oob);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not read OOB from IRAM");
- return retval;
- }
- return ERROR_OK;
- }
-
- /* Copy OOB from flash, stored in IRAM */
- static uint8_t foob[64];
- retval = target_read_memory(target, target_mem_base + SPARE_OFFS,
- 4, nand->page_size == 2048 ? 16 : 4, foob);
- lpc32xx_dump_oob(foob, nand->page_size == 2048 ? 64 : 16);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not read OOB from IRAM");
- return retval;
- }
- /* Copy ECC from HW, generated while reading */
- int ecc_count = nand->page_size == 2048 ? 8 : 2;
- static uint32_t hw_ecc[8]; /* max size */
- retval = target_read_memory(target, target_mem_base + ECC_OFFS, 4,
- ecc_count, (uint8_t *)hw_ecc);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not read hw generated ECC from IRAM");
- return retval;
- }
- static uint8_t ecc[24];
- slc_ecc_copy_to_buffer(ecc, hw_ecc, ecc_count);
- /* Copy ECC from flash using correct layout */
- static uint8_t fecc[24];/* max size */
- const int *layout = nand->page_size == 2048 ? lp_ooblayout : sp_ooblayout;
- int i;
- for (i = 0; i < ecc_count * 3; i++)
- fecc[i] = foob[layout[i]];
- /* Compare ECC and possibly correct data */
- for (i = 0; i < ecc_count; i++) {
- retval = nand_correct_data(nand, data + 256*i, &fecc[i * 3],
- &ecc[i * 3]);
- if (retval > 0)
- LOG_WARNING("error detected and corrected: %" PRIu32 "/%d",
- page, i);
- if (retval < 0)
- break;
- }
- if (i == ecc_count)
- retval = ERROR_OK;
- else {
- LOG_ERROR("uncorrectable error detected: %" PRIu32 "/%d", page, i);
- retval = ERROR_NAND_OPERATION_FAILED;
- }
- return retval;
-}
-
-static int lpc32xx_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval = ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (lpc32xx_info->selected_controller == LPC32xx_NO_CONTROLLER) {
- LOG_ERROR("BUG: no LPC32xx NAND flash controller selected");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- if (data_size > (uint32_t)nand->page_size) {
- LOG_ERROR("data size exceeds page size");
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
- retval = lpc32xx_read_page_mlc(nand, page, data, data_size,
- oob, oob_size);
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- struct working_area *pworking_area;
-
- retval = target_alloc_working_area(target,
- nand->page_size + 0x200,
- &pworking_area);
- if (retval != ERROR_OK) {
- LOG_ERROR("Can't allocate working area in "
- "LPC internal RAM");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- retval = lpc32xx_read_page_slc(nand, pworking_area, page,
- data, data_size, oob, oob_size);
- target_free_working_area(target, pworking_area);
- }
-
- return retval;
-}
-
-static int lpc32xx_controller_ready(struct nand_device *nand, int timeout)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_DEBUG("lpc32xx_controller_ready count start=%d", timeout);
-
- do {
- if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- uint8_t status;
-
- /* Read MLC_ISR, wait for controller to become ready */
- retval = target_read_u8(target, 0x200b8048, &status);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set MLC_STAT");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & 2) {
- LOG_DEBUG("lpc32xx_controller_ready count=%d",
- timeout);
- return 1;
- }
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- uint32_t status;
-
- /* Read SLC_STAT and check READY bit */
- retval = target_read_u32(target, 0x20020018, &status);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not set SLC_STAT");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & 1) {
- LOG_DEBUG("lpc32xx_controller_ready count=%d",
- timeout);
- return 1;
- }
- }
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-static int lpc32xx_nand_ready(struct nand_device *nand, int timeout)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use LPC32xx "
- "NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- LOG_DEBUG("lpc32xx_nand_ready count start=%d", timeout);
-
- do {
- if (lpc32xx_info->selected_controller == LPC32xx_MLC_CONTROLLER) {
- uint8_t status = 0x0;
-
- /* Read MLC_ISR, wait for NAND flash device to
- * become ready */
- retval = target_read_u8(target, 0x200b8048, &status);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read MLC_ISR");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & 1) {
- LOG_DEBUG("lpc32xx_nand_ready count end=%d",
- timeout);
- return 1;
- }
- } else if (lpc32xx_info->selected_controller == LPC32xx_SLC_CONTROLLER) {
- uint32_t status = 0x0;
-
- /* Read SLC_STAT and check READY bit */
- retval = target_read_u32(target, 0x20020018, &status);
- if (ERROR_OK != retval) {
- LOG_ERROR("could not read SLC_STAT");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (status & 1) {
- LOG_DEBUG("lpc32xx_nand_ready count end=%d",
- timeout);
- return 1;
- }
- }
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-static int lpc32xx_tc_ready(struct nand_device *nand, int timeout)
-{
- struct target *target = nand->target;
-
- LOG_DEBUG("lpc32xx_tc_ready count start=%d", timeout);
-
- do {
- uint32_t status = 0x0;
- int retval;
- /* Read SLC_INT_STAT and check INT_TC_STAT bit */
- retval = target_read_u32(target, 0x2002001c, &status);
- if (ERROR_OK != retval) {
- LOG_ERROR("Could not read SLC_INT_STAT");
- return 0;
- }
- if (status & 2) {
- LOG_DEBUG("lpc32xx_tc_ready count=%d", timeout);
- return 1;
- }
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-COMMAND_HANDLER(handle_lpc32xx_select_command)
-{
- struct lpc32xx_nand_controller *lpc32xx_info = NULL;
- char *selected[] = {
- "no", "mlc", "slc"
- };
-
- if ((CMD_ARGC < 1) || (CMD_ARGC > 3))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned num;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
- struct nand_device *nand = get_nand_device_by_num(num);
- if (!nand) {
- command_print(CMD_CTX, "nand device '#%s' is out of bounds",
- CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- lpc32xx_info = nand->controller_priv;
-
- if (CMD_ARGC >= 2) {
- if (strcmp(CMD_ARGV[1], "mlc") == 0) {
- lpc32xx_info->selected_controller =
- LPC32xx_MLC_CONTROLLER;
- } else if (strcmp(CMD_ARGV[1], "slc") == 0) {
- lpc32xx_info->selected_controller =
- LPC32xx_SLC_CONTROLLER;
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- command_print(CMD_CTX, "%s controller selected",
- selected[lpc32xx_info->selected_controller]);
-
- return ERROR_OK;
-}
-
-static const struct command_registration lpc32xx_exec_command_handlers[] = {
- {
- .name = "select",
- .handler = handle_lpc32xx_select_command,
- .mode = COMMAND_EXEC,
- .help = "select MLC or SLC controller (default is MLC)",
- .usage = "bank_id ['mlc'|'slc' ]",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration lpc32xx_command_handler[] = {
- {
- .name = "lpc32xx",
- .mode = COMMAND_ANY,
- .help = "LPC32xx NAND flash controller commands",
- .usage = "",
- .chain = lpc32xx_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct nand_flash_controller lpc32xx_nand_controller = {
- .name = "lpc32xx",
- .commands = lpc32xx_command_handler,
- .nand_device_command = lpc32xx_nand_device_command,
- .init = lpc32xx_init,
- .reset = lpc32xx_reset,
- .command = lpc32xx_command,
- .address = lpc32xx_address,
- .write_data = lpc32xx_write_data,
- .read_data = lpc32xx_read_data,
- .write_page = lpc32xx_write_page,
- .read_page = lpc32xx_read_page,
- .nand_ready = lpc32xx_nand_ready,
-};
diff --git a/src/flash/nand/lpc32xx.h b/src/flash/nand/lpc32xx.h
deleted file mode 100644
index 90b20b2..0000000
--- a/src/flash/nand/lpc32xx.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_LPC32XX_H
-#define OPENOCD_FLASH_NAND_LPC32XX_H
-
-enum lpc32xx_selected_controller {
- LPC32xx_NO_CONTROLLER,
- LPC32xx_MLC_CONTROLLER,
- LPC32xx_SLC_CONTROLLER,
-};
-
-struct lpc32xx_nand_controller {
- int osc_freq;
- enum lpc32xx_selected_controller selected_controller;
- int sw_write_protection;
- uint32_t sw_wp_lower_bound;
- uint32_t sw_wp_upper_bound;
-};
-
-#endif /* OPENOCD_FLASH_NAND_LPC32XX_H */
diff --git a/src/flash/nand/mx3.c b/src/flash/nand/mx3.c
deleted file mode 100644
index b61e475..0000000
--- a/src/flash/nand/mx3.c
+++ /dev/null
@@ -1,719 +0,0 @@
-
-/***************************************************************************
- * Copyright (C) 2009 by Alexei Babich *
- * Rezonans plc., Chelyabinsk, Russia *
- * impatt@mail.ru *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * Freescale iMX3* OpenOCD NAND Flash controller support.
- *
- * Many thanks to Ben Dooks for writing s3c24xx driver.
- */
-
-/*
-driver tested with STMicro NAND512W3A @imx31
-tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #", "nand write # file 0"
-get_next_halfword_from_sram_buffer() not tested
-*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "mx3.h"
-#include <target/target.h>
-
-static const char target_not_halted_err_msg[] =
- "target must be halted to use mx3 NAND flash controller";
-static const char data_block_size_err_msg[] =
- "minimal granularity is one half-word, %" PRId32 " is incorrect";
-static const char sram_buffer_bounds_err_msg[] =
- "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
-static const char get_status_register_err_msg[] = "can't get NAND status";
-static uint32_t in_sram_address;
-static unsigned char sign_of_sequental_byte_read;
-
-static int test_iomux_settings(struct target *target, uint32_t value,
- uint32_t mask, const char *text);
-static int initialize_nf_controller(struct nand_device *nand);
-static int get_next_byte_from_sram_buffer(struct target *target, uint8_t *value);
-static int get_next_halfword_from_sram_buffer(struct target *target,
- uint16_t *value);
-static int poll_for_complete_op(struct target *target, const char *text);
-static int validate_target_state(struct nand_device *nand);
-static int do_data_output(struct nand_device *nand);
-
-static int imx31_command(struct nand_device *nand, uint8_t command);
-static int imx31_address(struct nand_device *nand, uint8_t address);
-
-NAND_DEVICE_COMMAND_HANDLER(imx31_nand_device_command)
-{
- struct mx3_nf_controller *mx3_nf_info;
- mx3_nf_info = malloc(sizeof(struct mx3_nf_controller));
- if (mx3_nf_info == NULL) {
- LOG_ERROR("no memory for nand controller");
- return ERROR_FAIL;
- }
-
- nand->controller_priv = mx3_nf_info;
-
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
- /*
- * check hwecc requirements
- */
- {
- int hwecc_needed;
- hwecc_needed = strcmp(CMD_ARGV[2], "hwecc");
- if (hwecc_needed == 0)
- mx3_nf_info->flags.hw_ecc_enabled = 1;
- else
- mx3_nf_info->flags.hw_ecc_enabled = 0;
- }
-
- mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
- mx3_nf_info->fin = MX3_NF_FIN_NONE;
- mx3_nf_info->flags.target_little_endian =
- (nand->target->endianness == TARGET_LITTLE_ENDIAN);
-
- return ERROR_OK;
-}
-
-static int imx31_init(struct nand_device *nand)
-{
- struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
- struct target *target = nand->target;
-
- {
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
- }
-
- {
- uint16_t buffsize_register_content;
- target_read_u16(target, MX3_NF_BUFSIZ, &buffsize_register_content);
- mx3_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
- }
-
- {
- uint32_t pcsr_register_content;
- target_read_u32(target, MX3_PCSR, &pcsr_register_content);
- if (!nand->bus_width) {
- nand->bus_width = (pcsr_register_content & 0x80000000) ? 16 : 8;
- } else {
- pcsr_register_content |= ((nand->bus_width == 16) ? 0x80000000 : 0x00000000);
- target_write_u32(target, MX3_PCSR, pcsr_register_content);
- }
-
- if (!nand->page_size) {
- nand->page_size = (pcsr_register_content & 0x40000000) ? 2048 : 512;
- } else {
- pcsr_register_content |= ((nand->page_size == 2048) ? 0x40000000 : 0x00000000);
- target_write_u32(target, MX3_PCSR, pcsr_register_content);
- }
- if (mx3_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
- LOG_ERROR("NAND controller have only 1 kb SRAM, "
- "so pagesize 2048 is incompatible with it");
- }
- }
-
- {
- uint32_t cgr_register_content;
- target_read_u32(target, MX3_CCM_CGR2, &cgr_register_content);
- if (!(cgr_register_content & 0x00000300)) {
- LOG_ERROR("clock gating to EMI disabled");
- return ERROR_FAIL;
- }
- }
-
- {
- uint32_t gpr_register_content;
- target_read_u32(target, MX3_GPR, &gpr_register_content);
- if (gpr_register_content & 0x00000060) {
- LOG_ERROR("pins mode overrided by GPR");
- return ERROR_FAIL;
- }
- }
-
- {
- /*
- * testing IOMUX settings; must be in "functional-mode output and
- * functional-mode input" mode
- */
- int test_iomux;
- test_iomux = ERROR_OK;
- test_iomux |= test_iomux_settings(target, 0x43fac0c0, 0x7f7f7f00, "d0,d1,d2");
- test_iomux |= test_iomux_settings(target, 0x43fac0c4, 0x7f7f7f7f, "d3,d4,d5,d6");
- test_iomux |= test_iomux_settings(target, 0x43fac0c8, 0x0000007f, "d7");
- if (nand->bus_width == 16) {
- test_iomux |= test_iomux_settings(target, 0x43fac0c8, 0x7f7f7f00, "d8,d9,d10");
- test_iomux |= test_iomux_settings(target, 0x43fac0cc, 0x7f7f7f7f, "d11,d12,d13,d14");
- test_iomux |= test_iomux_settings(target, 0x43fac0d0, 0x0000007f, "d15");
- }
- test_iomux |= test_iomux_settings(target, 0x43fac0d0, 0x7f7f7f00, "nfwp,nfce,nfrb");
- test_iomux |= test_iomux_settings(target, 0x43fac0d4, 0x7f7f7f7f,
- "nfwe,nfre,nfale,nfcle");
- if (test_iomux != ERROR_OK)
- return ERROR_FAIL;
- }
-
- initialize_nf_controller(nand);
-
- {
- int retval;
- uint16_t nand_status_content;
- retval = ERROR_OK;
- retval |= imx31_command(nand, NAND_CMD_STATUS);
- retval |= imx31_address(nand, 0x00);
- retval |= do_data_output(nand);
- if (retval != ERROR_OK) {
- LOG_ERROR(get_status_register_err_msg);
- return ERROR_FAIL;
- }
- target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
- if (!(nand_status_content & 0x0080)) {
- /*
- * is host-big-endian correctly ??
- */
- LOG_INFO("NAND read-only");
- mx3_nf_info->flags.nand_readonly = 1;
- } else
- mx3_nf_info->flags.nand_readonly = 0;
- }
- return ERROR_OK;
-}
-
-static int imx31_read_data(struct nand_device *nand, void *data)
-{
- struct target *target = nand->target;
- {
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
- }
-
- {
- /*
- * get data from nand chip
- */
- int try_data_output_from_nand_chip;
- try_data_output_from_nand_chip = do_data_output(nand);
- if (try_data_output_from_nand_chip != ERROR_OK)
- return try_data_output_from_nand_chip;
- }
-
- if (nand->bus_width == 16)
- get_next_halfword_from_sram_buffer(target, data);
- else
- get_next_byte_from_sram_buffer(target, data);
-
- return ERROR_OK;
-}
-
-static int imx31_write_data(struct nand_device *nand, uint16_t data)
-{
- LOG_ERROR("write_data() not implemented");
- return ERROR_NAND_OPERATION_FAILED;
-}
-
-static int imx31_reset(struct nand_device *nand)
-{
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
- initialize_nf_controller(nand);
- return ERROR_OK;
-}
-
-static int imx31_command(struct nand_device *nand, uint8_t command)
-{
- struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- {
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
- }
-
- switch (command) {
- case NAND_CMD_READOOB:
- command = NAND_CMD_READ0;
- in_sram_address = MX3_NF_SPARE_BUFFER0; /* set read point for
- * data_read() and
- * read_block_data() to
- * spare area in SRAM
- * buffer */
- break;
- case NAND_CMD_READ1:
- command = NAND_CMD_READ0;
- /*
- * offset == one half of page size
- */
- in_sram_address = MX3_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
- default:
- in_sram_address = MX3_NF_MAIN_BUFFER0;
- }
-
- target_write_u16(target, MX3_NF_FCMD, command);
- /*
- * start command input operation (set MX3_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FCI);
- {
- int poll_result;
- poll_result = poll_for_complete_op(target, "command");
- if (poll_result != ERROR_OK)
- return poll_result;
- }
- /*
- * reset cursor to begin of the buffer
- */
- sign_of_sequental_byte_read = 0;
- switch (command) {
- case NAND_CMD_READID:
- mx3_nf_info->optype = MX3_NF_DATAOUT_NANDID;
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_STATUS:
- mx3_nf_info->optype = MX3_NF_DATAOUT_NANDSTATUS;
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_READ0:
- mx3_nf_info->fin = MX3_NF_FIN_DATAOUT;
- mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
- break;
- default:
- mx3_nf_info->optype = MX3_NF_DATAOUT_PAGE;
- }
- return ERROR_OK;
-}
-
-static int imx31_address(struct nand_device *nand, uint8_t address)
-{
- struct target *target = nand->target;
- {
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
- }
-
- target_write_u16(target, MX3_NF_FADDR, address);
- /*
- * start address input operation (set MX3_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FAI);
- {
- int poll_result;
- poll_result = poll_for_complete_op(target, "address");
- if (poll_result != ERROR_OK)
- return poll_result;
- }
- return ERROR_OK;
-}
-
-static int imx31_nand_ready(struct nand_device *nand, int tout)
-{
- uint16_t poll_complete_status;
- struct target *target = nand->target;
-
- {
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
- }
-
- do {
- target_read_u16(target, MX3_NF_CFG2, &poll_complete_status);
- if (poll_complete_status & MX3_NF_BIT_OP_DONE)
- return tout;
- alive_sleep(1);
- } while (tout-- > 0);
- return tout;
-}
-
-static int imx31_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob,
- uint32_t oob_size)
-{
- struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (data_size % 2) {
- LOG_ERROR(data_block_size_err_msg, data_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (oob_size % 2) {
- LOG_ERROR(data_block_size_err_msg, oob_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (!data) {
- LOG_ERROR("nothing to program");
- return ERROR_NAND_OPERATION_FAILED;
- }
- {
- /*
- * validate target state
- */
- int retval;
- retval = validate_target_state(nand);
- if (retval != ERROR_OK)
- return retval;
- }
- {
- int retval = ERROR_OK;
- retval |= imx31_command(nand, NAND_CMD_SEQIN);
- retval |= imx31_address(nand, 0x00);
- retval |= imx31_address(nand, page & 0xff);
- retval |= imx31_address(nand, (page >> 8) & 0xff);
- if (nand->address_cycles >= 4) {
- retval |= imx31_address(nand, (page >> 16) & 0xff);
- if (nand->address_cycles >= 5)
- retval |= imx31_address(nand, (page >> 24) & 0xff);
- }
- target_write_buffer(target, MX3_NF_MAIN_BUFFER0, data_size, data);
- if (oob) {
- if (mx3_nf_info->flags.hw_ecc_enabled) {
- /*
- * part of spare block will be overrided by hardware
- * ECC generator
- */
- LOG_DEBUG("part of spare block will be overrided by hardware ECC generator");
- }
- target_write_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size, oob);
- }
- /*
- * start data input operation (set MX3_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MX3_NF_CFG2, MX3_NF_BIT_OP_FDI);
- {
- int poll_result;
- poll_result = poll_for_complete_op(target, "data input");
- if (poll_result != ERROR_OK)
- return poll_result;
- }
- retval |= imx31_command(nand, NAND_CMD_PAGEPROG);
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * check status register
- */
- {
- uint16_t nand_status_content;
- retval = ERROR_OK;
- retval |= imx31_command(nand, NAND_CMD_STATUS);
- retval |= imx31_address(nand, 0x00);
- retval |= do_data_output(nand);
- if (retval != ERROR_OK) {
- LOG_ERROR(get_status_register_err_msg);
- return retval;
- }
- target_read_u16(target, MX3_NF_MAIN_BUFFER0, &nand_status_content);
- if (nand_status_content & 0x0001) {
- /*
- * is host-big-endian correctly ??
- */
- return ERROR_NAND_OPERATION_FAILED;
- }
- }
- }
- return ERROR_OK;
-}
-
-static int imx31_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size, uint8_t *oob,
- uint32_t oob_size)
-{
- struct target *target = nand->target;
-
- if (data_size % 2) {
- LOG_ERROR(data_block_size_err_msg, data_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (oob_size % 2) {
- LOG_ERROR(data_block_size_err_msg, oob_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- {
- /*
- * validate target state
- */
- int retval;
- retval = validate_target_state(nand);
- if (retval != ERROR_OK)
- return retval;
- }
- {
- int retval = ERROR_OK;
- retval |= imx31_command(nand, NAND_CMD_READ0);
- retval |= imx31_address(nand, 0x00);
- retval |= imx31_address(nand, page & 0xff);
- retval |= imx31_address(nand, (page >> 8) & 0xff);
- if (nand->address_cycles >= 4) {
- retval |= imx31_address(nand, (page >> 16) & 0xff);
- if (nand->address_cycles >= 5) {
- retval |= imx31_address(nand, (page >> 24) & 0xff);
- retval |= imx31_command(nand, NAND_CMD_READSTART);
- }
- }
- retval |= do_data_output(nand);
- if (retval != ERROR_OK)
- return retval;
-
- if (data) {
- target_read_buffer(target, MX3_NF_MAIN_BUFFER0, data_size,
- data);
- }
- if (oob) {
- target_read_buffer(target, MX3_NF_SPARE_BUFFER0, oob_size,
- oob);
- }
- }
- return ERROR_OK;
-}
-
-static int test_iomux_settings(struct target *target, uint32_t address,
- uint32_t mask, const char *text)
-{
- uint32_t register_content;
- target_read_u32(target, address, &register_content);
- if ((register_content & mask) != (0x12121212 & mask)) {
- LOG_ERROR("IOMUX for {%s} is bad", text);
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int initialize_nf_controller(struct nand_device *nand)
-{
- struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- /*
- * resets NAND flash controller in zero time ? I dont know.
- */
- target_write_u16(target, MX3_NF_CFG1, MX3_NF_BIT_RESET_EN);
- {
- uint16_t work_mode;
- work_mode = MX3_NF_BIT_INT_DIS; /* disable interrupt */
- if (target->endianness == TARGET_BIG_ENDIAN)
- work_mode |= MX3_NF_BIT_BE_EN;
- if (mx3_nf_info->flags.hw_ecc_enabled)
- work_mode |= MX3_NF_BIT_ECC_EN;
- target_write_u16(target, MX3_NF_CFG1, work_mode);
- }
- /*
- * unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock"
- */
- target_write_u16(target, MX3_NF_BUFCFG, 2);
- {
- uint16_t temp;
- target_read_u16(target, MX3_NF_FWP, &temp);
- if ((temp & 0x0007) == 1) {
- LOG_ERROR("NAND flash is tight-locked, reset needed");
- return ERROR_FAIL;
- }
-
- }
- /*
- * unlock NAND flash for write
- */
- target_write_u16(target, MX3_NF_FWP, 4);
- target_write_u16(target, MX3_NF_LOCKSTART, 0x0000);
- target_write_u16(target, MX3_NF_LOCKEND, 0xFFFF);
- /*
- * 0x0000 means that first SRAM buffer @0xB800_0000 will be used
- */
- target_write_u16(target, MX3_NF_BUFADDR, 0x0000);
- /*
- * address of SRAM buffer
- */
- in_sram_address = MX3_NF_MAIN_BUFFER0;
- sign_of_sequental_byte_read = 0;
- return ERROR_OK;
-}
-
-static int get_next_byte_from_sram_buffer(struct target *target, uint8_t *value)
-{
- static uint8_t even_byte;
- /*
- * host-big_endian ??
- */
- if (sign_of_sequental_byte_read == 0)
- even_byte = 0;
- if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) {
- LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
- *value = 0;
- sign_of_sequental_byte_read = 0;
- even_byte = 0;
- return ERROR_NAND_OPERATION_FAILED;
- } else {
- uint16_t temp;
- target_read_u16(target, in_sram_address, &temp);
- if (even_byte) {
- *value = temp >> 8;
- even_byte = 0;
- in_sram_address += 2;
- } else {
- *value = temp & 0xff;
- even_byte = 1;
- }
- }
- sign_of_sequental_byte_read = 1;
- return ERROR_OK;
-}
-
-static int get_next_halfword_from_sram_buffer(struct target *target,
- uint16_t *value)
-{
- if (in_sram_address > MX3_NF_LAST_BUFFER_ADDR) {
- LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
- *value = 0;
- return ERROR_NAND_OPERATION_FAILED;
- } else {
- target_read_u16(target, in_sram_address, value);
- in_sram_address += 2;
- }
- return ERROR_OK;
-}
-
-static int poll_for_complete_op(struct target *target, const char *text)
-{
- uint16_t poll_complete_status;
- for (int poll_cycle_count = 0; poll_cycle_count < 100; poll_cycle_count++) {
- usleep(25);
- target_read_u16(target, MX3_NF_CFG2, &poll_complete_status);
- if (poll_complete_status & MX3_NF_BIT_OP_DONE)
- break;
- }
- if (!(poll_complete_status & MX3_NF_BIT_OP_DONE)) {
- LOG_ERROR("%s sending timeout", text);
- return ERROR_NAND_OPERATION_FAILED;
- }
- return ERROR_OK;
-}
-
-static int validate_target_state(struct nand_device *nand)
-{
- struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR(target_not_halted_err_msg);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (mx3_nf_info->flags.target_little_endian !=
- (target->endianness == TARGET_LITTLE_ENDIAN)) {
- /*
- * endianness changed after NAND controller probed
- */
- return ERROR_NAND_OPERATION_FAILED;
- }
- return ERROR_OK;
-}
-
-static int do_data_output(struct nand_device *nand)
-{
- struct mx3_nf_controller *mx3_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- switch (mx3_nf_info->fin) {
- case MX3_NF_FIN_DATAOUT:
- /*
- * start data output operation (set MX3_NF_BIT_OP_DONE==0)
- */
- target_write_u16 (target, MX3_NF_CFG2,
- MX3_NF_BIT_DATAOUT_TYPE(mx3_nf_info->optype));
- {
- int poll_result;
- poll_result = poll_for_complete_op(target, "data output");
- if (poll_result != ERROR_OK)
- return poll_result;
- }
- mx3_nf_info->fin = MX3_NF_FIN_NONE;
- /*
- * ECC stuff
- */
- if ((mx3_nf_info->optype == MX3_NF_DATAOUT_PAGE)
- && mx3_nf_info->flags.hw_ecc_enabled) {
- uint16_t ecc_status;
- target_read_u16 (target, MX3_NF_ECCSTATUS, &ecc_status);
- switch (ecc_status & 0x000c) {
- case 1 << 2:
- LOG_DEBUG("main area readed with 1 (correctable) error");
- break;
- case 2 << 2:
- LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
- }
- switch (ecc_status & 0x0003) {
- case 1:
- LOG_DEBUG("spare area readed with 1 (correctable) error");
- break;
- case 2:
- LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
- }
- }
- break;
- case MX3_NF_FIN_NONE:
- break;
- }
- return ERROR_OK;
-}
-
-struct nand_flash_controller imx31_nand_flash_controller = {
- .name = "imx31",
- .usage = "nand device imx31 target noecc|hwecc",
- .nand_device_command = &imx31_nand_device_command,
- .init = &imx31_init,
- .reset = &imx31_reset,
- .command = &imx31_command,
- .address = &imx31_address,
- .write_data = &imx31_write_data,
- .read_data = &imx31_read_data,
- .write_page = &imx31_write_page,
- .read_page = &imx31_read_page,
- .nand_ready = &imx31_nand_ready,
-};
diff --git a/src/flash/nand/mx3.h b/src/flash/nand/mx3.h
deleted file mode 100644
index 00664d8..0000000
--- a/src/flash/nand/mx3.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Alexei Babich *
- * Rezonans plc., Chelyabinsk, Russia *
- * impatt@mail.ru *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_MX3_H
-#define OPENOCD_FLASH_NAND_MX3_H
-
-/*
- * Freescale iMX3* OpenOCD NAND Flash controller support.
- *
- * Many thanks to Ben Dooks for writing s3c24xx driver.
- */
-
-#define MX3_NF_BASE_ADDR 0xb8000000
-#define MX3_NF_BUFSIZ (MX3_NF_BASE_ADDR + 0xe00)
-#define MX3_NF_BUFADDR (MX3_NF_BASE_ADDR + 0xe04)
-#define MX3_NF_FADDR (MX3_NF_BASE_ADDR + 0xe06)
-#define MX3_NF_FCMD (MX3_NF_BASE_ADDR + 0xe08)
-#define MX3_NF_BUFCFG (MX3_NF_BASE_ADDR + 0xe0a)
-#define MX3_NF_ECCSTATUS (MX3_NF_BASE_ADDR + 0xe0c)
-#define MX3_NF_ECCMAINPOS (MX3_NF_BASE_ADDR + 0xe0e)
-#define MX3_NF_ECCSPAREPOS (MX3_NF_BASE_ADDR + 0xe10)
-#define MX3_NF_FWP (MX3_NF_BASE_ADDR + 0xe12)
-#define MX3_NF_LOCKSTART (MX3_NF_BASE_ADDR + 0xe14)
-#define MX3_NF_LOCKEND (MX3_NF_BASE_ADDR + 0xe16)
-#define MX3_NF_FWPSTATUS (MX3_NF_BASE_ADDR + 0xe18)
-/*
- * all bits not marked as self-clearing bit
- */
-#define MX3_NF_CFG1 (MX3_NF_BASE_ADDR + 0xe1a)
-#define MX3_NF_CFG2 (MX3_NF_BASE_ADDR + 0xe1c)
-
-#define MX3_NF_MAIN_BUFFER0 (MX3_NF_BASE_ADDR + 0x0000)
-#define MX3_NF_MAIN_BUFFER1 (MX3_NF_BASE_ADDR + 0x0200)
-#define MX3_NF_MAIN_BUFFER2 (MX3_NF_BASE_ADDR + 0x0400)
-#define MX3_NF_MAIN_BUFFER3 (MX3_NF_BASE_ADDR + 0x0600)
-#define MX3_NF_SPARE_BUFFER0 (MX3_NF_BASE_ADDR + 0x0800)
-#define MX3_NF_SPARE_BUFFER1 (MX3_NF_BASE_ADDR + 0x0810)
-#define MX3_NF_SPARE_BUFFER2 (MX3_NF_BASE_ADDR + 0x0820)
-#define MX3_NF_SPARE_BUFFER3 (MX3_NF_BASE_ADDR + 0x0830)
-#define MX3_NF_MAIN_BUFFER_LEN 512
-#define MX3_NF_SPARE_BUFFER_LEN 16
-#define MX3_NF_LAST_BUFFER_ADDR ((MX3_NF_SPARE_BUFFER3) + MX3_NF_SPARE_BUFFER_LEN - 2)
-
-/* bits in MX3_NF_CFG1 register */
-#define MX3_NF_BIT_SPARE_ONLY_EN (1<<2)
-#define MX3_NF_BIT_ECC_EN (1<<3)
-#define MX3_NF_BIT_INT_DIS (1<<4)
-#define MX3_NF_BIT_BE_EN (1<<5)
-#define MX3_NF_BIT_RESET_EN (1<<6)
-#define MX3_NF_BIT_FORCE_CE (1<<7)
-
-/* bits in MX3_NF_CFG2 register */
-
-/*Flash Command Input*/
-#define MX3_NF_BIT_OP_FCI (1<<0)
-/*
- * Flash Address Input
- */
-#define MX3_NF_BIT_OP_FAI (1<<1)
-/*
- * Flash Data Input
- */
-#define MX3_NF_BIT_OP_FDI (1<<2)
-
-/* see "enum mx_dataout_type" below */
-#define MX3_NF_BIT_DATAOUT_TYPE(x) ((x)<<3)
-#define MX3_NF_BIT_OP_DONE (1<<15)
-
-#define MX3_CCM_CGR2 0x53f80028
-#define MX3_GPR 0x43fac008
-#define MX3_PCSR 0x53f8000c
-
-enum mx_dataout_type {
- MX3_NF_DATAOUT_PAGE = 1,
- MX3_NF_DATAOUT_NANDID = 2,
- MX3_NF_DATAOUT_NANDSTATUS = 4,
-};
-enum mx_nf_finalize_action {
- MX3_NF_FIN_NONE,
- MX3_NF_FIN_DATAOUT,
-};
-
-struct mx3_nf_flags {
- unsigned target_little_endian:1;
- unsigned nand_readonly:1;
- unsigned one_kb_sram:1;
- unsigned hw_ecc_enabled:1;
-};
-
-struct mx3_nf_controller {
- enum mx_dataout_type optype;
- enum mx_nf_finalize_action fin;
- struct mx3_nf_flags flags;
-};
-
-#endif /* OPENOCD_FLASH_NAND_MX3_H */
diff --git a/src/flash/nand/mxc.c b/src/flash/nand/mxc.c
deleted file mode 100644
index 5e59b9a..0000000
--- a/src/flash/nand/mxc.c
+++ /dev/null
@@ -1,960 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Alexei Babich *
- * Rezonans plc., Chelyabinsk, Russia *
- * impatt@mail.ru *
- * *
- * Copyright (C) 2010 by Gaetan CARLIER *
- * Trump s.a., Belgium *
- * *
- * Copyright (C) 2011 by Erik Ahlen *
- * Avalon Innovation, Sweden *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * Freescale iMX OpenOCD NAND Flash controller support.
- * based on Freescale iMX2* and iMX3* OpenOCD NAND Flash controller support.
- */
-
-/*
- * driver tested with Samsung K9F2G08UXA and Numonyx/ST NAND02G-B2D @mxc
- * tested "nand probe #", "nand erase # 0 #", "nand dump # file 0 #",
- * "nand write # file 0", "nand verify"
- *
- * get_next_halfword_from_sram_buffer() not tested
- * !! all function only tested with 2k page nand device; mxc_write_page
- * writes the 4 MAIN_BUFFER's and is not compatible with < 2k page
- * !! oob must be be used due to NFS bug
- * !! oob must be 64 bytes per 2KiB page
-*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "mxc.h"
-#include <target/target.h>
-
-#define OOB_SIZE 64
-
-#define nfc_is_v1() (mxc_nf_info->mxc_version == MXC_VERSION_MX27 || \
- mxc_nf_info->mxc_version == MXC_VERSION_MX31)
-#define nfc_is_v2() (mxc_nf_info->mxc_version == MXC_VERSION_MX25 || \
- mxc_nf_info->mxc_version == MXC_VERSION_MX35)
-
-/* This permits to print (in LOG_INFO) how much bytes
- * has been written after a page read or write.
- * This is useful when OpenOCD is used with a graphical
- * front-end to estimate progression of the global read/write
- */
-#undef _MXC_PRINT_STAT
-/* #define _MXC_PRINT_STAT */
-
-static const char target_not_halted_err_msg[] =
- "target must be halted to use mxc NAND flash controller";
-static const char data_block_size_err_msg[] =
- "minimal granularity is one half-word, %" PRId32 " is incorrect";
-static const char sram_buffer_bounds_err_msg[] =
- "trying to access out of SRAM buffer bound (addr=0x%" PRIx32 ")";
-static const char get_status_register_err_msg[] = "can't get NAND status";
-static uint32_t in_sram_address;
-static unsigned char sign_of_sequental_byte_read;
-
-static uint32_t align_address_v2(struct nand_device *nand, uint32_t addr);
-static int initialize_nf_controller(struct nand_device *nand);
-static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *value);
-static int get_next_halfword_from_sram_buffer(struct nand_device *nand, uint16_t *value);
-static int poll_for_complete_op(struct nand_device *nand, const char *text);
-static int validate_target_state(struct nand_device *nand);
-static int do_data_output(struct nand_device *nand);
-
-static int mxc_command(struct nand_device *nand, uint8_t command);
-static int mxc_address(struct nand_device *nand, uint8_t address);
-
-NAND_DEVICE_COMMAND_HANDLER(mxc_nand_device_command)
-{
- struct mxc_nf_controller *mxc_nf_info;
- int hwecc_needed;
-
- mxc_nf_info = malloc(sizeof(struct mxc_nf_controller));
- if (mxc_nf_info == NULL) {
- LOG_ERROR("no memory for nand controller");
- return ERROR_FAIL;
- }
- nand->controller_priv = mxc_nf_info;
-
- if (CMD_ARGC < 4) {
- LOG_ERROR("use \"nand device mxc target mx25|mx27|mx31|mx35 noecc|hwecc [biswap]\"");
- return ERROR_FAIL;
- }
-
- /*
- * check board type
- */
- if (strcmp(CMD_ARGV[2], "mx25") == 0) {
- mxc_nf_info->mxc_version = MXC_VERSION_MX25;
- mxc_nf_info->mxc_base_addr = 0xBB000000;
- mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x1E00;
- } else if (strcmp(CMD_ARGV[2], "mx27") == 0) {
- mxc_nf_info->mxc_version = MXC_VERSION_MX27;
- mxc_nf_info->mxc_base_addr = 0xD8000000;
- mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x0E00;
- } else if (strcmp(CMD_ARGV[2], "mx31") == 0) {
- mxc_nf_info->mxc_version = MXC_VERSION_MX31;
- mxc_nf_info->mxc_base_addr = 0xB8000000;
- mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x0E00;
- } else if (strcmp(CMD_ARGV[2], "mx35") == 0) {
- mxc_nf_info->mxc_version = MXC_VERSION_MX35;
- mxc_nf_info->mxc_base_addr = 0xBB000000;
- mxc_nf_info->mxc_regs_addr = mxc_nf_info->mxc_base_addr + 0x1E00;
- }
-
- /*
- * check hwecc requirements
- */
- hwecc_needed = strcmp(CMD_ARGV[3], "hwecc");
- if (hwecc_needed == 0)
- mxc_nf_info->flags.hw_ecc_enabled = 1;
- else
- mxc_nf_info->flags.hw_ecc_enabled = 0;
-
- mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
- mxc_nf_info->fin = MXC_NF_FIN_NONE;
- mxc_nf_info->flags.target_little_endian =
- (nand->target->endianness == TARGET_LITTLE_ENDIAN);
-
- /*
- * should factory bad block indicator be swaped
- * as a workaround for how the nfc handles pages.
- */
- if (CMD_ARGC > 4 && strcmp(CMD_ARGV[4], "biswap") == 0) {
- LOG_DEBUG("BI-swap enabled");
- mxc_nf_info->flags.biswap_enabled = 1;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_mxc_biswap_command)
-{
- struct nand_device *nand = NULL;
- struct mxc_nf_controller *mxc_nf_info = NULL;
-
- if (CMD_ARGC < 1 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &nand);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX, "invalid nand device number or name: %s", CMD_ARGV[0]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- mxc_nf_info = nand->controller_priv;
- if (CMD_ARGC == 2) {
- if (strcmp(CMD_ARGV[1], "enable") == 0)
- mxc_nf_info->flags.biswap_enabled = true;
- else
- mxc_nf_info->flags.biswap_enabled = false;
- }
- if (mxc_nf_info->flags.biswap_enabled)
- command_print(CMD_CTX, "BI-swapping enabled on %s", nand->name);
- else
- command_print(CMD_CTX, "BI-swapping disabled on %s", nand->name);
-
- return ERROR_OK;
-}
-
-static const struct command_registration mxc_sub_command_handlers[] = {
- {
- .name = "biswap",
- .handler = handle_mxc_biswap_command,
- .help = "Turns on/off bad block information swaping from main area, "
- "without parameter query status.",
- .usage = "bank_id ['enable'|'disable']",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration mxc_nand_command_handler[] = {
- {
- .name = "mxc",
- .mode = COMMAND_ANY,
- .help = "MXC NAND flash controller commands",
- .chain = mxc_sub_command_handlers
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int mxc_init(struct nand_device *nand)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
-
- int validate_target_result;
- uint16_t buffsize_register_content;
- uint32_t sreg_content;
- uint32_t SREG = MX2_FMCR;
- uint32_t SEL_16BIT = MX2_FMCR_NF_16BIT_SEL;
- uint32_t SEL_FMS = MX2_FMCR_NF_FMS;
- int retval;
- uint16_t nand_status_content;
- /*
- * validate target state
- */
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
-
- if (nfc_is_v1()) {
- target_read_u16(target, MXC_NF_BUFSIZ, &buffsize_register_content);
- mxc_nf_info->flags.one_kb_sram = !(buffsize_register_content & 0x000f);
- } else
- mxc_nf_info->flags.one_kb_sram = 0;
-
- if (mxc_nf_info->mxc_version == MXC_VERSION_MX31) {
- SREG = MX3_PCSR;
- SEL_16BIT = MX3_PCSR_NF_16BIT_SEL;
- SEL_FMS = MX3_PCSR_NF_FMS;
- } else if (mxc_nf_info->mxc_version == MXC_VERSION_MX25) {
- SREG = MX25_RCSR;
- SEL_16BIT = MX25_RCSR_NF_16BIT_SEL;
- SEL_FMS = MX25_RCSR_NF_FMS;
- } else if (mxc_nf_info->mxc_version == MXC_VERSION_MX35) {
- SREG = MX35_RCSR;
- SEL_16BIT = MX35_RCSR_NF_16BIT_SEL;
- SEL_FMS = MX35_RCSR_NF_FMS;
- }
-
- target_read_u32(target, SREG, &sreg_content);
- if (!nand->bus_width) {
- /* bus_width not yet defined. Read it from MXC_FMCR */
- nand->bus_width = (sreg_content & SEL_16BIT) ? 16 : 8;
- } else {
- /* bus_width forced in soft. Sync it to MXC_FMCR */
- sreg_content |= ((nand->bus_width == 16) ? SEL_16BIT : 0x00000000);
- target_write_u32(target, SREG, sreg_content);
- }
- if (nand->bus_width == 16)
- LOG_DEBUG("MXC_NF : bus is 16-bit width");
- else
- LOG_DEBUG("MXC_NF : bus is 8-bit width");
-
- if (!nand->page_size)
- nand->page_size = (sreg_content & SEL_FMS) ? 2048 : 512;
- else {
- sreg_content |= ((nand->page_size == 2048) ? SEL_FMS : 0x00000000);
- target_write_u32(target, SREG, sreg_content);
- }
- if (mxc_nf_info->flags.one_kb_sram && (nand->page_size == 2048)) {
- LOG_ERROR("NAND controller have only 1 kb SRAM, so "
- "pagesize 2048 is incompatible with it");
- } else
- LOG_DEBUG("MXC_NF : NAND controller can handle pagesize of 2048");
-
- if (nfc_is_v2() && sreg_content & MX35_RCSR_NF_4K)
- LOG_ERROR("MXC driver does not have support for 4k pagesize.");
-
- initialize_nf_controller(nand);
-
- retval = ERROR_OK;
- retval |= mxc_command(nand, NAND_CMD_STATUS);
- retval |= mxc_address(nand, 0x00);
- retval |= do_data_output(nand);
- if (retval != ERROR_OK) {
- LOG_ERROR(get_status_register_err_msg);
- return ERROR_FAIL;
- }
- target_read_u16(target, MXC_NF_MAIN_BUFFER0, &nand_status_content);
- if (!(nand_status_content & 0x0080)) {
- LOG_INFO("NAND read-only");
- mxc_nf_info->flags.nand_readonly = 1;
- } else
- mxc_nf_info->flags.nand_readonly = 0;
- return ERROR_OK;
-}
-
-static int mxc_read_data(struct nand_device *nand, void *data)
-{
- int validate_target_result;
- int try_data_output_from_nand_chip;
- /*
- * validate target state
- */
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
-
- /*
- * get data from nand chip
- */
- try_data_output_from_nand_chip = do_data_output(nand);
- if (try_data_output_from_nand_chip != ERROR_OK) {
- LOG_ERROR("mxc_read_data : read data failed : '%x'",
- try_data_output_from_nand_chip);
- return try_data_output_from_nand_chip;
- }
-
- if (nand->bus_width == 16)
- get_next_halfword_from_sram_buffer(nand, data);
- else
- get_next_byte_from_sram_buffer(nand, data);
-
- return ERROR_OK;
-}
-
-static int mxc_write_data(struct nand_device *nand, uint16_t data)
-{
- LOG_ERROR("write_data() not implemented");
- return ERROR_NAND_OPERATION_FAILED;
-}
-
-static int mxc_reset(struct nand_device *nand)
-{
- /*
- * validate target state
- */
- int validate_target_result;
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
- initialize_nf_controller(nand);
- return ERROR_OK;
-}
-
-static int mxc_command(struct nand_device *nand, uint8_t command)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- int validate_target_result;
- int poll_result;
- /*
- * validate target state
- */
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
-
- switch (command) {
- case NAND_CMD_READOOB:
- command = NAND_CMD_READ0;
- /* set read point for data_read() and read_block_data() to
- * spare area in SRAM buffer
- */
- if (nfc_is_v1())
- in_sram_address = MXC_NF_V1_SPARE_BUFFER0;
- else
- in_sram_address = MXC_NF_V2_SPARE_BUFFER0;
- break;
- case NAND_CMD_READ1:
- command = NAND_CMD_READ0;
- /*
- * offset == one half of page size
- */
- in_sram_address = MXC_NF_MAIN_BUFFER0 + (nand->page_size >> 1);
- break;
- default:
- in_sram_address = MXC_NF_MAIN_BUFFER0;
- break;
- }
-
- target_write_u16(target, MXC_NF_FCMD, command);
- /*
- * start command input operation (set MXC_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FCI);
- poll_result = poll_for_complete_op(nand, "command");
- if (poll_result != ERROR_OK)
- return poll_result;
- /*
- * reset cursor to begin of the buffer
- */
- sign_of_sequental_byte_read = 0;
- /* Handle special read command and adjust NF_CFG2(FDO) */
- switch (command) {
- case NAND_CMD_READID:
- mxc_nf_info->optype = MXC_NF_DATAOUT_NANDID;
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- break;
- case NAND_CMD_STATUS:
- mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS;
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- target_write_u16 (target, MXC_NF_BUFADDR, 0);
- in_sram_address = 0;
- break;
- case NAND_CMD_READ0:
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
- break;
- default:
- /* Ohter command use the default 'One page data out' FDO */
- mxc_nf_info->optype = MXC_NF_DATAOUT_PAGE;
- break;
- }
- return ERROR_OK;
-}
-
-static int mxc_address(struct nand_device *nand, uint8_t address)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- int validate_target_result;
- int poll_result;
- /*
- * validate target state
- */
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
-
- target_write_u16(target, MXC_NF_FADDR, address);
- /*
- * start address input operation (set MXC_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FAI);
- poll_result = poll_for_complete_op(nand, "address");
- if (poll_result != ERROR_OK)
- return poll_result;
-
- return ERROR_OK;
-}
-
-static int mxc_nand_ready(struct nand_device *nand, int tout)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- uint16_t poll_complete_status;
- int validate_target_result;
-
- /*
- * validate target state
- */
- validate_target_result = validate_target_state(nand);
- if (validate_target_result != ERROR_OK)
- return validate_target_result;
-
- do {
- target_read_u16(target, MXC_NF_CFG2, &poll_complete_status);
- if (poll_complete_status & MXC_NF_BIT_OP_DONE)
- return tout;
-
- alive_sleep(1);
- } while (tout-- > 0);
- return tout;
-}
-
-static int mxc_write_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
- uint16_t nand_status_content;
- uint16_t swap1, swap2, new_swap1;
- uint8_t bufs;
- int poll_result;
-
- if (data_size % 2) {
- LOG_ERROR(data_block_size_err_msg, data_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (oob_size % 2) {
- LOG_ERROR(data_block_size_err_msg, oob_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (!data) {
- LOG_ERROR("nothing to program");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /*
- * validate target state
- */
- retval = validate_target_state(nand);
- if (retval != ERROR_OK)
- return retval;
-
- in_sram_address = MXC_NF_MAIN_BUFFER0;
- sign_of_sequental_byte_read = 0;
- retval = ERROR_OK;
- retval |= mxc_command(nand, NAND_CMD_SEQIN);
- retval |= mxc_address(nand, 0); /* col */
- retval |= mxc_address(nand, 0); /* col */
- retval |= mxc_address(nand, page & 0xff); /* page address */
- retval |= mxc_address(nand, (page >> 8) & 0xff);/* page address */
- retval |= mxc_address(nand, (page >> 16) & 0xff); /* page address */
-
- target_write_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data);
- if (oob) {
- if (mxc_nf_info->flags.hw_ecc_enabled) {
- /*
- * part of spare block will be overrided by hardware
- * ECC generator
- */
- LOG_DEBUG("part of spare block will be overrided "
- "by hardware ECC generator");
- }
- if (nfc_is_v1())
- target_write_buffer(target, MXC_NF_V1_SPARE_BUFFER0, oob_size, oob);
- else {
- uint32_t addr = MXC_NF_V2_SPARE_BUFFER0;
- while (oob_size > 0) {
- uint8_t len = MIN(oob_size, MXC_NF_SPARE_BUFFER_LEN);
- target_write_buffer(target, addr, len, oob);
- addr = align_address_v2(nand, addr + len);
- oob += len;
- oob_size -= len;
- }
- }
- }
-
- if (nand->page_size > 512 && mxc_nf_info->flags.biswap_enabled) {
- /* BI-swap - work-around of i.MX NFC for NAND device with page == 2kb*/
- target_read_u16(target, MXC_NF_MAIN_BUFFER3 + 464, &swap1);
- if (oob) {
- LOG_ERROR("Due to NFC Bug, oob is not correctly implemented in mxc driver");
- return ERROR_NAND_OPERATION_FAILED;
- }
- swap2 = 0xffff; /* Spare buffer unused forced to 0xffff */
- new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8);
- swap2 = (swap1 << 8) | (swap2 & 0xFF);
- target_write_u16(target, MXC_NF_MAIN_BUFFER3 + 464, new_swap1);
- if (nfc_is_v1())
- target_write_u16(target, MXC_NF_V1_SPARE_BUFFER3 + 4, swap2);
- else
- target_write_u16(target, MXC_NF_V2_SPARE_BUFFER3, swap2);
- }
-
- /*
- * start data input operation (set MXC_NF_BIT_OP_DONE==0)
- */
- if (nfc_is_v1() && nand->page_size > 512)
- bufs = 4;
- else
- bufs = 1;
-
- for (uint8_t i = 0; i < bufs; ++i) {
- target_write_u16(target, MXC_NF_BUFADDR, i);
- target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_OP_FDI);
- poll_result = poll_for_complete_op(nand, "data input");
- if (poll_result != ERROR_OK)
- return poll_result;
- }
-
- retval |= mxc_command(nand, NAND_CMD_PAGEPROG);
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * check status register
- */
- retval = ERROR_OK;
- retval |= mxc_command(nand, NAND_CMD_STATUS);
- target_write_u16 (target, MXC_NF_BUFADDR, 0);
- mxc_nf_info->optype = MXC_NF_DATAOUT_NANDSTATUS;
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- retval |= do_data_output(nand);
- if (retval != ERROR_OK) {
- LOG_ERROR(get_status_register_err_msg);
- return retval;
- }
- target_read_u16(target, MXC_NF_MAIN_BUFFER0, &nand_status_content);
- if (nand_status_content & 0x0001) {
- /*
- * page not correctly written
- */
- return ERROR_NAND_OPERATION_FAILED;
- }
-#ifdef _MXC_PRINT_STAT
- LOG_INFO("%d bytes newly written", data_size);
-#endif
- return ERROR_OK;
-}
-
-static int mxc_read_page(struct nand_device *nand, uint32_t page,
- uint8_t *data, uint32_t data_size,
- uint8_t *oob, uint32_t oob_size)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- int retval;
- uint8_t bufs;
- uint16_t swap1, swap2, new_swap1;
-
- if (data_size % 2) {
- LOG_ERROR(data_block_size_err_msg, data_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
- if (oob_size % 2) {
- LOG_ERROR(data_block_size_err_msg, oob_size);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- /*
- * validate target state
- */
- retval = validate_target_state(nand);
- if (retval != ERROR_OK)
- return retval;
- /* Reset address_cycles before mxc_command ?? */
- retval = mxc_command(nand, NAND_CMD_READ0);
- if (retval != ERROR_OK)
- return retval;
- retval = mxc_address(nand, 0); /* col */
- if (retval != ERROR_OK)
- return retval;
- retval = mxc_address(nand, 0); /* col */
- if (retval != ERROR_OK)
- return retval;
- retval = mxc_address(nand, page & 0xff);/* page address */
- if (retval != ERROR_OK)
- return retval;
- retval = mxc_address(nand, (page >> 8) & 0xff); /* page address */
- if (retval != ERROR_OK)
- return retval;
- retval = mxc_address(nand, (page >> 16) & 0xff);/* page address */
- if (retval != ERROR_OK)
- return retval;
- retval = mxc_command(nand, NAND_CMD_READSTART);
- if (retval != ERROR_OK)
- return retval;
-
- if (nfc_is_v1() && nand->page_size > 512)
- bufs = 4;
- else
- bufs = 1;
-
- for (uint8_t i = 0; i < bufs; ++i) {
- target_write_u16(target, MXC_NF_BUFADDR, i);
- mxc_nf_info->fin = MXC_NF_FIN_DATAOUT;
- retval = do_data_output(nand);
- if (retval != ERROR_OK) {
- LOG_ERROR("MXC_NF : Error reading page %d", i);
- return retval;
- }
- }
-
- if (nand->page_size > 512 && mxc_nf_info->flags.biswap_enabled) {
- uint32_t SPARE_BUFFER3;
- /* BI-swap - work-around of mxc NFC for NAND device with page == 2k */
- target_read_u16(target, MXC_NF_MAIN_BUFFER3 + 464, &swap1);
- if (nfc_is_v1())
- SPARE_BUFFER3 = MXC_NF_V1_SPARE_BUFFER3 + 4;
- else
- SPARE_BUFFER3 = MXC_NF_V2_SPARE_BUFFER3;
- target_read_u16(target, SPARE_BUFFER3, &swap2);
- new_swap1 = (swap1 & 0xFF00) | (swap2 >> 8);
- swap2 = (swap1 << 8) | (swap2 & 0xFF);
- target_write_u16(target, MXC_NF_MAIN_BUFFER3 + 464, new_swap1);
- target_write_u16(target, SPARE_BUFFER3, swap2);
- }
-
- if (data)
- target_read_buffer(target, MXC_NF_MAIN_BUFFER0, data_size, data);
- if (oob) {
- if (nfc_is_v1())
- target_read_buffer(target, MXC_NF_V1_SPARE_BUFFER0, oob_size, oob);
- else {
- uint32_t addr = MXC_NF_V2_SPARE_BUFFER0;
- while (oob_size > 0) {
- uint8_t len = MIN(oob_size, MXC_NF_SPARE_BUFFER_LEN);
- target_read_buffer(target, addr, len, oob);
- addr = align_address_v2(nand, addr + len);
- oob += len;
- oob_size -= len;
- }
- }
- }
-
-#ifdef _MXC_PRINT_STAT
- if (data_size > 0) {
- /* When Operation Status is read (when page is erased),
- * this function is used but data_size is null.
- */
- LOG_INFO("%d bytes newly read", data_size);
- }
-#endif
- return ERROR_OK;
-}
-
-static uint32_t align_address_v2(struct nand_device *nand, uint32_t addr)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- uint32_t ret = addr;
- if (addr > MXC_NF_V2_SPARE_BUFFER0 &&
- (addr & 0x1F) == MXC_NF_SPARE_BUFFER_LEN)
- ret += MXC_NF_SPARE_BUFFER_MAX - MXC_NF_SPARE_BUFFER_LEN;
- else if (addr >= (mxc_nf_info->mxc_base_addr + (uint32_t)nand->page_size))
- ret = MXC_NF_V2_SPARE_BUFFER0;
- return ret;
-}
-
-static int initialize_nf_controller(struct nand_device *nand)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- uint16_t work_mode = 0;
- uint16_t temp;
- /*
- * resets NAND flash controller in zero time ? I dont know.
- */
- target_write_u16(target, MXC_NF_CFG1, MXC_NF_BIT_RESET_EN);
- if (mxc_nf_info->mxc_version == MXC_VERSION_MX27)
- work_mode = MXC_NF_BIT_INT_DIS; /* disable interrupt */
-
- if (target->endianness == TARGET_BIG_ENDIAN) {
- LOG_DEBUG("MXC_NF : work in Big Endian mode");
- work_mode |= MXC_NF_BIT_BE_EN;
- } else
- LOG_DEBUG("MXC_NF : work in Little Endian mode");
- if (mxc_nf_info->flags.hw_ecc_enabled) {
- LOG_DEBUG("MXC_NF : work with ECC mode");
- work_mode |= MXC_NF_BIT_ECC_EN;
- } else
- LOG_DEBUG("MXC_NF : work without ECC mode");
- if (nfc_is_v2()) {
- target_write_u16(target, MXC_NF_V2_SPAS, OOB_SIZE / 2);
- if (nand->page_size) {
- uint16_t pages_per_block = nand->erase_size / nand->page_size;
- work_mode |= MXC_NF_V2_CFG1_PPB(ffs(pages_per_block) - 6);
- }
- work_mode |= MXC_NF_BIT_ECC_4BIT;
- }
- target_write_u16(target, MXC_NF_CFG1, work_mode);
-
- /*
- * unlock SRAM buffer for write; 2 mean "Unlock", other values means "Lock"
- */
- target_write_u16(target, MXC_NF_BUFCFG, 2);
- target_read_u16(target, MXC_NF_FWP, &temp);
- if ((temp & 0x0007) == 1) {
- LOG_ERROR("NAND flash is tight-locked, reset needed");
- return ERROR_FAIL;
- }
-
- /*
- * unlock NAND flash for write
- */
- if (nfc_is_v1()) {
- target_write_u16(target, MXC_NF_V1_UNLOCKSTART, 0x0000);
- target_write_u16(target, MXC_NF_V1_UNLOCKEND, 0xFFFF);
- } else {
- target_write_u16(target, MXC_NF_V2_UNLOCKSTART0, 0x0000);
- target_write_u16(target, MXC_NF_V2_UNLOCKSTART1, 0x0000);
- target_write_u16(target, MXC_NF_V2_UNLOCKSTART2, 0x0000);
- target_write_u16(target, MXC_NF_V2_UNLOCKSTART3, 0x0000);
- target_write_u16(target, MXC_NF_V2_UNLOCKEND0, 0xFFFF);
- target_write_u16(target, MXC_NF_V2_UNLOCKEND1, 0xFFFF);
- target_write_u16(target, MXC_NF_V2_UNLOCKEND2, 0xFFFF);
- target_write_u16(target, MXC_NF_V2_UNLOCKEND3, 0xFFFF);
- }
- target_write_u16(target, MXC_NF_FWP, 4);
-
- /*
- * 0x0000 means that first SRAM buffer @base_addr will be used
- */
- target_write_u16(target, MXC_NF_BUFADDR, 0x0000);
- /*
- * address of SRAM buffer
- */
- in_sram_address = MXC_NF_MAIN_BUFFER0;
- sign_of_sequental_byte_read = 0;
- return ERROR_OK;
-}
-
-static int get_next_byte_from_sram_buffer(struct nand_device *nand, uint8_t *value)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- static uint8_t even_byte;
- uint16_t temp;
- /*
- * host-big_endian ??
- */
- if (sign_of_sequental_byte_read == 0)
- even_byte = 0;
-
- if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
- LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
- *value = 0;
- sign_of_sequental_byte_read = 0;
- even_byte = 0;
- return ERROR_NAND_OPERATION_FAILED;
- } else {
- if (nfc_is_v2())
- in_sram_address = align_address_v2(nand, in_sram_address);
-
- target_read_u16(target, in_sram_address, &temp);
- if (even_byte) {
- *value = temp >> 8;
- even_byte = 0;
- in_sram_address += 2;
- } else {
- *value = temp & 0xff;
- even_byte = 1;
- }
- }
- sign_of_sequental_byte_read = 1;
- return ERROR_OK;
-}
-
-static int get_next_halfword_from_sram_buffer(struct nand_device *nand, uint16_t *value)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (in_sram_address > (nfc_is_v1() ? MXC_NF_V1_LAST_BUFFADDR : MXC_NF_V2_LAST_BUFFADDR)) {
- LOG_ERROR(sram_buffer_bounds_err_msg, in_sram_address);
- *value = 0;
- return ERROR_NAND_OPERATION_FAILED;
- } else {
- if (nfc_is_v2())
- in_sram_address = align_address_v2(nand, in_sram_address);
-
- target_read_u16(target, in_sram_address, value);
- in_sram_address += 2;
- }
- return ERROR_OK;
-}
-
-static int poll_for_complete_op(struct nand_device *nand, const char *text)
-{
- if (mxc_nand_ready(nand, 1000) == -1) {
- LOG_ERROR("%s sending timeout", text);
- return ERROR_NAND_OPERATION_FAILED;
- }
- return ERROR_OK;
-}
-
-static int validate_target_state(struct nand_device *nand)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR(target_not_halted_err_msg);
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- if (mxc_nf_info->flags.target_little_endian !=
- (target->endianness == TARGET_LITTLE_ENDIAN)) {
- /*
- * endianness changed after NAND controller probed
- */
- return ERROR_NAND_OPERATION_FAILED;
- }
- return ERROR_OK;
-}
-
-int ecc_status_v1(struct nand_device *nand)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- uint16_t ecc_status;
-
- target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status);
- switch (ecc_status & 0x000c) {
- case 1 << 2:
- LOG_INFO("main area read with 1 (correctable) error");
- break;
- case 2 << 2:
- LOG_INFO("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
- }
- switch (ecc_status & 0x0003) {
- case 1:
- LOG_INFO("spare area read with 1 (correctable) error");
- break;
- case 2:
- LOG_INFO("main area read with more than 1 (incorrectable) error");
- return ERROR_NAND_OPERATION_FAILED;
- break;
- }
- return ERROR_OK;
-}
-
-int ecc_status_v2(struct nand_device *nand)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- uint16_t ecc_status;
- uint8_t no_subpages;
- uint8_t err;
-
- no_subpages = nand->page_size >> 9;
-
- target_read_u16(target, MXC_NF_ECCSTATUS, &ecc_status);
- do {
- err = ecc_status & 0xF;
- if (err > 4) {
- LOG_INFO("UnCorrectable RS-ECC Error");
- return ERROR_NAND_OPERATION_FAILED;
- } else if (err > 0)
- LOG_INFO("%d Symbol Correctable RS-ECC Error", err);
- ecc_status >>= 4;
- } while (--no_subpages);
- return ERROR_OK;
-}
-
-static int do_data_output(struct nand_device *nand)
-{
- struct mxc_nf_controller *mxc_nf_info = nand->controller_priv;
- struct target *target = nand->target;
- int poll_result;
- switch (mxc_nf_info->fin) {
- case MXC_NF_FIN_DATAOUT:
- /*
- * start data output operation (set MXC_NF_BIT_OP_DONE==0)
- */
- target_write_u16(target, MXC_NF_CFG2, MXC_NF_BIT_DATAOUT_TYPE(mxc_nf_info->optype));
- poll_result = poll_for_complete_op(nand, "data output");
- if (poll_result != ERROR_OK)
- return poll_result;
-
- mxc_nf_info->fin = MXC_NF_FIN_NONE;
- /*
- * ECC stuff
- */
- if (mxc_nf_info->optype == MXC_NF_DATAOUT_PAGE && mxc_nf_info->flags.hw_ecc_enabled) {
- int ecc_status;
- if (nfc_is_v1())
- ecc_status = ecc_status_v1(nand);
- else
- ecc_status = ecc_status_v2(nand);
- if (ecc_status != ERROR_OK)
- return ecc_status;
- }
- break;
- case MXC_NF_FIN_NONE:
- break;
- }
- return ERROR_OK;
-}
-
-struct nand_flash_controller mxc_nand_flash_controller = {
- .name = "mxc",
- .nand_device_command = &mxc_nand_device_command,
- .commands = mxc_nand_command_handler,
- .init = &mxc_init,
- .reset = &mxc_reset,
- .command = &mxc_command,
- .address = &mxc_address,
- .write_data = &mxc_write_data,
- .read_data = &mxc_read_data,
- .write_page = &mxc_write_page,
- .read_page = &mxc_read_page,
- .nand_ready = &mxc_nand_ready,
-};
diff --git a/src/flash/nand/mxc.h b/src/flash/nand/mxc.h
deleted file mode 100644
index a188728..0000000
--- a/src/flash/nand/mxc.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Alexei Babich *
- * Rezonans plc., Chelyabinsk, Russia *
- * impatt@mail.ru *
- * *
- * Copyright (C) 2011 by Erik Ahlen *
- * Avalon Innovation, Sweden *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_MXC_H
-#define OPENOCD_FLASH_NAND_MXC_H
-
-/*
- * Freescale iMX OpenOCD NAND Flash controller support.
- * based on Freescale iMX2* and iMX3* OpenOCD NAND Flash controller support.
- *
- * Many thanks to Ben Dooks for writing s3c24xx driver.
- */
-
-#define MXC_NF_BUFSIZ (mxc_nf_info->mxc_regs_addr + 0x00)
-#define MXC_NF_BUFADDR (mxc_nf_info->mxc_regs_addr + 0x04)
-#define MXC_NF_FADDR (mxc_nf_info->mxc_regs_addr + 0x06)
-#define MXC_NF_FCMD (mxc_nf_info->mxc_regs_addr + 0x08)
-#define MXC_NF_BUFCFG (mxc_nf_info->mxc_regs_addr + 0x0a)
-#define MXC_NF_ECCSTATUS (mxc_nf_info->mxc_regs_addr + 0x0c)
-#define MXC_NF_ECCMAINPOS (mxc_nf_info->mxc_regs_addr + 0x0e)
-#define MXC_NF_V1_ECCSPAREPOS (mxc_nf_info->mxc_regs_addr + 0x10)
-#define MXC_NF_V2_SPAS (mxc_nf_info->mxc_regs_addr + 0x10)
-#define MXC_NF_FWP (mxc_nf_info->mxc_regs_addr + 0x12)
-#define MXC_NF_V1_UNLOCKSTART (mxc_nf_info->mxc_regs_addr + 0x14)
-#define MXC_NF_V1_UNLOCKEND (mxc_nf_info->mxc_regs_addr + 0x16)
-#define MXC_NF_V2_UNLOCKSTART0 (mxc_nf_info->mxc_regs_addr + 0x20)
-#define MXC_NF_V2_UNLOCKSTART1 (mxc_nf_info->mxc_regs_addr + 0x24)
-#define MXC_NF_V2_UNLOCKSTART2 (mxc_nf_info->mxc_regs_addr + 0x28)
-#define MXC_NF_V2_UNLOCKSTART3 (mxc_nf_info->mxc_regs_addr + 0x2c)
-#define MXC_NF_V2_UNLOCKEND0 (mxc_nf_info->mxc_regs_addr + 0x22)
-#define MXC_NF_V2_UNLOCKEND1 (mxc_nf_info->mxc_regs_addr + 0x26)
-#define MXC_NF_V2_UNLOCKEND2 (mxc_nf_info->mxc_regs_addr + 0x2a)
-#define MXC_NF_V2_UNLOCKEND3 (mxc_nf_info->mxc_regs_addr + 0x2e)
-#define MXC_NF_FWPSTATUS (mxc_nf_info->mxc_regs_addr + 0x18)
- /*
- * all bits not marked as self-clearing bit
- */
-#define MXC_NF_CFG1 (mxc_nf_info->mxc_regs_addr + 0x1a)
-#define MXC_NF_CFG2 (mxc_nf_info->mxc_regs_addr + 0x1c)
-
-#define MXC_NF_MAIN_BUFFER0 (mxc_nf_info->mxc_base_addr + 0x0000)
-#define MXC_NF_MAIN_BUFFER1 (mxc_nf_info->mxc_base_addr + 0x0200)
-#define MXC_NF_MAIN_BUFFER2 (mxc_nf_info->mxc_base_addr + 0x0400)
-#define MXC_NF_MAIN_BUFFER3 (mxc_nf_info->mxc_base_addr + 0x0600)
-#define MXC_NF_V1_SPARE_BUFFER0 (mxc_nf_info->mxc_base_addr + 0x0800)
-#define MXC_NF_V1_SPARE_BUFFER1 (mxc_nf_info->mxc_base_addr + 0x0810)
-#define MXC_NF_V1_SPARE_BUFFER2 (mxc_nf_info->mxc_base_addr + 0x0820)
-#define MXC_NF_V1_SPARE_BUFFER3 (mxc_nf_info->mxc_base_addr + 0x0830)
-#define MXC_NF_V2_MAIN_BUFFER4 (mxc_nf_info->mxc_base_addr + 0x0800)
-#define MXC_NF_V2_MAIN_BUFFER5 (mxc_nf_info->mxc_base_addr + 0x0a00)
-#define MXC_NF_V2_MAIN_BUFFER6 (mxc_nf_info->mxc_base_addr + 0x0c00)
-#define MXC_NF_V2_MAIN_BUFFER7 (mxc_nf_info->mxc_base_addr + 0x0e00)
-#define MXC_NF_V2_SPARE_BUFFER0 (mxc_nf_info->mxc_base_addr + 0x1000)
-#define MXC_NF_V2_SPARE_BUFFER1 (mxc_nf_info->mxc_base_addr + 0x1040)
-#define MXC_NF_V2_SPARE_BUFFER2 (mxc_nf_info->mxc_base_addr + 0x1080)
-#define MXC_NF_V2_SPARE_BUFFER3 (mxc_nf_info->mxc_base_addr + 0x10c0)
-#define MXC_NF_V2_SPARE_BUFFER4 (mxc_nf_info->mxc_base_addr + 0x1100)
-#define MXC_NF_V2_SPARE_BUFFER5 (mxc_nf_info->mxc_base_addr + 0x1140)
-#define MXC_NF_V2_SPARE_BUFFER6 (mxc_nf_info->mxc_base_addr + 0x1180)
-#define MXC_NF_V2_SPARE_BUFFER7 (mxc_nf_info->mxc_base_addr + 0x11c0)
-#define MXC_NF_MAIN_BUFFER_LEN 512
-#define MXC_NF_SPARE_BUFFER_LEN 16
-#define MXC_NF_SPARE_BUFFER_MAX 64
-#define MXC_NF_V1_LAST_BUFFADDR ((MXC_NF_V1_SPARE_BUFFER3) + \
- MXC_NF_SPARE_BUFFER_LEN - 2)
-#define MXC_NF_V2_LAST_BUFFADDR ((MXC_NF_V2_SPARE_BUFFER7) + \
- MXC_NF_SPARE_BUFFER_LEN - 2)
-
-/* bits in MXC_NF_CFG1 register */
-#define MXC_NF_BIT_ECC_4BIT (1<<0)
-#define MXC_NF_BIT_SPARE_ONLY_EN (1<<2)
-#define MXC_NF_BIT_ECC_EN (1<<3)
-#define MXC_NF_BIT_INT_DIS (1<<4)
-#define MXC_NF_BIT_BE_EN (1<<5)
-#define MXC_NF_BIT_RESET_EN (1<<6)
-#define MXC_NF_BIT_FORCE_CE (1<<7)
-#define MXC_NF_V2_CFG1_PPB(x) (((x) & 0x3) << 9)
-
-/* bits in MXC_NF_CFG2 register */
-
-/*Flash Command Input*/
-#define MXC_NF_BIT_OP_FCI (1<<0)
- /*
- * Flash Address Input
- */
-#define MXC_NF_BIT_OP_FAI (1<<1)
- /*
- * Flash Data Input
- */
-#define MXC_NF_BIT_OP_FDI (1<<2)
-
-/* see "enum mx_dataout_type" below */
-#define MXC_NF_BIT_DATAOUT_TYPE(x) ((x)<<3)
-#define MXC_NF_BIT_OP_DONE (1<<15)
-
-#define MXC_CCM_CGR2 0x53f80028
-#define MXC_GPR 0x43fac008
-#define MX2_FMCR 0x10027814
-#define MX2_FMCR_NF_16BIT_SEL (1<<4)
-#define MX2_FMCR_NF_FMS (1<<5)
-#define MX25_RCSR 0x53f80018
-#define MX25_RCSR_NF_16BIT_SEL (1<<14)
-#define MX25_RCSR_NF_FMS (1<<8)
-#define MX25_RCSR_NF_4K (1<<9)
-#define MX3_PCSR 0x53f8000c
-#define MX3_PCSR_NF_16BIT_SEL (1<<31)
-#define MX3_PCSR_NF_FMS (1<<30)
-#define MX35_RCSR 0x53f80018
-#define MX35_RCSR_NF_16BIT_SEL (1<<14)
-#define MX35_RCSR_NF_FMS (1<<8)
-#define MX35_RCSR_NF_4K (1<<9)
-
-enum mxc_version {
- MXC_VERSION_UKWN = 0,
- MXC_VERSION_MX25 = 1,
- MXC_VERSION_MX27 = 2,
- MXC_VERSION_MX31 = 3,
- MXC_VERSION_MX35 = 4
-};
-
-enum mxc_dataout_type {
- MXC_NF_DATAOUT_PAGE = 1,
- MXC_NF_DATAOUT_NANDID = 2,
- MXC_NF_DATAOUT_NANDSTATUS = 4,
-};
-
-enum mxc_nf_finalize_action {
- MXC_NF_FIN_NONE,
- MXC_NF_FIN_DATAOUT,
-};
-
-struct mxc_nf_flags {
- unsigned target_little_endian:1;
- unsigned nand_readonly:1;
- unsigned one_kb_sram:1;
- unsigned hw_ecc_enabled:1;
- unsigned biswap_enabled:1;
-};
-
-struct mxc_nf_controller {
- enum mxc_version mxc_version;
- uint32_t mxc_base_addr;
- uint32_t mxc_regs_addr;
- enum mxc_dataout_type optype;
- enum mxc_nf_finalize_action fin;
- struct mxc_nf_flags flags;
-};
-
-#endif /* OPENOCD_FLASH_NAND_MXC_H */
diff --git a/src/flash/nand/nonce.c b/src/flash/nand/nonce.c
deleted file mode 100644
index 6fda261..0000000
--- a/src/flash/nand/nonce.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "hello.h"
-
-static int nonce_nand_command(struct nand_device *nand, uint8_t command)
-{
- return ERROR_OK;
-}
-static int nonce_nand_address(struct nand_device *nand, uint8_t address)
-{
- return ERROR_OK;
-}
-static int nonce_nand_read(struct nand_device *nand, void *data)
-{
- return ERROR_OK;
-}
-static int nonce_nand_write(struct nand_device *nand, uint16_t data)
-{
- return ERROR_OK;
-}
-static int nonce_nand_fast_block_write(struct nand_device *nand,
- uint8_t *data, int size)
-{
- return ERROR_OK;
-}
-
-static int nonce_nand_reset(struct nand_device *nand)
-{
- return nonce_nand_command(nand, NAND_CMD_RESET);
-}
-
-NAND_DEVICE_COMMAND_HANDLER(nonce_nand_device_command)
-{
- return ERROR_OK;
-}
-
-static int nonce_nand_init(struct nand_device *nand)
-{
- return ERROR_OK;
-}
-
-struct nand_flash_controller nonce_nand_controller = {
- .name = "nonce",
- .commands = hello_command_handlers,
- .nand_device_command = &nonce_nand_device_command,
- .init = &nonce_nand_init,
- .reset = &nonce_nand_reset,
- .command = &nonce_nand_command,
- .address = &nonce_nand_address,
- .read_data = &nonce_nand_read,
- .write_data = &nonce_nand_write,
- .write_block_data = &nonce_nand_fast_block_write,
-};
diff --git a/src/flash/nand/nuc910.c b/src/flash/nand/nuc910.c
deleted file mode 100644
index 1a2dd59..0000000
--- a/src/flash/nand/nuc910.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * NAND controller interface for Nuvoton NUC910
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "nuc910.h"
-#include "arm_io.h"
-#include <target/arm.h>
-
-struct nuc910_nand_controller {
- struct arm_nand_data io;
-};
-
-static int validate_target_state(struct nand_device *nand)
-{
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int nuc910_nand_command(struct nand_device *nand, uint8_t command)
-{
- struct target *target = nand->target;
- int result;
-
- result = validate_target_state(nand);
- if (result != ERROR_OK)
- return result;
-
- target_write_u8(target, NUC910_SMCMD, command);
- return ERROR_OK;
-}
-
-static int nuc910_nand_address(struct nand_device *nand, uint8_t address)
-{
- struct target *target = nand->target;
- int result;
-
- result = validate_target_state(nand);
- if (result != ERROR_OK)
- return result;
-
- target_write_u32(target, NUC910_SMADDR, ((address & 0xff) | NUC910_SMADDR_EOA));
- return ERROR_OK;
-}
-
-static int nuc910_nand_read(struct nand_device *nand, void *data)
-{
- struct target *target = nand->target;
- int result;
-
- result = validate_target_state(nand);
- if (result != ERROR_OK)
- return result;
-
- target_read_u8(target, NUC910_SMDATA, data);
- return ERROR_OK;
-}
-
-static int nuc910_nand_write(struct nand_device *nand, uint16_t data)
-{
- struct target *target = nand->target;
- int result;
-
- result = validate_target_state(nand);
- if (result != ERROR_OK)
- return result;
-
- target_write_u8(target, NUC910_SMDATA, data);
- return ERROR_OK;
-}
-
-static int nuc910_nand_read_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
-{
- struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
- int result;
-
- result = validate_target_state(nand);
- if (result != ERROR_OK)
- return result;
-
- nuc910_nand->io.chunk_size = nand->page_size;
-
- /* try the fast way first */
- result = arm_nandread(&nuc910_nand->io, data, data_size);
- if (result != ERROR_NAND_NO_BUFFER)
- return result;
-
- /* else do it slowly */
- while (data_size--)
- nuc910_nand_read(nand, data++);
-
- return ERROR_OK;
-}
-
-static int nuc910_nand_write_block_data(struct nand_device *nand,
- uint8_t *data, int data_size)
-{
- struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
- int result;
-
- result = validate_target_state(nand);
- if (result != ERROR_OK)
- return result;
-
- nuc910_nand->io.chunk_size = nand->page_size;
-
- /* try the fast way first */
- result = arm_nandwrite(&nuc910_nand->io, data, data_size);
- if (result != ERROR_NAND_NO_BUFFER)
- return result;
-
- /* else do it slowly */
- while (data_size--)
- nuc910_nand_write(nand, *data++);
-
- return ERROR_OK;
-}
-
-static int nuc910_nand_reset(struct nand_device *nand)
-{
- return nuc910_nand_command(nand, NAND_CMD_RESET);
-}
-
-static int nuc910_nand_ready(struct nand_device *nand, int timeout)
-{
- struct target *target = nand->target;
- uint32_t status;
-
- do {
- target_read_u32(target, NUC910_SMISR, &status);
- if (status & NUC910_SMISR_RB_)
- return 1;
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-NAND_DEVICE_COMMAND_HANDLER(nuc910_nand_device_command)
-{
- struct nuc910_nand_controller *nuc910_nand;
-
- nuc910_nand = calloc(1, sizeof(struct nuc910_nand_controller));
- if (!nuc910_nand) {
- LOG_ERROR("no memory for nand controller");
- return ERROR_NAND_DEVICE_INVALID;
- }
-
- nand->controller_priv = nuc910_nand;
- return ERROR_OK;
-}
-
-static int nuc910_nand_init(struct nand_device *nand)
-{
- struct nuc910_nand_controller *nuc910_nand = nand->controller_priv;
- struct target *target = nand->target;
- int bus_width = nand->bus_width ? : 8;
- int result;
-
- result = validate_target_state(nand);
- if (result != ERROR_OK)
- return result;
-
- /* nuc910 only supports 8bit */
- if (bus_width != 8) {
- LOG_ERROR("nuc910 only supports 8 bit bus width, not %i", bus_width);
- return ERROR_NAND_OPERATION_NOT_SUPPORTED;
- }
-
- /* inform calling code about selected bus width */
- nand->bus_width = bus_width;
-
- nuc910_nand->io.target = target;
- nuc910_nand->io.data = NUC910_SMDATA;
- nuc910_nand->io.op = ARM_NAND_NONE;
-
- /* configure nand controller */
- target_write_u32(target, NUC910_FMICSR, NUC910_FMICSR_SM_EN);
- target_write_u32(target, NUC910_SMCSR, 0x010000a8); /* 2048 page size */
- target_write_u32(target, NUC910_SMTCR, 0x00010204);
- target_write_u32(target, NUC910_SMIER, 0x00000000);
-
- return ERROR_OK;
-}
-
-struct nand_flash_controller nuc910_nand_controller = {
- .name = "nuc910",
- .command = nuc910_nand_command,
- .address = nuc910_nand_address,
- .read_data = nuc910_nand_read,
- .write_data = nuc910_nand_write,
- .write_block_data = nuc910_nand_write_block_data,
- .read_block_data = nuc910_nand_read_block_data,
- .nand_ready = nuc910_nand_ready,
- .reset = nuc910_nand_reset,
- .nand_device_command = nuc910_nand_device_command,
- .init = nuc910_nand_init,
-};
diff --git a/src/flash/nand/nuc910.h b/src/flash/nand/nuc910.h
deleted file mode 100644
index 8877cf6..0000000
--- a/src/flash/nand/nuc910.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * NAND controller interface for Nuvoton NUC910
- */
-
-#ifndef OPENOCD_FLASH_NAND_NUC910_H
-#define OPENOCD_FLASH_NAND_NUC910_H
-
-#define NUC910_FMICSR 0xB000D000
-#define NUC910_SMCSR 0xB000D0A0
-#define NUC910_SMTCR 0xB000D0A4
-#define NUC910_SMIER 0xB000D0A8
-#define NUC910_SMISR 0xB000D0AC
-#define NUC910_SMCMD 0xB000D0B0
-#define NUC910_SMADDR 0xB000D0B4
-#define NUC910_SMDATA 0xB000D0B8
-
-#define NUC910_SMECC0 0xB000D0BC
-#define NUC910_SMECC1 0xB000D0C0
-#define NUC910_SMECC2 0xB000D0C4
-#define NUC910_SMECC3 0xB000D0C8
-#define NUC910_ECC4ST 0xB000D114
-
-/* Global Control and Status Register (FMICSR) */
-#define NUC910_FMICSR_SM_EN (1<<3)
-
-/* NAND Flash Address Port Register (SMADDR) */
-#define NUC910_SMADDR_EOA (1<<31)
-
-/* NAND Flash Control and Status Register (SMCSR) */
-#define NUC910_SMCSR_PSIZE (1<<3)
-#define NUC910_SMCSR_DBW (1<<4)
-
-/* NAND Flash Interrupt Status Register (SMISR) */
-#define NUC910_SMISR_ECC_IF (1<<2)
-#define NUC910_SMISR_RB_ (1<<18)
-
-/* ECC4 Correction Status (ECC4ST) */
-
-#endif /* OPENOCD_FLASH_NAND_NUC910_H */
diff --git a/src/flash/nand/orion.c b/src/flash/nand/orion.c
deleted file mode 100644
index 69814ec..0000000
--- a/src/flash/nand/orion.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Marvell Semiconductors, Inc. *
- * Written by Nicolas Pitre <nico at marvell.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * NAND controller interface for Marvell Orion/Kirkwood SoCs.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "arm_io.h"
-#include <target/arm.h>
-
-struct orion_nand_controller {
- struct arm_nand_data io;
-
- uint32_t cmd;
- uint32_t addr;
- uint32_t data;
-};
-
-#define CHECK_HALTED \
- do { \
- if (target->state != TARGET_HALTED) { \
- LOG_ERROR("NAND flash access requires halted target"); \
- return ERROR_NAND_OPERATION_FAILED; \
- } \
- } while (0)
-
-static int orion_nand_command(struct nand_device *nand, uint8_t command)
-{
- struct orion_nand_controller *hw = nand->controller_priv;
- struct target *target = nand->target;
-
- CHECK_HALTED;
- target_write_u8(target, hw->cmd, command);
- return ERROR_OK;
-}
-
-static int orion_nand_address(struct nand_device *nand, uint8_t address)
-{
- struct orion_nand_controller *hw = nand->controller_priv;
- struct target *target = nand->target;
-
- CHECK_HALTED;
- target_write_u8(target, hw->addr, address);
- return ERROR_OK;
-}
-
-static int orion_nand_read(struct nand_device *nand, void *data)
-{
- struct orion_nand_controller *hw = nand->controller_priv;
- struct target *target = nand->target;
-
- CHECK_HALTED;
- target_read_u8(target, hw->data, data);
- return ERROR_OK;
-}
-
-static int orion_nand_write(struct nand_device *nand, uint16_t data)
-{
- struct orion_nand_controller *hw = nand->controller_priv;
- struct target *target = nand->target;
-
- CHECK_HALTED;
- target_write_u8(target, hw->data, data);
- return ERROR_OK;
-}
-
-static int orion_nand_slow_block_write(struct nand_device *nand, uint8_t *data, int size)
-{
- while (size--)
- orion_nand_write(nand, *data++);
- return ERROR_OK;
-}
-
-static int orion_nand_fast_block_write(struct nand_device *nand, uint8_t *data, int size)
-{
- struct orion_nand_controller *hw = nand->controller_priv;
- int retval;
-
- hw->io.chunk_size = nand->page_size;
-
- retval = arm_nandwrite(&hw->io, data, size);
- if (retval == ERROR_NAND_NO_BUFFER)
- retval = orion_nand_slow_block_write(nand, data, size);
-
- return retval;
-}
-
-static int orion_nand_reset(struct nand_device *nand)
-{
- return orion_nand_command(nand, NAND_CMD_RESET);
-}
-
-NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
-{
- struct orion_nand_controller *hw;
- uint32_t base;
- uint8_t ale, cle;
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- hw = calloc(1, sizeof(*hw));
- if (!hw) {
- LOG_ERROR("no memory for nand controller");
- return ERROR_NAND_DEVICE_INVALID;
- }
-
- nand->controller_priv = hw;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base);
- cle = 0;
- ale = 1;
-
- hw->data = base;
- hw->cmd = base + (1 << cle);
- hw->addr = base + (1 << ale);
-
- hw->io.target = nand->target;
- hw->io.data = hw->data;
- hw->io.op = ARM_NAND_NONE;
-
- return ERROR_OK;
-}
-
-static int orion_nand_init(struct nand_device *nand)
-{
- return ERROR_OK;
-}
-
-struct nand_flash_controller orion_nand_controller = {
- .name = "orion",
- .usage = "<target_id> <NAND_address>",
- .command = orion_nand_command,
- .address = orion_nand_address,
- .read_data = orion_nand_read,
- .write_data = orion_nand_write,
- .write_block_data = orion_nand_fast_block_write,
- .reset = orion_nand_reset,
- .nand_device_command = orion_nand_device_command,
- .init = orion_nand_init,
-};
diff --git a/src/flash/nand/s3c2410.c b/src/flash/nand/s3c2410.c
deleted file mode 100644
index 57b51b4..0000000
--- a/src/flash/nand/s3c2410.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007, 2008 by Ben Dooks *
- * ben@fluff.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * S3C2410 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx.h"
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2410_nand_device_command)
-{
- struct s3c24xx_nand_controller *info;
- CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
- /* fill in the address fields for the core device */
- info->cmd = S3C2410_NFCMD;
- info->addr = S3C2410_NFADDR;
- info->data = S3C2410_NFDATA;
- info->nfstat = S3C2410_NFSTAT;
-
- return ERROR_OK;
-}
-
-static int s3c2410_init(struct nand_device *nand)
-{
- struct target *target = nand->target;
-
- target_write_u32(target, S3C2410_NFCONF,
- S3C2410_NFCONF_EN | S3C2410_NFCONF_TACLS(3) |
- S3C2410_NFCONF_TWRPH0(5) | S3C2410_NFCONF_TWRPH1(3));
-
- return ERROR_OK;
-}
-
-static int s3c2410_write_data(struct nand_device *nand, uint16_t data)
-{
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_write_u32(target, S3C2410_NFDATA, data);
- return ERROR_OK;
-}
-
-static int s3c2410_read_data(struct nand_device *nand, void *data)
-{
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_read_u8(target, S3C2410_NFDATA, data);
- return ERROR_OK;
-}
-
-static int s3c2410_nand_ready(struct nand_device *nand, int timeout)
-{
- struct target *target = nand->target;
- uint8_t status;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- do {
- target_read_u8(target, S3C2410_NFSTAT, &status);
-
- if (status & S3C2410_NFSTAT_BUSY)
- return 1;
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
- return 0;
-}
-
-struct nand_flash_controller s3c2410_nand_controller = {
- .name = "s3c2410",
- .nand_device_command = &s3c2410_nand_device_command,
- .init = &s3c2410_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c2410_write_data,
- .read_data = &s3c2410_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .nand_ready = &s3c2410_nand_ready,
-};
diff --git a/src/flash/nand/s3c2412.c b/src/flash/nand/s3c2412.c
deleted file mode 100644
index 002378a..0000000
--- a/src/flash/nand/s3c2412.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007, 2008 by Ben Dooks *
- * ben@fluff.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * S3C2412 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx.h"
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2412_nand_device_command)
-{
- struct s3c24xx_nand_controller *info;
- CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
- /* fill in the address fields for the core device */
- info->cmd = S3C2440_NFCMD;
- info->addr = S3C2440_NFADDR;
- info->data = S3C2440_NFDATA;
- info->nfstat = S3C2412_NFSTAT;
-
- return ERROR_OK;
-}
-
-static int s3c2412_init(struct nand_device *nand)
-{
- struct target *target = nand->target;
-
- target_write_u32(target, S3C2410_NFCONF,
- S3C2440_NFCONF_TACLS(3) |
- S3C2440_NFCONF_TWRPH0(7) |
- S3C2440_NFCONF_TWRPH1(7));
-
- target_write_u32(target, S3C2440_NFCONT,
- S3C2412_NFCONT_INIT_MAIN_ECC |
- S3C2440_NFCONT_ENABLE);
-
- return ERROR_OK;
-}
-
-struct nand_flash_controller s3c2412_nand_controller = {
- .name = "s3c2412",
- .nand_device_command = &s3c2412_nand_device_command,
- .init = &s3c2412_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
-};
diff --git a/src/flash/nand/s3c2440.c b/src/flash/nand/s3c2440.c
deleted file mode 100644
index 44670e6..0000000
--- a/src/flash/nand/s3c2440.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007, 2008 by Ben Dooks *
- * ben@fluff.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * S3C2440 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx.h"
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2440_nand_device_command)
-{
- struct s3c24xx_nand_controller *info;
- CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
- /* fill in the address fields for the core device */
- info->cmd = S3C2440_NFCMD;
- info->addr = S3C2440_NFADDR;
- info->data = S3C2440_NFDATA;
- info->nfstat = S3C2440_NFSTAT;
-
- return ERROR_OK;
-}
-
-static int s3c2440_init(struct nand_device *nand)
-{
- struct target *target = nand->target;
-
- target_write_u32(target, S3C2410_NFCONF,
- S3C2440_NFCONF_TACLS(3) |
- S3C2440_NFCONF_TWRPH0(7) |
- S3C2440_NFCONF_TWRPH1(7));
-
- target_write_u32(target, S3C2440_NFCONT,
- S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
-
- return ERROR_OK;
-}
-
-int s3c2440_nand_ready(struct nand_device *nand, int timeout)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
- uint8_t status;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- do {
- target_read_u8(target, s3c24xx_info->nfstat, &status);
-
- if (status & S3C2440_NFSTAT_READY)
- return 1;
-
- alive_sleep(1);
- } while (timeout-- > 0);
-
-
- return 0;
-}
-
-/* use the fact we can read/write 4 bytes in one go via a single 32bit op */
-
-int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t nfdata = s3c24xx_info->data;
- uint32_t tmp;
-
- LOG_INFO("%s: reading data: %p, %p, %d", __func__, nand, data, data_size);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- while (data_size >= 4) {
- target_read_u32(target, nfdata, &tmp);
-
- data[0] = tmp;
- data[1] = tmp >> 8;
- data[2] = tmp >> 16;
- data[3] = tmp >> 24;
-
- data_size -= 4;
- data += 4;
- }
-
- while (data_size > 0) {
- target_read_u8(target, nfdata, data);
-
- data_size -= 1;
- data += 1;
- }
-
- return ERROR_OK;
-}
-
-int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
- uint32_t nfdata = s3c24xx_info->data;
- uint32_t tmp;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- while (data_size >= 4) {
- tmp = le_to_h_u32(data);
- target_write_u32(target, nfdata, tmp);
-
- data_size -= 4;
- data += 4;
- }
-
- while (data_size > 0) {
- target_write_u8(target, nfdata, *data);
-
- data_size -= 1;
- data += 1;
- }
-
- return ERROR_OK;
-}
-
-struct nand_flash_controller s3c2440_nand_controller = {
- .name = "s3c2440",
- .nand_device_command = &s3c2440_nand_device_command,
- .init = &s3c2440_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
-};
diff --git a/src/flash/nand/s3c2443.c b/src/flash/nand/s3c2443.c
deleted file mode 100644
index ffd3864..0000000
--- a/src/flash/nand/s3c2443.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007, 2008 by Ben Dooks *
- * ben@fluff.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * S3C2443 OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx.h"
-
-NAND_DEVICE_COMMAND_HANDLER(s3c2443_nand_device_command)
-{
- struct s3c24xx_nand_controller *info;
- CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
- /* fill in the address fields for the core device */
- info->cmd = S3C2440_NFCMD;
- info->addr = S3C2440_NFADDR;
- info->data = S3C2440_NFDATA;
- info->nfstat = S3C2412_NFSTAT;
-
- return ERROR_OK;
-}
-
-static int s3c2443_init(struct nand_device *nand)
-{
- struct target *target = nand->target;
-
- target_write_u32(target, S3C2410_NFCONF,
- S3C2440_NFCONF_TACLS(3) |
- S3C2440_NFCONF_TWRPH0(7) |
- S3C2440_NFCONF_TWRPH1(7));
-
- target_write_u32(target, S3C2440_NFCONT,
- S3C2412_NFCONT_INIT_MAIN_ECC |
- S3C2440_NFCONT_ENABLE);
-
- return ERROR_OK;
-}
-
-struct nand_flash_controller s3c2443_nand_controller = {
- .name = "s3c2443",
- .nand_device_command = &s3c2443_nand_device_command,
- .init = &s3c2443_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
-};
diff --git a/src/flash/nand/s3c24xx.c b/src/flash/nand/s3c24xx.c
deleted file mode 100644
index ae3f137..0000000
--- a/src/flash/nand/s3c24xx.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007, 2008 by Ben Dooks *
- * ben@fluff.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * S3C24XX Series OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx.h"
-
-S3C24XX_DEVICE_COMMAND()
-{
- *info = NULL;
-
- struct s3c24xx_nand_controller *s3c24xx_info;
- s3c24xx_info = malloc(sizeof(struct s3c24xx_nand_controller));
- if (s3c24xx_info == NULL) {
- LOG_ERROR("no memory for nand controller");
- return -ENOMEM;
- }
-
- nand->controller_priv = s3c24xx_info;
- *info = s3c24xx_info;
-
- return ERROR_OK;
-}
-
-int s3c24xx_reset(struct nand_device *nand)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_write_u32(target, s3c24xx_info->cmd, 0xff);
-
- return ERROR_OK;
-}
-
-int s3c24xx_command(struct nand_device *nand, uint8_t command)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_write_u16(target, s3c24xx_info->cmd, command);
- return ERROR_OK;
-}
-
-int s3c24xx_address(struct nand_device *nand, uint8_t address)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_write_u16(target, s3c24xx_info->addr, address);
- return ERROR_OK;
-}
-
-int s3c24xx_write_data(struct nand_device *nand, uint16_t data)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_write_u8(target, s3c24xx_info->data, data);
- return ERROR_OK;
-}
-
-int s3c24xx_read_data(struct nand_device *nand, void *data)
-{
- struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
- struct target *target = nand->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target must be halted to use S3C24XX NAND flash controller");
- return ERROR_NAND_OPERATION_FAILED;
- }
-
- target_read_u8(target, s3c24xx_info->data, data);
- return ERROR_OK;
-}
diff --git a/src/flash/nand/s3c24xx.h b/src/flash/nand/s3c24xx.h
deleted file mode 100644
index 5c7782d..0000000
--- a/src/flash/nand/s3c24xx.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007, 2008 by Ben Dooks *
- * ben@fluff.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NAND_S3C24XX_H
-#define OPENOCD_FLASH_NAND_S3C24XX_H
-
-/*
- * S3C24XX Series OpenOCD NAND Flash controller support.
- *
- * Many thanks to Simtec Electronics for sponsoring this work.
- */
-
-#include "imp.h"
-#include "s3c24xx_regs.h"
-#include <target/target.h>
-
-struct s3c24xx_nand_controller {
- /* register addresses */
- uint32_t cmd;
- uint32_t addr;
- uint32_t data;
- uint32_t nfstat;
-};
-
-/* Default to using the un-translated NAND register based address */
-#undef S3C2410_NFREG
-#define S3C2410_NFREG(x) ((x) + 0x4e000000)
-
-#define S3C24XX_DEVICE_COMMAND() \
- COMMAND_HELPER(s3c24xx_nand_device_command, \
- struct nand_device *nand, \
- struct s3c24xx_nand_controller **info)
-
-S3C24XX_DEVICE_COMMAND();
-
-#define CALL_S3C24XX_DEVICE_COMMAND(d, i) \
- do { \
- int retval = CALL_COMMAND_HANDLER(s3c24xx_nand_device_command, d, i); \
- if (ERROR_OK != retval) \
- return retval; \
- } while (0)
-
-int s3c24xx_reset(struct nand_device *nand);
-
-int s3c24xx_command(struct nand_device *nand, uint8_t command);
-int s3c24xx_address(struct nand_device *nand, uint8_t address);
-
-int s3c24xx_write_data(struct nand_device *nand, uint16_t data);
-int s3c24xx_read_data(struct nand_device *nand, void *data);
-
-#define s3c24xx_write_page NULL
-#define s3c24xx_read_page NULL
-
-/* code shared between different controllers */
-
-int s3c2440_nand_ready(struct nand_device *nand, int timeout);
-
-int s3c2440_read_block_data(struct nand_device *nand,
- uint8_t *data, int data_size);
-int s3c2440_write_block_data(struct nand_device *nand,
- uint8_t *data, int data_size);
-
-#endif /* OPENOCD_FLASH_NAND_S3C24XX_H */
diff --git a/src/flash/nand/s3c24xx_regs.h b/src/flash/nand/s3c24xx_regs.h
deleted file mode 100644
index 88bc665..0000000
--- a/src/flash/nand/s3c24xx_regs.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Simtec Electronics *
- * linux@simtec.co.uk *
- * http://www.simtec.co.uk/products/SWLINUX/ *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; version 2 of the License. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * S3C2410 NAND register definitions
- */
-
-#ifndef OPENOCD_FLASH_NAND_S3C24XX_REGS_H
-#define OPENOCD_FLASH_NAND_S3C24XX_REGS_H
-
-#define S3C2410_NFREG(x) (x)
-
-#define S3C2410_NFCONF S3C2410_NFREG(0x00)
-#define S3C2410_NFCMD S3C2410_NFREG(0x04)
-#define S3C2410_NFADDR S3C2410_NFREG(0x08)
-#define S3C2410_NFDATA S3C2410_NFREG(0x0C)
-#define S3C2410_NFSTAT S3C2410_NFREG(0x10)
-#define S3C2410_NFECC S3C2410_NFREG(0x14)
-
-#define S3C2440_NFCONT S3C2410_NFREG(0x04)
-#define S3C2440_NFCMD S3C2410_NFREG(0x08)
-#define S3C2440_NFADDR S3C2410_NFREG(0x0C)
-#define S3C2440_NFDATA S3C2410_NFREG(0x10)
-#define S3C2440_NFECCD0 S3C2410_NFREG(0x14)
-#define S3C2440_NFECCD1 S3C2410_NFREG(0x18)
-#define S3C2440_NFECCD S3C2410_NFREG(0x1C)
-#define S3C2440_NFSTAT S3C2410_NFREG(0x20)
-#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
-#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
-#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
-#define S3C2440_NFMECC1 S3C2410_NFREG(0x30)
-#define S3C2440_NFSECC S3C2410_NFREG(0x34)
-#define S3C2440_NFSBLK S3C2410_NFREG(0x38)
-#define S3C2440_NFEBLK S3C2410_NFREG(0x3C)
-
-#define S3C2412_NFSBLK S3C2410_NFREG(0x20)
-#define S3C2412_NFEBLK S3C2410_NFREG(0x24)
-#define S3C2412_NFSTAT S3C2410_NFREG(0x28)
-#define S3C2412_NFMECC_ERR0 S3C2410_NFREG(0x2C)
-#define S3C2412_NFMECC_ERR1 S3C2410_NFREG(0x30)
-#define S3C2412_NFMECC0 S3C2410_NFREG(0x34)
-#define S3C2412_NFMECC1 S3C2410_NFREG(0x38)
-#define S3C2412_NFSECC S3C2410_NFREG(0x3C)
-
-#define S3C2410_NFCONF_EN (1 << 15)
-#define S3C2410_NFCONF_512BYTE (1 << 14)
-#define S3C2410_NFCONF_4STEP (1 << 13)
-#define S3C2410_NFCONF_INITECC (1 << 12)
-#define S3C2410_NFCONF_nFCE (1 << 11)
-#define S3C2410_NFCONF_TACLS(x) ((x) << 8)
-#define S3C2410_NFCONF_TWRPH0(x) ((x) << 4)
-#define S3C2410_NFCONF_TWRPH1(x) ((x) << 0)
-
-#define S3C2410_NFSTAT_BUSY (1 << 0)
-
-#define S3C2440_NFCONF_BUSWIDTH_8 (0 << 0)
-#define S3C2440_NFCONF_BUSWIDTH_16 (1 << 0)
-#define S3C2440_NFCONF_ADVFLASH (1 << 3)
-#define S3C2440_NFCONF_TACLS(x) ((x) << 12)
-#define S3C2440_NFCONF_TWRPH0(x) ((x) << 8)
-#define S3C2440_NFCONF_TWRPH1(x) ((x) << 4)
-
-#define S3C2440_NFCONT_LOCKTIGHT (1 << 13)
-#define S3C2440_NFCONT_SOFTLOCK (1 << 12)
-#define S3C2440_NFCONT_ILLEGALACC_EN (1 << 10)
-#define S3C2440_NFCONT_RNBINT_EN (1 << 9)
-#define S3C2440_NFCONT_RN_FALLING (1 << 8)
-#define S3C2440_NFCONT_SPARE_ECCLOCK (1 << 6)
-#define S3C2440_NFCONT_MAIN_ECCLOCK (1 << 5)
-#define S3C2440_NFCONT_INITECC (1 << 4)
-#define S3C2440_NFCONT_nFCE (1 << 1)
-#define S3C2440_NFCONT_ENABLE (1 << 0)
-
-#define S3C2440_NFSTAT_READY (1 << 0)
-#define S3C2440_NFSTAT_nCE (1 << 1)
-#define S3C2440_NFSTAT_RnB_CHANGE (1 << 2)
-#define S3C2440_NFSTAT_ILLEGAL_ACCESS (1 << 3)
-
-#define S3C2412_NFCONF_NANDBOOT (1 << 31)
-#define S3C2412_NFCONF_ECCCLKCON (1 << 30)
-#define S3C2412_NFCONF_ECC_MLC (1 << 24)
-#define S3C2412_NFCONF_TACLS_MASK (7 << 12) /* 1 extra bit of Tacls */
-
-#define S3C2412_NFCONT_ECC4_DIRWR (1 << 18)
-#define S3C2412_NFCONT_LOCKTIGHT (1 << 17)
-#define S3C2412_NFCONT_SOFTLOCK (1 << 16)
-#define S3C2412_NFCONT_ECC4_ENCINT (1 << 13)
-#define S3C2412_NFCONT_ECC4_DECINT (1 << 12)
-#define S3C2412_NFCONT_MAIN_ECC_LOCK (1 << 7)
-#define S3C2412_NFCONT_INIT_MAIN_ECC (1 << 5)
-#define S3C2412_NFCONT_nFCE1 (1 << 2)
-#define S3C2412_NFCONT_nFCE0 (1 << 1)
-
-#define S3C2412_NFSTAT_ECC_ENCDONE (1 << 7)
-#define S3C2412_NFSTAT_ECC_DECDONE (1 << 6)
-#define S3C2412_NFSTAT_ILLEGAL_ACCESS (1 << 5)
-#define S3C2412_NFSTAT_RnB_CHANGE (1 << 4)
-#define S3C2412_NFSTAT_nFCE1 (1 << 3)
-#define S3C2412_NFSTAT_nFCE0 (1 << 2)
-#define S3C2412_NFSTAT_Res1 (1 << 1)
-#define S3C2412_NFSTAT_READY (1 << 0)
-
-#define S3C2412_NFECCERR_SERRDATA(x) (((x) >> 21) & 0xf)
-#define S3C2412_NFECCERR_SERRBIT(x) (((x) >> 18) & 0x7)
-#define S3C2412_NFECCERR_MERRDATA(x) (((x) >> 7) & 0x3ff)
-#define S3C2412_NFECCERR_MERRBIT(x) (((x) >> 4) & 0x7)
-#define S3C2412_NFECCERR_SPARE_ERR(x) (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_MAIN_ERR(x) (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_NONE (0)
-#define S3C2412_NFECCERR_1BIT (1)
-#define S3C2412_NFECCERR_MULTIBIT (2)
-#define S3C2412_NFECCERR_ECCAREA (3)
-
-#endif /* OPENOCD_FLASH_NAND_S3C24XX_REGS_H */
diff --git a/src/flash/nand/s3c6400.c b/src/flash/nand/s3c6400.c
deleted file mode 100644
index 7058133..0000000
--- a/src/flash/nand/s3c6400.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Peter Korsgaard <jacmet@sunsite.dk> *
- * Heavily based on s3c2412.c by Ben Dooks <ben@fluff.org> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "s3c24xx.h"
-/* s3c64xx uses another base address for the nand controller than 24xx */
-#undef S3C2410_NFREG
-#define S3C2410_NFREG(x) ((x) + 0x70200000)
-
-NAND_DEVICE_COMMAND_HANDLER(s3c6400_nand_device_command)
-{
- struct s3c24xx_nand_controller *info;
- CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
-
- /* fill in the address fields for the core device */
- info->cmd = S3C2440_NFCMD;
- info->addr = S3C2440_NFADDR;
- info->data = S3C2440_NFDATA;
- info->nfstat = S3C2412_NFSTAT;
-
- return ERROR_OK;
-}
-
-static int s3c6400_init(struct nand_device *nand)
-{
- struct target *target = nand->target;
-
- target_write_u32(target, S3C2410_NFCONF,
- S3C2440_NFCONF_TACLS(3) |
- S3C2440_NFCONF_TWRPH0(7) |
- S3C2440_NFCONF_TWRPH1(7) | 4);
-
- target_write_u32(target, S3C2440_NFCONT,
- S3C2412_NFCONT_INIT_MAIN_ECC |
- S3C2440_NFCONT_ENABLE);
-
- return ERROR_OK;
-}
-
-struct nand_flash_controller s3c6400_nand_controller = {
- .name = "s3c6400",
- .nand_device_command = &s3c6400_nand_device_command,
- .init = &s3c6400_init,
- .reset = &s3c24xx_reset,
- .command = &s3c24xx_command,
- .address = &s3c24xx_address,
- .write_data = &s3c24xx_write_data,
- .read_data = &s3c24xx_read_data,
- .write_page = s3c24xx_write_page,
- .read_page = s3c24xx_read_page,
- .write_block_data = &s3c2440_write_block_data,
- .read_block_data = &s3c2440_read_block_data,
- .nand_ready = &s3c2440_nand_ready,
-};
diff --git a/src/flash/nand/tcl.c b/src/flash/nand/tcl.c
deleted file mode 100644
index cbdeda5..0000000
--- a/src/flash/nand/tcl.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * Partially based on drivers/mtd/nand_ids.c from Linux. *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "core.h"
-#include "imp.h"
-#include "fileio.h"
-#include <target/target.h>
-
-/* to be removed */
-extern struct nand_device *nand_devices;
-
-COMMAND_HANDLER(handle_nand_list_command)
-{
- struct nand_device *p;
- int i;
-
- if (!nand_devices) {
- command_print(CMD_CTX, "no NAND flash devices configured");
- return ERROR_OK;
- }
-
- for (p = nand_devices, i = 0; p; p = p->next, i++) {
- if (p->device)
- command_print(CMD_CTX, "#%i: %s (%s) "
- "pagesize: %i, buswidth: %i,\n\t"
- "blocksize: %i, blocks: %i",
- i, p->device->name, p->manufacturer->name,
- p->page_size, p->bus_width,
- p->erase_size, p->num_blocks);
- else
- command_print(CMD_CTX, "#%i: not probed", i);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nand_info_command)
-{
- int i = 0;
- int j = 0;
- int first = -1;
- int last = -1;
-
- switch (CMD_ARGC) {
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- case 1:
- first = 0;
- last = INT32_MAX;
- break;
- case 2:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
- first = last = i;
- i = 0;
- break;
- case 3:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
- break;
- }
-
- struct nand_device *p;
- int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- if (NULL == p->device) {
- command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- if (first >= p->num_blocks)
- first = p->num_blocks - 1;
-
- if (last >= p->num_blocks)
- last = p->num_blocks - 1;
-
- command_print(CMD_CTX,
- "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
- i++,
- p->device->name,
- p->manufacturer->name,
- p->page_size,
- p->bus_width,
- p->erase_size);
-
- for (j = first; j <= last; j++) {
- char *erase_state, *bad_state;
-
- if (p->blocks[j].is_erased == 0)
- erase_state = "not erased";
- else if (p->blocks[j].is_erased == 1)
- erase_state = "erased";
- else
- erase_state = "erase state unknown";
-
- if (p->blocks[j].is_bad == 0)
- bad_state = "";
- else if (p->blocks[j].is_bad == 1)
- bad_state = " (marked bad)";
- else
- bad_state = " (block condition unknown)";
-
- command_print(CMD_CTX,
- "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s",
- j,
- p->blocks[j].offset,
- p->blocks[j].size / 1024,
- erase_state,
- bad_state);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nand_probe_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct nand_device *p;
- int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- retval = nand_probe(p);
- if (retval == ERROR_OK) {
- command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
- p->device->name, p->manufacturer->name);
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_nand_erase_command)
-{
- if (CMD_ARGC != 1 && CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct nand_device *p;
- int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- unsigned long offset;
- unsigned long length;
-
- /* erase specified part of the chip; or else everything */
- if (CMD_ARGC == 3) {
- unsigned long size = p->erase_size * p->num_blocks;
-
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
- if ((offset % p->erase_size) != 0 || offset >= size)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
- if ((length == 0) || (length % p->erase_size) != 0
- || (length + offset) > size)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- offset /= p->erase_size;
- length /= p->erase_size;
- } else {
- offset = 0;
- length = p->num_blocks;
- }
-
- retval = nand_erase(p, offset, offset + length - 1);
- if (retval == ERROR_OK) {
- command_print(CMD_CTX, "erased blocks %lu to %lu "
- "on NAND flash device #%s '%s'",
- offset, offset + length - 1,
- CMD_ARGV[0], p->device->name);
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
-{
- int first = -1;
- int last = -1;
-
- if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct nand_device *p;
- int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- if (CMD_ARGC == 3) {
- unsigned long offset;
- unsigned long length;
-
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
- if (offset % p->erase_size)
- return ERROR_COMMAND_SYNTAX_ERROR;
- offset /= p->erase_size;
-
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
- if (length % p->erase_size)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- length -= 1;
- length /= p->erase_size;
-
- first = offset;
- last = offset + length;
- }
-
- retval = nand_build_bbt(p, first, last);
- if (retval == ERROR_OK) {
- command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
- "use \"nand info\" command to list blocks");
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_nand_write_command)
-{
- struct nand_device *nand = NULL;
- struct nand_fileio_state s;
- int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
- &s, &nand, FILEIO_READ, false, true);
- if (ERROR_OK != retval)
- return retval;
-
- uint32_t total_bytes = s.size;
- while (s.size > 0) {
- int bytes_read = nand_fileio_read(nand, &s);
- if (bytes_read <= 0) {
- command_print(CMD_CTX, "error while reading file");
- return nand_fileio_cleanup(&s);
- }
- s.size -= bytes_read;
-
- retval = nand_write_page(nand, s.address / nand->page_size,
- s.page, s.page_size, s.oob, s.oob_size);
- if (ERROR_OK != retval) {
- command_print(CMD_CTX, "failed writing file %s "
- "to NAND flash %s at offset 0x%8.8" PRIx32,
- CMD_ARGV[1], CMD_ARGV[0], s.address);
- return nand_fileio_cleanup(&s);
- }
- s.address += s.page_size;
- }
-
- if (nand_fileio_finish(&s) == ERROR_OK) {
- command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
- "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
- CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
- duration_kbps(&s.bench, total_bytes));
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nand_verify_command)
-{
- struct nand_device *nand = NULL;
- struct nand_fileio_state file;
- int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
- &file, &nand, FILEIO_READ, false, true);
- if (ERROR_OK != retval)
- return retval;
-
- struct nand_fileio_state dev;
- nand_fileio_init(&dev);
- dev.address = file.address;
- dev.size = file.size;
- dev.oob_format = file.oob_format;
- retval = nand_fileio_start(CMD_CTX, nand, NULL, FILEIO_NONE, &dev);
- if (ERROR_OK != retval)
- return retval;
-
- while (file.size > 0) {
- retval = nand_read_page(nand, dev.address / dev.page_size,
- dev.page, dev.page_size, dev.oob, dev.oob_size);
- if (ERROR_OK != retval) {
- command_print(CMD_CTX, "reading NAND flash page failed");
- nand_fileio_cleanup(&dev);
- nand_fileio_cleanup(&file);
- return retval;
- }
-
- int bytes_read = nand_fileio_read(nand, &file);
- if (bytes_read <= 0) {
- command_print(CMD_CTX, "error while reading file");
- nand_fileio_cleanup(&dev);
- nand_fileio_cleanup(&file);
- return ERROR_FAIL;
- }
-
- if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
- (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size))) {
- command_print(CMD_CTX, "NAND flash contents differ "
- "at 0x%8.8" PRIx32, dev.address);
- nand_fileio_cleanup(&dev);
- nand_fileio_cleanup(&file);
- return ERROR_FAIL;
- }
-
- file.size -= bytes_read;
- dev.address += nand->page_size;
- }
-
- if (nand_fileio_finish(&file) == ERROR_OK) {
- command_print(CMD_CTX, "verified file %s in NAND flash %s "
- "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
- CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
- duration_kbps(&file.bench, dev.size));
- }
-
- return nand_fileio_cleanup(&dev);
-}
-
-COMMAND_HANDLER(handle_nand_dump_command)
-{
- size_t filesize;
- struct nand_device *nand = NULL;
- struct nand_fileio_state s;
- int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
- &s, &nand, FILEIO_WRITE, true, false);
- if (ERROR_OK != retval)
- return retval;
-
- while (s.size > 0) {
- size_t size_written;
- retval = nand_read_page(nand, s.address / nand->page_size,
- s.page, s.page_size, s.oob, s.oob_size);
- if (ERROR_OK != retval) {
- command_print(CMD_CTX, "reading NAND flash page failed");
- nand_fileio_cleanup(&s);
- return retval;
- }
-
- if (NULL != s.page)
- fileio_write(s.fileio, s.page_size, s.page, &size_written);
-
- if (NULL != s.oob)
- fileio_write(s.fileio, s.oob_size, s.oob, &size_written);
-
- s.size -= nand->page_size;
- s.address += nand->page_size;
- }
-
- retval = fileio_size(s.fileio, &filesize);
- if (retval != ERROR_OK)
- return retval;
-
- if (nand_fileio_finish(&s) == ERROR_OK) {
- command_print(CMD_CTX, "dumped %zu bytes in %fs (%0.3f KiB/s)",
- filesize, duration_elapsed(&s.bench),
- duration_kbps(&s.bench, filesize));
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nand_raw_access_command)
-{
- if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct nand_device *p;
- int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- if (NULL == p->device) {
- command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- if (CMD_ARGC == 2)
- COMMAND_PARSE_ENABLE(CMD_ARGV[1], p->use_raw);
-
- const char *msg = p->use_raw ? "enabled" : "disabled";
- command_print(CMD_CTX, "raw access is %s", msg);
-
- return ERROR_OK;
-}
-
-static const struct command_registration nand_exec_command_handlers[] = {
- {
- .name = "list",
- .handler = handle_nand_list_command,
- .mode = COMMAND_EXEC,
- .help = "list configured NAND flash devices",
- },
- {
- .name = "info",
- .handler = handle_nand_info_command,
- .mode = COMMAND_EXEC,
- .usage = "[banknum | first_bank_num last_bank_num]",
- .help = "print info about one or more NAND flash devices",
- },
- {
- .name = "probe",
- .handler = handle_nand_probe_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "identify NAND flash device",
- },
- {
- .name = "check_bad_blocks",
- .handler = handle_nand_check_bad_blocks_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id [offset length]",
- .help = "check all or part of NAND flash device for bad blocks",
- },
- {
- .name = "erase",
- .handler = handle_nand_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id [offset length]",
- .help = "erase all or subset of blocks on NAND flash device",
- },
- {
- .name = "dump",
- .handler = handle_nand_dump_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename offset length "
- "['oob_raw'|'oob_only']",
- .help = "dump from NAND flash device",
- },
- {
- .name = "verify",
- .handler = handle_nand_verify_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename offset "
- "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
- .help = "verify NAND flash device",
- },
- {
- .name = "write",
- .handler = handle_nand_write_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename offset "
- "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
- .help = "write to NAND flash device",
- },
- {
- .name = "raw_access",
- .handler = handle_nand_raw_access_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ['enable'|'disable']",
- .help = "raw access to NAND flash device",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int nand_init(struct command_context *cmd_ctx)
-{
- if (!nand_devices)
- return ERROR_OK;
- struct command *parent = command_find_in_context(cmd_ctx, "nand");
- return register_commands(cmd_ctx, parent, nand_exec_command_handlers);
-}
-
-COMMAND_HANDLER(handle_nand_init_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- static bool nand_initialized;
- if (nand_initialized) {
- LOG_INFO("'nand init' has already been called");
- return ERROR_OK;
- }
- nand_initialized = true;
-
- LOG_DEBUG("Initializing NAND devices...");
- return nand_init(CMD_CTX);
-}
-
-static int nand_list_walker(struct nand_flash_controller *c, void *x)
-{
- struct command_context *cmd_ctx = x;
- command_print(cmd_ctx, " %s", c->name);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nand_list_drivers)
-{
- command_print(CMD_CTX, "Available NAND flash controller drivers:");
- return nand_driver_walk(&nand_list_walker, CMD_CTX);
-}
-
-static COMMAND_HELPER(create_nand_device, const char *bank_name,
- struct nand_flash_controller *controller)
-{
- struct nand_device *c;
- struct target *target;
- int retval;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- target = get_target(CMD_ARGV[1]);
- if (!target) {
- LOG_ERROR("invalid target %s", CMD_ARGV[1]);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- if (NULL != controller->commands) {
- retval = register_commands(CMD_CTX, NULL,
- controller->commands);
- if (ERROR_OK != retval)
- return retval;
- }
- c = malloc(sizeof(struct nand_device));
- if (c == NULL) {
- LOG_ERROR("End of memory");
- return ERROR_FAIL;
- }
-
- c->name = strdup(bank_name);
- c->target = target;
- c->controller = controller;
- c->controller_priv = NULL;
- c->manufacturer = NULL;
- c->device = NULL;
- c->bus_width = 0;
- c->address_cycles = 0;
- c->page_size = 0;
- c->use_raw = false;
- c->next = NULL;
-
- retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
- if (ERROR_OK != retval) {
- LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
- controller->name,
- controller->usage);
- free(c);
- return retval;
- }
-
- if (controller->usage == NULL)
- LOG_DEBUG("'%s' driver usage field missing", controller->name);
-
- nand_device_add(c);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nand_device_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* save name and increment (for compatibility) with drivers */
- const char *bank_name = *CMD_ARGV++;
- CMD_ARGC--;
-
- const char *driver_name = CMD_ARGV[0];
- struct nand_flash_controller *controller;
- controller = nand_driver_find_by_name(CMD_ARGV[0]);
- if (NULL == controller) {
- LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
- return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
- }
- return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller);
-}
-
-static const struct command_registration nand_config_command_handlers[] = {
- {
- .name = "device",
- .handler = &handle_nand_device_command,
- .mode = COMMAND_CONFIG,
- .help = "defines a new NAND bank",
- .usage = "bank_id driver target [driver_options ...]",
- },
- {
- .name = "drivers",
- .handler = &handle_nand_list_drivers,
- .mode = COMMAND_ANY,
- .help = "lists available NAND drivers",
- .usage = ""
- },
- {
- .name = "init",
- .mode = COMMAND_CONFIG,
- .handler = &handle_nand_init_command,
- .help = "initialize NAND devices",
- .usage = ""
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration nand_command_handlers[] = {
- {
- .name = "nand",
- .mode = COMMAND_ANY,
- .help = "NAND flash command group",
- .usage = "",
- .chain = nand_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int nand_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, nand_command_handlers);
-}
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
deleted file mode 100644
index 084e6b6..0000000
--- a/src/flash/nor/Makefile.am
+++ /dev/null
@@ -1,70 +0,0 @@
-include $(top_srcdir)/common.mk
-
-noinst_LTLIBRARIES = libocdflashnor.la
-libocdflashnor_la_SOURCES = \
- core.c \
- tcl.c \
- $(NOR_DRIVERS) \
- drivers.c
-
-NOR_DRIVERS = \
- aduc702x.c \
- aducm360.c \
- ambiqmicro.c \
- at91sam4.c \
- at91sam4l.c \
- at91samd.c \
- at91sam3.c \
- at91sam7.c \
- atsamv.c \
- avrf.c \
- cfi.c \
- dsp5680xx_flash.c \
- efm32.c \
- em357.c \
- fespi.c \
- faux.c \
- fm3.c \
- fm4.c \
- jtagspi.c \
- kinetis.c \
- kinetis_ke.c \
- lpc2000.c \
- lpc288x.c \
- lpc2900.c \
- lpcspifi.c \
- mdr.c \
- mrvlqspi.c \
- niietcm4.c \
- non_cfi.c \
- nrf51.c \
- numicro.c \
- ocl.c \
- pic32mx.c \
- psoc4.c \
- sim3x.c \
- spi.c \
- stmsmi.c \
- stellaris.c \
- stm32f1x.c \
- stm32f2x.c \
- stm32lx.c \
- stm32l4x.c \
- str7x.c \
- str9x.c \
- str9xpec.c \
- tms470.c \
- virtual.c \
- xmc1xxx.c \
- xmc4xxx.c
-
-noinst_HEADERS = \
- core.h \
- cfi.h \
- driver.h \
- imp.h \
- non_cfi.h \
- ocl.h \
- spi.h
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/flash/nor/aduc702x.c b/src/flash/nor/aduc702x.c
deleted file mode 100644
index 34cc362..0000000
--- a/src/flash/nor/aduc702x.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Kevin McGuire *
- * Copyright (C) 2008 by Marcel Wijlaars *
- * Copyright (C) 2009 by Michael Ashton *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <helper/time_support.h>
-#include <target/algorithm.h>
-#include <target/arm.h>
-
-static int aduc702x_build_sector_list(struct flash_bank *bank);
-static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms);
-static int aduc702x_set_write_enable(struct target *target, int enable);
-
-#define ADUC702x_FLASH 0xfffff800
-#define ADUC702x_FLASH_FEESTA (0*4)
-#define ADUC702x_FLASH_FEEMOD (1*4)
-#define ADUC702x_FLASH_FEECON (2*4)
-#define ADUC702x_FLASH_FEEDAT (3*4)
-#define ADUC702x_FLASH_FEEADR (4*4)
-#define ADUC702x_FLASH_FEESIGN (5*4)
-#define ADUC702x_FLASH_FEEPRO (6*4)
-#define ADUC702x_FLASH_FEEHIDE (7*4)
-
-/* flash bank aduc702x 0 0 0 0 <target#>
- * The ADC7019-28 devices all have the same flash layout */
-FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
-{
- bank->base = 0x80000;
- bank->size = 0xF800; /* top 4k not accessible */
-
- aduc702x_build_sector_list(bank);
-
- return ERROR_OK;
-}
-
-static int aduc702x_build_sector_list(struct flash_bank *bank)
-{
- /* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */
-
- int i = 0;
- uint32_t offset = 0;
-
- /* sector size is 512 */
- bank->num_sectors = bank->size / 512;
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- for (i = 0; i < bank->num_sectors; ++i) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 512;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 0;
- }
-
- return ERROR_OK;
-}
-
-static int aduc702x_protect_check(struct flash_bank *bank)
-{
- printf("aduc702x_protect_check not implemented yet.\n");
- return ERROR_OK;
-}
-
-static int aduc702x_erase(struct flash_bank *bank, int first, int last)
-{
- /* int res; */
- int x;
- int count;
- /* uint32_t v; */
- struct target *target = bank->target;
-
- aduc702x_set_write_enable(target, 1);
-
- /* mass erase */
- if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
- LOG_DEBUG("performing mass erase.");
- target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, 0x3cff);
- target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
- target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);
-
- if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) {
- LOG_ERROR("mass erase failed");
- aduc702x_set_write_enable(target, 0);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- LOG_DEBUG("mass erase successful.");
- return ERROR_OK;
- } else {
- unsigned long adr;
-
- count = last - first + 1;
- for (x = 0; x < count; ++x) {
- adr = bank->base + ((first + x) * 512);
-
- target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
- target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);
-
- if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) {
- LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
- aduc702x_set_write_enable(target, 0);
- return ERROR_FLASH_SECTOR_NOT_ERASED;
- }
-
- LOG_DEBUG("erased sector at address 0x%08lX", adr);
- }
- }
-
- aduc702x_set_write_enable(target, 0);
-
- return ERROR_OK;
-}
-
-static int aduc702x_protect(struct flash_bank *bank, int set, int first, int last)
-{
- printf("aduc702x_protect not implemented yet.\n");
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-/* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
- * back to another mechanism that does not require onboard RAM
- *
- * Caller should not check for other return values specifically
- */
-static int aduc702x_write_block(struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 7000;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[6];
- struct arm_algorithm arm_algo;
- int retval = ERROR_OK;
-
- if (((count%2) != 0) || ((offset%2) != 0)) {
- LOG_ERROR("write block must be multiple of two bytes in offset & length");
- return ERROR_FAIL;
- }
-
- /* parameters:
-
- r0 - address of source data (absolute)
- r1 - number of halfwords to be copied
- r2 - start address in flash (offset from beginning of flash memory)
- r3 - exit code
- r4 - base address of flash controller (0xFFFFF800)
-
- registers:
-
- r5 - scratch
- r6 - set to 2, used to write flash command
-
- */
- static const uint32_t aduc702x_flash_write_code[] = {
- /* <_start>: */
- 0xe3a05008, /* mov r5, #8 ; 0x8 */
- 0xe5845004, /* str r5, [r4, #4] */
- 0xe3a06002, /* mov r6, #2 ; 0x2 */
- /* <next>: */
- 0xe1c421b0, /* strh r2, [r4, #16] */
- 0xe0d050b2, /* ldrh r5, [r0], #2 */
- 0xe1c450bc, /* strh r5, [r4, #12] */
- 0xe5c46008, /* strb r6, [r4, #8] */
- /* <wait_complete>: */
- 0xe1d430b0, /* ldrh r3, [r4] */
- 0xe3130004, /* tst r3, #4 ; 0x4 */
- 0x1afffffc, /* bne 1001c <wait_complete> */
- 0xe2822002, /* add r2, r2, #2 ; 0x2 */
- 0xe2511001, /* subs r1, r1, #1 ; 0x1 */
- 0x0a000001, /* beq 1003c <done> */
- 0xe3130001, /* tst r3, #1 ; 0x1 */
- 0x1afffff3, /* bne 1000c <next> */
- /* <done>: */
- 0xeafffffe /* b 1003c <done> */
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- uint8_t code[sizeof(aduc702x_flash_write_code)];
- target_buffer_set_u32_array(target, code, ARRAY_SIZE(aduc702x_flash_write_code),
- aduc702x_flash_write_code);
- retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a buffer,
- *free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- 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_IN);
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
-
- while (count > 0) {
- uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
-
- retval = target_write_buffer(target, source->address, thisrun_count, buffer);
- if (retval != ERROR_OK)
- break;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
- buf_set_u32(reg_params[2].value, 0, 32, address);
- buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
-
- retval = target_run_algorithm(target, 0, NULL, 5,
- reg_params, write_algorithm->address,
- write_algorithm->address +
- sizeof(aduc702x_flash_write_code) - 4,
- 10000, &arm_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("error executing aduc702x flash write algorithm");
- break;
- }
-
- if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) {
- /* FIX!!!! what does this mean??? replace w/sensible error message */
- LOG_ERROR("aduc702x detected error writing flash");
- retval = ERROR_FAIL;
- break;
- }
-
- buffer += thisrun_count;
- address += thisrun_count;
- count -= thisrun_count;
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-/* All-JTAG, single-access method. Very slow. Used only if there is no
- * working area available. */
-static int aduc702x_write_single(struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- uint32_t x;
- uint8_t b;
- struct target *target = bank->target;
-
- aduc702x_set_write_enable(target, 1);
-
- for (x = 0; x < count; x += 2) {
- /* FEEADR = address */
- target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x);
-
- /* set up data */
- if ((x + 1) == count) {
- /* last byte */
- target_read_u8(target, offset + x + 1, &b);
- } else
- b = buffer[x + 1];
-
- target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8));
-
- /* do single-write command */
- target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02);
-
- if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) {
- LOG_ERROR("single write failed for address 0x%08lX",
- (unsigned long)(offset + x));
- aduc702x_set_write_enable(target, 0);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- }
- LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x));
-
- aduc702x_set_write_enable(target, 0);
-
- return ERROR_OK;
-}
-
-static int aduc702x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- int retval;
-
- /* try using a block write */
- retval = aduc702x_write_block(bank, buffer, offset, count);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * use normal (slow) JTAG method */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
-
- retval = aduc702x_write_single(bank, buffer, offset, count);
- if (retval != ERROR_OK) {
- LOG_ERROR("slow write failed");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
- }
-
- return retval;
-}
-
-static int aduc702x_probe(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-/* sets FEEMOD bit 3
- * enable = 1 enables writes & erases, 0 disables them */
-static int aduc702x_set_write_enable(struct target *target, int enable)
-{
- /* don't bother to preserve int enable bit here */
- target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);
-
- return ERROR_OK;
-}
-
-/* wait up to timeout_ms for controller to not be busy,
- * then check whether the command passed or failed.
- *
- * this function sleeps 1ms between checks (after the first one),
- * so in some cases may slow things down without a usleep after the first read */
-static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms)
-{
- uint8_t v = 4;
-
- int64_t endtime = timeval_ms() + timeout_ms;
- while (1) {
- target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
- if ((v & 4) == 0)
- break;
- alive_sleep(1);
- if (timeval_ms() >= endtime)
- break;
- }
-
- if (v & 2)
- return ERROR_FAIL;
- /* if a command is ignored, both the success and fail bits may be 0 */
- else if ((v & 3) == 0)
- return ERROR_FAIL;
- else
- return ERROR_OK;
-}
-
-struct flash_driver aduc702x_flash = {
- .name = "aduc702x",
- .flash_bank_command = aduc702x_flash_bank_command,
- .erase = aduc702x_erase,
- .protect = aduc702x_protect,
- .write = aduc702x_write,
- .read = default_flash_read,
- .probe = aduc702x_probe,
- .auto_probe = aduc702x_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = aduc702x_protect_check,
-};
diff --git a/src/flash/nor/aducm360.c b/src/flash/nor/aducm360.c
deleted file mode 100644
index 8681a25..0000000
--- a/src/flash/nor/aducm360.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Ivan Buliev *
- * i.buliev@mikrosistemi.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/***************************************************************************
- * This version for ADuCM360 is largely based on the following flash *
- * drivers: *
- * - aduc702x.c *
- * Copyright (C) 2008 by Kevin McGuire *
- * Copyright (C) 2008 by Marcel Wijlaars *
- * Copyright (C) 2009 by Michael Ashton *
- * and *
- * - stm32f1x.c *
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <helper/time_support.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-static int aducm360_build_sector_list(struct flash_bank *bank);
-static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms);
-static int aducm360_set_write_enable(struct target *target, int enable);
-
-#define ADUCM360_FLASH_BASE 0x40002800
-#define ADUCM360_FLASH_FEESTA 0x0000
-#define ADUCM360_FLASH_FEECON0 0x0004
-#define ADUCM360_FLASH_FEECMD 0x0008
-#define ADUCM360_FLASH_FEEADR0L 0x0010
-#define ADUCM360_FLASH_FEEADR0H 0x0014
-#define ADUCM360_FLASH_FEEADR1L 0x0018
-#define ADUCM360_FLASH_FEEADR1H 0x001C
-#define ADUCM360_FLASH_FEEKEY 0x0020
-#define ADUCM360_FLASH_FEEPROL 0x0028
-#define ADUCM360_FLASH_FEEPROH 0x002C
-#define ADUCM360_FLASH_FEESIGL 0x0030
-#define ADUCM360_FLASH_FEESIGH 0x0034
-#define ADUCM360_FLASH_FEECON1 0x0038
-#define ADUCM360_FLASH_FEEADRAL 0x0048
-#define ADUCM360_FLASH_FEEADRAH 0x004C
-#define ADUCM360_FLASH_FEEAEN0 0x0078
-#define ADUCM360_FLASH_FEEAEN1 0x007C
-#define ADUCM360_FLASH_FEEAEN2 0x0080
-
-/* flash bank aducm360 0 0 0 0 <target#> */
-FLASH_BANK_COMMAND_HANDLER(aducm360_flash_bank_command)
-{
- bank->base = 0x00000000;
- bank->size = 0x00020000;
-
- aducm360_build_sector_list(bank);
-
- return ERROR_OK;
-}
-
-#define FLASH_SECTOR_SIZE 512
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_build_sector_list(struct flash_bank *bank)
-{
- int i = 0;
- uint32_t offset = 0;
-
- /* sector size is 512 */
- bank->num_sectors = bank->size / FLASH_SECTOR_SIZE;
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- for (i = 0; i < bank->num_sectors; ++i) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = FLASH_SECTOR_SIZE;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 0;
- }
-
- return ERROR_OK;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_protect_check(struct flash_bank *bank)
-{
- LOG_WARNING("aducm360_protect_check not implemented.");
- return ERROR_OK;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_mass_erase(struct target *target)
-{
- uint32_t value;
- int res = ERROR_OK;
-
- /* Clear any old status */
- target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
-
- /* Enable the writing to the flash*/
- aducm360_set_write_enable(target, 1);
-
- /* Unlock for writing */
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F456);
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F123);
- /* Issue the 'MASSERASE' command */
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD, 0x00000003);
-
- /* Check the result */
- res = aducm360_check_flash_completion(target, 3500);
- if (res != ERROR_OK) {
- LOG_ERROR("mass erase failed.");
- aducm360_set_write_enable(target, 0);
- res = ERROR_FLASH_OPERATION_FAILED;
- }
-
- return res;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_page_erase(struct target *target, uint32_t padd)
-{
- uint32_t value;
- int res = ERROR_OK;
-
- /* Clear any old status */
- target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
-
- /* Enable the writing to the flash*/
- aducm360_set_write_enable(target, 1);
-
- /* Unlock for writing */
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F456);
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F123);
- /* Write the sector address */
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0L, padd & 0xFFFF);
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0H, (padd>>16) & 0xFFFF);
- /* Issue the 'ERASEPAGE' command */
- target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD, 0x00000001);
-
- /* Check the result */
- res = aducm360_check_flash_completion(target, 50);
- if (res != ERROR_OK) {
- LOG_ERROR("page erase failed at 0x%08" PRIx32, padd);
- aducm360_set_write_enable(target, 0);
- res = ERROR_FLASH_OPERATION_FAILED;
- }
-
- return res;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_erase(struct flash_bank *bank, int first, int last)
-{
- int res = ERROR_OK;
- int i;
- int count;
- struct target *target = bank->target;
- uint32_t padd;
-
- if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
- res = aducm360_mass_erase(target);
- } else {
- count = last - first + 1;
- for (i = 0; i < count; ++i) {
- padd = bank->base + ((first+i)*FLASH_SECTOR_SIZE);
- res = aducm360_page_erase(target, padd);
- if (res != ERROR_OK)
- break;
- }
- }
-
- return res;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_protect(struct flash_bank *bank, int set, int first, int last)
-{
- LOG_ERROR("aducm360_protect not implemented.");
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_write_block_sync(
- struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t target_buffer_size = 8192;
- struct working_area *helper;
- struct working_area *target_buffer;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[8];
- int retval = ERROR_OK;
- uint32_t entry_point = 0, exit_point = 0;
- uint32_t res;
- struct armv7m_algorithm armv7m_algo;
-
- static const uint32_t aducm360_flash_write_code[] = {
- /* helper.code */
- 0x88AF4D10, 0x0704F047, 0x682F80AF, 0x600E6806,
- 0xF017882F, 0xF43F0F08, 0xF851AFFB, 0x42B77B04,
- 0x800DF040, 0x0004F100, 0xF47F3A04, 0x686FAFEF,
- 0x0704F027, 0xF04F80AF, 0xF0000400, 0xF04FB802,
- 0xBE000480, 0x40002800, 0x00015000, 0x20000000,
- 0x00013000
- };
-
- LOG_DEBUG("'aducm360_write_block_sync' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
- address, count);
-
- /* ----- Check the destination area for a Long Word alignment ----- */
- if (((count%4) != 0) || ((offset%4) != 0)) {
- LOG_ERROR("write block must be multiple of four bytes in offset & length");
- return ERROR_FAIL;
- }
-
- /* ----- Allocate space in the target's RAM for the helper code ----- */
- if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code),
- &helper) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* ----- Upload the helper code to the space in the target's RAM ----- */
- uint8_t code[sizeof(aducm360_flash_write_code)];
- target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code),
- aducm360_flash_write_code);
- retval = target_write_buffer(target, helper->address, sizeof(code), code);
- if (retval != ERROR_OK)
- return retval;
- entry_point = helper->address;
-
- /* ----- Allocate space in the target's RAM for the user application's object code ----- */
- while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) {
- LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
- target_buffer_size);
- target_buffer_size /= 2;
- if (target_buffer_size <= 256) { /* No room available */
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- target_free_working_area(target, helper);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- /* ----- Prepare the target for the helper ----- */
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /*SRC */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /*DST */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /*COUNT */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /*not used */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN); /*RESULT */
-
- /* ===== Execute the Main Programming Loop! ===== */
- while (count > 0) {
- uint32_t thisrun_count = (count > target_buffer_size) ? target_buffer_size : count;
-
- /* ----- Upload the chunk ----- */
- retval = target_write_buffer(target, target_buffer->address, thisrun_count, buffer);
- if (retval != ERROR_OK)
- break;
- /* Set the arguments for the helper */
- buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address); /*SRC */
- buf_set_u32(reg_params[1].value, 0, 32, address); /*DST */
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); /*COUNT */
- buf_set_u32(reg_params[3].value, 0, 32, 0); /*NOT USED*/
-
- retval = target_run_algorithm(target, 0, NULL, 5,
- reg_params, entry_point, exit_point, 10000, &armv7m_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("error executing aducm360 flash write algorithm");
- break;
- }
-
- res = buf_get_u32(reg_params[4].value, 0, 32);
- if (res) {
- LOG_ERROR("aducm360 fast sync algorithm reports an error (%02X)", res);
- retval = ERROR_FAIL;
- break;
- }
-
- buffer += thisrun_count;
- address += thisrun_count;
- count -= thisrun_count;
- }
-
- target_free_working_area(target, target_buffer);
- target_free_working_area(target, helper);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_write_block_async(
- struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t target_buffer_size = 1024;
- struct working_area *helper;
- struct working_area *target_buffer;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[9];
- int retval = ERROR_OK;
- uint32_t entry_point = 0, exit_point = 0;
- uint32_t res;
- uint32_t wcount;
- struct armv7m_algorithm armv7m_algo;
-
- static const uint32_t aducm360_flash_write_code[] = {
- /* helper.code */
- 0x4050F8DF, 0xF04588A5, 0x80A50504, 0x8000F8D0,
- 0x0F00F1B8, 0x8016F000, 0x45476847, 0xAFF6F43F,
- 0x6B04F857, 0x6B04F842, 0xF0158825, 0xF43F0F08,
- 0x428FAFFB, 0xF100BF28, 0x60470708, 0xB10B3B01,
- 0xBFE4F7FF, 0xF02588A5, 0x80A50504, 0x0900F04F,
- 0xBE00BF00, 0x40002800, 0x20000000, 0x20000100,
- 0x00013000
- };
-
- LOG_DEBUG("'aducm360_write_block_async' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
- address, count);
-
- /* ----- Check the destination area for a Long Word alignment ----- */
- if (((count%4) != 0) || ((offset%4) != 0)) {
- LOG_ERROR("write block must be multiple of four bytes in offset & length");
- return ERROR_FAIL;
- }
- wcount = count/4;
-
- /* ----- Allocate space in the target's RAM for the helper code ----- */
- if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code),
- &helper) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* ----- Upload the helper code to the space in the target's RAM ----- */
- uint8_t code[sizeof(aducm360_flash_write_code)];
- target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code),
- aducm360_flash_write_code);
- retval = target_write_buffer(target, helper->address, sizeof(code), code);
- if (retval != ERROR_OK)
- return retval;
- entry_point = helper->address;
-
- /* ----- Allocate space in the target's RAM for the user application's object code ----- */
- while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) {
- LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
- target_buffer_size);
- target_buffer_size /= 2;
- if (target_buffer_size <= 256) { /* No room available */
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- target_free_working_area(target, helper);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- /* ----- Prepare the target for the helper ----- */
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /*SRCBEG */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /*SRCEND */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /*DST */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /*COUNT (LWs)*/
- init_reg_param(&reg_params[4], "r9", 32, PARAM_IN); /*RESULT */
-
- buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address);
- buf_set_u32(reg_params[1].value, 0, 32, target_buffer->address + target_buffer->size);
- buf_set_u32(reg_params[2].value, 0, 32, address);
- buf_set_u32(reg_params[3].value, 0, 32, wcount);
-
- retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
- 0, NULL,
- 5, reg_params,
- target_buffer->address, target_buffer->size,
- entry_point, exit_point,
- &armv7m_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("error executing aducm360 flash write algorithm");
- } else {
- res = buf_get_u32(reg_params[4].value, 0, 32); /*RESULT*/
- if (res) {
- LOG_ERROR("aducm360 fast async algorithm reports an error (%02X)", res);
- retval = ERROR_FAIL;
- }
- }
-
- target_free_working_area(target, target_buffer);
- target_free_working_area(target, helper);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-/* ----------------------------------------------------------------------- */
-/* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
- * back to another mechanism that does not require onboard RAM
- *
- * Caller should not check for other return values specifically
- */
-static int aducm360_write_block(struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- int choice = 0;
-
- switch (choice) {
- case 0:
- return aducm360_write_block_sync(bank, buffer, offset, count);
- break;
- case 1:
- return aducm360_write_block_async(bank, buffer, offset, count);
- break;
- default:
- LOG_ERROR("aducm360_write_block was cancelled (no writing method was chosen)!");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-}
-
-/* ----------------------------------------------------------------------- */
-#define FEESTA_WRDONE 0x00000008
-
-static int aducm360_write_modified(struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- uint32_t value;
- int res = ERROR_OK;
- uint32_t i, j, a, d;
- struct target *target = bank->target;
-
- LOG_DEBUG("performing slow write (offset=0x%08" PRIx32 ", count=0x%08" PRIx32 ")...",
- offset, count);
-
- /* Enable the writing to the flash */
- aducm360_set_write_enable(target, 1);
-
- /* Clear any old status */
- target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
-
- for (i = 0; i < count; i += 4) {
- a = offset+i;
- for (j = 0; i < 4; i += 1)
- *((uint8_t *)(&d) + j) = buffer[i+j];
- target_write_u32(target, a, d);
- do {
- target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
- } while (!(value & FEESTA_WRDONE));
- }
- aducm360_set_write_enable(target, 0);
-
- return res;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- int retval;
-
- /* try using a block write */
- retval = aducm360_write_block(bank, buffer, offset, count);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * use normal (slow) JTAG method */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
-
- retval = aducm360_write_modified(bank, buffer, offset, count);
- if (retval != ERROR_OK) {
- LOG_ERROR("slow write failed");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
- }
- return retval;
-}
-
-/* ----------------------------------------------------------------------- */
-static int aducm360_probe(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-/* ----------------------------------------------------------------------- */
-/* sets FEECON0 bit 2
- * enable = 1 enables writes & erases, 0 disables them */
-static int aducm360_set_write_enable(struct target *target, int enable)
-{
- /* don't bother to preserve int enable bit here */
- uint32_t value;
-
- target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, &value);
- if (enable)
- value |= 0x00000004;
- else
- value &= ~0x00000004;
- target_write_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, value);
-
- return ERROR_OK;
-}
-
-/* ----------------------------------------------------------------------- */
-/* wait up to timeout_ms for controller to not be busy,
- * then check whether the command passed or failed.
- *
- * this function sleeps 1ms between checks (after the first one),
- * so in some cases may slow things down without a usleep after the first read */
-static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms)
-{
- uint32_t v = 1;
-
- int64_t endtime = timeval_ms() + timeout_ms;
- while (1) {
- target_read_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEESTA, &v);
- if ((v & 0x00000001) == 0)
- break;
- alive_sleep(1);
- if (timeval_ms() >= endtime)
- break;
- }
-
- if (!(v & 0x00000004)) /* b2 */
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-/* ----------------------------------------------------------------------- */
-struct flash_driver aducm360_flash = {
- .name = "aducm360",
- .flash_bank_command = aducm360_flash_bank_command,
- .erase = aducm360_erase,
- .protect = aducm360_protect,
- .write = aducm360_write,
- .read = default_flash_read,
- .probe = aducm360_probe,
- .auto_probe = aducm360_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = aducm360_protect_check,
-};
diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c
deleted file mode 100644
index b2c30e6..0000000
--- a/src/flash/nor/ambiqmicro.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/******************************************************************************
- *
- * @file ambiqmicro.c
- *
- * @brief Ambiq Micro flash driver.
- *
- *****************************************************************************/
-
-/******************************************************************************
- * Copyright (c) 2015, David Racine <dracine at ambiqmicro.com>
- *
- * Copyright (c) 2016, Rick Foos <rfoos at solengtech.com>
- *
- * Copyright (c) 2015-2016, Ambiq Micro, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "imp.h"
-#include "target/algorithm.h"
-#include "target/armv7m.h"
-#include "target/cortex_m.h"
-
-/** Check error, log error. */
-#define CHECK_STATUS(rc, msg) { \
- if (rc != ERROR_OK) { \
- LOG_ERROR("status(%d):%s\n", rc, msg); } }
-
-/*
- * Address and Key defines.
- */
-#define PROGRAM_KEY (0x12344321)
-#define OTP_PROGRAM_KEY (0x87655678)
-
-#define FLASH_PROGRAM_MAIN_FROM_SRAM 0x0800005d
-#define FLASH_PROGRAM_OTP_FROM_SRAM 0x08000061
-#define FLASH_ERASE_LIST_MAIN_PAGES_FROM_SRAM 0x08000065
-#define FLASH_MASS_ERASE_MAIN_PAGES_FROM_SRAM 0x08000069
-
-
-static const uint32_t apollo_flash_size[] = {
- 1 << 15,
- 1 << 16,
- 1 << 17,
- 1 << 18,
- 1 << 19,
- 1 << 20,
- 1 << 21
-};
-
-static const uint32_t apollo_sram_size[] = {
- 1 << 15,
- 1 << 16,
- 1 << 17,
- 1 << 18,
- 1 << 19,
- 1 << 20,
- 1 << 21
-};
-
-struct ambiqmicro_flash_bank {
- /* chip id register */
-
- uint32_t probed;
-
- const char *target_name;
- uint8_t target_class;
-
- uint32_t sramsiz;
- uint32_t flshsiz;
-
- /* flash geometry */
- uint32_t num_pages;
- uint32_t pagesize;
- uint32_t pages_in_lockregion;
-
- /* nv memory bits */
- uint16_t num_lockbits;
-
- /* main clock status */
- uint32_t rcc;
- uint32_t rcc2;
- uint8_t mck_valid;
- uint8_t xtal_mask;
- uint32_t iosc_freq;
- uint32_t mck_freq;
- const char *iosc_desc;
- const char *mck_desc;
-};
-
-static struct {
- uint8_t class;
- uint8_t partno;
- const char *partname;
-} ambiqmicroParts[6] = {
- {0xFF, 0x00, "Unknown"},
- {0x01, 0x00, "Apollo"},
- {0x02, 0x00, "Apollo2"},
- {0x03, 0x00, "Unknown"},
- {0x04, 0x00, "Unknown"},
- {0x05, 0x00, "Apollo"},
-};
-
-static char *ambiqmicroClassname[6] = {
- "Unknown", "Apollo", "Apollo2", "Unknown", "Unknown", "Apollo"
-};
-
-/***************************************************************************
-* openocd command interface *
-***************************************************************************/
-
-/* flash_bank ambiqmicro <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(ambiqmicro_flash_bank_command)
-{
- struct ambiqmicro_flash_bank *ambiqmicro_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- ambiqmicro_info = calloc(sizeof(struct ambiqmicro_flash_bank), 1);
-
- bank->driver_priv = ambiqmicro_info;
-
- ambiqmicro_info->target_name = "Unknown target";
-
- /* part wasn't probed yet */
- ambiqmicro_info->probed = 0;
-
- return ERROR_OK;
-}
-
-static int get_ambiqmicro_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
- int printed;
- char *classname;
-
- if (ambiqmicro_info->probed == 0) {
- LOG_ERROR("Target not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /* Check class name in range. */
- if (ambiqmicro_info->target_class < sizeof(ambiqmicroClassname))
- classname = ambiqmicroClassname[ambiqmicro_info->target_class];
- else
- classname = ambiqmicroClassname[0];
-
- printed = snprintf(buf,
- buf_size,
- "\nAmbiq Micro information: Chip is "
- "class %d (%s) %s\n",
- ambiqmicro_info->target_class,
- classname,
- ambiqmicro_info->target_name);
-
- if ((printed < 0))
- return ERROR_BUF_TOO_SMALL;
- return ERROR_OK;
-}
-
-/***************************************************************************
-* chip identification and status *
-***************************************************************************/
-
-/* Fill in driver info structure */
-static int ambiqmicro_read_part_info(struct flash_bank *bank)
-{
- struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t PartNum = 0;
- int retval;
-
- /*
- * Read Part Number.
- */
- retval = target_read_u32(target, 0x40020000, &PartNum);
- if (retval != ERROR_OK) {
- LOG_ERROR("status(0x%x):Could not read PartNum.\n", retval);
- /* Set PartNum to default device */
- PartNum = 0;
- }
- LOG_DEBUG("Part number: 0x%x", PartNum);
-
- /*
- * Determine device class.
- */
- ambiqmicro_info->target_class = (PartNum & 0xFF000000) >> 24;
-
- switch (ambiqmicro_info->target_class) {
- case 1: /* 1 - Apollo */
- case 5: /* 5 - Apollo Bootloader */
- bank->base = bank->bank_number * 0x40000;
- ambiqmicro_info->pagesize = 2048;
- ambiqmicro_info->flshsiz =
- apollo_flash_size[(PartNum & 0x00F00000) >> 20];
- ambiqmicro_info->sramsiz =
- apollo_sram_size[(PartNum & 0x000F0000) >> 16];
- ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
- ambiqmicro_info->pagesize;
- if (ambiqmicro_info->num_pages > 128) {
- ambiqmicro_info->num_pages = 128;
- ambiqmicro_info->flshsiz = 1024 * 256;
- }
- break;
-
- default:
- LOG_INFO("Unknown Class. Using Apollo-64 as default.");
-
- bank->base = bank->bank_number * 0x40000;
- ambiqmicro_info->pagesize = 2048;
- ambiqmicro_info->flshsiz = apollo_flash_size[1];
- ambiqmicro_info->sramsiz = apollo_sram_size[0];
- ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz /
- ambiqmicro_info->pagesize;
- if (ambiqmicro_info->num_pages > 128) {
- ambiqmicro_info->num_pages = 128;
- ambiqmicro_info->flshsiz = 1024 * 256;
- }
- break;
-
- }
-
- if (ambiqmicro_info->target_class <
- (sizeof(ambiqmicroParts)/sizeof(ambiqmicroParts[0])))
- ambiqmicro_info->target_name =
- ambiqmicroParts[ambiqmicro_info->target_class].partname;
- else
- ambiqmicro_info->target_name =
- ambiqmicroParts[0].partname;
-
- LOG_DEBUG("num_pages: %d, pagesize: %d, flash: %d, sram: %d",
- ambiqmicro_info->num_pages,
- ambiqmicro_info->pagesize,
- ambiqmicro_info->flshsiz,
- ambiqmicro_info->sramsiz);
-
- return ERROR_OK;
-}
-
-/***************************************************************************
-* flash operations *
-***************************************************************************/
-
-static int ambiqmicro_protect_check(struct flash_bank *bank)
-{
- struct ambiqmicro_flash_bank *ambiqmicro = bank->driver_priv;
- int status = ERROR_OK;
- uint32_t i;
-
-
- if (ambiqmicro->probed == 0) {
- LOG_ERROR("Target not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- for (i = 0; i < (unsigned) bank->num_sectors; i++)
- bank->sectors[i].is_protected = -1;
-
- return status;
-}
-/** Read flash status from bootloader. */
-static int check_flash_status(struct target *target, uint32_t address)
-{
- uint32_t retflash;
- int rc;
- rc = target_read_u32(target, address, &retflash);
- /* target connection failed. */
- if (rc != ERROR_OK) {
- LOG_DEBUG("%s:%d:%s(): status(0x%x)\n",
- __FILE__, __LINE__, __func__, rc);
- return rc;
- }
- /* target flash failed, unknown cause. */
- if (retflash != 0) {
- LOG_ERROR("Flash not happy: status(0x%x)", retflash);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- return ERROR_OK;
-}
-
-static int ambiqmicro_exec_command(struct target *target,
- uint32_t command,
- uint32_t flash_return_address)
-{
- int retval, retflash;
-
- retval = target_resume(
- target,
- false,
- command,
- true,
- true);
-
- CHECK_STATUS(retval, "error executing ambiqmicro command");
-
- /*
- * Wait for halt.
- */
- for (;; ) {
- target_poll(target);
- if (target->state == TARGET_HALTED)
- break;
- else if (target->state == TARGET_RUNNING ||
- target->state == TARGET_DEBUG_RUNNING) {
- /*
- * Keep polling until target halts.
- */
- target_poll(target);
- alive_sleep(100);
- LOG_DEBUG("state = %d", target->state);
- } else {
- LOG_ERROR("Target not halted or running %d", target->state);
- break;
- }
- }
-
- /*
- * Read return value, flash error takes precedence.
- */
- retflash = check_flash_status(target, flash_return_address);
- if (retflash != ERROR_OK)
- retval = retflash;
-
- /* Return code from target_resume OR flash. */
- return retval;
-}
-
-static int ambiqmicro_mass_erase(struct flash_bank *bank)
-{
- struct target *target = NULL;
- struct ambiqmicro_flash_bank *ambiqmicro_info = NULL;
- int retval = ERROR_OK;
-
- ambiqmicro_info = bank->driver_priv;
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (ambiqmicro_info->probed == 0) {
- LOG_ERROR("Target not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /*
- * Clear Bootloader bit.
- */
- retval = target_write_u32(target, 0x400201a0, 0x0);
- CHECK_STATUS(retval, "error clearing bootloader bit.");
-
- /*
- * Set up the SRAM.
- */
-
- /*
- * Bank.
- */
- retval = target_write_u32(target, 0x10000000, bank->bank_number);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Write Key.
- */
- retval = target_write_u32(target, 0x10000004, PROGRAM_KEY);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Breakpoint.
- */
- retval = target_write_u32(target, 0x10000008, 0xfffffffe);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Erase the main array.
- */
- LOG_INFO("Mass erase on bank %d.", bank->bank_number);
-
- /*
- * passed pc, addr = ROM function, handle breakpoints, not debugging.
- */
- retval = ambiqmicro_exec_command(target, FLASH_MASS_ERASE_MAIN_PAGES_FROM_SRAM, 0x10000008);
- CHECK_STATUS(retval, "error executing ambiqmicro flash mass erase.");
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * Set Bootloader bit, regardless of command execution.
- */
- retval = target_write_u32(target, 0x400201a0, 0x1);
- CHECK_STATUS(retval, "error setting bootloader bit.");
-
- return retval;
-}
-
-
-static int ambiqmicro_erase(struct flash_bank *bank, int first, int last)
-{
- struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t retval = ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (ambiqmicro_info->probed == 0) {
- LOG_ERROR("Target not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /*
- * Check pages.
- * Fix num_pages for the device.
- */
- if ((first < 0) || (last < first) || (last >= (int)ambiqmicro_info->num_pages))
- return ERROR_FLASH_SECTOR_INVALID;
-
- /*
- * Just Mass Erase if all pages are given.
- * TODO: Fix num_pages for the device
- */
- if ((first == 0) && (last == ((int)ambiqmicro_info->num_pages-1)))
- return ambiqmicro_mass_erase(bank);
-
- /*
- * Clear Bootloader bit.
- */
- retval = target_write_u32(target, 0x400201a0, 0x0);
- CHECK_STATUS(retval, "error clearing bootloader bit.");
-
- /*
- * Set up the SRAM.
- */
-
- /*
- * Bank.
- */
- retval = target_write_u32(target, 0x10000000, bank->bank_number);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Number of pages to erase.
- */
- retval = target_write_u32(target, 0x10000004, 1 + (last-first));
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Write Key.
- */
- retval = target_write_u32(target, 0x10000008, PROGRAM_KEY);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Breakpoint.
- */
- retval = target_write_u32(target, 0x1000000c, 0xfffffffe);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Pointer to flash address.
- */
- retval = target_write_u32(target, 0x10000010, first);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * Erase the pages.
- */
- LOG_INFO("Erasing pages %d to %d on bank %d", first, last, bank->bank_number);
-
- /*
- * passed pc, addr = ROM function, handle breakpoints, not debugging.
- */
- retval = ambiqmicro_exec_command(target, FLASH_ERASE_LIST_MAIN_PAGES_FROM_SRAM, 0x1000000C);
- CHECK_STATUS(retval, "error executing flash page erase");
- if (retval != ERROR_OK)
- return retval;
-
- LOG_INFO("%d pages erased!", 1+(last-first));
-
- if (first == 0) {
- /*
- * Set Bootloader bit.
- */
- retval = target_write_u32(target, 0x400201a0, 0x1);
- CHECK_STATUS(retval, "error setting bootloader bit.");
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int ambiqmicro_protect(struct flash_bank *bank, int set, int first, int last)
-{
- /* struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
- * struct target *target = bank->target; */
-
- /*
- * TODO
- */
- LOG_INFO("Not yet implemented");
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- return ERROR_OK;
-}
-
-static int ambiqmicro_write_block(struct flash_bank *bank,
- const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- /* struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; */
- struct target *target = bank->target;
- uint32_t address = bank->base + offset;
- uint32_t buffer_pointer = 0x10000010;
- uint32_t maxbuffer;
- uint32_t thisrun_count;
- int retval = ERROR_OK;
-
- if (((count%4) != 0) || ((offset%4) != 0)) {
- LOG_ERROR("write block must be multiple of 4 bytes in offset & length");
- return ERROR_FAIL;
- }
-
- /*
- * Max buffer size for this device.
- * Hard code 6kB for the buffer.
- */
- maxbuffer = 0x1800;
-
- LOG_INFO("Flashing main array");
-
- while (count > 0) {
- if (count > maxbuffer)
- thisrun_count = maxbuffer;
- else
- thisrun_count = count;
-
- /*
- * Set up the SRAM.
- */
-
- /*
- * Pointer to flash.
- */
- retval = target_write_u32(target, 0x10000000, address);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Number of 32-bit words to program.
- */
- retval = target_write_u32(target, 0x10000004, thisrun_count/4);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Write Key.
- */
- retval = target_write_u32(target, 0x10000008, PROGRAM_KEY);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Breakpoint.
- */
- retval = target_write_u32(target, 0x1000000c, 0xfffffffe);
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
-
- /*
- * Write Buffer.
- */
- retval = target_write_buffer(target, buffer_pointer, thisrun_count, buffer);
-
- if (retval != ERROR_OK) {
- CHECK_STATUS(retval, "error writing target SRAM parameters.");
- break;
- }
-
- LOG_DEBUG("address = 0x%08x", address);
-
- retval = ambiqmicro_exec_command(target, FLASH_PROGRAM_MAIN_FROM_SRAM, 0x1000000c);
- CHECK_STATUS(retval, "error executing ambiqmicro flash write algorithm");
- if (retval != ERROR_OK)
- break;
- buffer += thisrun_count;
- address += thisrun_count;
- count -= thisrun_count;
- }
-
-
- LOG_INFO("Main array flashed");
-
- /*
- * Clear Bootloader bit.
- */
- retval = target_write_u32(target, 0x400201a0, 0x0);
- CHECK_STATUS(retval, "error clearing bootloader bit");
-
- return retval;
-}
-
-static int ambiqmicro_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- uint32_t retval;
-
- /* try using a block write */
- retval = ambiqmicro_write_block(bank, buffer, offset, count);
- if (retval != ERROR_OK)
- LOG_ERROR("write failed");
-
- return retval;
-}
-
-static int ambiqmicro_probe(struct flash_bank *bank)
-{
- struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv;
- uint32_t retval;
-
- /* If this is a ambiqmicro chip, it has flash; probe() is just
- * to figure out how much is present. Only do it once.
- */
- if (ambiqmicro_info->probed == 1) {
- LOG_INFO("Target already probed");
- return ERROR_OK;
- }
-
- /* ambiqmicro_read_part_info() already handled error checking and
- * reporting. Note that it doesn't write, so we don't care about
- * whether the target is halted or not.
- */
- retval = ambiqmicro_read_part_info(bank);
- if (retval != ERROR_OK)
- return retval;
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- /* provide this for the benefit of the NOR flash framework */
- bank->size = ambiqmicro_info->pagesize * ambiqmicro_info->num_pages;
- bank->num_sectors = ambiqmicro_info->num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = i * ambiqmicro_info->pagesize;
- bank->sectors[i].size = ambiqmicro_info->pagesize;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- /*
- * Part has been probed.
- */
- ambiqmicro_info->probed = 1;
-
- return retval;
-}
-
-static int ambiqmicro_otp_program(struct flash_bank *bank,
- uint32_t offset, uint32_t count)
-{
- struct target *target = NULL;
- struct ambiqmicro_flash_bank *ambiqmicro_info = NULL;
- uint32_t retval = ERROR_OK;
-
- ambiqmicro_info = bank->driver_priv;
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (ambiqmicro_info->probed == 0) {
- LOG_ERROR("Target not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- if (count > 256) {
- LOG_ERROR("Count must be < 256");
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /*
- * Clear Bootloader bit.
- */
- retval = target_write_u32(target, 0x400201a0, 0x0);
- CHECK_STATUS(retval, "error clearing bootloader bit.");
-
- /*
- * Set up the SRAM.
- */
-
- /*
- * Bank.
- */
- retval = target_write_u32(target, 0x10000000, offset);
- CHECK_STATUS(retval, "error setting target SRAM parameters.");
-
- /*
- * Num of words to program.
- */
- retval = target_write_u32(target, 0x10000004, count);
- CHECK_STATUS(retval, "error setting target SRAM parameters.");
-
- /*
- * Write Key.
- */
- retval = target_write_u32(target, 0x10000008, OTP_PROGRAM_KEY);
- CHECK_STATUS(retval, "error setting target SRAM parameters.");
-
- /*
- * Breakpoint.
- */
- retval = target_write_u32(target, 0x1000000c, 0xfffffffe);
- CHECK_STATUS(retval, "error setting target SRAM parameters.");
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * Program OTP.
- */
- LOG_INFO("Programming OTP offset 0x%08x", offset);
-
- /*
- * passed pc, addr = ROM function, handle breakpoints, not debugging.
- */
- retval = ambiqmicro_exec_command(target, FLASH_PROGRAM_OTP_FROM_SRAM, 0x1000000C);
- CHECK_STATUS(retval, "error executing ambiqmicro otp program algorithm");
-
- LOG_INFO("Programming OTP finished.");
-
- return retval;
-}
-
-
-
-COMMAND_HANDLER(ambiqmicro_handle_mass_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- uint32_t retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (ambiqmicro_mass_erase(bank) == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "ambiqmicro mass erase complete");
- } else
- command_print(CMD_CTX, "ambiqmicro mass erase failed");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ambiqmicro_handle_page_erase_command)
-{
- struct flash_bank *bank;
- uint32_t first, last;
- uint32_t retval;
-
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
-
- retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (ambiqmicro_erase(bank, first, last) == ERROR_OK)
- command_print(CMD_CTX, "ambiqmicro page erase complete");
- else
- command_print(CMD_CTX, "ambiqmicro page erase failed");
-
- return ERROR_OK;
-}
-
-
-/**
- * Program the otp block.
- */
-COMMAND_HANDLER(ambiqmicro_handle_program_otp_command)
-{
- struct flash_bank *bank;
- uint32_t offset, count;
- uint32_t retval;
-
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], offset);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
-
- command_print(CMD_CTX, "offset=0x%08x count=%d", offset, count);
-
- CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-
- retval = ambiqmicro_otp_program(bank, offset, count);
-
- if (retval != ERROR_OK)
- LOG_ERROR("error check log");
-
- return ERROR_OK;
-}
-
-
-
-static const struct command_registration ambiqmicro_exec_command_handlers[] = {
- {
- .name = "mass_erase",
- .usage = "<bank>",
- .handler = ambiqmicro_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .help = "Erase entire device",
- },
- {
- .name = "page_erase",
- .usage = "<bank> <first> <last>",
- .handler = ambiqmicro_handle_page_erase_command,
- .mode = COMMAND_EXEC,
- .help = "Erase device pages",
- },
- {
- .name = "program_otp",
- .handler = ambiqmicro_handle_program_otp_command,
- .mode = COMMAND_EXEC,
- .usage = "<bank> <offset> <count>",
- .help =
- "Program OTP (assumes you have already written array starting at 0x10000010)",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration ambiqmicro_command_handlers[] = {
- {
- .name = "ambiqmicro",
- .mode = COMMAND_EXEC,
- .help = "ambiqmicro flash command group",
- .usage = "Support for Ambiq Micro parts.",
- .chain = ambiqmicro_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver ambiqmicro_flash = {
- .name = "ambiqmicro",
- .commands = ambiqmicro_command_handlers,
- .flash_bank_command = ambiqmicro_flash_bank_command,
- .erase = ambiqmicro_erase,
- .protect = ambiqmicro_protect,
- .write = ambiqmicro_write,
- .read = default_flash_read,
- .probe = ambiqmicro_probe,
- .auto_probe = ambiqmicro_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = ambiqmicro_protect_check,
- .info = get_ambiqmicro_info,
-};
diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c
deleted file mode 100644
index 1536378..0000000
--- a/src/flash/nor/at91sam3.c
+++ /dev/null
@@ -1,3774 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Duane Ellis *
- * openocd@duaneellis.com *
- * *
- * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) *
- * olaf@uni-paderborn.de *
- * *
- * Copyright (C) 2011 by Olivier Schonken (at91sam3x* support) * *
- * and Jim Norris *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
-****************************************************************************/
-
-/* Some of the the lower level code was based on code supplied by
- * ATMEL under this copyright. */
-
-/* BEGIN ATMEL COPYRIGHT */
-/* ----------------------------------------------------------------------------
- * ATMEL Microcontroller Software Support
- * ----------------------------------------------------------------------------
- * Copyright (c) 2009, Atmel Corporation
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the disclaimer below.
- *
- * Atmel's name may not be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * ----------------------------------------------------------------------------
- */
-/* END ATMEL COPYRIGHT */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/time_support.h>
-
-#define REG_NAME_WIDTH (12)
-
-/* at91sam3u series (has one or two flash banks) */
-#define FLASH_BANK0_BASE_U 0x00080000
-#define FLASH_BANK1_BASE_U 0x00100000
-
-/* at91sam3s series (has always one flash bank) */
-#define FLASH_BANK_BASE_S 0x00400000
-
-/* at91sam3sd series (has always two flash banks) */
-#define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S
-#define FLASH_BANK1_BASE_512K_SD (FLASH_BANK0_BASE_SD+(512*1024/2))
-
-
-/* at91sam3n series (has always one flash bank) */
-#define FLASH_BANK_BASE_N 0x00400000
-
-/* at91sam3a/x series has two flash banks*/
-#define FLASH_BANK0_BASE_AX 0x00080000
-/*Bank 1 of the at91sam3a/x series starts at 0x00080000 + half flash size*/
-#define FLASH_BANK1_BASE_256K_AX 0x000A0000
-#define FLASH_BANK1_BASE_512K_AX 0x000C0000
-
-#define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
-#define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
-#define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
-#define AT91C_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */
-#define AT91C_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page and Write Page then Lock */
-#define AT91C_EFC_FCMD_EA (0x5) /* (EFC) Erase All */
-/* cmd6 is not present in the at91sam3u4/2/1 data sheet table 17-2 */
-/* #define AT91C_EFC_FCMD_EPL (0x6) // (EFC) Erase plane? */
-/* cmd7 is not present in the at91sam3u4/2/1 data sheet table 17-2 */
-/* #define AT91C_EFC_FCMD_EPA (0x7) // (EFC) Erase pages? */
-#define AT91C_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */
-#define AT91C_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */
-#define AT91C_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */
-#define AT91C_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
-#define AT91C_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
-#define AT91C_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
-#define AT91C_EFC_FCMD_STUI (0xE) /* (EFC) Start Read Unique ID */
-#define AT91C_EFC_FCMD_SPUI (0xF) /* (EFC) Stop Read Unique ID */
-
-#define offset_EFC_FMR 0
-#define offset_EFC_FCR 4
-#define offset_EFC_FSR 8
-#define offset_EFC_FRR 12
-
-extern struct flash_driver at91sam3_flash;
-
-static float _tomhz(uint32_t freq_hz)
-{
- float f;
-
- f = ((float)(freq_hz)) / 1000000.0;
- return f;
-}
-
-/* How the chip is configured. */
-struct sam3_cfg {
- uint32_t unique_id[4];
-
- uint32_t slow_freq;
- uint32_t rc_freq;
- uint32_t mainosc_freq;
- uint32_t plla_freq;
- uint32_t mclk_freq;
- uint32_t cpu_freq;
- uint32_t fclk_freq;
- uint32_t pclk0_freq;
- uint32_t pclk1_freq;
- uint32_t pclk2_freq;
-
-
-#define SAM3_CHIPID_CIDR (0x400E0740)
- uint32_t CHIPID_CIDR;
-#define SAM3_CHIPID_CIDR2 (0x400E0940) /*SAM3X and SAM3A cidr at this address*/
- uint32_t CHIPID_CIDR2;
-#define SAM3_CHIPID_EXID (0x400E0744)
- uint32_t CHIPID_EXID;
-#define SAM3_CHIPID_EXID2 (0x400E0944) /*SAM3X and SAM3A cidr at this address*/
- uint32_t CHIPID_EXID2;
-
-
-#define SAM3_PMC_BASE (0x400E0400)
-#define SAM3_PMC_SCSR (SAM3_PMC_BASE + 0x0008)
- uint32_t PMC_SCSR;
-#define SAM3_PMC_PCSR (SAM3_PMC_BASE + 0x0018)
- uint32_t PMC_PCSR;
-#define SAM3_CKGR_UCKR (SAM3_PMC_BASE + 0x001c)
- uint32_t CKGR_UCKR;
-#define SAM3_CKGR_MOR (SAM3_PMC_BASE + 0x0020)
- uint32_t CKGR_MOR;
-#define SAM3_CKGR_MCFR (SAM3_PMC_BASE + 0x0024)
- uint32_t CKGR_MCFR;
-#define SAM3_CKGR_PLLAR (SAM3_PMC_BASE + 0x0028)
- uint32_t CKGR_PLLAR;
-#define SAM3_PMC_MCKR (SAM3_PMC_BASE + 0x0030)
- uint32_t PMC_MCKR;
-#define SAM3_PMC_PCK0 (SAM3_PMC_BASE + 0x0040)
- uint32_t PMC_PCK0;
-#define SAM3_PMC_PCK1 (SAM3_PMC_BASE + 0x0044)
- uint32_t PMC_PCK1;
-#define SAM3_PMC_PCK2 (SAM3_PMC_BASE + 0x0048)
- uint32_t PMC_PCK2;
-#define SAM3_PMC_SR (SAM3_PMC_BASE + 0x0068)
- uint32_t PMC_SR;
-#define SAM3_PMC_IMR (SAM3_PMC_BASE + 0x006c)
- uint32_t PMC_IMR;
-#define SAM3_PMC_FSMR (SAM3_PMC_BASE + 0x0070)
- uint32_t PMC_FSMR;
-#define SAM3_PMC_FSPR (SAM3_PMC_BASE + 0x0074)
- uint32_t PMC_FSPR;
-};
-
-/*
- * The AT91SAM3N data sheet 04-Oct-2010, AT91SAM3U data sheet 22-Aug-2011
- * and AT91SAM3S data sheet 09-Feb-2011 state that for flash writes
- * the flash wait state (FWS) should be set to 6. It seems like that the
- * cause of the problem is not the flash itself, but the flash write
- * buffer. Ie the wait states have to be set before writing into the
- * buffer.
- * Tested and confirmed with SAM3N and SAM3U
- */
-
-struct sam3_bank_private {
- int probed;
- /* DANGER: THERE ARE DRAGONS HERE.. */
- /* NOTE: If you add more 'ghost' pointers */
- /* be aware that you must *manually* update */
- /* these pointers in the function sam3_GetDetails() */
- /* See the comment "Here there be dragons" */
-
- /* so we can find the chip we belong to */
- struct sam3_chip *pChip;
- /* so we can find the original bank pointer */
- struct flash_bank *pBank;
- unsigned bank_number;
- uint32_t controller_address;
- uint32_t base_address;
- uint32_t flash_wait_states;
- bool present;
- unsigned size_bytes;
- unsigned nsectors;
- unsigned sector_size;
- unsigned page_size;
-};
-
-struct sam3_chip_details {
- /* THERE ARE DRAGONS HERE.. */
- /* note: If you add pointers here */
- /* be careful about them as they */
- /* may need to be updated inside */
- /* the function: "sam3_GetDetails() */
- /* which copy/overwrites the */
- /* 'runtime' copy of this structure */
- uint32_t chipid_cidr;
- const char *name;
-
- unsigned n_gpnvms;
-#define SAM3_N_NVM_BITS 3
- unsigned gpnvm[SAM3_N_NVM_BITS];
- unsigned total_flash_size;
- unsigned total_sram_size;
- unsigned n_banks;
-#define SAM3_MAX_FLASH_BANKS 2
- /* these are "initialized" from the global const data */
- struct sam3_bank_private bank[SAM3_MAX_FLASH_BANKS];
-};
-
-struct sam3_chip {
- struct sam3_chip *next;
- int probed;
-
- /* this is "initialized" from the global const structure */
- struct sam3_chip_details details;
- struct target *target;
- struct sam3_cfg cfg;
-};
-
-
-struct sam3_reg_list {
- uint32_t address; size_t struct_offset; const char *name;
- void (*explain_func)(struct sam3_chip *pInfo);
-};
-
-static struct sam3_chip *all_sam3_chips;
-
-static struct sam3_chip *get_current_sam3(struct command_context *cmd_ctx)
-{
- struct target *t;
- static struct sam3_chip *p;
-
- t = get_current_target(cmd_ctx);
- if (!t) {
- command_print(cmd_ctx, "No current target?");
- return NULL;
- }
-
- p = all_sam3_chips;
- if (!p) {
- /* this should not happen */
- /* the command is not registered until the chip is created? */
- command_print(cmd_ctx, "No SAM3 chips exist?");
- return NULL;
- }
-
- while (p) {
- if (p->target == t)
- return p;
- p = p->next;
- }
- command_print(cmd_ctx, "Cannot find SAM3 chip?");
- return NULL;
-}
-
-/* these are used to *initialize* the "pChip->details" structure. */
-static const struct sam3_chip_details all_sam3_details[] = {
- /* Start at91sam3u* series */
- {
- .chipid_cidr = 0x28100960,
- .name = "at91sam3u4e",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 52 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_U,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
- },
- },
-
- {
- .chipid_cidr = 0x281a0760,
- .name = "at91sam3u2e",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 36 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
- {
- .chipid_cidr = 0x28190560,
- .name = "at91sam3u1e",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 20 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 8,
- .sector_size = 8192,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x28000960,
- .name = "at91sam3u4c",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 52 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
- {
- {
-/* .bank[0] = { */
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_U,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
- },
- },
-
- {
- .chipid_cidr = 0x280a0760,
- .name = "at91sam3u2c",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 36 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
- {
- .chipid_cidr = 0x28090560,
- .name = "at91sam3u1c",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 20 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
-
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 8,
- .sector_size = 8192,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
-
- /* Start at91sam3s* series */
-
- /* Note: The preliminary at91sam3s datasheet says on page 302 */
- /* that the flash controller is at address 0x400E0800. */
- /* This is _not_ the case, the controller resides at address 0x400e0a00. */
- {
- .chipid_cidr = 0x28A00960,
- .name = "at91sam3s4c",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 48 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
-
- {
- .chipid_cidr = 0x28900960,
- .name = "at91sam3s4b",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 48 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x28800960,
- .name = "at91sam3s4a",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 48 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x28AA0760,
- .name = "at91sam3s2c",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 32 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x289A0760,
- .name = "at91sam3s2b",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 32 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x298B0A60,
- .name = "at91sam3sd8a",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
- },
- },
- {
- .chipid_cidr = 0x299B0A60,
- .name = "at91sam3sd8b",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
- },
- },
- {
- .chipid_cidr = 0x29ab0a60,
- .name = "at91sam3sd8c",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
- },
- },
- {
- .chipid_cidr = 0x288A0760,
- .name = "at91sam3s2a",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 32 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x28A90560,
- .name = "at91sam3s1c",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 16 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 4,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x28990560,
- .name = "at91sam3s1b",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 16 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 4,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x28890560,
- .name = "at91sam3s1a",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 16 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 4,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x288B0A60,
- .name = "at91sam3s8a",
- .total_flash_size = 256 * 2048,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 2048,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x289B0A60,
- .name = "at91sam3s8b",
- .total_flash_size = 256 * 2048,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 2048,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- {
- .chipid_cidr = 0x28AB0A60,
- .name = "at91sam3s8c",
- .total_flash_size = 256 * 2048,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 2048,
- .nsectors = 16,
- .sector_size = 32768,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
-
- /* Start at91sam3n* series */
- {
- .chipid_cidr = 0x29540960,
- .name = "at91sam3n4c",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 24 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29440960,
- .name = "at91sam3n4b",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 24 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29340960,
- .name = "at91sam3n4a",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 24 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29590760,
- .name = "at91sam3n2c",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 16 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29490760,
- .name = "at91sam3n2b",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 16 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29390760,
- .name = "at91sam3n2a",
- .total_flash_size = 128 * 1024,
- .total_sram_size = 16 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29580560,
- .name = "at91sam3n1c",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 8 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 4,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29480560,
- .name = "at91sam3n1b",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 8 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 4,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29380560,
- .name = "at91sam3n1a",
- .total_flash_size = 64 * 1024,
- .total_sram_size = 8 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 64 * 1024,
- .nsectors = 4,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29480360,
- .name = "at91sam3n0b",
- .total_flash_size = 32 * 1024,
- .total_sram_size = 8 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 32 * 1024,
- .nsectors = 2,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29380360,
- .name = "at91sam3n0a",
- .total_flash_size = 32 * 1024,
- .total_sram_size = 8 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 32 * 1024,
- .nsectors = 2,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29450260,
- .name = "at91sam3n00b",
- .total_flash_size = 16 * 1024,
- .total_sram_size = 4 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 16 * 1024,
- .nsectors = 1,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
- {
- .chipid_cidr = 0x29350260,
- .name = "at91sam3n00a",
- .total_flash_size = 16 * 1024,
- .total_sram_size = 4 * 1024,
- .n_gpnvms = 3,
- .n_banks = 1,
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_N,
- .controller_address = 0x400e0A00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 16 * 1024,
- .nsectors = 1,
- .sector_size = 16384,
- .page_size = 256,
- },
-
-/* .bank[1] = { */
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
- },
- },
- },
-
-
- /* Start at91sam3a series*/
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
-
- {
- .chipid_cidr = 0x283E0A60,
- .name = "at91sam3a8c",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 96 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_AX,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
- {
- .chipid_cidr = 0x283B0960,
- .name = "at91sam3a4c",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_256K_AX,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
-
- /* Start at91sam3x* series */
- /* System boots at address 0x0 */
- /* gpnvm[1] = selects boot code */
- /* if gpnvm[1] == 0 */
- /* boot is via "SAMBA" (rom) */
- /* else */
- /* boot is via FLASH */
- /* Selection is via gpnvm[2] */
- /* endif */
- /* */
- /* NOTE: banks 0 & 1 switch places */
- /* if gpnvm[2] == 0 */
- /* Bank0 is the boot rom */
- /* else */
- /* Bank1 is the boot rom */
- /* endif */
- /*at91sam3x8h - ES has an incorrect CIDR of 0x286E0A20*/
- {
- .chipid_cidr = 0x286E0A20,
- .name = "at91sam3x8h - ES",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 96 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_AX,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
- /*at91sam3x8h - ES2 and up uses the correct CIDR of 0x286E0A60*/
- {
- .chipid_cidr = 0x286E0A60,
- .name = "at91sam3x8h",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 96 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_AX,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
- {
- .chipid_cidr = 0x285E0A60,
- .name = "at91sam3x8e",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 96 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_AX,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
- {
- .chipid_cidr = 0x284E0A60,
- .name = "at91sam3x8c",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 96 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_512K_AX ,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 16,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
- {
- .chipid_cidr = 0x285B0960,
- .name = "at91sam3x4e",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_256K_AX,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
- {
- .chipid_cidr = 0x284B0960,
- .name = "at91sam3x4c",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
- {
-/* .bank[0] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_AX,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
- },
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_256K_AX,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 8,
- .sector_size = 16384,
- .page_size = 256,
-
- },
- },
- },
- /* terminate */
- {
- .chipid_cidr = 0,
- .name = NULL,
- }
-};
-
-/* Globals above */
-/***********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************/
-/* *ATMEL* style code - from the SAM3 driver code */
-
-/**
- * Get the current status of the EEFC and
- * the value of some status bits (LOCKE, PROGE).
- * @param pPrivate - info about the bank
- * @param v - result goes here
- */
-static int EFC_GetStatus(struct sam3_bank_private *pPrivate, uint32_t *v)
-{
- int r;
- r = target_read_u32(pPrivate->pChip->target,
- pPrivate->controller_address + offset_EFC_FSR,
- v);
- LOG_DEBUG("Status: 0x%08x (lockerror: %d, cmderror: %d, ready: %d)",
- (unsigned int)(*v),
- ((unsigned int)((*v >> 2) & 1)),
- ((unsigned int)((*v >> 1) & 1)),
- ((unsigned int)((*v >> 0) & 1)));
-
- return r;
-}
-
-/**
- * Get the result of the last executed command.
- * @param pPrivate - info about the bank
- * @param v - result goes here
- */
-static int EFC_GetResult(struct sam3_bank_private *pPrivate, uint32_t *v)
-{
- int r;
- uint32_t rv;
- r = target_read_u32(pPrivate->pChip->target,
- pPrivate->controller_address + offset_EFC_FRR,
- &rv);
- if (v)
- *v = rv;
- LOG_DEBUG("Result: 0x%08x", ((unsigned int)(rv)));
- return r;
-}
-
-static int EFC_StartCommand(struct sam3_bank_private *pPrivate,
- unsigned command, unsigned argument)
-{
- uint32_t n, v;
- int r;
- int retry;
-
- retry = 0;
-do_retry:
-
- /* Check command & argument */
- switch (command) {
-
- case AT91C_EFC_FCMD_WP:
- case AT91C_EFC_FCMD_WPL:
- case AT91C_EFC_FCMD_EWP:
- case AT91C_EFC_FCMD_EWPL:
- /* case AT91C_EFC_FCMD_EPL: */
- /* case AT91C_EFC_FCMD_EPA: */
- case AT91C_EFC_FCMD_SLB:
- case AT91C_EFC_FCMD_CLB:
- n = (pPrivate->size_bytes / pPrivate->page_size);
- if (argument >= n)
- LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n));
- break;
-
- case AT91C_EFC_FCMD_SFB:
- case AT91C_EFC_FCMD_CFB:
- if (argument >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
- pPrivate->pChip->details.n_gpnvms);
- }
- break;
-
- case AT91C_EFC_FCMD_GETD:
- case AT91C_EFC_FCMD_EA:
- case AT91C_EFC_FCMD_GLB:
- case AT91C_EFC_FCMD_GFB:
- case AT91C_EFC_FCMD_STUI:
- case AT91C_EFC_FCMD_SPUI:
- if (argument != 0)
- LOG_ERROR("Argument is meaningless for cmd: %d", command);
- break;
- default:
- LOG_ERROR("Unknown command %d", command);
- break;
- }
-
- if (command == AT91C_EFC_FCMD_SPUI) {
- /* this is a very special situation. */
- /* Situation (1) - error/retry - see below */
- /* And we are being called recursively */
- /* Situation (2) - normal, finished reading unique id */
- } else {
- /* it should be "ready" */
- EFC_GetStatus(pPrivate, &v);
- if (v & 1) {
- /* then it is ready */
- /* we go on */
- } else {
- if (retry) {
- /* we have done this before */
- /* the controller is not responding. */
- LOG_ERROR("flash controller(%d) is not ready! Error",
- pPrivate->bank_number);
- return ERROR_FAIL;
- } else {
- retry++;
- LOG_ERROR("Flash controller(%d) is not ready, attempting reset",
- pPrivate->bank_number);
- /* we do that by issuing the *STOP* command */
- EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0);
- /* above is recursive, and further recursion is blocked by */
- /* if (command == AT91C_EFC_FCMD_SPUI) above */
- goto do_retry;
- }
- }
- }
-
- v = (0x5A << 24) | (argument << 8) | command;
- LOG_DEBUG("Command: 0x%08x", ((unsigned int)(v)));
- r = target_write_u32(pPrivate->pBank->target,
- pPrivate->controller_address + offset_EFC_FCR, v);
- if (r != ERROR_OK)
- LOG_DEBUG("Error Write failed");
- return r;
-}
-
-/**
- * Performs the given command and wait until its completion (or an error).
- * @param pPrivate - info about the bank
- * @param command - Command to perform.
- * @param argument - Optional command argument.
- * @param status - put command status bits here
- */
-static int EFC_PerformCommand(struct sam3_bank_private *pPrivate,
- unsigned command,
- unsigned argument,
- uint32_t *status)
-{
-
- int r;
- uint32_t v;
- int64_t ms_now, ms_end;
-
- /* default */
- if (status)
- *status = 0;
-
- r = EFC_StartCommand(pPrivate, command, argument);
- if (r != ERROR_OK)
- return r;
-
- ms_end = 500 + timeval_ms();
-
- do {
- r = EFC_GetStatus(pPrivate, &v);
- if (r != ERROR_OK)
- return r;
- ms_now = timeval_ms();
- if (ms_now > ms_end) {
- /* error */
- LOG_ERROR("Command timeout");
- return ERROR_FAIL;
- }
- } while ((v & 1) == 0);
-
- /* error bits.. */
- if (status)
- *status = (v & 0x6);
- return ERROR_OK;
-
-}
-
-/**
- * Read the unique ID.
- * @param pPrivate - info about the bank
- * The unique ID is stored in the 'pPrivate' structure.
- */
-static int FLASHD_ReadUniqueID(struct sam3_bank_private *pPrivate)
-{
- int r;
- uint32_t v;
- int x;
- /* assume 0 */
- pPrivate->pChip->cfg.unique_id[0] = 0;
- pPrivate->pChip->cfg.unique_id[1] = 0;
- pPrivate->pChip->cfg.unique_id[2] = 0;
- pPrivate->pChip->cfg.unique_id[3] = 0;
-
- LOG_DEBUG("Begin");
- r = EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_STUI, 0);
- if (r < 0)
- return r;
-
- for (x = 0; x < 4; x++) {
- r = target_read_u32(pPrivate->pChip->target,
- pPrivate->pBank->base + (x * 4),
- &v);
- if (r < 0)
- return r;
- pPrivate->pChip->cfg.unique_id[x] = v;
- }
-
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0, NULL);
- LOG_DEBUG("End: R=%d, id = 0x%08x, 0x%08x, 0x%08x, 0x%08x",
- r,
- (unsigned int)(pPrivate->pChip->cfg.unique_id[0]),
- (unsigned int)(pPrivate->pChip->cfg.unique_id[1]),
- (unsigned int)(pPrivate->pChip->cfg.unique_id[2]),
- (unsigned int)(pPrivate->pChip->cfg.unique_id[3]));
- return r;
-
-}
-
-/**
- * Erases the entire flash.
- * @param pPrivate - the info about the bank.
- */
-static int FLASHD_EraseEntireBank(struct sam3_bank_private *pPrivate)
-{
- LOG_DEBUG("Here");
- return EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_EA, 0, NULL);
-}
-
-/**
- * Gets current GPNVM state.
- * @param pPrivate - info about the bank.
- * @param gpnvm - GPNVM bit index.
- * @param puthere - result stored here.
- */
-/* ------------------------------------------------------------------------------ */
-static int FLASHD_GetGPNVM(struct sam3_bank_private *pPrivate, unsigned gpnvm, unsigned *puthere)
-{
- uint32_t v;
- int r;
-
- LOG_DEBUG("Here");
- if (pPrivate->bank_number != 0) {
- LOG_ERROR("GPNVM only works with Bank0");
- return ERROR_FAIL;
- }
-
- if (gpnvm >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("Invalid GPNVM %d, max: %d, ignored",
- gpnvm, pPrivate->pChip->details.n_gpnvms);
- return ERROR_FAIL;
- }
-
- /* Get GPNVMs status */
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GFB, 0, NULL);
- if (r != ERROR_OK) {
- LOG_ERROR("Failed");
- return r;
- }
-
- r = EFC_GetResult(pPrivate, &v);
-
- if (puthere) {
- /* Check if GPNVM is set */
- /* get the bit and make it a 0/1 */
- *puthere = (v >> gpnvm) & 1;
- }
-
- return r;
-}
-
-/**
- * Clears the selected GPNVM bit.
- * @param pPrivate info about the bank
- * @param gpnvm GPNVM index.
- * @returns 0 if successful; otherwise returns an error code.
- */
-static int FLASHD_ClrGPNVM(struct sam3_bank_private *pPrivate, unsigned gpnvm)
-{
- int r;
- unsigned v;
-
- LOG_DEBUG("Here");
- if (pPrivate->bank_number != 0) {
- LOG_ERROR("GPNVM only works with Bank0");
- return ERROR_FAIL;
- }
-
- if (gpnvm >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("Invalid GPNVM %d, max: %d, ignored",
- gpnvm, pPrivate->pChip->details.n_gpnvms);
- return ERROR_FAIL;
- }
-
- r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v);
- if (r != ERROR_OK) {
- LOG_DEBUG("Failed: %d", r);
- return r;
- }
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CFB, gpnvm, NULL);
- LOG_DEBUG("End: %d", r);
- return r;
-}
-
-/**
- * Sets the selected GPNVM bit.
- * @param pPrivate info about the bank
- * @param gpnvm GPNVM index.
- */
-static int FLASHD_SetGPNVM(struct sam3_bank_private *pPrivate, unsigned gpnvm)
-{
- int r;
- unsigned v;
-
- if (pPrivate->bank_number != 0) {
- LOG_ERROR("GPNVM only works with Bank0");
- return ERROR_FAIL;
- }
-
- if (gpnvm >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("Invalid GPNVM %d, max: %d, ignored",
- gpnvm, pPrivate->pChip->details.n_gpnvms);
- return ERROR_FAIL;
- }
-
- r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v);
- if (r != ERROR_OK)
- return r;
- if (v) {
- /* already set */
- r = ERROR_OK;
- } else {
- /* set it */
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SFB, gpnvm, NULL);
- }
- return r;
-}
-
-/**
- * Returns a bit field (at most 64) of locked regions within a page.
- * @param pPrivate info about the bank
- * @param v where to store locked bits
- */
-static int FLASHD_GetLockBits(struct sam3_bank_private *pPrivate, uint32_t *v)
-{
- int r;
- LOG_DEBUG("Here");
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GLB, 0, NULL);
- if (r == ERROR_OK)
- r = EFC_GetResult(pPrivate, v);
- LOG_DEBUG("End: %d", r);
- return r;
-}
-
-/**
- * Unlocks all the regions in the given address range.
- * @param pPrivate info about the bank
- * @param start_sector first sector to unlock
- * @param end_sector last (inclusive) to unlock
- */
-
-static int FLASHD_Unlock(struct sam3_bank_private *pPrivate,
- unsigned start_sector,
- unsigned end_sector)
-{
- int r;
- uint32_t status;
- uint32_t pg;
- uint32_t pages_per_sector;
-
- pages_per_sector = pPrivate->sector_size / pPrivate->page_size;
-
- /* Unlock all pages */
- while (start_sector <= end_sector) {
- pg = start_sector * pages_per_sector;
-
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CLB, pg, &status);
- if (r != ERROR_OK)
- return r;
- start_sector++;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Locks regions
- * @param pPrivate - info about the bank
- * @param start_sector - first sector to lock
- * @param end_sector - last sector (inclusive) to lock
- */
-static int FLASHD_Lock(struct sam3_bank_private *pPrivate,
- unsigned start_sector,
- unsigned end_sector)
-{
- uint32_t status;
- uint32_t pg;
- uint32_t pages_per_sector;
- int r;
-
- pages_per_sector = pPrivate->sector_size / pPrivate->page_size;
-
- /* Lock all pages */
- while (start_sector <= end_sector) {
- pg = start_sector * pages_per_sector;
-
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SLB, pg, &status);
- if (r != ERROR_OK)
- return r;
- start_sector++;
- }
- return ERROR_OK;
-}
-
-/****** END SAM3 CODE ********/
-
-/* begin helpful debug code */
-/* print the fieldname, the field value, in dec & hex, and return field value */
-static uint32_t sam3_reg_fieldname(struct sam3_chip *pChip,
- const char *regname,
- uint32_t value,
- unsigned shift,
- unsigned width)
-{
- uint32_t v;
- int hwidth, dwidth;
-
-
- /* extract the field */
- v = value >> shift;
- v = v & ((1 << width)-1);
- if (width <= 16) {
- hwidth = 4;
- dwidth = 5;
- } else {
- hwidth = 8;
- dwidth = 12;
- }
-
- /* show the basics */
- LOG_USER_N("\t%*s: %*" PRIu32 " [0x%0*" PRIx32 "] ",
- REG_NAME_WIDTH, regname,
- dwidth, v,
- hwidth, v);
- return v;
-}
-
-static const char _unknown[] = "unknown";
-static const char *const eproc_names[] = {
- _unknown, /* 0 */
- "arm946es", /* 1 */
- "arm7tdmi", /* 2 */
- "Cortex-M3", /* 3 */
- "arm920t", /* 4 */
- "arm926ejs", /* 5 */
- _unknown, /* 6 */
- _unknown, /* 7 */
- _unknown, /* 8 */
- _unknown, /* 9 */
- _unknown, /* 10 */
- _unknown, /* 11 */
- _unknown, /* 12 */
- _unknown, /* 13 */
- _unknown, /* 14 */
- _unknown, /* 15 */
-};
-
-#define nvpsize2 nvpsize /* these two tables are identical */
-static const char *const nvpsize[] = {
- "none", /* 0 */
- "8K bytes", /* 1 */
- "16K bytes", /* 2 */
- "32K bytes", /* 3 */
- _unknown, /* 4 */
- "64K bytes", /* 5 */
- _unknown, /* 6 */
- "128K bytes", /* 7 */
- _unknown, /* 8 */
- "256K bytes", /* 9 */
- "512K bytes", /* 10 */
- _unknown, /* 11 */
- "1024K bytes", /* 12 */
- _unknown, /* 13 */
- "2048K bytes", /* 14 */
- _unknown, /* 15 */
-};
-
-static const char *const sramsize[] = {
- "48K Bytes", /* 0 */
- "1K Bytes", /* 1 */
- "2K Bytes", /* 2 */
- "6K Bytes", /* 3 */
- "112K Bytes", /* 4 */
- "4K Bytes", /* 5 */
- "80K Bytes", /* 6 */
- "160K Bytes", /* 7 */
- "8K Bytes", /* 8 */
- "16K Bytes", /* 9 */
- "32K Bytes", /* 10 */
- "64K Bytes", /* 11 */
- "128K Bytes", /* 12 */
- "256K Bytes", /* 13 */
- "96K Bytes", /* 14 */
- "512K Bytes", /* 15 */
-
-};
-
-static const struct archnames { unsigned value; const char *name; } archnames[] = {
- { 0x19, "AT91SAM9xx Series" },
- { 0x29, "AT91SAM9XExx Series" },
- { 0x34, "AT91x34 Series" },
- { 0x37, "CAP7 Series" },
- { 0x39, "CAP9 Series" },
- { 0x3B, "CAP11 Series" },
- { 0x40, "AT91x40 Series" },
- { 0x42, "AT91x42 Series" },
- { 0x55, "AT91x55 Series" },
- { 0x60, "AT91SAM7Axx Series" },
- { 0x61, "AT91SAM7AQxx Series" },
- { 0x63, "AT91x63 Series" },
- { 0x70, "AT91SAM7Sxx Series" },
- { 0x71, "AT91SAM7XCxx Series" },
- { 0x72, "AT91SAM7SExx Series" },
- { 0x73, "AT91SAM7Lxx Series" },
- { 0x75, "AT91SAM7Xxx Series" },
- { 0x76, "AT91SAM7SLxx Series" },
- { 0x80, "ATSAM3UxC Series (100-pin version)" },
- { 0x81, "ATSAM3UxE Series (144-pin version)" },
- { 0x83, "ATSAM3AxC Series (100-pin version)" },
- { 0x84, "ATSAM3XxC Series (100-pin version)" },
- { 0x85, "ATSAM3XxE Series (144-pin version)" },
- { 0x86, "ATSAM3XxG Series (208/217-pin version)" },
- { 0x88, "ATSAM3SxA Series (48-pin version)" },
- { 0x89, "ATSAM3SxB Series (64-pin version)" },
- { 0x8A, "ATSAM3SxC Series (100-pin version)" },
- { 0x92, "AT91x92 Series" },
- { 0x93, "ATSAM3NxA Series (48-pin version)" },
- { 0x94, "ATSAM3NxB Series (64-pin version)" },
- { 0x95, "ATSAM3NxC Series (100-pin version)" },
- { 0x98, "ATSAM3SDxA Series (48-pin version)" },
- { 0x99, "ATSAM3SDxB Series (64-pin version)" },
- { 0x9A, "ATSAM3SDxC Series (100-pin version)" },
- { 0xA5, "ATSAM5A" },
- { 0xF0, "AT75Cxx Series" },
- { -1, NULL },
-};
-
-static const char *const nvptype[] = {
- "rom", /* 0 */
- "romless or onchip flash", /* 1 */
- "embedded flash memory",/* 2 */
- "rom(nvpsiz) + embedded flash (nvpsiz2)", /* 3 */
- "sram emulating flash", /* 4 */
- _unknown, /* 5 */
- _unknown, /* 6 */
- _unknown, /* 7 */
-};
-
-static const char *_yes_or_no(uint32_t v)
-{
- if (v)
- return "YES";
- else
- return "NO";
-}
-
-static const char *const _rc_freq[] = {
- "4 MHz", "8 MHz", "12 MHz", "reserved"
-};
-
-static void sam3_explain_ckgr_mor(struct sam3_chip *pChip)
-{
- uint32_t v;
- uint32_t rcen;
-
- v = sam3_reg_fieldname(pChip, "MOSCXTEN", pChip->cfg.CKGR_MOR, 0, 1);
- LOG_USER("(main xtal enabled: %s)", _yes_or_no(v));
- v = sam3_reg_fieldname(pChip, "MOSCXTBY", pChip->cfg.CKGR_MOR, 1, 1);
- LOG_USER("(main osc bypass: %s)", _yes_or_no(v));
- rcen = sam3_reg_fieldname(pChip, "MOSCRCEN", pChip->cfg.CKGR_MOR, 3, 1);
- LOG_USER("(onchip RC-OSC enabled: %s)", _yes_or_no(rcen));
- v = sam3_reg_fieldname(pChip, "MOSCRCF", pChip->cfg.CKGR_MOR, 4, 3);
- LOG_USER("(onchip RC-OSC freq: %s)", _rc_freq[v]);
-
- pChip->cfg.rc_freq = 0;
- if (rcen) {
- switch (v) {
- default:
- pChip->cfg.rc_freq = 0;
- break;
- case 0:
- pChip->cfg.rc_freq = 4 * 1000 * 1000;
- break;
- case 1:
- pChip->cfg.rc_freq = 8 * 1000 * 1000;
- break;
- case 2:
- pChip->cfg.rc_freq = 12 * 1000 * 1000;
- break;
- }
- }
-
- v = sam3_reg_fieldname(pChip, "MOSCXTST", pChip->cfg.CKGR_MOR, 8, 8);
- LOG_USER("(startup clks, time= %f uSecs)",
- ((float)(v * 1000000)) / ((float)(pChip->cfg.slow_freq)));
- v = sam3_reg_fieldname(pChip, "MOSCSEL", pChip->cfg.CKGR_MOR, 24, 1);
- LOG_USER("(mainosc source: %s)",
- v ? "external xtal" : "internal RC");
-
- v = sam3_reg_fieldname(pChip, "CFDEN", pChip->cfg.CKGR_MOR, 25, 1);
- LOG_USER("(clock failure enabled: %s)",
- _yes_or_no(v));
-}
-
-static void sam3_explain_chipid_cidr(struct sam3_chip *pChip)
-{
- int x;
- uint32_t v;
- const char *cp;
-
- sam3_reg_fieldname(pChip, "Version", pChip->cfg.CHIPID_CIDR, 0, 5);
- LOG_USER_N("\n");
-
- v = sam3_reg_fieldname(pChip, "EPROC", pChip->cfg.CHIPID_CIDR, 5, 3);
- LOG_USER("%s", eproc_names[v]);
-
- v = sam3_reg_fieldname(pChip, "NVPSIZE", pChip->cfg.CHIPID_CIDR, 8, 4);
- LOG_USER("%s", nvpsize[v]);
-
- v = sam3_reg_fieldname(pChip, "NVPSIZE2", pChip->cfg.CHIPID_CIDR, 12, 4);
- LOG_USER("%s", nvpsize2[v]);
-
- v = sam3_reg_fieldname(pChip, "SRAMSIZE", pChip->cfg.CHIPID_CIDR, 16, 4);
- LOG_USER("%s", sramsize[v]);
-
- v = sam3_reg_fieldname(pChip, "ARCH", pChip->cfg.CHIPID_CIDR, 20, 8);
- cp = _unknown;
- for (x = 0; archnames[x].name; x++) {
- if (v == archnames[x].value) {
- cp = archnames[x].name;
- break;
- }
- }
-
- LOG_USER("%s", cp);
-
- v = sam3_reg_fieldname(pChip, "NVPTYP", pChip->cfg.CHIPID_CIDR, 28, 3);
- LOG_USER("%s", nvptype[v]);
-
- v = sam3_reg_fieldname(pChip, "EXTID", pChip->cfg.CHIPID_CIDR, 31, 1);
- LOG_USER("(exists: %s)", _yes_or_no(v));
-}
-
-static void sam3_explain_ckgr_mcfr(struct sam3_chip *pChip)
-{
- uint32_t v;
-
- v = sam3_reg_fieldname(pChip, "MAINFRDY", pChip->cfg.CKGR_MCFR, 16, 1);
- LOG_USER("(main ready: %s)", _yes_or_no(v));
-
- v = sam3_reg_fieldname(pChip, "MAINF", pChip->cfg.CKGR_MCFR, 0, 16);
-
- v = (v * pChip->cfg.slow_freq) / 16;
- pChip->cfg.mainosc_freq = v;
-
- LOG_USER("(%3.03f Mhz (%" PRIu32 ".%03" PRIu32 "khz slowclk)",
- _tomhz(v),
- (uint32_t)(pChip->cfg.slow_freq / 1000),
- (uint32_t)(pChip->cfg.slow_freq % 1000));
-}
-
-static void sam3_explain_ckgr_plla(struct sam3_chip *pChip)
-{
- uint32_t mula, diva;
-
- diva = sam3_reg_fieldname(pChip, "DIVA", pChip->cfg.CKGR_PLLAR, 0, 8);
- LOG_USER_N("\n");
- mula = sam3_reg_fieldname(pChip, "MULA", pChip->cfg.CKGR_PLLAR, 16, 11);
- LOG_USER_N("\n");
- pChip->cfg.plla_freq = 0;
- if (mula == 0)
- LOG_USER("\tPLLA Freq: (Disabled,mula = 0)");
- else if (diva == 0)
- LOG_USER("\tPLLA Freq: (Disabled,diva = 0)");
- else if (diva >= 1) {
- pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1) / diva);
- LOG_USER("\tPLLA Freq: %3.03f MHz",
- _tomhz(pChip->cfg.plla_freq));
- }
-}
-
-static void sam3_explain_mckr(struct sam3_chip *pChip)
-{
- uint32_t css, pres, fin = 0;
- int pdiv = 0;
- const char *cp = NULL;
-
- css = sam3_reg_fieldname(pChip, "CSS", pChip->cfg.PMC_MCKR, 0, 2);
- switch (css & 3) {
- case 0:
- fin = pChip->cfg.slow_freq;
- cp = "slowclk";
- break;
- case 1:
- fin = pChip->cfg.mainosc_freq;
- cp = "mainosc";
- break;
- case 2:
- fin = pChip->cfg.plla_freq;
- cp = "plla";
- break;
- case 3:
- if (pChip->cfg.CKGR_UCKR & (1 << 16)) {
- fin = 480 * 1000 * 1000;
- cp = "upll";
- } else {
- fin = 0;
- cp = "upll (*ERROR* UPLL is disabled)";
- }
- break;
- default:
- assert(0);
- break;
- }
-
- LOG_USER("%s (%3.03f Mhz)",
- cp,
- _tomhz(fin));
- pres = sam3_reg_fieldname(pChip, "PRES", pChip->cfg.PMC_MCKR, 4, 3);
- switch (pres & 0x07) {
- case 0:
- pdiv = 1;
- cp = "selected clock";
- break;
- case 1:
- pdiv = 2;
- cp = "clock/2";
- break;
- case 2:
- pdiv = 4;
- cp = "clock/4";
- break;
- case 3:
- pdiv = 8;
- cp = "clock/8";
- break;
- case 4:
- pdiv = 16;
- cp = "clock/16";
- break;
- case 5:
- pdiv = 32;
- cp = "clock/32";
- break;
- case 6:
- pdiv = 64;
- cp = "clock/64";
- break;
- case 7:
- pdiv = 6;
- cp = "clock/6";
- break;
- default:
- assert(0);
- break;
- }
- LOG_USER("(%s)", cp);
- fin = fin / pdiv;
- /* sam3 has a *SINGLE* clock - */
- /* other at91 series parts have divisors for these. */
- pChip->cfg.cpu_freq = fin;
- pChip->cfg.mclk_freq = fin;
- pChip->cfg.fclk_freq = fin;
- LOG_USER("\t\tResult CPU Freq: %3.03f",
- _tomhz(fin));
-}
-
-#if 0
-static struct sam3_chip *target2sam3(struct target *pTarget)
-{
- struct sam3_chip *pChip;
-
- if (pTarget == NULL)
- return NULL;
-
- pChip = all_sam3_chips;
- while (pChip) {
- if (pChip->target == pTarget)
- break; /* return below */
- else
- pChip = pChip->next;
- }
- return pChip;
-}
-#endif
-
-static uint32_t *sam3_get_reg_ptr(struct sam3_cfg *pCfg, const struct sam3_reg_list *pList)
-{
- /* this function exists to help */
- /* keep funky offsetof() errors */
- /* and casting from causing bugs */
-
- /* By using prototypes - we can detect what would */
- /* be casting errors. */
-
- return (uint32_t *)(void *)(((char *)(pCfg)) + pList->struct_offset);
-}
-
-
-#define SAM3_ENTRY(NAME, FUNC) { .address = SAM3_ ## NAME, .struct_offset = offsetof( \
- struct sam3_cfg, \
- NAME), # NAME, FUNC }
-static const struct sam3_reg_list sam3_all_regs[] = {
- SAM3_ENTRY(CKGR_MOR, sam3_explain_ckgr_mor),
- SAM3_ENTRY(CKGR_MCFR, sam3_explain_ckgr_mcfr),
- SAM3_ENTRY(CKGR_PLLAR, sam3_explain_ckgr_plla),
- SAM3_ENTRY(CKGR_UCKR, NULL),
- SAM3_ENTRY(PMC_FSMR, NULL),
- SAM3_ENTRY(PMC_FSPR, NULL),
- SAM3_ENTRY(PMC_IMR, NULL),
- SAM3_ENTRY(PMC_MCKR, sam3_explain_mckr),
- SAM3_ENTRY(PMC_PCK0, NULL),
- SAM3_ENTRY(PMC_PCK1, NULL),
- SAM3_ENTRY(PMC_PCK2, NULL),
- SAM3_ENTRY(PMC_PCSR, NULL),
- SAM3_ENTRY(PMC_SCSR, NULL),
- SAM3_ENTRY(PMC_SR, NULL),
- SAM3_ENTRY(CHIPID_CIDR, sam3_explain_chipid_cidr),
- SAM3_ENTRY(CHIPID_CIDR2, sam3_explain_chipid_cidr),
- SAM3_ENTRY(CHIPID_EXID, NULL),
- SAM3_ENTRY(CHIPID_EXID2, NULL),
- /* TERMINATE THE LIST */
- { .name = NULL }
-};
-#undef SAM3_ENTRY
-
-static struct sam3_bank_private *get_sam3_bank_private(struct flash_bank *bank)
-{
- return bank->driver_priv;
-}
-
-/**
- * Given a pointer to where it goes in the structure,
- * determine the register name, address from the all registers table.
- */
-static const struct sam3_reg_list *sam3_GetReg(struct sam3_chip *pChip, uint32_t *goes_here)
-{
- const struct sam3_reg_list *pReg;
-
- pReg = &(sam3_all_regs[0]);
- while (pReg->name) {
- uint32_t *pPossible;
-
- /* calculate where this one go.. */
- /* it is "possibly" this register. */
-
- pPossible = ((uint32_t *)(void *)(((char *)(&(pChip->cfg))) + pReg->struct_offset));
-
- /* well? Is it this register */
- if (pPossible == goes_here) {
- /* Jump for joy! */
- return pReg;
- }
-
- /* next... */
- pReg++;
- }
- /* This is *TOTAL*PANIC* - we are totally screwed. */
- LOG_ERROR("INVALID SAM3 REGISTER");
- return NULL;
-}
-
-static int sam3_ReadThisReg(struct sam3_chip *pChip, uint32_t *goes_here)
-{
- const struct sam3_reg_list *pReg;
- int r;
-
- pReg = sam3_GetReg(pChip, goes_here);
- if (!pReg)
- return ERROR_FAIL;
-
- r = target_read_u32(pChip->target, pReg->address, goes_here);
- if (r != ERROR_OK) {
- LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Err: %d",
- pReg->name, (unsigned)(pReg->address), r);
- }
- return r;
-}
-
-static int sam3_ReadAllRegs(struct sam3_chip *pChip)
-{
- int r;
- const struct sam3_reg_list *pReg;
-
- pReg = &(sam3_all_regs[0]);
- while (pReg->name) {
- r = sam3_ReadThisReg(pChip,
- sam3_get_reg_ptr(&(pChip->cfg), pReg));
- if (r != ERROR_OK) {
- LOG_ERROR("Cannot read SAM3 register: %s @ 0x%08x, Error: %d",
- pReg->name, ((unsigned)(pReg->address)), r);
- return r;
- }
- pReg++;
- }
-
- /* Chip identification register
- *
- * Unfortunately, the chip identification register is not at
- * a constant address across all of the SAM3 series'. As a
- * consequence, a simple heuristic is used to find where it's
- * at...
- *
- * If the contents at the first address is zero, then we know
- * that the second address is where the chip id register is.
- * We can deduce this because for those SAM's that have the
- * chip id @ 0x400e0940, the first address, 0x400e0740, is
- * located in the memory map of the Power Management Controller
- * (PMC). Furthermore, the address is not used by the PMC.
- * So when read, the memory controller returns zero.*/
- if (pChip->cfg.CHIPID_CIDR == 0) {
- /*Put the correct CIDR and EXID values in the pChip structure */
- pChip->cfg.CHIPID_CIDR = pChip->cfg.CHIPID_CIDR2;
- pChip->cfg.CHIPID_EXID = pChip->cfg.CHIPID_EXID2;
- }
- return ERROR_OK;
-}
-
-static int sam3_GetInfo(struct sam3_chip *pChip)
-{
- const struct sam3_reg_list *pReg;
- uint32_t regval;
-
- pReg = &(sam3_all_regs[0]);
- while (pReg->name) {
- /* display all regs */
- LOG_DEBUG("Start: %s", pReg->name);
- regval = *sam3_get_reg_ptr(&(pChip->cfg), pReg);
- LOG_USER("%*s: [0x%08" PRIx32 "] -> 0x%08" PRIx32,
- REG_NAME_WIDTH,
- pReg->name,
- pReg->address,
- regval);
- if (pReg->explain_func)
- (*(pReg->explain_func))(pChip);
- LOG_DEBUG("End: %s", pReg->name);
- pReg++;
- }
- LOG_USER(" rc-osc: %3.03f MHz", _tomhz(pChip->cfg.rc_freq));
- LOG_USER(" mainosc: %3.03f MHz", _tomhz(pChip->cfg.mainosc_freq));
- LOG_USER(" plla: %3.03f MHz", _tomhz(pChip->cfg.plla_freq));
- LOG_USER(" cpu-freq: %3.03f MHz", _tomhz(pChip->cfg.cpu_freq));
- LOG_USER("mclk-freq: %3.03f MHz", _tomhz(pChip->cfg.mclk_freq));
-
- LOG_USER(" UniqueId: 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32,
- pChip->cfg.unique_id[0],
- pChip->cfg.unique_id[1],
- pChip->cfg.unique_id[2],
- pChip->cfg.unique_id[3]);
-
- return ERROR_OK;
-}
-
-static int sam3_erase_check(struct flash_bank *bank)
-{
- int x;
-
- LOG_DEBUG("Here");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
- if (0 == bank->num_sectors) {
- LOG_ERROR("Target: not supported/not probed");
- return ERROR_FAIL;
- }
-
- LOG_INFO("sam3 - supports auto-erase, erase_check ignored");
- for (x = 0; x < bank->num_sectors; x++)
- bank->sectors[x].is_erased = 1;
-
- LOG_DEBUG("Done");
- return ERROR_OK;
-}
-
-static int sam3_protect_check(struct flash_bank *bank)
-{
- int r;
- uint32_t v = 0;
- unsigned x;
- struct sam3_bank_private *pPrivate;
-
- LOG_DEBUG("Begin");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- pPrivate = get_sam3_bank_private(bank);
- if (!pPrivate) {
- LOG_ERROR("no private for this bank?");
- return ERROR_FAIL;
- }
- if (!(pPrivate->probed))
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- r = FLASHD_GetLockBits(pPrivate, &v);
- if (r != ERROR_OK) {
- LOG_DEBUG("Failed: %d", r);
- return r;
- }
-
- for (x = 0; x < pPrivate->nsectors; x++)
- bank->sectors[x].is_protected = (!!(v & (1 << x)));
- LOG_DEBUG("Done");
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command)
-{
- struct sam3_chip *pChip;
-
- pChip = all_sam3_chips;
-
- /* is this an existing chip? */
- while (pChip) {
- if (pChip->target == bank->target)
- break;
- pChip = pChip->next;
- }
-
- if (!pChip) {
- /* this is a *NEW* chip */
- pChip = calloc(1, sizeof(struct sam3_chip));
- if (!pChip) {
- LOG_ERROR("NO RAM!");
- return ERROR_FAIL;
- }
- pChip->target = bank->target;
- /* insert at head */
- pChip->next = all_sam3_chips;
- all_sam3_chips = pChip;
- pChip->target = bank->target;
- /* assumption is this runs at 32khz */
- pChip->cfg.slow_freq = 32768;
- pChip->probed = 0;
- }
-
- switch (bank->base) {
- default:
- LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x "
- "[at91sam3u series] or 0x%08x [at91sam3s series] or "
- "0x%08x [at91sam3n series] or 0x%08x or 0x%08x or 0x%08x[at91sam3ax series] )",
- ((unsigned int)(bank->base)),
- ((unsigned int)(FLASH_BANK0_BASE_U)),
- ((unsigned int)(FLASH_BANK1_BASE_U)),
- ((unsigned int)(FLASH_BANK_BASE_S)),
- ((unsigned int)(FLASH_BANK_BASE_N)),
- ((unsigned int)(FLASH_BANK0_BASE_AX)),
- ((unsigned int)(FLASH_BANK1_BASE_256K_AX)),
- ((unsigned int)(FLASH_BANK1_BASE_512K_AX)));
- return ERROR_FAIL;
- break;
-
- /* at91sam3s and at91sam3n series only has bank 0*/
- /* at91sam3u and at91sam3ax series has the same address for bank 0*/
- case FLASH_BANK_BASE_S:
- case FLASH_BANK0_BASE_U:
- bank->driver_priv = &(pChip->details.bank[0]);
- bank->bank_number = 0;
- pChip->details.bank[0].pChip = pChip;
- pChip->details.bank[0].pBank = bank;
- break;
-
- /* Bank 1 of at91sam3u or at91sam3ax series */
- case FLASH_BANK1_BASE_U:
- case FLASH_BANK1_BASE_256K_AX:
- case FLASH_BANK1_BASE_512K_AX:
- bank->driver_priv = &(pChip->details.bank[1]);
- bank->bank_number = 1;
- pChip->details.bank[1].pChip = pChip;
- pChip->details.bank[1].pBank = bank;
- break;
- }
-
- /* we initialize after probing. */
- return ERROR_OK;
-}
-
-static int sam3_GetDetails(struct sam3_bank_private *pPrivate)
-{
- const struct sam3_chip_details *pDetails;
- struct sam3_chip *pChip;
- struct flash_bank *saved_banks[SAM3_MAX_FLASH_BANKS];
- unsigned x;
-
- LOG_DEBUG("Begin");
- pDetails = all_sam3_details;
- while (pDetails->name) {
- /* Compare cidr without version bits */
- if (((pDetails->chipid_cidr ^ pPrivate->pChip->cfg.CHIPID_CIDR) & 0xFFFFFFE0) == 0)
- break;
- else
- pDetails++;
- }
- if (pDetails->name == NULL) {
- LOG_ERROR("SAM3 ChipID 0x%08x not found in table (perhaps you can ID this chip?)",
- (unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR));
- /* Help the victim, print details about the chip */
- LOG_INFO("SAM3 CHIPID_CIDR: 0x%08" PRIx32 " decodes as follows",
- pPrivate->pChip->cfg.CHIPID_CIDR);
- sam3_explain_chipid_cidr(pPrivate->pChip);
- return ERROR_FAIL;
- }
-
- /* DANGER: THERE ARE DRAGONS HERE */
-
- /* get our pChip - it is going */
- /* to be over-written shortly */
- pChip = pPrivate->pChip;
-
- /* Note that, in reality: */
- /* */
- /* pPrivate = &(pChip->details.bank[0]) */
- /* or pPrivate = &(pChip->details.bank[1]) */
- /* */
-
- /* save the "bank" pointers */
- for (x = 0; x < SAM3_MAX_FLASH_BANKS; x++)
- saved_banks[x] = pChip->details.bank[x].pBank;
-
- /* Overwrite the "details" structure. */
- memcpy(&(pPrivate->pChip->details),
- pDetails,
- sizeof(pPrivate->pChip->details));
-
- /* now fix the ghosted pointers */
- for (x = 0; x < SAM3_MAX_FLASH_BANKS; x++) {
- pChip->details.bank[x].pChip = pChip;
- pChip->details.bank[x].pBank = saved_banks[x];
- }
-
- /* update the *BANK*SIZE* */
-
- LOG_DEBUG("End");
- return ERROR_OK;
-}
-
-static int _sam3_probe(struct flash_bank *bank, int noise)
-{
- unsigned x;
- int r;
- struct sam3_bank_private *pPrivate;
-
-
- LOG_DEBUG("Begin: Bank: %d, Noise: %d", bank->bank_number, noise);
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- pPrivate = get_sam3_bank_private(bank);
- if (!pPrivate) {
- LOG_ERROR("Invalid/unknown bank number");
- return ERROR_FAIL;
- }
-
- r = sam3_ReadAllRegs(pPrivate->pChip);
- if (r != ERROR_OK)
- return r;
-
- LOG_DEBUG("Here");
- if (pPrivate->pChip->probed)
- r = sam3_GetInfo(pPrivate->pChip);
- else
- r = sam3_GetDetails(pPrivate);
- if (r != ERROR_OK)
- return r;
-
- /* update the flash bank size */
- for (x = 0; x < SAM3_MAX_FLASH_BANKS; x++) {
- if (bank->base == pPrivate->pChip->details.bank[x].base_address) {
- bank->size = pPrivate->pChip->details.bank[x].size_bytes;
- break;
- }
- }
-
- if (bank->sectors == NULL) {
- bank->sectors = calloc(pPrivate->nsectors, (sizeof((bank->sectors)[0])));
- if (bank->sectors == NULL) {
- LOG_ERROR("No memory!");
- return ERROR_FAIL;
- }
- bank->num_sectors = pPrivate->nsectors;
-
- for (x = 0; ((int)(x)) < bank->num_sectors; x++) {
- bank->sectors[x].size = pPrivate->sector_size;
- bank->sectors[x].offset = x * (pPrivate->sector_size);
- /* mark as unknown */
- bank->sectors[x].is_erased = -1;
- bank->sectors[x].is_protected = -1;
- }
- }
-
- pPrivate->probed = 1;
-
- r = sam3_protect_check(bank);
- if (r != ERROR_OK)
- return r;
-
- LOG_DEBUG("Bank = %d, nbanks = %d",
- pPrivate->bank_number, pPrivate->pChip->details.n_banks);
- if ((pPrivate->bank_number + 1) == pPrivate->pChip->details.n_banks) {
- /* read unique id, */
- /* it appears to be associated with the *last* flash bank. */
- FLASHD_ReadUniqueID(pPrivate);
- }
-
- return r;
-}
-
-static int sam3_probe(struct flash_bank *bank)
-{
- return _sam3_probe(bank, 1);
-}
-
-static int sam3_auto_probe(struct flash_bank *bank)
-{
- return _sam3_probe(bank, 0);
-}
-
-static int sam3_erase(struct flash_bank *bank, int first, int last)
-{
- struct sam3_bank_private *pPrivate;
- int r;
-
- LOG_DEBUG("Here");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- r = sam3_auto_probe(bank);
- if (r != ERROR_OK) {
- LOG_DEBUG("Here,r=%d", r);
- return r;
- }
-
- pPrivate = get_sam3_bank_private(bank);
- if (!(pPrivate->probed))
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if ((first == 0) && ((last + 1) == ((int)(pPrivate->nsectors)))) {
- /* whole chip */
- LOG_DEBUG("Here");
- return FLASHD_EraseEntireBank(pPrivate);
- }
- LOG_INFO("sam3 auto-erases while programming (request ignored)");
- return ERROR_OK;
-}
-
-static int sam3_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct sam3_bank_private *pPrivate;
- int r;
-
- LOG_DEBUG("Here");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- pPrivate = get_sam3_bank_private(bank);
- if (!(pPrivate->probed))
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (set)
- r = FLASHD_Lock(pPrivate, (unsigned)(first), (unsigned)(last));
- else
- r = FLASHD_Unlock(pPrivate, (unsigned)(first), (unsigned)(last));
- LOG_DEBUG("End: r=%d", r);
-
- return r;
-
-}
-
-static int sam3_page_read(struct sam3_bank_private *pPrivate, unsigned pagenum, uint8_t *buf)
-{
- uint32_t adr;
- int r;
-
- adr = pagenum * pPrivate->page_size;
- adr += pPrivate->base_address;
-
- r = target_read_memory(pPrivate->pChip->target,
- adr,
- 4, /* THIS*MUST*BE* in 32bit values */
- pPrivate->page_size / 4,
- buf);
- if (r != ERROR_OK)
- LOG_ERROR("SAM3: Flash program failed to read page phys address: 0x%08x",
- (unsigned int)(adr));
- return r;
-}
-
-static int sam3_page_write(struct sam3_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf)
-{
- uint32_t adr;
- uint32_t status;
- uint32_t fmr; /* EEFC Flash Mode Register */
- int r;
-
- adr = pagenum * pPrivate->page_size;
- adr += pPrivate->base_address;
-
- /* Get flash mode register value */
- r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address, &fmr);
- if (r != ERROR_OK)
- LOG_DEBUG("Error Read failed: read flash mode register");
-
- /* Clear flash wait state field */
- fmr &= 0xfffff0ff;
-
- /* set FWS (flash wait states) field in the FMR (flash mode register) */
- fmr |= (pPrivate->flash_wait_states << 8);
-
- LOG_DEBUG("Flash Mode: 0x%08x", ((unsigned int)(fmr)));
- r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address, fmr);
- if (r != ERROR_OK)
- LOG_DEBUG("Error Write failed: set flash mode register");
-
- LOG_DEBUG("Wr Page %u @ phys address: 0x%08x", pagenum, (unsigned int)(adr));
- r = target_write_memory(pPrivate->pChip->target,
- adr,
- 4, /* THIS*MUST*BE* in 32bit values */
- pPrivate->page_size / 4,
- buf);
- if (r != ERROR_OK) {
- LOG_ERROR("SAM3: Failed to write (buffer) page at phys address 0x%08x",
- (unsigned int)(adr));
- return r;
- }
-
- r = EFC_PerformCommand(pPrivate,
- /* send Erase & Write Page */
- AT91C_EFC_FCMD_EWP,
- pagenum,
- &status);
-
- if (r != ERROR_OK)
- LOG_ERROR("SAM3: Error performing Erase & Write page @ phys address 0x%08x",
- (unsigned int)(adr));
- if (status & (1 << 2)) {
- LOG_ERROR("SAM3: Page @ Phys address 0x%08x is locked", (unsigned int)(adr));
- return ERROR_FAIL;
- }
- if (status & (1 << 1)) {
- LOG_ERROR("SAM3: Flash Command error @phys address 0x%08x", (unsigned int)(adr));
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int sam3_write(struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- int n;
- unsigned page_cur;
- unsigned page_end;
- int r;
- unsigned page_offset;
- struct sam3_bank_private *pPrivate;
- uint8_t *pagebuffer;
-
- /* incase we bail further below, set this to null */
- pagebuffer = NULL;
-
- /* ignore dumb requests */
- if (count == 0) {
- r = ERROR_OK;
- goto done;
- }
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- r = ERROR_TARGET_NOT_HALTED;
- goto done;
- }
-
- pPrivate = get_sam3_bank_private(bank);
- if (!(pPrivate->probed)) {
- r = ERROR_FLASH_BANK_NOT_PROBED;
- goto done;
- }
-
- if ((offset + count) > pPrivate->size_bytes) {
- LOG_ERROR("Flash write error - past end of bank");
- LOG_ERROR(" offset: 0x%08x, count 0x%08x, BankEnd: 0x%08x",
- (unsigned int)(offset),
- (unsigned int)(count),
- (unsigned int)(pPrivate->size_bytes));
- r = ERROR_FAIL;
- goto done;
- }
-
- pagebuffer = malloc(pPrivate->page_size);
- if (!pagebuffer) {
- LOG_ERROR("No memory for %d Byte page buffer", (int)(pPrivate->page_size));
- r = ERROR_FAIL;
- goto done;
- }
-
- /* what page do we start & end in? */
- page_cur = offset / pPrivate->page_size;
- page_end = (offset + count - 1) / pPrivate->page_size;
-
- LOG_DEBUG("Offset: 0x%08x, Count: 0x%08x", (unsigned int)(offset), (unsigned int)(count));
- LOG_DEBUG("Page start: %d, Page End: %d", (int)(page_cur), (int)(page_end));
-
- /* Special case: all one page */
- /* */
- /* Otherwise: */
- /* (1) non-aligned start */
- /* (2) body pages */
- /* (3) non-aligned end. */
-
- /* Handle special case - all one page. */
- if (page_cur == page_end) {
- LOG_DEBUG("Special case, all in one page");
- r = sam3_page_read(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
-
- page_offset = (offset & (pPrivate->page_size-1));
- memcpy(pagebuffer + page_offset,
- buffer,
- count);
-
- r = sam3_page_write(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
- r = ERROR_OK;
- goto done;
- }
-
- /* non-aligned start */
- page_offset = offset & (pPrivate->page_size - 1);
- if (page_offset) {
- LOG_DEBUG("Not-Aligned start");
- /* read the partial */
- r = sam3_page_read(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
-
- /* over-write with new data */
- n = (pPrivate->page_size - page_offset);
- memcpy(pagebuffer + page_offset,
- buffer,
- n);
-
- r = sam3_page_write(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
-
- count -= n;
- offset += n;
- buffer += n;
- page_cur++;
- }
-
- /* By checking that offset is correct here, we also
- fix a clang warning */
- assert(offset % pPrivate->page_size == 0);
-
- /* intermediate large pages */
- /* also - the final *terminal* */
- /* if that terminal page is a full page */
- LOG_DEBUG("Full Page Loop: cur=%d, end=%d, count = 0x%08x",
- (int)page_cur, (int)page_end, (unsigned int)(count));
-
- while ((page_cur < page_end) &&
- (count >= pPrivate->page_size)) {
- r = sam3_page_write(pPrivate, page_cur, buffer);
- if (r != ERROR_OK)
- goto done;
- count -= pPrivate->page_size;
- buffer += pPrivate->page_size;
- page_cur += 1;
- }
-
- /* terminal partial page? */
- if (count) {
- LOG_DEBUG("Terminal partial page, count = 0x%08x", (unsigned int)(count));
- /* we have a partial page */
- r = sam3_page_read(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
- /* data goes at start */
- memcpy(pagebuffer, buffer, count);
- r = sam3_page_write(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
- }
- LOG_DEBUG("Done!");
- r = ERROR_OK;
-done:
- if (pagebuffer)
- free(pagebuffer);
- return r;
-}
-
-COMMAND_HANDLER(sam3_handle_info_command)
-{
- struct sam3_chip *pChip;
- pChip = get_current_sam3(CMD_CTX);
- if (!pChip)
- return ERROR_OK;
-
- unsigned x;
- int r;
-
- /* bank0 must exist before we can do anything */
- if (pChip->details.bank[0].pBank == NULL) {
- x = 0;
-need_define:
- command_print(CMD_CTX,
- "Please define bank %d via command: flash bank %s ... ",
- x,
- at91sam3_flash.name);
- return ERROR_FAIL;
- }
-
- /* if bank 0 is not probed, then probe it */
- if (!(pChip->details.bank[0].probed)) {
- r = sam3_auto_probe(pChip->details.bank[0].pBank);
- if (r != ERROR_OK)
- return ERROR_FAIL;
- }
- /* above guarantees the "chip details" structure is valid */
- /* and thus, bank private areas are valid */
- /* and we have a SAM3 chip, what a concept! */
-
- /* auto-probe other banks, 0 done above */
- for (x = 1; x < SAM3_MAX_FLASH_BANKS; x++) {
- /* skip banks not present */
- if (!(pChip->details.bank[x].present))
- continue;
-
- if (pChip->details.bank[x].pBank == NULL)
- goto need_define;
-
- if (pChip->details.bank[x].probed)
- continue;
-
- r = sam3_auto_probe(pChip->details.bank[x].pBank);
- if (r != ERROR_OK)
- return r;
- }
-
- r = sam3_GetInfo(pChip);
- if (r != ERROR_OK) {
- LOG_DEBUG("Sam3Info, Failed %d", r);
- return r;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sam3_handle_gpnvm_command)
-{
- unsigned x, v;
- int r, who;
- struct sam3_chip *pChip;
-
- pChip = get_current_sam3(CMD_CTX);
- if (!pChip)
- return ERROR_OK;
-
- if (pChip->target->state != TARGET_HALTED) {
- LOG_ERROR("sam3 - target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (pChip->details.bank[0].pBank == NULL) {
- command_print(CMD_CTX, "Bank0 must be defined first via: flash bank %s ...",
- at91sam3_flash.name);
- return ERROR_FAIL;
- }
- if (!pChip->details.bank[0].probed) {
- r = sam3_auto_probe(pChip->details.bank[0].pBank);
- if (r != ERROR_OK)
- return r;
- }
-
- switch (CMD_ARGC) {
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- case 0:
- goto showall;
- break;
- case 1:
- who = -1;
- break;
- case 2:
- if ((0 == strcmp(CMD_ARGV[0], "show")) && (0 == strcmp(CMD_ARGV[1], "all")))
- who = -1;
- else {
- uint32_t v32;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
- who = v32;
- }
- break;
- }
-
- if (0 == strcmp("show", CMD_ARGV[0])) {
- if (who == -1) {
-showall:
- r = ERROR_OK;
- for (x = 0; x < pChip->details.n_gpnvms; x++) {
- r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v);
- if (r != ERROR_OK)
- break;
- command_print(CMD_CTX, "sam3-gpnvm%u: %u", x, v);
- }
- return r;
- }
- if ((who >= 0) && (((unsigned)(who)) < pChip->details.n_gpnvms)) {
- r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), who, &v);
- command_print(CMD_CTX, "sam3-gpnvm%u: %u", who, v);
- return r;
- } else {
- command_print(CMD_CTX, "sam3-gpnvm invalid GPNVM: %u", who);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- if (who == -1) {
- command_print(CMD_CTX, "Missing GPNVM number");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (0 == strcmp("set", CMD_ARGV[0]))
- r = FLASHD_SetGPNVM(&(pChip->details.bank[0]), who);
- else if ((0 == strcmp("clr", CMD_ARGV[0])) ||
- (0 == strcmp("clear", CMD_ARGV[0]))) /* quietly accept both */
- r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who);
- else {
- command_print(CMD_CTX, "Unknown command: %s", CMD_ARGV[0]);
- r = ERROR_COMMAND_SYNTAX_ERROR;
- }
- return r;
-}
-
-COMMAND_HANDLER(sam3_handle_slowclk_command)
-{
- struct sam3_chip *pChip;
-
- pChip = get_current_sam3(CMD_CTX);
- if (!pChip)
- return ERROR_OK;
-
- switch (CMD_ARGC) {
- case 0:
- /* show */
- break;
- case 1:
- {
- /* set */
- uint32_t v;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
- if (v > 200000) {
- /* absurd slow clock of 200Khz? */
- command_print(CMD_CTX, "Absurd/illegal slow clock freq: %d\n", (int)(v));
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- pChip->cfg.slow_freq = v;
- break;
- }
- default:
- /* error */
- command_print(CMD_CTX, "Too many parameters");
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- }
- command_print(CMD_CTX, "Slowclk freq: %d.%03dkhz",
- (int)(pChip->cfg.slow_freq / 1000),
- (int)(pChip->cfg.slow_freq % 1000));
- return ERROR_OK;
-}
-
-static const struct command_registration at91sam3_exec_command_handlers[] = {
- {
- .name = "gpnvm",
- .handler = sam3_handle_gpnvm_command,
- .mode = COMMAND_EXEC,
- .usage = "[('clr'|'set'|'show') bitnum]",
- .help = "Without arguments, shows all bits in the gpnvm "
- "register. Otherwise, clears, sets, or shows one "
- "General Purpose Non-Volatile Memory (gpnvm) bit.",
- },
- {
- .name = "info",
- .handler = sam3_handle_info_command,
- .mode = COMMAND_EXEC,
- .help = "Print information about the current at91sam3 chip"
- "and its flash configuration.",
- },
- {
- .name = "slowclk",
- .handler = sam3_handle_slowclk_command,
- .mode = COMMAND_EXEC,
- .usage = "[clock_hz]",
- .help = "Display or set the slowclock frequency "
- "(default 32768 Hz).",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration at91sam3_command_handlers[] = {
- {
- .name = "at91sam3",
- .mode = COMMAND_ANY,
- .help = "at91sam3 flash command group",
- .usage = "",
- .chain = at91sam3_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver at91sam3_flash = {
- .name = "at91sam3",
- .commands = at91sam3_command_handlers,
- .flash_bank_command = sam3_flash_bank_command,
- .erase = sam3_erase,
- .protect = sam3_protect,
- .write = sam3_write,
- .read = default_flash_read,
- .probe = sam3_probe,
- .auto_probe = sam3_auto_probe,
- .erase_check = sam3_erase_check,
- .protect_check = sam3_protect_check,
-};
diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c
deleted file mode 100644
index 50aa98b..0000000
--- a/src/flash/nor/at91sam4.c
+++ /dev/null
@@ -1,2678 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Duane Ellis *
- * openocd@duaneellis.com *
- * *
- * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) *
- * olaf@uni-paderborn.de *
- * *
- * Copyright (C) 2011 by Olivier Schonken, Jim Norris *
- * (at91sam3x* & at91sam4 support)* *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
-****************************************************************************/
-
-/* Some of the the lower level code was based on code supplied by
- * ATMEL under this copyright. */
-
-/* BEGIN ATMEL COPYRIGHT */
-/* ----------------------------------------------------------------------------
- * ATMEL Microcontroller Software Support
- * ----------------------------------------------------------------------------
- * Copyright (c) 2009, Atmel Corporation
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the disclaimer below.
- *
- * Atmel's name may not be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * ----------------------------------------------------------------------------
- */
-/* END ATMEL COPYRIGHT */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/time_support.h>
-
-#define REG_NAME_WIDTH (12)
-
-/* at91sam4s/at91sam4e series (has always one flash bank)*/
-#define FLASH_BANK_BASE_S 0x00400000
-
-/* at91sam4sd series (two one flash banks), first bank address */
-#define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S
-/* at91sam4sd16x, second bank address */
-#define FLASH_BANK1_BASE_1024K_SD (FLASH_BANK0_BASE_SD+(1024*1024/2))
-/* at91sam4sd32x, second bank address */
-#define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2))
-
-#define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
-#define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
-#define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
-#define AT91C_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */
-#define AT91C_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page and Write Page then Lock */
-#define AT91C_EFC_FCMD_EA (0x5) /* (EFC) Erase All */
-/* cmd6 is not present in the at91sam4u4/2/1 data sheet table 19-2 */
-/* #define AT91C_EFC_FCMD_EPL (0x6) // (EFC) Erase plane? */
-#define AT91C_EFC_FCMD_EPA (0x7) /* (EFC) Erase pages */
-#define AT91C_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */
-#define AT91C_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */
-#define AT91C_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */
-#define AT91C_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
-#define AT91C_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
-#define AT91C_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
-#define AT91C_EFC_FCMD_STUI (0xE) /* (EFC) Start Read Unique ID */
-#define AT91C_EFC_FCMD_SPUI (0xF) /* (EFC) Stop Read Unique ID */
-
-#define offset_EFC_FMR 0
-#define offset_EFC_FCR 4
-#define offset_EFC_FSR 8
-#define offset_EFC_FRR 12
-
-extern struct flash_driver at91sam4_flash;
-
-static float _tomhz(uint32_t freq_hz)
-{
- float f;
-
- f = ((float)(freq_hz)) / 1000000.0;
- return f;
-}
-
-/* How the chip is configured. */
-struct sam4_cfg {
- uint32_t unique_id[4];
-
- uint32_t slow_freq;
- uint32_t rc_freq;
- uint32_t mainosc_freq;
- uint32_t plla_freq;
- uint32_t mclk_freq;
- uint32_t cpu_freq;
- uint32_t fclk_freq;
- uint32_t pclk0_freq;
- uint32_t pclk1_freq;
- uint32_t pclk2_freq;
-
-
-#define SAM4_CHIPID_CIDR (0x400E0740)
- uint32_t CHIPID_CIDR;
-#define SAM4_CHIPID_EXID (0x400E0744)
- uint32_t CHIPID_EXID;
-
-#define SAM4_PMC_BASE (0x400E0400)
-#define SAM4_PMC_SCSR (SAM4_PMC_BASE + 0x0008)
- uint32_t PMC_SCSR;
-#define SAM4_PMC_PCSR (SAM4_PMC_BASE + 0x0018)
- uint32_t PMC_PCSR;
-#define SAM4_CKGR_UCKR (SAM4_PMC_BASE + 0x001c)
- uint32_t CKGR_UCKR;
-#define SAM4_CKGR_MOR (SAM4_PMC_BASE + 0x0020)
- uint32_t CKGR_MOR;
-#define SAM4_CKGR_MCFR (SAM4_PMC_BASE + 0x0024)
- uint32_t CKGR_MCFR;
-#define SAM4_CKGR_PLLAR (SAM4_PMC_BASE + 0x0028)
- uint32_t CKGR_PLLAR;
-#define SAM4_PMC_MCKR (SAM4_PMC_BASE + 0x0030)
- uint32_t PMC_MCKR;
-#define SAM4_PMC_PCK0 (SAM4_PMC_BASE + 0x0040)
- uint32_t PMC_PCK0;
-#define SAM4_PMC_PCK1 (SAM4_PMC_BASE + 0x0044)
- uint32_t PMC_PCK1;
-#define SAM4_PMC_PCK2 (SAM4_PMC_BASE + 0x0048)
- uint32_t PMC_PCK2;
-#define SAM4_PMC_SR (SAM4_PMC_BASE + 0x0068)
- uint32_t PMC_SR;
-#define SAM4_PMC_IMR (SAM4_PMC_BASE + 0x006c)
- uint32_t PMC_IMR;
-#define SAM4_PMC_FSMR (SAM4_PMC_BASE + 0x0070)
- uint32_t PMC_FSMR;
-#define SAM4_PMC_FSPR (SAM4_PMC_BASE + 0x0074)
- uint32_t PMC_FSPR;
-};
-
-struct sam4_bank_private {
- int probed;
- /* DANGER: THERE ARE DRAGONS HERE.. */
- /* NOTE: If you add more 'ghost' pointers */
- /* be aware that you must *manually* update */
- /* these pointers in the function sam4_GetDetails() */
- /* See the comment "Here there be dragons" */
-
- /* so we can find the chip we belong to */
- struct sam4_chip *pChip;
- /* so we can find the original bank pointer */
- struct flash_bank *pBank;
- unsigned bank_number;
- uint32_t controller_address;
- uint32_t base_address;
- uint32_t flash_wait_states;
- bool present;
- unsigned size_bytes;
- unsigned nsectors;
- unsigned sector_size;
- unsigned page_size;
-};
-
-struct sam4_chip_details {
- /* THERE ARE DRAGONS HERE.. */
- /* note: If you add pointers here */
- /* be careful about them as they */
- /* may need to be updated inside */
- /* the function: "sam4_GetDetails() */
- /* which copy/overwrites the */
- /* 'runtime' copy of this structure */
- uint32_t chipid_cidr;
- const char *name;
-
- unsigned n_gpnvms;
-#define SAM4_N_NVM_BITS 3
- unsigned gpnvm[SAM4_N_NVM_BITS];
- unsigned total_flash_size;
- unsigned total_sram_size;
- unsigned n_banks;
-#define SAM4_MAX_FLASH_BANKS 2
- /* these are "initialized" from the global const data */
- struct sam4_bank_private bank[SAM4_MAX_FLASH_BANKS];
-};
-
-struct sam4_chip {
- struct sam4_chip *next;
- int probed;
-
- /* this is "initialized" from the global const structure */
- struct sam4_chip_details details;
- struct target *target;
- struct sam4_cfg cfg;
-};
-
-
-struct sam4_reg_list {
- uint32_t address; size_t struct_offset; const char *name;
- void (*explain_func)(struct sam4_chip *pInfo);
-};
-
-static struct sam4_chip *all_sam4_chips;
-
-static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx)
-{
- struct target *t;
- static struct sam4_chip *p;
-
- t = get_current_target(cmd_ctx);
- if (!t) {
- command_print(cmd_ctx, "No current target?");
- return NULL;
- }
-
- p = all_sam4_chips;
- if (!p) {
- /* this should not happen */
- /* the command is not registered until the chip is created? */
- command_print(cmd_ctx, "No SAM4 chips exist?");
- return NULL;
- }
-
- while (p) {
- if (p->target == t)
- return p;
- p = p->next;
- }
- command_print(cmd_ctx, "Cannot find SAM4 chip?");
- return NULL;
-}
-
-/*The actual sector size of the SAM4S flash memory is 65536 bytes. 16 sectors for a 1024KB device*/
-/*The lockregions are 8KB per lock region, with a 1024KB device having 128 lock regions. */
-/*For the best results, nsectors are thus set to the amount of lock regions, and the sector_size*/
-/*set to the lock region size. Page erases are used to erase 8KB sections when programming*/
-
-/* these are used to *initialize* the "pChip->details" structure. */
-static const struct sam4_chip_details all_sam4_details[] = {
-
- /* Start at91sam4e* series */
- /*atsam4e16e - LQFP144/LFBGA144*/
- {
- .chipid_cidr = 0xA3CC0CE0,
- .name = "at91sam4e16e",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 128 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
-
- /* Start at91sam4n* series */
- /*atsam4n8a - LQFP48/QFN48*/
- {
- .chipid_cidr = 0x293B0AE0,
- .name = "at91sam4n8a",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4n8b - LQFP64/QFN64*/
- {
- .chipid_cidr = 0x294B0AE0,
- .name = "at91sam4n8b",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4n8c - LQFP100/TFBGA100/VFBGA100*/
- {
- .chipid_cidr = 0x295B0AE0,
- .name = "at91sam4n8c",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4n16b - LQFP64/QFN64*/
- {
- .chipid_cidr = 0x29460CE0,
- .name = "at91sam4n16b",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 80 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4n16c - LQFP100/TFBGA100/VFBGA100*/
- {
- .chipid_cidr = 0x29560CE0,
- .name = "at91sam4n16c",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 80 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
-
- /* Start at91sam4s* series */
- /*atsam4s16c - LQFP100/BGA100*/
- {
- .chipid_cidr = 0x28AC0CE0,
- .name = "at91sam4s16c",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 128 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4s16b - LQFP64/QFN64*/
- {
- .chipid_cidr = 0x289C0CE0,
- .name = "at91sam4s16b",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 128 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4sa16b - LQFP64/QFN64*/
- {
- .chipid_cidr = 0x28970CE0,
- .name = "at91sam4sa16b",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 160 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4s16a - LQFP48/QFN48*/
- {
- .chipid_cidr = 0x288C0CE0,
- .name = "at91sam4s16a",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 128 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4s8c - LQFP100/BGA100*/
- {
- .chipid_cidr = 0x28AC0AE0,
- .name = "at91sam4s8c",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 128 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4s8b - LQFP64/BGA64*/
- {
- .chipid_cidr = 0x289C0AE0,
- .name = "at91sam4s8b",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 128 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
- /*atsam4s8a - LQFP48/BGA48*/
- {
- .chipid_cidr = 0x288C0AE0,
- .name = "at91sam4s8a",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 128 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
-
- /*atsam4s4a - LQFP48/BGA48*/
- {
- .chipid_cidr = 0x288b09e0,
- .name = "at91sam4s4a",
- .total_flash_size = 256 * 1024,
- .total_sram_size = 64 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
- {
-/* .bank[0] = {*/
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 256 * 1024,
- .nsectors = 32,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- },
- },
-
- /*at91sam4sd32c*/
- {
- .chipid_cidr = 0x29a70ee0,
- .name = "at91sam4sd32c",
- .total_flash_size = 2048 * 1024,
- .total_sram_size = 160 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
-
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_2048K_SD,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 1024 * 1024,
- .nsectors = 128,
- .sector_size = 8192,
- .page_size = 512,
- },
- },
- },
-
- /*at91sam4sd16c*/
- {
- .chipid_cidr = 0x29a70ce0,
- .name = "at91sam4sd16c",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 160 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_1024K_SD,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
- },
- },
-
- /*at91sam4sa16c*/
- {
- .chipid_cidr = 0x28a70ce0,
- .name = "at91sam4sa16c",
- .total_flash_size = 1024 * 1024,
- .total_sram_size = 160 * 1024,
- .n_gpnvms = 3,
- .n_banks = 2,
-
-/* .bank[0] = { */
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_SD,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-
-/* .bank[1] = { */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_1024K_SD,
- .controller_address = 0x400e0c00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
- },
- },
-
- /* at91samg53n19 */
- {
- .chipid_cidr = 0x247e0ae0,
- .name = "at91samg53n19",
- .total_flash_size = 512 * 1024,
- .total_sram_size = 96 * 1024,
- .n_gpnvms = 2,
- .n_banks = 1,
-
-/* .bank[0] = {*/
- {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK_BASE_S,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 512 * 1024,
- .nsectors = 64,
- .sector_size = 8192,
- .page_size = 512,
- },
-/* .bank[1] = {*/
- {
- .present = 0,
- .probed = 0,
- .bank_number = 1,
-
- },
- }
- },
-
- /* terminate */
- {
- .chipid_cidr = 0,
- .name = NULL,
- }
-};
-
-/* Globals above */
-/***********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************
- **********************************************************************/
-/* *ATMEL* style code - from the SAM4 driver code */
-
-/**
- * Get the current status of the EEFC and
- * the value of some status bits (LOCKE, PROGE).
- * @param pPrivate - info about the bank
- * @param v - result goes here
- */
-static int EFC_GetStatus(struct sam4_bank_private *pPrivate, uint32_t *v)
-{
- int r;
- r = target_read_u32(pPrivate->pChip->target,
- pPrivate->controller_address + offset_EFC_FSR,
- v);
- LOG_DEBUG("Status: 0x%08x (lockerror: %d, cmderror: %d, ready: %d)",
- (unsigned int)(*v),
- ((unsigned int)((*v >> 2) & 1)),
- ((unsigned int)((*v >> 1) & 1)),
- ((unsigned int)((*v >> 0) & 1)));
-
- return r;
-}
-
-/**
- * Get the result of the last executed command.
- * @param pPrivate - info about the bank
- * @param v - result goes here
- */
-static int EFC_GetResult(struct sam4_bank_private *pPrivate, uint32_t *v)
-{
- int r;
- uint32_t rv;
- r = target_read_u32(pPrivate->pChip->target,
- pPrivate->controller_address + offset_EFC_FRR,
- &rv);
- if (v)
- *v = rv;
- LOG_DEBUG("Result: 0x%08x", ((unsigned int)(rv)));
- return r;
-}
-
-static int EFC_StartCommand(struct sam4_bank_private *pPrivate,
- unsigned command, unsigned argument)
-{
- uint32_t n, v;
- int r;
- int retry;
-
- retry = 0;
-do_retry:
-
- /* Check command & argument */
- switch (command) {
-
- case AT91C_EFC_FCMD_WP:
- case AT91C_EFC_FCMD_WPL:
- case AT91C_EFC_FCMD_EWP:
- case AT91C_EFC_FCMD_EWPL:
- /* case AT91C_EFC_FCMD_EPL: */
- case AT91C_EFC_FCMD_EPA:
- case AT91C_EFC_FCMD_SLB:
- case AT91C_EFC_FCMD_CLB:
- n = (pPrivate->size_bytes / pPrivate->page_size);
- if (argument >= n)
- LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n));
- break;
-
- case AT91C_EFC_FCMD_SFB:
- case AT91C_EFC_FCMD_CFB:
- if (argument >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
- pPrivate->pChip->details.n_gpnvms);
- }
- break;
-
- case AT91C_EFC_FCMD_GETD:
- case AT91C_EFC_FCMD_EA:
- case AT91C_EFC_FCMD_GLB:
- case AT91C_EFC_FCMD_GFB:
- case AT91C_EFC_FCMD_STUI:
- case AT91C_EFC_FCMD_SPUI:
- if (argument != 0)
- LOG_ERROR("Argument is meaningless for cmd: %d", command);
- break;
- default:
- LOG_ERROR("Unknown command %d", command);
- break;
- }
-
- if (command == AT91C_EFC_FCMD_SPUI) {
- /* this is a very special situation. */
- /* Situation (1) - error/retry - see below */
- /* And we are being called recursively */
- /* Situation (2) - normal, finished reading unique id */
- } else {
- /* it should be "ready" */
- EFC_GetStatus(pPrivate, &v);
- if (v & 1) {
- /* then it is ready */
- /* we go on */
- } else {
- if (retry) {
- /* we have done this before */
- /* the controller is not responding. */
- LOG_ERROR("flash controller(%d) is not ready! Error",
- pPrivate->bank_number);
- return ERROR_FAIL;
- } else {
- retry++;
- LOG_ERROR("Flash controller(%d) is not ready, attempting reset",
- pPrivate->bank_number);
- /* we do that by issuing the *STOP* command */
- EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0);
- /* above is recursive, and further recursion is blocked by */
- /* if (command == AT91C_EFC_FCMD_SPUI) above */
- goto do_retry;
- }
- }
- }
-
- v = (0x5A << 24) | (argument << 8) | command;
- LOG_DEBUG("Command: 0x%08x", ((unsigned int)(v)));
- r = target_write_u32(pPrivate->pBank->target,
- pPrivate->controller_address + offset_EFC_FCR, v);
- if (r != ERROR_OK)
- LOG_DEBUG("Error Write failed");
- return r;
-}
-
-/**
- * Performs the given command and wait until its completion (or an error).
- * @param pPrivate - info about the bank
- * @param command - Command to perform.
- * @param argument - Optional command argument.
- * @param status - put command status bits here
- */
-static int EFC_PerformCommand(struct sam4_bank_private *pPrivate,
- unsigned command,
- unsigned argument,
- uint32_t *status)
-{
-
- int r;
- uint32_t v;
- int64_t ms_now, ms_end;
-
- /* default */
- if (status)
- *status = 0;
-
- r = EFC_StartCommand(pPrivate, command, argument);
- if (r != ERROR_OK)
- return r;
-
- ms_end = 10000 + timeval_ms();
-
- do {
- r = EFC_GetStatus(pPrivate, &v);
- if (r != ERROR_OK)
- return r;
- ms_now = timeval_ms();
- if (ms_now > ms_end) {
- /* error */
- LOG_ERROR("Command timeout");
- return ERROR_FAIL;
- }
- } while ((v & 1) == 0);
-
- /* error bits.. */
- if (status)
- *status = (v & 0x6);
- return ERROR_OK;
-
-}
-
-/**
- * Read the unique ID.
- * @param pPrivate - info about the bank
- * The unique ID is stored in the 'pPrivate' structure.
- */
-static int FLASHD_ReadUniqueID(struct sam4_bank_private *pPrivate)
-{
- int r;
- uint32_t v;
- int x;
- /* assume 0 */
- pPrivate->pChip->cfg.unique_id[0] = 0;
- pPrivate->pChip->cfg.unique_id[1] = 0;
- pPrivate->pChip->cfg.unique_id[2] = 0;
- pPrivate->pChip->cfg.unique_id[3] = 0;
-
- LOG_DEBUG("Begin");
- r = EFC_StartCommand(pPrivate, AT91C_EFC_FCMD_STUI, 0);
- if (r < 0)
- return r;
-
- for (x = 0; x < 4; x++) {
- r = target_read_u32(pPrivate->pChip->target,
- pPrivate->pBank->base + (x * 4),
- &v);
- if (r < 0)
- return r;
- pPrivate->pChip->cfg.unique_id[x] = v;
- }
-
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SPUI, 0, NULL);
- LOG_DEBUG("End: R=%d, id = 0x%08x, 0x%08x, 0x%08x, 0x%08x",
- r,
- (unsigned int)(pPrivate->pChip->cfg.unique_id[0]),
- (unsigned int)(pPrivate->pChip->cfg.unique_id[1]),
- (unsigned int)(pPrivate->pChip->cfg.unique_id[2]),
- (unsigned int)(pPrivate->pChip->cfg.unique_id[3]));
- return r;
-
-}
-
-/**
- * Erases the entire flash.
- * @param pPrivate - the info about the bank.
- */
-static int FLASHD_EraseEntireBank(struct sam4_bank_private *pPrivate)
-{
- LOG_DEBUG("Here");
- return EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_EA, 0, NULL);
-}
-
-/**
- * Erases the entire flash.
- * @param pPrivate - the info about the bank.
- */
-static int FLASHD_ErasePages(struct sam4_bank_private *pPrivate,
- int firstPage,
- int numPages,
- uint32_t *status)
-{
- LOG_DEBUG("Here");
- uint8_t erasePages;
- switch (numPages) {
- case 4:
- erasePages = 0x00;
- break;
- case 8:
- erasePages = 0x01;
- break;
- case 16:
- erasePages = 0x02;
- break;
- case 32:
- erasePages = 0x03;
- break;
- default:
- erasePages = 0x00;
- break;
- }
-
- /* AT91C_EFC_FCMD_EPA
- * According to the datasheet FARG[15:2] defines the page from which
- * the erase will start.This page must be modulo 4, 8, 16 or 32
- * according to the number of pages to erase. FARG[1:0] defines the
- * number of pages to be erased. Previously (firstpage << 2) was used
- * to conform to this, seems it should not be shifted...
- */
- return EFC_PerformCommand(pPrivate,
- /* send Erase Page */
- AT91C_EFC_FCMD_EPA,
- (firstPage) | erasePages,
- status);
-}
-
-/**
- * Gets current GPNVM state.
- * @param pPrivate - info about the bank.
- * @param gpnvm - GPNVM bit index.
- * @param puthere - result stored here.
- */
-/* ------------------------------------------------------------------------------ */
-static int FLASHD_GetGPNVM(struct sam4_bank_private *pPrivate, unsigned gpnvm, unsigned *puthere)
-{
- uint32_t v;
- int r;
-
- LOG_DEBUG("Here");
- if (pPrivate->bank_number != 0) {
- LOG_ERROR("GPNVM only works with Bank0");
- return ERROR_FAIL;
- }
-
- if (gpnvm >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("Invalid GPNVM %d, max: %d, ignored",
- gpnvm, pPrivate->pChip->details.n_gpnvms);
- return ERROR_FAIL;
- }
-
- /* Get GPNVMs status */
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GFB, 0, NULL);
- if (r != ERROR_OK) {
- LOG_ERROR("Failed");
- return r;
- }
-
- r = EFC_GetResult(pPrivate, &v);
-
- if (puthere) {
- /* Check if GPNVM is set */
- /* get the bit and make it a 0/1 */
- *puthere = (v >> gpnvm) & 1;
- }
-
- return r;
-}
-
-/**
- * Clears the selected GPNVM bit.
- * @param pPrivate info about the bank
- * @param gpnvm GPNVM index.
- * @returns 0 if successful; otherwise returns an error code.
- */
-static int FLASHD_ClrGPNVM(struct sam4_bank_private *pPrivate, unsigned gpnvm)
-{
- int r;
- unsigned v;
-
- LOG_DEBUG("Here");
- if (pPrivate->bank_number != 0) {
- LOG_ERROR("GPNVM only works with Bank0");
- return ERROR_FAIL;
- }
-
- if (gpnvm >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("Invalid GPNVM %d, max: %d, ignored",
- gpnvm, pPrivate->pChip->details.n_gpnvms);
- return ERROR_FAIL;
- }
-
- r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v);
- if (r != ERROR_OK) {
- LOG_DEBUG("Failed: %d", r);
- return r;
- }
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CFB, gpnvm, NULL);
- LOG_DEBUG("End: %d", r);
- return r;
-}
-
-/**
- * Sets the selected GPNVM bit.
- * @param pPrivate info about the bank
- * @param gpnvm GPNVM index.
- */
-static int FLASHD_SetGPNVM(struct sam4_bank_private *pPrivate, unsigned gpnvm)
-{
- int r;
- unsigned v;
-
- if (pPrivate->bank_number != 0) {
- LOG_ERROR("GPNVM only works with Bank0");
- return ERROR_FAIL;
- }
-
- if (gpnvm >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("Invalid GPNVM %d, max: %d, ignored",
- gpnvm, pPrivate->pChip->details.n_gpnvms);
- return ERROR_FAIL;
- }
-
- r = FLASHD_GetGPNVM(pPrivate, gpnvm, &v);
- if (r != ERROR_OK)
- return r;
- if (v) {
- /* already set */
- r = ERROR_OK;
- } else {
- /* set it */
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SFB, gpnvm, NULL);
- }
- return r;
-}
-
-/**
- * Returns a bit field (at most 64) of locked regions within a page.
- * @param pPrivate info about the bank
- * @param v where to store locked bits
- */
-static int FLASHD_GetLockBits(struct sam4_bank_private *pPrivate, uint32_t *v)
-{
- int r;
- LOG_DEBUG("Here");
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_GLB, 0, NULL);
- if (r == ERROR_OK) {
- EFC_GetResult(pPrivate, v);
- EFC_GetResult(pPrivate, v);
- EFC_GetResult(pPrivate, v);
- r = EFC_GetResult(pPrivate, v);
- }
- LOG_DEBUG("End: %d", r);
- return r;
-}
-
-/**
- * Unlocks all the regions in the given address range.
- * @param pPrivate info about the bank
- * @param start_sector first sector to unlock
- * @param end_sector last (inclusive) to unlock
- */
-
-static int FLASHD_Unlock(struct sam4_bank_private *pPrivate,
- unsigned start_sector,
- unsigned end_sector)
-{
- int r;
- uint32_t status;
- uint32_t pg;
- uint32_t pages_per_sector;
-
- pages_per_sector = pPrivate->sector_size / pPrivate->page_size;
-
- /* Unlock all pages */
- while (start_sector <= end_sector) {
- pg = start_sector * pages_per_sector;
-
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_CLB, pg, &status);
- if (r != ERROR_OK)
- return r;
- start_sector++;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Locks regions
- * @param pPrivate - info about the bank
- * @param start_sector - first sector to lock
- * @param end_sector - last sector (inclusive) to lock
- */
-static int FLASHD_Lock(struct sam4_bank_private *pPrivate,
- unsigned start_sector,
- unsigned end_sector)
-{
- uint32_t status;
- uint32_t pg;
- uint32_t pages_per_sector;
- int r;
-
- pages_per_sector = pPrivate->sector_size / pPrivate->page_size;
-
- /* Lock all pages */
- while (start_sector <= end_sector) {
- pg = start_sector * pages_per_sector;
-
- r = EFC_PerformCommand(pPrivate, AT91C_EFC_FCMD_SLB, pg, &status);
- if (r != ERROR_OK)
- return r;
- start_sector++;
- }
- return ERROR_OK;
-}
-
-/****** END SAM4 CODE ********/
-
-/* begin helpful debug code */
-/* print the fieldname, the field value, in dec & hex, and return field value */
-static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip,
- const char *regname,
- uint32_t value,
- unsigned shift,
- unsigned width)
-{
- uint32_t v;
- int hwidth, dwidth;
-
-
- /* extract the field */
- v = value >> shift;
- v = v & ((1 << width)-1);
- if (width <= 16) {
- hwidth = 4;
- dwidth = 5;
- } else {
- hwidth = 8;
- dwidth = 12;
- }
-
- /* show the basics */
- LOG_USER_N("\t%*s: %*" PRId32 " [0x%0*" PRIx32 "] ",
- REG_NAME_WIDTH, regname,
- dwidth, v,
- hwidth, v);
- return v;
-}
-
-static const char _unknown[] = "unknown";
-static const char *const eproc_names[] = {
- _unknown, /* 0 */
- "arm946es", /* 1 */
- "arm7tdmi", /* 2 */
- "Cortex-M3", /* 3 */
- "arm920t", /* 4 */
- "arm926ejs", /* 5 */
- "Cortex-A5", /* 6 */
- "Cortex-M4", /* 7 */
- _unknown, /* 8 */
- _unknown, /* 9 */
- _unknown, /* 10 */
- _unknown, /* 11 */
- _unknown, /* 12 */
- _unknown, /* 13 */
- _unknown, /* 14 */
- _unknown, /* 15 */
-};
-
-#define nvpsize2 nvpsize /* these two tables are identical */
-static const char *const nvpsize[] = {
- "none", /* 0 */
- "8K bytes", /* 1 */
- "16K bytes", /* 2 */
- "32K bytes", /* 3 */
- _unknown, /* 4 */
- "64K bytes", /* 5 */
- _unknown, /* 6 */
- "128K bytes", /* 7 */
- _unknown, /* 8 */
- "256K bytes", /* 9 */
- "512K bytes", /* 10 */
- _unknown, /* 11 */
- "1024K bytes", /* 12 */
- _unknown, /* 13 */
- "2048K bytes", /* 14 */
- _unknown, /* 15 */
-};
-
-static const char *const sramsize[] = {
- "48K Bytes", /* 0 */
- "1K Bytes", /* 1 */
- "2K Bytes", /* 2 */
- "6K Bytes", /* 3 */
- "112K Bytes", /* 4 */
- "4K Bytes", /* 5 */
- "80K Bytes", /* 6 */
- "160K Bytes", /* 7 */
- "8K Bytes", /* 8 */
- "16K Bytes", /* 9 */
- "32K Bytes", /* 10 */
- "64K Bytes", /* 11 */
- "128K Bytes", /* 12 */
- "256K Bytes", /* 13 */
- "96K Bytes", /* 14 */
- "512K Bytes", /* 15 */
-
-};
-
-static const struct archnames { unsigned value; const char *name; } archnames[] = {
- { 0x19, "AT91SAM9xx Series" },
- { 0x29, "AT91SAM9XExx Series" },
- { 0x34, "AT91x34 Series" },
- { 0x37, "CAP7 Series" },
- { 0x39, "CAP9 Series" },
- { 0x3B, "CAP11 Series" },
- { 0x3C, "ATSAM4E" },
- { 0x40, "AT91x40 Series" },
- { 0x42, "AT91x42 Series" },
- { 0x43, "SAMG51 Series"
- },
- { 0x47, "SAMG53 Series"
- },
- { 0x55, "AT91x55 Series" },
- { 0x60, "AT91SAM7Axx Series" },
- { 0x61, "AT91SAM7AQxx Series" },
- { 0x63, "AT91x63 Series" },
- { 0x70, "AT91SAM7Sxx Series" },
- { 0x71, "AT91SAM7XCxx Series" },
- { 0x72, "AT91SAM7SExx Series" },
- { 0x73, "AT91SAM7Lxx Series" },
- { 0x75, "AT91SAM7Xxx Series" },
- { 0x76, "AT91SAM7SLxx Series" },
- { 0x80, "ATSAM3UxC Series (100-pin version)" },
- { 0x81, "ATSAM3UxE Series (144-pin version)" },
- { 0x83, "ATSAM3A/SAM4A xC Series (100-pin version)"},
- { 0x84, "ATSAM3X/SAM4X xC Series (100-pin version)"},
- { 0x85, "ATSAM3X/SAM4X xE Series (144-pin version)"},
- { 0x86, "ATSAM3X/SAM4X xG Series (208/217-pin version)" },
- { 0x88, "ATSAM3S/SAM4S xA Series (48-pin version)" },
- { 0x89, "ATSAM3S/SAM4S xB Series (64-pin version)" },
- { 0x8A, "ATSAM3S/SAM4S xC Series (100-pin version)"},
- { 0x92, "AT91x92 Series" },
- { 0x93, "ATSAM3NxA Series (48-pin version)" },
- { 0x94, "ATSAM3NxB Series (64-pin version)" },
- { 0x95, "ATSAM3NxC Series (100-pin version)" },
- { 0x98, "ATSAM3SDxA Series (48-pin version)" },
- { 0x99, "ATSAM3SDxB Series (64-pin version)" },
- { 0x9A, "ATSAM3SDxC Series (100-pin version)" },
- { 0xA5, "ATSAM5A" },
- { 0xF0, "AT75Cxx Series" },
- { -1, NULL },
-};
-
-static const char *const nvptype[] = {
- "rom", /* 0 */
- "romless or onchip flash", /* 1 */
- "embedded flash memory",/* 2 */
- "rom(nvpsiz) + embedded flash (nvpsiz2)", /* 3 */
- "sram emulating flash", /* 4 */
- _unknown, /* 5 */
- _unknown, /* 6 */
- _unknown, /* 7 */
-};
-
-static const char *_yes_or_no(uint32_t v)
-{
- if (v)
- return "YES";
- else
- return "NO";
-}
-
-static const char *const _rc_freq[] = {
- "4 MHz", "8 MHz", "12 MHz", "reserved"
-};
-
-static void sam4_explain_ckgr_mor(struct sam4_chip *pChip)
-{
- uint32_t v;
- uint32_t rcen;
-
- v = sam4_reg_fieldname(pChip, "MOSCXTEN", pChip->cfg.CKGR_MOR, 0, 1);
- LOG_USER("(main xtal enabled: %s)", _yes_or_no(v));
- v = sam4_reg_fieldname(pChip, "MOSCXTBY", pChip->cfg.CKGR_MOR, 1, 1);
- LOG_USER("(main osc bypass: %s)", _yes_or_no(v));
- rcen = sam4_reg_fieldname(pChip, "MOSCRCEN", pChip->cfg.CKGR_MOR, 3, 1);
- LOG_USER("(onchip RC-OSC enabled: %s)", _yes_or_no(rcen));
- v = sam4_reg_fieldname(pChip, "MOSCRCF", pChip->cfg.CKGR_MOR, 4, 3);
- LOG_USER("(onchip RC-OSC freq: %s)", _rc_freq[v]);
-
- pChip->cfg.rc_freq = 0;
- if (rcen) {
- switch (v) {
- default:
- pChip->cfg.rc_freq = 0;
- break;
- case 0:
- pChip->cfg.rc_freq = 4 * 1000 * 1000;
- break;
- case 1:
- pChip->cfg.rc_freq = 8 * 1000 * 1000;
- break;
- case 2:
- pChip->cfg.rc_freq = 12 * 1000 * 1000;
- break;
- }
- }
-
- v = sam4_reg_fieldname(pChip, "MOSCXTST", pChip->cfg.CKGR_MOR, 8, 8);
- LOG_USER("(startup clks, time= %f uSecs)",
- ((float)(v * 1000000)) / ((float)(pChip->cfg.slow_freq)));
- v = sam4_reg_fieldname(pChip, "MOSCSEL", pChip->cfg.CKGR_MOR, 24, 1);
- LOG_USER("(mainosc source: %s)",
- v ? "external xtal" : "internal RC");
-
- v = sam4_reg_fieldname(pChip, "CFDEN", pChip->cfg.CKGR_MOR, 25, 1);
- LOG_USER("(clock failure enabled: %s)",
- _yes_or_no(v));
-}
-
-static void sam4_explain_chipid_cidr(struct sam4_chip *pChip)
-{
- int x;
- uint32_t v;
- const char *cp;
-
- sam4_reg_fieldname(pChip, "Version", pChip->cfg.CHIPID_CIDR, 0, 5);
- LOG_USER_N("\n");
-
- v = sam4_reg_fieldname(pChip, "EPROC", pChip->cfg.CHIPID_CIDR, 5, 3);
- LOG_USER("%s", eproc_names[v]);
-
- v = sam4_reg_fieldname(pChip, "NVPSIZE", pChip->cfg.CHIPID_CIDR, 8, 4);
- LOG_USER("%s", nvpsize[v]);
-
- v = sam4_reg_fieldname(pChip, "NVPSIZE2", pChip->cfg.CHIPID_CIDR, 12, 4);
- LOG_USER("%s", nvpsize2[v]);
-
- v = sam4_reg_fieldname(pChip, "SRAMSIZE", pChip->cfg.CHIPID_CIDR, 16, 4);
- LOG_USER("%s", sramsize[v]);
-
- v = sam4_reg_fieldname(pChip, "ARCH", pChip->cfg.CHIPID_CIDR, 20, 8);
- cp = _unknown;
- for (x = 0; archnames[x].name; x++) {
- if (v == archnames[x].value) {
- cp = archnames[x].name;
- break;
- }
- }
-
- LOG_USER("%s", cp);
-
- v = sam4_reg_fieldname(pChip, "NVPTYP", pChip->cfg.CHIPID_CIDR, 28, 3);
- LOG_USER("%s", nvptype[v]);
-
- v = sam4_reg_fieldname(pChip, "EXTID", pChip->cfg.CHIPID_CIDR, 31, 1);
- LOG_USER("(exists: %s)", _yes_or_no(v));
-}
-
-static void sam4_explain_ckgr_mcfr(struct sam4_chip *pChip)
-{
- uint32_t v;
-
- v = sam4_reg_fieldname(pChip, "MAINFRDY", pChip->cfg.CKGR_MCFR, 16, 1);
- LOG_USER("(main ready: %s)", _yes_or_no(v));
-
- v = sam4_reg_fieldname(pChip, "MAINF", pChip->cfg.CKGR_MCFR, 0, 16);
-
- v = (v * pChip->cfg.slow_freq) / 16;
- pChip->cfg.mainosc_freq = v;
-
- LOG_USER("(%3.03f Mhz (%" PRIu32 ".%03" PRIu32 "khz slowclk)",
- _tomhz(v),
- (uint32_t)(pChip->cfg.slow_freq / 1000),
- (uint32_t)(pChip->cfg.slow_freq % 1000));
-}
-
-static void sam4_explain_ckgr_plla(struct sam4_chip *pChip)
-{
- uint32_t mula, diva;
-
- diva = sam4_reg_fieldname(pChip, "DIVA", pChip->cfg.CKGR_PLLAR, 0, 8);
- LOG_USER_N("\n");
- mula = sam4_reg_fieldname(pChip, "MULA", pChip->cfg.CKGR_PLLAR, 16, 11);
- LOG_USER_N("\n");
- pChip->cfg.plla_freq = 0;
- if (mula == 0)
- LOG_USER("\tPLLA Freq: (Disabled,mula = 0)");
- else if (diva == 0)
- LOG_USER("\tPLLA Freq: (Disabled,diva = 0)");
- else if (diva >= 1) {
- pChip->cfg.plla_freq = (pChip->cfg.mainosc_freq * (mula + 1) / diva);
- LOG_USER("\tPLLA Freq: %3.03f MHz",
- _tomhz(pChip->cfg.plla_freq));
- }
-}
-
-static void sam4_explain_mckr(struct sam4_chip *pChip)
-{
- uint32_t css, pres, fin = 0;
- int pdiv = 0;
- const char *cp = NULL;
-
- css = sam4_reg_fieldname(pChip, "CSS", pChip->cfg.PMC_MCKR, 0, 2);
- switch (css & 3) {
- case 0:
- fin = pChip->cfg.slow_freq;
- cp = "slowclk";
- break;
- case 1:
- fin = pChip->cfg.mainosc_freq;
- cp = "mainosc";
- break;
- case 2:
- fin = pChip->cfg.plla_freq;
- cp = "plla";
- break;
- case 3:
- if (pChip->cfg.CKGR_UCKR & (1 << 16)) {
- fin = 480 * 1000 * 1000;
- cp = "upll";
- } else {
- fin = 0;
- cp = "upll (*ERROR* UPLL is disabled)";
- }
- break;
- default:
- assert(0);
- break;
- }
-
- LOG_USER("%s (%3.03f Mhz)",
- cp,
- _tomhz(fin));
- pres = sam4_reg_fieldname(pChip, "PRES", pChip->cfg.PMC_MCKR, 4, 3);
- switch (pres & 0x07) {
- case 0:
- pdiv = 1;
- cp = "selected clock";
- break;
- case 1:
- pdiv = 2;
- cp = "clock/2";
- break;
- case 2:
- pdiv = 4;
- cp = "clock/4";
- break;
- case 3:
- pdiv = 8;
- cp = "clock/8";
- break;
- case 4:
- pdiv = 16;
- cp = "clock/16";
- break;
- case 5:
- pdiv = 32;
- cp = "clock/32";
- break;
- case 6:
- pdiv = 64;
- cp = "clock/64";
- break;
- case 7:
- pdiv = 6;
- cp = "clock/6";
- break;
- default:
- assert(0);
- break;
- }
- LOG_USER("(%s)", cp);
- fin = fin / pdiv;
- /* sam4 has a *SINGLE* clock - */
- /* other at91 series parts have divisors for these. */
- pChip->cfg.cpu_freq = fin;
- pChip->cfg.mclk_freq = fin;
- pChip->cfg.fclk_freq = fin;
- LOG_USER("\t\tResult CPU Freq: %3.03f",
- _tomhz(fin));
-}
-
-#if 0
-static struct sam4_chip *target2sam4(struct target *pTarget)
-{
- struct sam4_chip *pChip;
-
- if (pTarget == NULL)
- return NULL;
-
- pChip = all_sam4_chips;
- while (pChip) {
- if (pChip->target == pTarget)
- break; /* return below */
- else
- pChip = pChip->next;
- }
- return pChip;
-}
-#endif
-
-static uint32_t *sam4_get_reg_ptr(struct sam4_cfg *pCfg, const struct sam4_reg_list *pList)
-{
- /* this function exists to help */
- /* keep funky offsetof() errors */
- /* and casting from causing bugs */
-
- /* By using prototypes - we can detect what would */
- /* be casting errors. */
-
- return (uint32_t *)(void *)(((char *)(pCfg)) + pList->struct_offset);
-}
-
-
-#define SAM4_ENTRY(NAME, FUNC) { .address = SAM4_ ## NAME, .struct_offset = offsetof( \
- struct sam4_cfg, \
- NAME), # NAME, FUNC }
-static const struct sam4_reg_list sam4_all_regs[] = {
- SAM4_ENTRY(CKGR_MOR, sam4_explain_ckgr_mor),
- SAM4_ENTRY(CKGR_MCFR, sam4_explain_ckgr_mcfr),
- SAM4_ENTRY(CKGR_PLLAR, sam4_explain_ckgr_plla),
- SAM4_ENTRY(CKGR_UCKR, NULL),
- SAM4_ENTRY(PMC_FSMR, NULL),
- SAM4_ENTRY(PMC_FSPR, NULL),
- SAM4_ENTRY(PMC_IMR, NULL),
- SAM4_ENTRY(PMC_MCKR, sam4_explain_mckr),
- SAM4_ENTRY(PMC_PCK0, NULL),
- SAM4_ENTRY(PMC_PCK1, NULL),
- SAM4_ENTRY(PMC_PCK2, NULL),
- SAM4_ENTRY(PMC_PCSR, NULL),
- SAM4_ENTRY(PMC_SCSR, NULL),
- SAM4_ENTRY(PMC_SR, NULL),
- SAM4_ENTRY(CHIPID_CIDR, sam4_explain_chipid_cidr),
- SAM4_ENTRY(CHIPID_EXID, NULL),
- /* TERMINATE THE LIST */
- { .name = NULL }
-};
-#undef SAM4_ENTRY
-
-static struct sam4_bank_private *get_sam4_bank_private(struct flash_bank *bank)
-{
- return bank->driver_priv;
-}
-
-/**
- * Given a pointer to where it goes in the structure,
- * determine the register name, address from the all registers table.
- */
-static const struct sam4_reg_list *sam4_GetReg(struct sam4_chip *pChip, uint32_t *goes_here)
-{
- const struct sam4_reg_list *pReg;
-
- pReg = &(sam4_all_regs[0]);
- while (pReg->name) {
- uint32_t *pPossible;
-
- /* calculate where this one go.. */
- /* it is "possibly" this register. */
-
- pPossible = ((uint32_t *)(void *)(((char *)(&(pChip->cfg))) + pReg->struct_offset));
-
- /* well? Is it this register */
- if (pPossible == goes_here) {
- /* Jump for joy! */
- return pReg;
- }
-
- /* next... */
- pReg++;
- }
- /* This is *TOTAL*PANIC* - we are totally screwed. */
- LOG_ERROR("INVALID SAM4 REGISTER");
- return NULL;
-}
-
-static int sam4_ReadThisReg(struct sam4_chip *pChip, uint32_t *goes_here)
-{
- const struct sam4_reg_list *pReg;
- int r;
-
- pReg = sam4_GetReg(pChip, goes_here);
- if (!pReg)
- return ERROR_FAIL;
-
- r = target_read_u32(pChip->target, pReg->address, goes_here);
- if (r != ERROR_OK) {
- LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Err: %d",
- pReg->name, (unsigned)(pReg->address), r);
- }
- return r;
-}
-
-static int sam4_ReadAllRegs(struct sam4_chip *pChip)
-{
- int r;
- const struct sam4_reg_list *pReg;
-
- pReg = &(sam4_all_regs[0]);
- while (pReg->name) {
- r = sam4_ReadThisReg(pChip,
- sam4_get_reg_ptr(&(pChip->cfg), pReg));
- if (r != ERROR_OK) {
- LOG_ERROR("Cannot read SAM4 register: %s @ 0x%08x, Error: %d",
- pReg->name, ((unsigned)(pReg->address)), r);
- return r;
- }
- pReg++;
- }
-
- return ERROR_OK;
-}
-
-static int sam4_GetInfo(struct sam4_chip *pChip)
-{
- const struct sam4_reg_list *pReg;
- uint32_t regval;
-
- pReg = &(sam4_all_regs[0]);
- while (pReg->name) {
- /* display all regs */
- LOG_DEBUG("Start: %s", pReg->name);
- regval = *sam4_get_reg_ptr(&(pChip->cfg), pReg);
- LOG_USER("%*s: [0x%08" PRIx32 "] -> 0x%08" PRIx32,
- REG_NAME_WIDTH,
- pReg->name,
- pReg->address,
- regval);
- if (pReg->explain_func)
- (*(pReg->explain_func))(pChip);
- LOG_DEBUG("End: %s", pReg->name);
- pReg++;
- }
- LOG_USER(" rc-osc: %3.03f MHz", _tomhz(pChip->cfg.rc_freq));
- LOG_USER(" mainosc: %3.03f MHz", _tomhz(pChip->cfg.mainosc_freq));
- LOG_USER(" plla: %3.03f MHz", _tomhz(pChip->cfg.plla_freq));
- LOG_USER(" cpu-freq: %3.03f MHz", _tomhz(pChip->cfg.cpu_freq));
- LOG_USER("mclk-freq: %3.03f MHz", _tomhz(pChip->cfg.mclk_freq));
-
- LOG_USER(" UniqueId: 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08"PRIx32,
- pChip->cfg.unique_id[0],
- pChip->cfg.unique_id[1],
- pChip->cfg.unique_id[2],
- pChip->cfg.unique_id[3]);
-
- return ERROR_OK;
-}
-
-static int sam4_protect_check(struct flash_bank *bank)
-{
- int r;
- uint32_t v[4] = {0};
- unsigned x;
- struct sam4_bank_private *pPrivate;
-
- LOG_DEBUG("Begin");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- pPrivate = get_sam4_bank_private(bank);
- if (!pPrivate) {
- LOG_ERROR("no private for this bank?");
- return ERROR_FAIL;
- }
- if (!(pPrivate->probed))
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- r = FLASHD_GetLockBits(pPrivate, v);
- if (r != ERROR_OK) {
- LOG_DEBUG("Failed: %d", r);
- return r;
- }
-
- for (x = 0; x < pPrivate->nsectors; x++)
- bank->sectors[x].is_protected = (!!(v[x >> 5] & (1 << (x % 32))));
- LOG_DEBUG("Done");
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
-{
- struct sam4_chip *pChip;
-
- pChip = all_sam4_chips;
-
- /* is this an existing chip? */
- while (pChip) {
- if (pChip->target == bank->target)
- break;
- pChip = pChip->next;
- }
-
- if (!pChip) {
- /* this is a *NEW* chip */
- pChip = calloc(1, sizeof(struct sam4_chip));
- if (!pChip) {
- LOG_ERROR("NO RAM!");
- return ERROR_FAIL;
- }
- pChip->target = bank->target;
- /* insert at head */
- pChip->next = all_sam4_chips;
- all_sam4_chips = pChip;
- pChip->target = bank->target;
- /* assumption is this runs at 32khz */
- pChip->cfg.slow_freq = 32768;
- pChip->probed = 0;
- }
-
- switch (bank->base) {
- default:
- LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x"
- "[at91sam4s series] )",
- ((unsigned int)(bank->base)),
- ((unsigned int)(FLASH_BANK_BASE_S)));
- return ERROR_FAIL;
- break;
-
- /* at91sam4s series only has bank 0*/
- /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/
- case FLASH_BANK_BASE_S:
- bank->driver_priv = &(pChip->details.bank[0]);
- bank->bank_number = 0;
- pChip->details.bank[0].pChip = pChip;
- pChip->details.bank[0].pBank = bank;
- break;
-
- /* Bank 1 of at91sam4sd series */
- case FLASH_BANK1_BASE_1024K_SD:
- case FLASH_BANK1_BASE_2048K_SD:
- bank->driver_priv = &(pChip->details.bank[1]);
- bank->bank_number = 1;
- pChip->details.bank[1].pChip = pChip;
- pChip->details.bank[1].pBank = bank;
- break;
- }
-
- /* we initialize after probing. */
- return ERROR_OK;
-}
-
-static int sam4_GetDetails(struct sam4_bank_private *pPrivate)
-{
- const struct sam4_chip_details *pDetails;
- struct sam4_chip *pChip;
- struct flash_bank *saved_banks[SAM4_MAX_FLASH_BANKS];
- unsigned x;
-
- LOG_DEBUG("Begin");
- pDetails = all_sam4_details;
- while (pDetails->name) {
- /* Compare cidr without version bits */
- if (pDetails->chipid_cidr == (pPrivate->pChip->cfg.CHIPID_CIDR & 0xFFFFFFE0))
- break;
- else
- pDetails++;
- }
- if (pDetails->name == NULL) {
- LOG_ERROR("SAM4 ChipID 0x%08x not found in table (perhaps you can ID this chip?)",
- (unsigned int)(pPrivate->pChip->cfg.CHIPID_CIDR));
- /* Help the victim, print details about the chip */
- LOG_INFO("SAM4 CHIPID_CIDR: 0x%08" PRIx32 " decodes as follows",
- pPrivate->pChip->cfg.CHIPID_CIDR);
- sam4_explain_chipid_cidr(pPrivate->pChip);
- return ERROR_FAIL;
- }
-
- /* DANGER: THERE ARE DRAGONS HERE */
-
- /* get our pChip - it is going */
- /* to be over-written shortly */
- pChip = pPrivate->pChip;
-
- /* Note that, in reality: */
- /* */
- /* pPrivate = &(pChip->details.bank[0]) */
- /* or pPrivate = &(pChip->details.bank[1]) */
- /* */
-
- /* save the "bank" pointers */
- for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++)
- saved_banks[x] = pChip->details.bank[x].pBank;
-
- /* Overwrite the "details" structure. */
- memcpy(&(pPrivate->pChip->details),
- pDetails,
- sizeof(pPrivate->pChip->details));
-
- /* now fix the ghosted pointers */
- for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) {
- pChip->details.bank[x].pChip = pChip;
- pChip->details.bank[x].pBank = saved_banks[x];
- }
-
- /* update the *BANK*SIZE* */
-
- LOG_DEBUG("End");
- return ERROR_OK;
-}
-
-static int _sam4_probe(struct flash_bank *bank, int noise)
-{
- unsigned x;
- int r;
- struct sam4_bank_private *pPrivate;
-
-
- LOG_DEBUG("Begin: Bank: %d, Noise: %d", bank->bank_number, noise);
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- pPrivate = get_sam4_bank_private(bank);
- if (!pPrivate) {
- LOG_ERROR("Invalid/unknown bank number");
- return ERROR_FAIL;
- }
-
- r = sam4_ReadAllRegs(pPrivate->pChip);
- if (r != ERROR_OK)
- return r;
-
- LOG_DEBUG("Here");
- if (pPrivate->pChip->probed)
- r = sam4_GetInfo(pPrivate->pChip);
- else
- r = sam4_GetDetails(pPrivate);
- if (r != ERROR_OK)
- return r;
-
- /* update the flash bank size */
- for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) {
- if (bank->base == pPrivate->pChip->details.bank[x].base_address) {
- bank->size = pPrivate->pChip->details.bank[x].size_bytes;
- break;
- }
- }
-
- if (bank->sectors == NULL) {
- bank->sectors = calloc(pPrivate->nsectors, (sizeof((bank->sectors)[0])));
- if (bank->sectors == NULL) {
- LOG_ERROR("No memory!");
- return ERROR_FAIL;
- }
- bank->num_sectors = pPrivate->nsectors;
-
- for (x = 0; ((int)(x)) < bank->num_sectors; x++) {
- bank->sectors[x].size = pPrivate->sector_size;
- bank->sectors[x].offset = x * (pPrivate->sector_size);
- /* mark as unknown */
- bank->sectors[x].is_erased = -1;
- bank->sectors[x].is_protected = -1;
- }
- }
-
- pPrivate->probed = 1;
-
- r = sam4_protect_check(bank);
- if (r != ERROR_OK)
- return r;
-
- LOG_DEBUG("Bank = %d, nbanks = %d",
- pPrivate->bank_number, pPrivate->pChip->details.n_banks);
- if ((pPrivate->bank_number + 1) == pPrivate->pChip->details.n_banks) {
- /* read unique id, */
- /* it appears to be associated with the *last* flash bank. */
- FLASHD_ReadUniqueID(pPrivate);
- }
-
- return r;
-}
-
-static int sam4_probe(struct flash_bank *bank)
-{
- return _sam4_probe(bank, 1);
-}
-
-static int sam4_auto_probe(struct flash_bank *bank)
-{
- return _sam4_probe(bank, 0);
-}
-
-static int sam4_erase(struct flash_bank *bank, int first, int last)
-{
- struct sam4_bank_private *pPrivate;
- int r;
- int i;
- int pageCount;
- /*16 pages equals 8KB - Same size as a lock region*/
- pageCount = 16;
- uint32_t status;
-
- LOG_DEBUG("Here");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- r = sam4_auto_probe(bank);
- if (r != ERROR_OK) {
- LOG_DEBUG("Here,r=%d", r);
- return r;
- }
-
- pPrivate = get_sam4_bank_private(bank);
- if (!(pPrivate->probed))
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if ((first == 0) && ((last + 1) == ((int)(pPrivate->nsectors)))) {
- /* whole chip */
- LOG_DEBUG("Here");
- return FLASHD_EraseEntireBank(pPrivate);
- }
- LOG_INFO("sam4 does not auto-erase while programming (Erasing relevant sectors)");
- LOG_INFO("sam4 First: 0x%08x Last: 0x%08x", (unsigned int)(first), (unsigned int)(last));
- for (i = first; i <= last; i++) {
- /*16 pages equals 8KB - Same size as a lock region*/
- r = FLASHD_ErasePages(pPrivate, (i * pageCount), pageCount, &status);
- LOG_INFO("Erasing sector: 0x%08x", (unsigned int)(i));
- if (r != ERROR_OK)
- LOG_ERROR("SAM4: Error performing Erase page @ lock region number %d",
- (unsigned int)(i));
- if (status & (1 << 2)) {
- LOG_ERROR("SAM4: Lock Region %d is locked", (unsigned int)(i));
- return ERROR_FAIL;
- }
- if (status & (1 << 1)) {
- LOG_ERROR("SAM4: Flash Command error @lock region %d", (unsigned int)(i));
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int sam4_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct sam4_bank_private *pPrivate;
- int r;
-
- LOG_DEBUG("Here");
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- pPrivate = get_sam4_bank_private(bank);
- if (!(pPrivate->probed))
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (set)
- r = FLASHD_Lock(pPrivate, (unsigned)(first), (unsigned)(last));
- else
- r = FLASHD_Unlock(pPrivate, (unsigned)(first), (unsigned)(last));
- LOG_DEBUG("End: r=%d", r);
-
- return r;
-
-}
-
-static int sam4_page_read(struct sam4_bank_private *pPrivate, unsigned pagenum, uint8_t *buf)
-{
- uint32_t adr;
- int r;
-
- adr = pagenum * pPrivate->page_size;
- adr = adr + pPrivate->base_address;
-
- r = target_read_memory(pPrivate->pChip->target,
- adr,
- 4, /* THIS*MUST*BE* in 32bit values */
- pPrivate->page_size / 4,
- buf);
- if (r != ERROR_OK)
- LOG_ERROR("SAM4: Flash program failed to read page phys address: 0x%08x",
- (unsigned int)(adr));
- return r;
-}
-
-static int sam4_page_write(struct sam4_bank_private *pPrivate, unsigned pagenum, const uint8_t *buf)
-{
- uint32_t adr;
- uint32_t status;
- uint32_t fmr; /* EEFC Flash Mode Register */
- int r;
-
- adr = pagenum * pPrivate->page_size;
- adr = (adr + pPrivate->base_address);
-
- /* Get flash mode register value */
- r = target_read_u32(pPrivate->pChip->target, pPrivate->controller_address, &fmr);
- if (r != ERROR_OK)
- LOG_DEBUG("Error Read failed: read flash mode register");
-
- /* Clear flash wait state field */
- fmr &= 0xfffff0ff;
-
- /* set FWS (flash wait states) field in the FMR (flash mode register) */
- fmr |= (pPrivate->flash_wait_states << 8);
-
- LOG_DEBUG("Flash Mode: 0x%08x", ((unsigned int)(fmr)));
- r = target_write_u32(pPrivate->pBank->target, pPrivate->controller_address, fmr);
- if (r != ERROR_OK)
- LOG_DEBUG("Error Write failed: set flash mode register");
-
- /* 1st sector 8kBytes - page 0 - 15*/
- /* 2nd sector 8kBytes - page 16 - 30*/
- /* 3rd sector 48kBytes - page 31 - 127*/
- LOG_DEBUG("Wr Page %u @ phys address: 0x%08x", pagenum, (unsigned int)(adr));
- r = target_write_memory(pPrivate->pChip->target,
- adr,
- 4, /* THIS*MUST*BE* in 32bit values */
- pPrivate->page_size / 4,
- buf);
- if (r != ERROR_OK) {
- LOG_ERROR("SAM4: Failed to write (buffer) page at phys address 0x%08x",
- (unsigned int)(adr));
- return r;
- }
-
- r = EFC_PerformCommand(pPrivate,
- /* send Erase & Write Page */
- AT91C_EFC_FCMD_WP, /*AT91C_EFC_FCMD_EWP only works on first two 8kb sectors*/
- pagenum,
- &status);
-
- if (r != ERROR_OK)
- LOG_ERROR("SAM4: Error performing Write page @ phys address 0x%08x",
- (unsigned int)(adr));
- if (status & (1 << 2)) {
- LOG_ERROR("SAM4: Page @ Phys address 0x%08x is locked", (unsigned int)(adr));
- return ERROR_FAIL;
- }
- if (status & (1 << 1)) {
- LOG_ERROR("SAM4: Flash Command error @phys address 0x%08x", (unsigned int)(adr));
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int sam4_write(struct flash_bank *bank,
- const uint8_t *buffer,
- uint32_t offset,
- uint32_t count)
-{
- int n;
- unsigned page_cur;
- unsigned page_end;
- int r;
- unsigned page_offset;
- struct sam4_bank_private *pPrivate;
- uint8_t *pagebuffer;
-
- /* incase we bail further below, set this to null */
- pagebuffer = NULL;
-
- /* ignore dumb requests */
- if (count == 0) {
- r = ERROR_OK;
- goto done;
- }
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- r = ERROR_TARGET_NOT_HALTED;
- goto done;
- }
-
- pPrivate = get_sam4_bank_private(bank);
- if (!(pPrivate->probed)) {
- r = ERROR_FLASH_BANK_NOT_PROBED;
- goto done;
- }
-
- if ((offset + count) > pPrivate->size_bytes) {
- LOG_ERROR("Flash write error - past end of bank");
- LOG_ERROR(" offset: 0x%08x, count 0x%08x, BankEnd: 0x%08x",
- (unsigned int)(offset),
- (unsigned int)(count),
- (unsigned int)(pPrivate->size_bytes));
- r = ERROR_FAIL;
- goto done;
- }
-
- pagebuffer = malloc(pPrivate->page_size);
- if (!pagebuffer) {
- LOG_ERROR("No memory for %d Byte page buffer", (int)(pPrivate->page_size));
- r = ERROR_FAIL;
- goto done;
- }
-
- /* what page do we start & end in? */
- page_cur = offset / pPrivate->page_size;
- page_end = (offset + count - 1) / pPrivate->page_size;
-
- LOG_DEBUG("Offset: 0x%08x, Count: 0x%08x", (unsigned int)(offset), (unsigned int)(count));
- LOG_DEBUG("Page start: %d, Page End: %d", (int)(page_cur), (int)(page_end));
-
- /* Special case: all one page */
- /* */
- /* Otherwise: */
- /* (1) non-aligned start */
- /* (2) body pages */
- /* (3) non-aligned end. */
-
- /* Handle special case - all one page. */
- if (page_cur == page_end) {
- LOG_DEBUG("Special case, all in one page");
- r = sam4_page_read(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
-
- page_offset = (offset & (pPrivate->page_size-1));
- memcpy(pagebuffer + page_offset,
- buffer,
- count);
-
- r = sam4_page_write(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
- r = ERROR_OK;
- goto done;
- }
-
- /* non-aligned start */
- page_offset = offset & (pPrivate->page_size - 1);
- if (page_offset) {
- LOG_DEBUG("Not-Aligned start");
- /* read the partial */
- r = sam4_page_read(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
-
- /* over-write with new data */
- n = (pPrivate->page_size - page_offset);
- memcpy(pagebuffer + page_offset,
- buffer,
- n);
-
- r = sam4_page_write(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
-
- count -= n;
- offset += n;
- buffer += n;
- page_cur++;
- }
-
- /* By checking that offset is correct here, we also
- fix a clang warning */
- assert(offset % pPrivate->page_size == 0);
-
- /* intermediate large pages */
- /* also - the final *terminal* */
- /* if that terminal page is a full page */
- LOG_DEBUG("Full Page Loop: cur=%d, end=%d, count = 0x%08x",
- (int)page_cur, (int)page_end, (unsigned int)(count));
-
- while ((page_cur < page_end) &&
- (count >= pPrivate->page_size)) {
- r = sam4_page_write(pPrivate, page_cur, buffer);
- if (r != ERROR_OK)
- goto done;
- count -= pPrivate->page_size;
- buffer += pPrivate->page_size;
- page_cur += 1;
- }
-
- /* terminal partial page? */
- if (count) {
- LOG_DEBUG("Terminal partial page, count = 0x%08x", (unsigned int)(count));
- /* we have a partial page */
- r = sam4_page_read(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
- /* data goes at start */
- memcpy(pagebuffer, buffer, count);
- r = sam4_page_write(pPrivate, page_cur, pagebuffer);
- if (r != ERROR_OK)
- goto done;
- }
- LOG_DEBUG("Done!");
- r = ERROR_OK;
-done:
- if (pagebuffer)
- free(pagebuffer);
- return r;
-}
-
-COMMAND_HANDLER(sam4_handle_info_command)
-{
- struct sam4_chip *pChip;
- pChip = get_current_sam4(CMD_CTX);
- if (!pChip)
- return ERROR_OK;
-
- unsigned x;
- int r;
-
- /* bank0 must exist before we can do anything */
- if (pChip->details.bank[0].pBank == NULL) {
- x = 0;
-need_define:
- command_print(CMD_CTX,
- "Please define bank %d via command: flash bank %s ... ",
- x,
- at91sam4_flash.name);
- return ERROR_FAIL;
- }
-
- /* if bank 0 is not probed, then probe it */
- if (!(pChip->details.bank[0].probed)) {
- r = sam4_auto_probe(pChip->details.bank[0].pBank);
- if (r != ERROR_OK)
- return ERROR_FAIL;
- }
- /* above guarantees the "chip details" structure is valid */
- /* and thus, bank private areas are valid */
- /* and we have a SAM4 chip, what a concept! */
-
- /* auto-probe other banks, 0 done above */
- for (x = 1; x < SAM4_MAX_FLASH_BANKS; x++) {
- /* skip banks not present */
- if (!(pChip->details.bank[x].present))
- continue;
-
- if (pChip->details.bank[x].pBank == NULL)
- goto need_define;
-
- if (pChip->details.bank[x].probed)
- continue;
-
- r = sam4_auto_probe(pChip->details.bank[x].pBank);
- if (r != ERROR_OK)
- return r;
- }
-
- r = sam4_GetInfo(pChip);
- if (r != ERROR_OK) {
- LOG_DEBUG("Sam4Info, Failed %d", r);
- return r;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sam4_handle_gpnvm_command)
-{
- unsigned x, v;
- int r, who;
- struct sam4_chip *pChip;
-
- pChip = get_current_sam4(CMD_CTX);
- if (!pChip)
- return ERROR_OK;
-
- if (pChip->target->state != TARGET_HALTED) {
- LOG_ERROR("sam4 - target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (pChip->details.bank[0].pBank == NULL) {
- command_print(CMD_CTX, "Bank0 must be defined first via: flash bank %s ...",
- at91sam4_flash.name);
- return ERROR_FAIL;
- }
- if (!pChip->details.bank[0].probed) {
- r = sam4_auto_probe(pChip->details.bank[0].pBank);
- if (r != ERROR_OK)
- return r;
- }
-
- switch (CMD_ARGC) {
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- case 0:
- goto showall;
- break;
- case 1:
- who = -1;
- break;
- case 2:
- if ((0 == strcmp(CMD_ARGV[0], "show")) && (0 == strcmp(CMD_ARGV[1], "all")))
- who = -1;
- else {
- uint32_t v32;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
- who = v32;
- }
- break;
- }
-
- if (0 == strcmp("show", CMD_ARGV[0])) {
- if (who == -1) {
-showall:
- r = ERROR_OK;
- for (x = 0; x < pChip->details.n_gpnvms; x++) {
- r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v);
- if (r != ERROR_OK)
- break;
- command_print(CMD_CTX, "sam4-gpnvm%u: %u", x, v);
- }
- return r;
- }
- if ((who >= 0) && (((unsigned)(who)) < pChip->details.n_gpnvms)) {
- r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), who, &v);
- command_print(CMD_CTX, "sam4-gpnvm%u: %u", who, v);
- return r;
- } else {
- command_print(CMD_CTX, "sam4-gpnvm invalid GPNVM: %u", who);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- if (who == -1) {
- command_print(CMD_CTX, "Missing GPNVM number");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (0 == strcmp("set", CMD_ARGV[0]))
- r = FLASHD_SetGPNVM(&(pChip->details.bank[0]), who);
- else if ((0 == strcmp("clr", CMD_ARGV[0])) ||
- (0 == strcmp("clear", CMD_ARGV[0]))) /* quietly accept both */
- r = FLASHD_ClrGPNVM(&(pChip->details.bank[0]), who);
- else {
- command_print(CMD_CTX, "Unknown command: %s", CMD_ARGV[0]);
- r = ERROR_COMMAND_SYNTAX_ERROR;
- }
- return r;
-}
-
-COMMAND_HANDLER(sam4_handle_slowclk_command)
-{
- struct sam4_chip *pChip;
-
- pChip = get_current_sam4(CMD_CTX);
- if (!pChip)
- return ERROR_OK;
-
- switch (CMD_ARGC) {
- case 0:
- /* show */
- break;
- case 1:
- {
- /* set */
- uint32_t v;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], v);
- if (v > 200000) {
- /* absurd slow clock of 200Khz? */
- command_print(CMD_CTX, "Absurd/illegal slow clock freq: %d\n", (int)(v));
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- pChip->cfg.slow_freq = v;
- break;
- }
- default:
- /* error */
- command_print(CMD_CTX, "Too many parameters");
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- }
- command_print(CMD_CTX, "Slowclk freq: %d.%03dkhz",
- (int)(pChip->cfg.slow_freq / 1000),
- (int)(pChip->cfg.slow_freq % 1000));
- return ERROR_OK;
-}
-
-static const struct command_registration at91sam4_exec_command_handlers[] = {
- {
- .name = "gpnvm",
- .handler = sam4_handle_gpnvm_command,
- .mode = COMMAND_EXEC,
- .usage = "[('clr'|'set'|'show') bitnum]",
- .help = "Without arguments, shows all bits in the gpnvm "
- "register. Otherwise, clears, sets, or shows one "
- "General Purpose Non-Volatile Memory (gpnvm) bit.",
- },
- {
- .name = "info",
- .handler = sam4_handle_info_command,
- .mode = COMMAND_EXEC,
- .help = "Print information about the current at91sam4 chip"
- "and its flash configuration.",
- },
- {
- .name = "slowclk",
- .handler = sam4_handle_slowclk_command,
- .mode = COMMAND_EXEC,
- .usage = "[clock_hz]",
- .help = "Display or set the slowclock frequency "
- "(default 32768 Hz).",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration at91sam4_command_handlers[] = {
- {
- .name = "at91sam4",
- .mode = COMMAND_ANY,
- .help = "at91sam4 flash command group",
- .usage = "",
- .chain = at91sam4_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver at91sam4_flash = {
- .name = "at91sam4",
- .commands = at91sam4_command_handlers,
- .flash_bank_command = sam4_flash_bank_command,
- .erase = sam4_erase,
- .protect = sam4_protect,
- .write = sam4_write,
- .read = default_flash_read,
- .probe = sam4_probe,
- .auto_probe = sam4_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = sam4_protect_check,
-};
diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c
deleted file mode 100644
index 4710512..0000000
--- a/src/flash/nor/at91sam4l.c
+++ /dev/null
@@ -1,707 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andrey Yurovsky *
- * Andrey Yurovsky <yurovsky@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-
-#include <target/cortex_m.h>
-
-/* At this time, the SAM4L Flash is available in these capacities:
- * ATSAM4Lx4xx: 256KB (512 pages)
- * ATSAM4Lx2xx: 128KB (256 pages)
- * ATSAM4Lx8xx: 512KB (1024 pages)
- */
-
-/* There are 16 lockable regions regardless of overall capacity. The number
- * of pages per sector is therefore dependant on capacity. */
-#define SAM4L_NUM_SECTORS 16
-
-/* Locations in memory map */
-#define SAM4L_FLASH ((uint32_t)0x00000000) /* Flash region */
-#define SAM4L_FLASH_USER 0x00800000 /* Flash user page region */
-#define SAM4L_FLASHCALW 0x400A0000 /* Flash controller */
-#define SAM4L_CHIPID 0x400E0740 /* Chip Identification */
-
-/* Offsets from SAM4L_FLASHCALW */
-#define SAM4L_FCR 0x00 /* Flash Control Register (RW) */
-#define SAM4L_FCMD 0x04 /* Flash Command Register (RW) */
-#define SAM4L_FSR 0x08 /* Flash Status Register (RO) */
-#define SAM4L_FPR 0x0C /* Flash Parameter Register (RO) */
-#define SAM4L_FVR 0x10 /* Flash Version Register (RO) */
-#define SAM4L_FGPFRHI 0x14 /* Flash General Purpose Register High (RO) */
-#define SAM4L_FGPFRLO 0x18 /* Flash General Purpose Register Low (RO) */
-
-/* Offsets from SAM4L_CHIPID */
-#define SAM4L_CIDR 0x00 /* Chip ID Register (RO) */
-#define SAM4L_EXID 0x04 /* Chip ID Extension Register (RO) */
-
-/* Flash commands (for SAM4L_FCMD), see Table 14-5 */
-#define SAM4L_FCMD_NOP 0 /* No Operation */
-#define SAM4L_FCMD_WP 1 /* Write Page */
-#define SAM4L_FCMD_EP 2 /* Erase Page */
-#define SAM4L_FCMD_CPB 3 /* Clear Page Buffer */
-#define SAM4L_FCMD_LP 4 /* Lock region containing given page */
-#define SAM4L_FCMD_UP 5 /* Unlock region containing given page */
-#define SAM4L_FCMD_EA 6 /* Erase All */
-#define SAM4L_FCMD_WGPB 7 /* Write general-purpose fuse bit */
-#define SAM4L_FCMD_EGPB 8 /* Erase general-purpose fuse bit */
-#define SAM4L_FCMD_SSB 9 /* Set security fuses */
-#define SAM4L_FCMD_PGPFB 10 /* Program general-purpose fuse byte */
-#define SAM4L_FCMD_EAGPF 11 /* Erase all general-purpose fuse bits */
-#define SAM4L_FCMD_QPR 12 /* Quick page read */
-#define SAM4L_FCMD_WUP 13 /* Write user page */
-#define SAM4L_FCMD_EUP 14 /* Erase user page */
-#define SAM4L_FCMD_QPRUP 15 /* Quick page read (user page) */
-#define SAM4L_FCMD_HSEN 16 /* High speed mode enable */
-#define SAM4L_FCMD_HSDIS 17 /* High speed mode disable */
-
-#define SAM4L_FMCD_CMDKEY 0xA5UL /* 'key' to issue commands, see 14.10.2 */
-
-
-/* SMAP registers and bits */
-#define SMAP_BASE 0x400A3000
-
-#define SMAP_SCR (SMAP_BASE + 8)
-#define SMAP_SCR_HCR (1 << 1)
-
-
-struct sam4l_chip_info {
- uint32_t id;
- uint32_t exid;
- const char *name;
-};
-
-/* These are taken from Table 9-1 in 42023E-SAM-07/2013 */
-static const struct sam4l_chip_info sam4l_known_chips[] = {
- { 0xAB0B0AE0, 0x1400000F, "ATSAM4LC8C" },
- { 0xAB0A09E0, 0x0400000F, "ATSAM4LC4C" },
- { 0xAB0A07E0, 0x0400000F, "ATSAM4LC2C" },
- { 0xAB0B0AE0, 0x1300000F, "ATSAM4LC8B" },
- { 0xAB0A09E0, 0x0300000F, "ATSAM4LC4B" },
- { 0xAB0A07E0, 0x0300000F, "ATSAM4LC2B" },
- { 0xAB0B0AE0, 0x1200000F, "ATSAM4LC8A" },
- { 0xAB0A09E0, 0x0200000F, "ATSAM4LC4A" },
- { 0xAB0A07E0, 0x0200000F, "ATSAM4LC2A" },
- { 0xAB0B0AE0, 0x14000002, "ATSAM4LS8C" },
- { 0xAB0A09E0, 0x04000002, "ATSAM4LS4C" },
- { 0xAB0A07E0, 0x04000002, "ATSAM4LS2C" },
- { 0xAB0B0AE0, 0x13000002, "ATSAM4LS8B" },
- { 0xAB0A09E0, 0x03000002, "ATSAM4LS4B" },
- { 0xAB0A07E0, 0x03000002, "ATSAM4LS2B" },
- { 0xAB0B0AE0, 0x12000002, "ATSAM4LS8A" },
- { 0xAB0A09E0, 0x02000002, "ATSAM4LS4A" },
- { 0xAB0A07E0, 0x02000002, "ATSAM4LS2A" },
-};
-
-/* Meaning of SRAMSIZ field in CHIPID, see 9.3.1 in 42023E-SAM-07/2013 */
-static const uint16_t sam4l_ram_sizes[16] = { 48, 1, 2, 6, 24, 4, 80, 160, 8, 16, 32, 64, 128, 256, 96, 512 };
-
-/* Meaning of PSZ field in FPR, see 14.10.4 in 42023E-SAM-07/2013 */
-static const uint16_t sam4l_page_sizes[8] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };
-
-struct sam4l_info {
- const struct sam4l_chip_info *details;
-
- uint32_t flash_kb;
- uint32_t ram_kb;
- uint32_t page_size;
- int num_pages;
- int sector_size;
- int pages_per_sector;
-
- bool probed;
- struct target *target;
- struct sam4l_info *next;
-};
-
-static struct sam4l_info *sam4l_chips;
-
-static int sam4l_flash_wait_until_ready(struct target *target)
-{
- volatile unsigned int t = 0;
- uint32_t st;
- int res;
-
- /* Poll the status register until the FRDY bit is set */
- do {
- res = target_read_u32(target, SAM4L_FLASHCALW + SAM4L_FSR, &st);
- } while (res == ERROR_OK && !(st & (1<<0)) && ++t < 10);
-
- return res;
-}
-
-static int sam4l_flash_check_error(struct target *target, uint32_t *err)
-{
- uint32_t st;
- int res;
-
- res = target_read_u32(target, SAM4L_FLASHCALW + SAM4L_FSR, &st);
-
- if (res == ERROR_OK)
- *err = st & ((1<<3) | (1<<2)); /* grab PROGE and LOCKE bits */
-
- return res;
-}
-
-static int sam4l_flash_command(struct target *target, uint8_t cmd, int page)
-{
- int res;
- uint32_t fcmd;
- uint32_t err;
-
- res = sam4l_flash_wait_until_ready(target);
- if (res != ERROR_OK)
- return res;
-
- if (page >= 0) {
- /* Set the page number. For some commands, the page number is just an
- * argument (ex: fuse bit number). */
- fcmd = (SAM4L_FMCD_CMDKEY << 24) | ((page & 0xFFFF) << 8) | (cmd & 0x3F);
- } else {
- /* Reuse the page number that was read from the flash command register. */
- res = target_read_u32(target, SAM4L_FLASHCALW + SAM4L_FCMD, &fcmd);
- if (res != ERROR_OK)
- return res;
-
- fcmd &= ~0x3F; /* clear out the command code */
- fcmd |= (SAM4L_FMCD_CMDKEY << 24) | (cmd & 0x3F);
- }
-
- /* Send the command */
- res = target_write_u32(target, SAM4L_FLASHCALW + SAM4L_FCMD, fcmd);
- if (res != ERROR_OK)
- return res;
-
- res = sam4l_flash_check_error(target, &err);
- if (res != ERROR_OK)
- return res;
-
- if (err != 0)
- LOG_ERROR("%s got error status 0x%08" PRIx32, __func__, err);
-
- res = sam4l_flash_wait_until_ready(target);
-
- return res;
-}
-
-FLASH_BANK_COMMAND_HANDLER(sam4l_flash_bank_command)
-{
- struct sam4l_info *chip = sam4l_chips;
-
- while (chip) {
- if (chip->target == bank->target)
- break;
- chip = chip->next;
- }
-
- if (!chip) {
- /* Create a new chip */
- chip = calloc(1, sizeof(*chip));
- if (!chip)
- return ERROR_FAIL;
-
- chip->target = bank->target;
- chip->probed = false;
-
- bank->driver_priv = chip;
-
- /* Insert it into the chips list (at head) */
- chip->next = sam4l_chips;
- sam4l_chips = chip;
- }
-
- if (bank->base != SAM4L_FLASH) {
- LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32
- "[at91sam4l series] )",
- bank->base, SAM4L_FLASH);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static const struct sam4l_chip_info *sam4l_find_chip_name(uint32_t id, uint32_t exid)
-{
- unsigned int i;
-
- id &= ~0xF;
-
- for (i = 0; i < ARRAY_SIZE(sam4l_known_chips); i++) {
- if (sam4l_known_chips[i].id == id && sam4l_known_chips[i].exid == exid)
- return &sam4l_known_chips[i];
- }
-
- return NULL;
-}
-
-static int sam4l_check_page_erased(struct flash_bank *bank, uint32_t pn,
- bool *is_erased_p)
-{
- int res;
- uint32_t st;
-
- /* Issue a quick page read to verify that we've erased this page */
- res = sam4l_flash_command(bank->target, SAM4L_FCMD_QPR, pn);
- if (res != ERROR_OK) {
- LOG_ERROR("Quick page read %" PRIu32 " failed", pn);
- return res;
- }
-
- /* Retrieve the flash status */
- res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FSR, &st);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read erase status");
- return res;
- }
-
- /* Is the page in question really erased? */
- *is_erased_p = !!(st & (1<<5));
-
- return ERROR_OK;
-}
-
-static int sam4l_probe(struct flash_bank *bank)
-{
- uint32_t id, exid, param;
- int res;
- struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv;
-
- if (chip->probed)
- return ERROR_OK;
-
- res = target_read_u32(bank->target, SAM4L_CHIPID + SAM4L_CIDR, &id);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read chip ID");
- return res;
- }
-
- res = target_read_u32(bank->target, SAM4L_CHIPID + SAM4L_EXID, &exid);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read extended chip ID");
- return res;
- }
-
- chip->details = sam4l_find_chip_name(id, exid);
-
- /* The RAM capacity is in a lookup table. */
- chip->ram_kb = sam4l_ram_sizes[0xF & (id >> 16)];
-
- switch (0xF & (id >> 8)) {
- case 0x07:
- chip->flash_kb = 128;
- break;
- case 0x09:
- chip->flash_kb = 256;
- break;
- case 0x0A:
- chip->flash_kb = 512;
- break;
- default:
- LOG_ERROR("Unknown flash size (chip ID is %08" PRIx32 "), assuming 128K", id);
- chip->flash_kb = 128;
- break;
- }
-
- /* Retrieve the Flash parameters */
- res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FPR, &param);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read Flash parameters");
- return res;
- }
-
- /* Fetch the page size from the parameter register. Technically the flash
- * capacity is there too though the manual mentions that not all parts will
- * have it set so we use the Chip ID capacity information instead. */
- chip->page_size = sam4l_page_sizes[0x7 & (param >> 8)];
- assert(chip->page_size);
- chip->num_pages = chip->flash_kb * 1024 / chip->page_size;
-
- chip->sector_size = (chip->flash_kb * 1024) / SAM4L_NUM_SECTORS;
- chip->pages_per_sector = chip->sector_size / chip->page_size;
-
- /* Make sure the bank size is correct */
- bank->size = chip->flash_kb * 1024;
-
- /* Allocate the sector table. */
- bank->num_sectors = SAM4L_NUM_SECTORS;
- bank->sectors = calloc(bank->num_sectors, (sizeof((bank->sectors)[0])));
- if (!bank->sectors)
- return ERROR_FAIL;
-
- /* Fill out the sector information: all SAM4L sectors are the same size and
- * there is always a fixed number of them. */
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].size = chip->sector_size;
- bank->sectors[i].offset = i * chip->sector_size;
- /* mark as unknown */
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- /* Done */
- chip->probed = true;
-
- LOG_INFO("SAM4L MCU: %s (Rev %c) (%" PRIu32 "KB Flash with %d %" PRId32 "B pages, %" PRIu32 "KB RAM)",
- chip->details ? chip->details->name : "unknown", (char)('A' + (id & 0xF)),
- chip->flash_kb, chip->num_pages, chip->page_size, chip->ram_kb);
-
- return ERROR_OK;
-}
-
-static int sam4l_protect_check(struct flash_bank *bank)
-{
- int res;
- uint32_t st;
- struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
-
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!chip->probed) {
- if (sam4l_probe(bank) != ERROR_OK)
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FSR, &st);
- if (res != ERROR_OK)
- return res;
-
- st >>= 16; /* There are 16 lock region bits in the upper half word */
- for (int i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_protected = !!(st & (1<<i));
-
- return ERROR_OK;
-}
-
-static int sam4l_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct sam4l_info *chip = sam4l_chips;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
-
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!chip->probed) {
- if (sam4l_probe(bank) != ERROR_OK)
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /* Make sure the pages make sense. */
- if (first >= bank->num_sectors || last >= bank->num_sectors) {
- LOG_ERROR("Protect range %d - %d not valid (%d sectors total)", first, last,
- bank->num_sectors);
- return ERROR_FAIL;
- }
-
- /* Try to lock or unlock each sector in the range. This is done by locking
- * a region containing one page in that sector, we arbitrarily choose the 0th
- * page in the sector. */
- for (int i = first; i <= last; i++) {
- int res;
-
- res = sam4l_flash_command(bank->target,
- set ? SAM4L_FCMD_LP : SAM4L_FCMD_UP, i * chip->pages_per_sector);
- if (res != ERROR_OK) {
- LOG_ERROR("Can't %slock region containing page %d", set ? "" : "un", i);
- return res;
- }
- }
-
- return ERROR_OK;
-}
-
-static int sam4l_erase(struct flash_bank *bank, int first, int last)
-{
- int ret;
- struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
-
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!chip->probed) {
- if (sam4l_probe(bank) != ERROR_OK)
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /* Make sure the pages make sense. */
- if (first >= bank->num_sectors || last >= bank->num_sectors) {
- LOG_ERROR("Erase range %d - %d not valid (%d sectors total)", first, last,
- bank->num_sectors);
- return ERROR_FAIL;
- }
-
- /* Erase */
- if ((first == 0) && ((last + 1) == bank->num_sectors)) {
- LOG_DEBUG("Erasing the whole chip");
-
- ret = sam4l_flash_command(bank->target, SAM4L_FCMD_EA, -1);
- if (ret != ERROR_OK) {
- LOG_ERROR("Erase All failed");
- return ret;
- }
- } else {
- LOG_DEBUG("Erasing sectors %d through %d...\n", first, last);
-
- /* For each sector... */
- for (int i = first; i <= last; i++) {
- /* For each page in that sector... */
- for (int j = 0; j < chip->pages_per_sector; j++) {
- int pn = i * chip->pages_per_sector + j;
- bool is_erased = false;
-
- /* Issue the page erase */
- ret = sam4l_flash_command(bank->target, SAM4L_FCMD_EP, pn);
- if (ret != ERROR_OK) {
- LOG_ERROR("Erasing page %d failed", pn);
- return ret;
- }
-
- ret = sam4l_check_page_erased(bank, pn, &is_erased);
- if (ret != ERROR_OK)
- return ret;
-
- if (!is_erased) {
- LOG_DEBUG("Page %d was not erased.", pn);
- return ERROR_FAIL;
- }
- }
-
- /* This sector is definitely erased. */
- bank->sectors[i].is_erased = 1;
- }
- }
-
- return ERROR_OK;
-}
-
-/* Write an entire page from host buffer 'buf' to page-aligned 'address' in the
- * Flash. */
-static int sam4l_write_page(struct sam4l_info *chip, struct target *target,
- uint32_t address, const uint8_t *buf)
-{
- int res;
-
- LOG_DEBUG("sam4l_write_page address=%08" PRIx32, address);
-
- /* Clear the page buffer before we write to it */
- res = sam4l_flash_command(target, SAM4L_FCMD_CPB, -1);
- if (res != ERROR_OK) {
- LOG_ERROR("%s: can't clear page buffer", __func__);
- return res;
- }
-
- /* Write the modified page back to the target's page buffer */
- res = target_write_memory(target, address, 4, chip->page_size / 4, buf);
-
- if (res != ERROR_OK) {
- LOG_ERROR("%s: %d", __func__, __LINE__);
- return res;
- }
-
- /* Commit the page contents to Flash: erase the current page and then
- * write it out. */
- res = sam4l_flash_command(target, SAM4L_FCMD_EP, -1);
- if (res != ERROR_OK)
- return res;
- res = sam4l_flash_command(target, SAM4L_FCMD_WP, -1);
-
- return res;
-}
-
-/* Write partial contents into page-aligned 'address' on the Flash from host
- * buffer 'buf' by writing 'nb' of 'buf' at 'offset' into the Flash page. */
-static int sam4l_write_page_partial(struct sam4l_info *chip,
- struct flash_bank *bank, uint32_t address, const uint8_t *buf,
- uint32_t page_offset, uint32_t nb)
-{
- int res;
- uint8_t *pg = malloc(chip->page_size);
- if (!pg)
- return ERROR_FAIL;
-
- LOG_DEBUG("sam4l_write_page_partial address=%08" PRIx32 " nb=%08" PRIx32, address, nb);
-
- assert(page_offset + nb < chip->page_size);
- assert((address % chip->page_size) == 0);
-
- /* Retrieve the full page contents from Flash */
- res = target_read_memory(bank->target, address, 4,
- chip->page_size / 4, pg);
- if (res != ERROR_OK) {
- free(pg);
- return res;
- }
-
- /* Insert our partial page over the data from Flash */
- memcpy(pg + (page_offset % chip->page_size), buf, nb);
-
- /* Write the page back out */
- res = sam4l_write_page(chip, bank->target, address, pg);
- free(pg);
-
- return res;
-}
-
-static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- int res;
- uint32_t nb = 0;
- struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv;
-
- LOG_DEBUG("sam4l_write offset=%08" PRIx32 " count=%08" PRIx32, offset, count);
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
-
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!chip->probed) {
- if (sam4l_probe(bank) != ERROR_OK)
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- if (offset % chip->page_size) {
- /* We're starting at an unaligned offset so we'll write a partial page
- * comprising that offset and up to the end of that page. */
- nb = chip->page_size - (offset % chip->page_size);
- if (nb > count)
- nb = count;
- } else if (count < chip->page_size) {
- /* We're writing an aligned but partial page. */
- nb = count;
- }
-
- if (nb > 0) {
- res = sam4l_write_page_partial(chip, bank,
- (offset / chip->page_size) * chip->page_size + bank->base,
- buffer,
- offset % chip->page_size, nb);
- if (res != ERROR_OK)
- return res;
-
- /* We're done with the page contents */
- count -= nb;
- offset += nb;
- }
-
- /* There's at least one aligned page to write out. */
- if (count >= chip->page_size) {
- int np = count / chip->page_size + ((count % chip->page_size) ? 1 : 0);
-
- for (int i = 0; i < np; i++) {
- if (count >= chip->page_size) {
- res = sam4l_write_page(chip, bank->target,
- bank->base + offset,
- buffer + (i * chip->page_size));
- /* Advance one page */
- offset += chip->page_size;
- count -= chip->page_size;
- } else {
- res = sam4l_write_page_partial(chip, bank,
- bank->base + offset,
- buffer + (i * chip->page_size), 0, count);
- /* We're done after this. */
- offset += count;
- count = 0;
- }
-
- if (res != ERROR_OK)
- return res;
- }
- }
-
- return ERROR_OK;
-}
-
-
-COMMAND_HANDLER(sam4l_handle_reset_deassert)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- int retval = ERROR_OK;
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
- * so we just release reset held by SMAP
- *
- * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
- *
- * After vectreset SMAP release is not needed however makes no harm
- */
- if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
- if (retval == ERROR_OK)
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR,
- TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
- /* do not return on error here, releasing SMAP reset is more important */
- }
-
- int retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, SMAP_SCR, SMAP_SCR_HCR);
- if (retval2 != ERROR_OK)
- return retval2;
-
- return retval;
-}
-
-static const struct command_registration at91sam4l_exec_command_handlers[] = {
- {
- .name = "smap_reset_deassert",
- .handler = sam4l_handle_reset_deassert,
- .mode = COMMAND_EXEC,
- .help = "deasert internal reset held by SMAP"
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration at91sam4l_command_handlers[] = {
- {
- .name = "at91sam4l",
- .mode = COMMAND_ANY,
- .help = "at91sam4l flash command group",
- .usage = "",
- .chain = at91sam4l_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver at91sam4l_flash = {
- .name = "at91sam4l",
- .commands = at91sam4l_command_handlers,
- .flash_bank_command = sam4l_flash_bank_command,
- .erase = sam4l_erase,
- .protect = sam4l_protect,
- .write = sam4l_write,
- .read = default_flash_read,
- .probe = sam4l_probe,
- .auto_probe = sam4l_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = sam4l_protect_check,
-};
diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c
deleted file mode 100644
index ccb1a74..0000000
--- a/src/flash/nor/at91sam7.c
+++ /dev/null
@@ -1,1203 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Gheorghe Guran (atlas) *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
-****************************************************************************/
-
-/***************************************************************************
-*
-* New flash setup command:
-*
-* flash bank <driver> <base_addr> <size> <chip_width> <bus_width> <target_id>
-* [<chip_type> <banks>
-* <sectors_per_bank> <pages_per_sector>
-* <page_size> <num_nvmbits>
-* <ext_freq_khz>]
-*
-* <ext_freq_khz> - MUST be used if clock is from external source,
-* CAN be used if main oscillator frequency is known (recommended)
-* Examples:
-* ==== RECOMMENDED (covers clock speed) ============
-* flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 25000
-* (if auto-detect fails; provides clock spec)
-* flash bank at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 25000
-* (auto-detect everything except the clock)
-* ==== NOT RECOMMENDED !!! (clock speed is not configured) ====
-* flash bank at91sam7 0x00100000 0 0 4 $_TARGETNAME AT91SAM7XC256 1 16 64 256 3 0
-* (if auto-detect fails)
-* flash bank at91sam7 0 0 0 0 $_TARGETNAME
-* (old style, auto-detect everything)
-****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-
-/* AT91SAM7 control registers */
-#define DBGU_CIDR 0xFFFFF240
-#define CKGR_MCFR 0xFFFFFC24
-#define CKGR_MOR 0xFFFFFC20
-#define CKGR_MCFR_MAINRDY 0x10000
-#define CKGR_PLLR 0xFFFFFC2c
-#define CKGR_PLLR_DIV 0xff
-#define CKGR_PLLR_MUL 0x07ff0000
-#define PMC_MCKR 0xFFFFFC30
-#define PMC_MCKR_CSS 0x03
-#define PMC_MCKR_PRES 0x1c
-
-/* Flash Controller Commands */
-#define WP 0x01
-#define SLB 0x02
-#define WPL 0x03
-#define CLB 0x04
-#define EA 0x08
-#define SGPB 0x0B
-#define CGPB 0x0D
-#define SSB 0x0F
-
-/* MC_FSR bit definitions */
-#define MC_FSR_FRDY 1
-#define MC_FSR_EOL 2
-
-/* AT91SAM7 constants */
-#define RC_FREQ 32000
-
-/* Flash timing modes */
-#define FMR_TIMING_NONE 0
-#define FMR_TIMING_NVBITS 1
-#define FMR_TIMING_FLASH 2
-
-/* Flash size constants */
-#define FLASH_SIZE_8KB 1
-#define FLASH_SIZE_16KB 2
-#define FLASH_SIZE_32KB 3
-#define FLASH_SIZE_64KB 5
-#define FLASH_SIZE_128KB 7
-#define FLASH_SIZE_256KB 9
-#define FLASH_SIZE_512KB 10
-#define FLASH_SIZE_1024KB 12
-#define FLASH_SIZE_2048KB 14
-
-static int at91sam7_protect_check(struct flash_bank *bank);
-static int at91sam7_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset,
- uint32_t count);
-
-static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number);
-static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode);
-static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout);
-static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t pagen);
-
-static const uint32_t MC_FMR[4] = { 0xFFFFFF60, 0xFFFFFF70, 0xFFFFFF80, 0xFFFFFF90 };
-static const uint32_t MC_FCR[4] = { 0xFFFFFF64, 0xFFFFFF74, 0xFFFFFF84, 0xFFFFFF94 };
-static const uint32_t MC_FSR[4] = { 0xFFFFFF68, 0xFFFFFF78, 0xFFFFFF88, 0xFFFFFF98 };
-
-static const char *EPROC[8] = {
- "Unknown", "ARM946-E", "ARM7TDMI", "Unknown", "ARM920T", "ARM926EJ-S", "Unknown", "Unknown"
-};
-
-struct at91sam7_flash_bank {
- /* chip id register */
- uint32_t cidr;
- uint16_t cidr_ext;
- uint16_t cidr_nvptyp;
- uint16_t cidr_arch;
- uint16_t cidr_sramsiz;
- uint16_t cidr_nvpsiz;
- uint16_t cidr_nvpsiz2;
- uint16_t cidr_eproc;
- uint16_t cidr_version;
- const char *target_name;
-
- /* flash auto-detection */
- uint8_t flash_autodetection;
-
- /* flash geometry */
- uint16_t pages_per_sector;
- uint16_t pagesize;
- uint16_t pages_in_lockregion;
-
- /* nv memory bits */
- uint16_t num_lockbits_on;
- uint16_t lockbits;
- uint16_t num_nvmbits;
- uint16_t num_nvmbits_on;
- uint16_t nvmbits;
- uint8_t securitybit;
-
- /* 0: not init
- * 1: fmcn for nvbits (1uS)
- * 2: fmcn for flash (1.5uS) */
- uint8_t flashmode;
-
- /* main clock status */
- uint8_t mck_valid;
- uint32_t mck_freq;
-
- /* external clock frequency */
- uint32_t ext_freq;
-
-};
-
-#if 0
-static long SRAMSIZ[16] = {
- -1,
- 0x0400, /* 1K */
- 0x0800, /* 2K */
- -1,
- 0x1c000, /* 112K */
- 0x1000, /* 4K */
- 0x14000, /* 80K */
- 0x28000, /* 160K */
- 0x2000, /* 8K */
- 0x4000, /* 16K */
- 0x8000, /* 32K */
- 0x10000, /* 64K */
- 0x20000, /* 128K */
- 0x40000, /* 256K */
- 0x18000, /* 96K */
- 0x80000, /* 512K */
-};
-#endif
-
-static uint32_t at91sam7_get_flash_status(struct target *target, int bank_number)
-{
- uint32_t fsr;
- target_read_u32(target, MC_FSR[bank_number], &fsr);
-
- return fsr;
-}
-
-/* Read clock configuration and set at91sam7_info->mck_freq */
-static void at91sam7_read_clock_info(struct flash_bank *bank)
-{
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t mckr, mcfr, pllr, mor;
- unsigned long tmp = 0, mainfreq;
-
- /* Read Clock Generator Main Oscillator Register */
- target_read_u32(target, CKGR_MOR, &mor);
- /* Read Clock Generator Main Clock Frequency Register */
- target_read_u32(target, CKGR_MCFR, &mcfr);
- /* Read Master Clock Register*/
- target_read_u32(target, PMC_MCKR, &mckr);
- /* Read Clock Generator PLL Register */
- target_read_u32(target, CKGR_PLLR, &pllr);
-
- at91sam7_info->mck_valid = 0;
- at91sam7_info->mck_freq = 0;
- switch (mckr & PMC_MCKR_CSS) {
- case 0: /* Slow Clock */
- at91sam7_info->mck_valid = 1;
- tmp = RC_FREQ;
- break;
-
- case 1: /* Main Clock */
- if ((mcfr & CKGR_MCFR_MAINRDY) &&
- (at91sam7_info->ext_freq == 0)) {
- at91sam7_info->mck_valid = 1;
- tmp = RC_FREQ / 16ul * (mcfr & 0xffff);
- } else if (at91sam7_info->ext_freq != 0) {
- at91sam7_info->mck_valid = 1;
- tmp = at91sam7_info->ext_freq;
- }
- break;
-
- case 2: /* Reserved */
- break;
-
- case 3: /* PLL Clock */
- if ((mcfr & CKGR_MCFR_MAINRDY) &&
- (at91sam7_info->ext_freq == 0)) {
- target_read_u32(target, CKGR_PLLR, &pllr);
- if (!(pllr & CKGR_PLLR_DIV))
- break; /* 0 Hz */
- at91sam7_info->mck_valid = 1;
- mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff);
- /* Integer arithmetic should have sufficient precision
- * as long as PLL is properly configured. */
- tmp = mainfreq / (pllr & CKGR_PLLR_DIV)*
- (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
- } else if ((at91sam7_info->ext_freq != 0) &&
- ((pllr&CKGR_PLLR_DIV) != 0)) {
- at91sam7_info->mck_valid = 1;
- tmp = at91sam7_info->ext_freq / (pllr&CKGR_PLLR_DIV)*
- (((pllr & CKGR_PLLR_MUL) >> 16) + 1);
- }
- break;
- }
-
- /* Prescaler adjust */
- if ((((mckr & PMC_MCKR_PRES) >> 2) == 7) || (tmp == 0)) {
- at91sam7_info->mck_valid = 0;
- at91sam7_info->mck_freq = 0;
- } else if (((mckr & PMC_MCKR_PRES) >> 2) != 0)
- at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2);
- else
- at91sam7_info->mck_freq = tmp;
-}
-
-/* Setup the timimg registers for nvbits or normal flash */
-static void at91sam7_set_flash_mode(struct flash_bank *bank, int mode)
-{
- uint32_t fmr, fmcn = 0, fws = 0;
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
- struct target *target = bank->target;
-
- if (mode && (mode != at91sam7_info->flashmode)) {
- /* Always round up (ceil) */
- if (mode == FMR_TIMING_NVBITS) {
- if (at91sam7_info->cidr_arch == 0x60) {
- /* AT91SAM7A3 uses master clocks in 100 ns */
- fmcn = (at91sam7_info->mck_freq/10000000ul) + 1;
- } else {
- /* master clocks in 1uS for ARCH 0x7 types */
- fmcn = (at91sam7_info->mck_freq/1000000ul) + 1;
- }
- } else if (mode == FMR_TIMING_FLASH) {
- /* main clocks in 1.5uS */
- fmcn = (at91sam7_info->mck_freq/1000000ul)+
- (at91sam7_info->mck_freq/2000000ul) + 1;
- }
-
- /* hard overclocking */
- if (fmcn > 0xFF)
- fmcn = 0xFF;
-
- /* Only allow fmcn = 0 if clock period is > 30 us = 33kHz. */
- if (at91sam7_info->mck_freq <= 33333ul)
- fmcn = 0;
- /* Only allow fws = 0 if clock frequency is < 30 MHz. */
- if (at91sam7_info->mck_freq > 30000000ul)
- fws = 1;
-
- LOG_DEBUG("fmcn[%i]: %i", bank->bank_number, (int)(fmcn));
- fmr = fmcn << 16 | fws << 8;
- target_write_u32(target, MC_FMR[bank->bank_number], fmr);
- }
-
- at91sam7_info->flashmode = mode;
-}
-
-static uint32_t at91sam7_wait_status_busy(struct flash_bank *bank, uint32_t waitbits, int timeout)
-{
- uint32_t status;
-
- while ((!((status = at91sam7_get_flash_status(bank->target,
- bank->bank_number)) & waitbits)) && (timeout-- > 0)) {
- LOG_DEBUG("status[%i]: 0x%" PRIx32 "", (int)bank->bank_number, status);
- alive_sleep(1);
- }
-
- LOG_DEBUG("status[%i]: 0x%" PRIx32 "", bank->bank_number, status);
-
- if (status & 0x0C) {
- LOG_ERROR("status register: 0x%" PRIx32 "", status);
- if (status & 0x4)
- LOG_ERROR("Lock Error Bit Detected, Operation Abort");
- if (status & 0x8)
- LOG_ERROR("Invalid command and/or bad keyword, Operation Abort");
- if (status & 0x10)
- LOG_ERROR("Security Bit Set, Operation Abort");
- }
-
- return status;
-}
-
-/* Send one command to the AT91SAM flash controller */
-static int at91sam7_flash_command(struct flash_bank *bank, uint8_t cmd, uint16_t pagen)
-{
- uint32_t fcr;
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
- struct target *target = bank->target;
-
- fcr = (0x5A << 24) | ((pagen&0x3FF) << 8) | cmd;
- target_write_u32(target, MC_FCR[bank->bank_number], fcr);
- LOG_DEBUG("Flash command: 0x%" PRIx32 ", flash bank: %i, page number: %u",
- fcr,
- bank->bank_number + 1,
- pagen);
-
- if ((at91sam7_info->cidr_arch == 0x60) && ((cmd == SLB) | (cmd == CLB))) {
- /* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */
- if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C)
- return ERROR_FLASH_OPERATION_FAILED;
- return ERROR_OK;
- }
-
- if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C)
- return ERROR_FLASH_OPERATION_FAILED;
-
- return ERROR_OK;
-}
-
-/* Read device id register, main clock frequency register and fill in driver info structure */
-static int at91sam7_read_part_info(struct flash_bank *bank)
-{
- struct at91sam7_flash_bank *at91sam7_info;
- struct target *target = bank->target;
-
- uint16_t bnk, sec;
- uint16_t arch;
- uint32_t cidr;
- uint8_t banks_num = 0;
- uint16_t num_nvmbits = 0;
- uint16_t sectors_num = 0;
- uint16_t pages_per_sector = 0;
- uint16_t page_size = 0;
- uint32_t ext_freq;
- uint32_t bank_size;
- uint32_t base_address = 0;
- char *target_name_t = "Unknown";
-
- at91sam7_info = bank->driver_priv;
-
- if (at91sam7_info->cidr != 0) {
- /* flash already configured, update clock and check for protected sectors */
- for (struct flash_bank *t_bank = bank; t_bank; t_bank = t_bank->next) {
- if (t_bank->target != target)
- continue;
- /* re-calculate master clock frequency */
- at91sam7_read_clock_info(t_bank);
-
- /* no timming */
- at91sam7_set_flash_mode(t_bank, FMR_TIMING_NONE);
-
- /* check protect state */
- at91sam7_protect_check(t_bank);
- }
-
- return ERROR_OK;
- }
-
- /* Read and parse chip identification register */
- target_read_u32(target, DBGU_CIDR, &cidr);
- if (cidr == 0) {
- LOG_WARNING("Cannot identify target as an AT91SAM");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (at91sam7_info->flash_autodetection == 0) {
- /* banks and sectors are already created, based on data from input file */
- for (struct flash_bank *t_bank = bank; t_bank; t_bank = t_bank->next) {
- if (t_bank->target != target)
- continue;
-
- at91sam7_info = t_bank->driver_priv;
-
- at91sam7_info->cidr = cidr;
- at91sam7_info->cidr_ext = (cidr >> 31)&0x0001;
- at91sam7_info->cidr_nvptyp = (cidr >> 28)&0x0007;
- at91sam7_info->cidr_arch = (cidr >> 20)&0x00FF;
- at91sam7_info->cidr_sramsiz = (cidr >> 16)&0x000F;
- at91sam7_info->cidr_nvpsiz2 = (cidr >> 12)&0x000F;
- at91sam7_info->cidr_nvpsiz = (cidr >> 8)&0x000F;
- at91sam7_info->cidr_eproc = (cidr >> 5)&0x0007;
- at91sam7_info->cidr_version = cidr&0x001F;
-
- /* calculate master clock frequency */
- at91sam7_read_clock_info(t_bank);
-
- /* no timming */
- at91sam7_set_flash_mode(t_bank, FMR_TIMING_NONE);
-
- /* check protect state */
- at91sam7_protect_check(t_bank);
- }
-
- return ERROR_OK;
- }
-
- arch = (cidr >> 20)&0x00FF;
-
- /* check flash size */
- switch ((cidr >> 8)&0x000F) {
- case FLASH_SIZE_8KB:
- break;
-
- case FLASH_SIZE_16KB:
- banks_num = 1;
- sectors_num = 8;
- pages_per_sector = 32;
- page_size = 64;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S161/16";
- }
- break;
-
- case FLASH_SIZE_32KB:
- banks_num = 1;
- sectors_num = 8;
- pages_per_sector = 32;
- page_size = 128;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S321/32";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE32";
- }
- break;
-
- case FLASH_SIZE_64KB:
- banks_num = 1;
- sectors_num = 16;
- pages_per_sector = 32;
- page_size = 128;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S64";
- }
- break;
-
- case FLASH_SIZE_128KB:
- banks_num = 1;
- sectors_num = 8;
- pages_per_sector = 64;
- page_size = 256;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S128";
- }
- if (arch == 0x71) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7XC128";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE128";
- }
- if (arch == 0x75) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7X128";
- }
- break;
-
- case FLASH_SIZE_256KB:
- banks_num = 1;
- sectors_num = 16;
- pages_per_sector = 64;
- page_size = 256;
- base_address = 0x00100000;
- if (arch == 0x60) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7A3";
- }
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S256";
- }
- if (arch == 0x71) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7XC256";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE256";
- }
- if (arch == 0x75) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7X256";
- }
- break;
-
- case FLASH_SIZE_512KB:
- banks_num = 2;
- sectors_num = 16;
- pages_per_sector = 64;
- page_size = 256;
- base_address = 0x00100000;
- if (arch == 0x70) {
- num_nvmbits = 2;
- target_name_t = "AT91SAM7S512";
- }
- if (arch == 0x71) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7XC512";
- }
- if (arch == 0x72) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7SE512";
- }
- if (arch == 0x75) {
- num_nvmbits = 3;
- target_name_t = "AT91SAM7X512";
- }
- break;
-
- case FLASH_SIZE_1024KB:
- break;
-
- case FLASH_SIZE_2048KB:
- break;
- }
-
- if (strcmp(target_name_t, "Unknown") == 0) {
- LOG_ERROR(
- "Target autodetection failed! Please specify target parameters in configuration file");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- ext_freq = at91sam7_info->ext_freq;
-
- /* calculate bank size */
- bank_size = sectors_num * pages_per_sector * page_size;
-
- for (bnk = 0; bnk < banks_num; bnk++) {
- struct flash_bank *t_bank = bank;
- if (bnk > 0) {
- if (!t_bank->next) {
- /* create a new flash bank element */
- struct flash_bank *fb = malloc(sizeof(struct flash_bank));
- fb->target = target;
- fb->driver = bank->driver;
- fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank));
- fb->name = "sam7_probed";
- fb->next = NULL;
-
- /* link created bank in 'flash_banks' list */
- t_bank->next = fb;
- }
- t_bank = t_bank->next;
- }
-
- t_bank->bank_number = bnk;
- t_bank->base = base_address + bnk * bank_size;
- t_bank->size = bank_size;
- t_bank->chip_width = 0;
- t_bank->bus_width = 4;
- t_bank->num_sectors = sectors_num;
-
- /* allocate sectors */
- t_bank->sectors = malloc(sectors_num * sizeof(struct flash_sector));
- for (sec = 0; sec < sectors_num; sec++) {
- t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
- t_bank->sectors[sec].size = pages_per_sector * page_size;
- t_bank->sectors[sec].is_erased = -1;
- t_bank->sectors[sec].is_protected = -1;
- }
-
- at91sam7_info = t_bank->driver_priv;
-
- at91sam7_info->cidr = cidr;
- at91sam7_info->cidr_ext = (cidr >> 31)&0x0001;
- at91sam7_info->cidr_nvptyp = (cidr >> 28)&0x0007;
- at91sam7_info->cidr_arch = (cidr >> 20)&0x00FF;
- at91sam7_info->cidr_sramsiz = (cidr >> 16)&0x000F;
- at91sam7_info->cidr_nvpsiz2 = (cidr >> 12)&0x000F;
- at91sam7_info->cidr_nvpsiz = (cidr >> 8)&0x000F;
- at91sam7_info->cidr_eproc = (cidr >> 5)&0x0007;
- at91sam7_info->cidr_version = cidr&0x001F;
-
- at91sam7_info->target_name = target_name_t;
- at91sam7_info->flashmode = 0;
- at91sam7_info->ext_freq = ext_freq;
- at91sam7_info->num_nvmbits = num_nvmbits;
- at91sam7_info->num_nvmbits_on = 0;
- at91sam7_info->pagesize = page_size;
- at91sam7_info->pages_per_sector = pages_per_sector;
-
- /* calculate master clock frequency */
- at91sam7_read_clock_info(t_bank);
-
- /* no timming */
- at91sam7_set_flash_mode(t_bank, FMR_TIMING_NONE);
-
- /* check protect state */
- at91sam7_protect_check(t_bank);
- }
-
- LOG_DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x",
- at91sam7_info->cidr_nvptyp,
- at91sam7_info->cidr_arch);
-
- return ERROR_OK;
-}
-
-static int at91sam7_erase_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- uint16_t retval;
- uint32_t blank;
- uint16_t fast_check;
- uint8_t *buffer;
- uint16_t nSector;
- uint16_t nByte;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Configure the flash controller timing */
- at91sam7_read_clock_info(bank);
- at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
-
- fast_check = 1;
- for (nSector = 0; nSector < bank->num_sectors; nSector++) {
- retval = target_blank_check_memory(target,
- bank->base + bank->sectors[nSector].offset,
- bank->sectors[nSector].size,
- &blank);
- if (retval != ERROR_OK) {
- fast_check = 0;
- break;
- }
- if (blank == 0xFF)
- bank->sectors[nSector].is_erased = 1;
- else
- bank->sectors[nSector].is_erased = 0;
- }
-
- if (fast_check)
- return ERROR_OK;
-
- LOG_USER("Running slow fallback erase check - add working memory");
-
- buffer = malloc(bank->sectors[0].size);
- for (nSector = 0; nSector < bank->num_sectors; nSector++) {
- bank->sectors[nSector].is_erased = 1;
- retval = target_read_memory(target, bank->base + bank->sectors[nSector].offset, 4,
- bank->sectors[nSector].size/4, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- for (nByte = 0; nByte < bank->sectors[nSector].size; nByte++) {
- if (buffer[nByte] != 0xFF) {
- bank->sectors[nSector].is_erased = 0;
- break;
- }
- }
- }
- free(buffer);
-
- return ERROR_OK;
-}
-
-static int at91sam7_protect_check(struct flash_bank *bank)
-{
- uint8_t lock_pos, gpnvm_pos;
- uint32_t status;
-
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
-
- if (at91sam7_info->cidr == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- status = at91sam7_get_flash_status(bank->target, bank->bank_number);
- at91sam7_info->lockbits = (status >> 16);
-
- at91sam7_info->num_lockbits_on = 0;
- for (lock_pos = 0; lock_pos < bank->num_sectors; lock_pos++) {
- if (((status >> (16 + lock_pos))&(0x0001)) == 1) {
- at91sam7_info->num_lockbits_on++;
- bank->sectors[lock_pos].is_protected = 1;
- } else
- bank->sectors[lock_pos].is_protected = 0;
- }
-
- /* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
- status = at91sam7_get_flash_status(bank->target, 0);
-
- at91sam7_info->securitybit = (status >> 4)&0x01;
- at91sam7_info->nvmbits = (status >> 8)&0xFF;
-
- at91sam7_info->num_nvmbits_on = 0;
- for (gpnvm_pos = 0; gpnvm_pos < at91sam7_info->num_nvmbits; gpnvm_pos++) {
- if (((status >> (8 + gpnvm_pos))&(0x01)) == 1)
- at91sam7_info->num_nvmbits_on++;
- }
-
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
-{
- struct flash_bank *t_bank = bank;
- struct at91sam7_flash_bank *at91sam7_info;
- struct target *target = t_bank->target;
-
- uint32_t base_address;
- uint32_t bank_size;
- uint32_t ext_freq = 0;
-
- int chip_width;
- int bus_width;
- int banks_num;
- int num_sectors;
-
- uint16_t pages_per_sector;
- uint16_t page_size;
- uint16_t num_nvmbits;
-
- char *target_name_t;
-
- int bnk, sec;
-
- at91sam7_info = malloc(sizeof(struct at91sam7_flash_bank));
- t_bank->driver_priv = at91sam7_info;
-
- /* part wasn't probed for info yet */
- at91sam7_info->cidr = 0;
- at91sam7_info->flashmode = 0;
- at91sam7_info->ext_freq = 0;
- at91sam7_info->flash_autodetection = 0;
-
- if (CMD_ARGC < 13) {
- at91sam7_info->flash_autodetection = 1;
- return ERROR_OK;
- }
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], base_address);
-
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], chip_width);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], bus_width);
-
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[8], banks_num);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[9], num_sectors);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[10], pages_per_sector);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[11], page_size);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[12], num_nvmbits);
-
- if (CMD_ARGC == 14) {
- unsigned long freq;
- COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[13], freq);
- ext_freq = freq * 1000;
- at91sam7_info->ext_freq = ext_freq;
- }
-
- if ((bus_width == 0) || (banks_num == 0) || (num_sectors == 0) ||
- (pages_per_sector == 0) || (page_size == 0) || (num_nvmbits == 0)) {
- at91sam7_info->flash_autodetection = 1;
- return ERROR_OK;
- }
-
- target_name_t = calloc(strlen(CMD_ARGV[7]) + 1, sizeof(char));
- strcpy(target_name_t, CMD_ARGV[7]);
-
- /* calculate bank size */
- bank_size = num_sectors * pages_per_sector * page_size;
-
- for (bnk = 0; bnk < banks_num; bnk++) {
- if (bnk > 0) {
- if (!t_bank->next) {
- /* create a new bank element */
- struct flash_bank *fb = malloc(sizeof(struct flash_bank));
- fb->target = target;
- fb->driver = bank->driver;
- fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank));
- fb->name = "sam7_probed";
- fb->next = NULL;
-
- /* link created bank in 'flash_banks' list */
- t_bank->next = fb;
- }
- t_bank = t_bank->next;
- }
-
- t_bank->bank_number = bnk;
- t_bank->base = base_address + bnk * bank_size;
- t_bank->size = bank_size;
- t_bank->chip_width = chip_width;
- t_bank->bus_width = bus_width;
- t_bank->num_sectors = num_sectors;
-
- /* allocate sectors */
- t_bank->sectors = malloc(num_sectors * sizeof(struct flash_sector));
- for (sec = 0; sec < num_sectors; sec++) {
- t_bank->sectors[sec].offset = sec * pages_per_sector * page_size;
- t_bank->sectors[sec].size = pages_per_sector * page_size;
- t_bank->sectors[sec].is_erased = -1;
- t_bank->sectors[sec].is_protected = -1;
- }
-
- at91sam7_info = t_bank->driver_priv;
-
- at91sam7_info->target_name = target_name_t;
- at91sam7_info->flashmode = 0;
- at91sam7_info->ext_freq = ext_freq;
- at91sam7_info->num_nvmbits = num_nvmbits;
- at91sam7_info->num_nvmbits_on = 0;
- at91sam7_info->pagesize = page_size;
- at91sam7_info->pages_per_sector = pages_per_sector;
- }
-
- return ERROR_OK;
-}
-
-static int at91sam7_erase(struct flash_bank *bank, int first, int last)
-{
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
- int sec;
- uint32_t nbytes, pos;
- uint8_t *buffer;
- uint8_t erase_all;
-
- if (at91sam7_info->cidr == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first < 0) || (last < first) || (last >= bank->num_sectors))
- return ERROR_FLASH_SECTOR_INVALID;
-
- erase_all = 0;
- if ((first == 0) && (last == (bank->num_sectors-1)))
- erase_all = 1;
-
- /* Configure the flash controller timing */
- at91sam7_read_clock_info(bank);
- at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
-
- if (erase_all) {
- if (at91sam7_flash_command(bank, EA, 0) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
- } else {
- /* allocate and clean buffer */
- nbytes = (last - first + 1) * bank->sectors[first].size;
- buffer = malloc(nbytes * sizeof(uint8_t));
- for (pos = 0; pos < nbytes; pos++)
- buffer[pos] = 0xFF;
-
- if (at91sam7_write(bank, buffer, bank->sectors[first].offset, nbytes) != ERROR_OK) {
- free(buffer);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- free(buffer);
- }
-
- /* mark erased sectors */
- for (sec = first; sec <= last; sec++)
- bank->sectors[sec].is_erased = 1;
-
- return ERROR_OK;
-}
-
-static int at91sam7_protect(struct flash_bank *bank, int set, int first, int last)
-{
- uint32_t cmd;
- int sector;
- uint32_t pagen;
-
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
-
- if (at91sam7_info->cidr == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first < 0) || (last < first) || (last >= bank->num_sectors))
- return ERROR_FLASH_SECTOR_INVALID;
-
- /* Configure the flash controller timing */
- at91sam7_read_clock_info(bank);
- at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
-
- for (sector = first; sector <= last; sector++) {
- if (set)
- cmd = SLB;
- else
- cmd = CLB;
-
- /* if we lock a page from one sector then entire sector will be locked, also,
- * if we unlock a page from a locked sector, entire sector will be unlocked */
- pagen = sector * at91sam7_info->pages_per_sector;
-
- if (at91sam7_flash_command(bank, cmd, pagen) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- at91sam7_protect_check(bank);
-
- return ERROR_OK;
-}
-
-static int at91sam7_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- int retval;
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t dst_min_alignment, wcount, bytes_remaining = count;
- uint32_t first_page, last_page, pagen, buffer_pos;
-
- if (at91sam7_info->cidr == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- 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;
-
- dst_min_alignment = at91sam7_info->pagesize;
-
- if (offset % dst_min_alignment) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
- offset,
- dst_min_alignment);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- if (at91sam7_info->cidr_arch == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- first_page = offset/dst_min_alignment;
- last_page = DIV_ROUND_UP(offset + count, dst_min_alignment);
-
- LOG_DEBUG("first_page: %i, last_page: %i, count %i",
- (int)first_page,
- (int)last_page,
- (int)count);
-
- /* Configure the flash controller timing */
- at91sam7_read_clock_info(bank);
- at91sam7_set_flash_mode(bank, FMR_TIMING_FLASH);
-
- for (pagen = first_page; pagen < last_page; pagen++) {
- if (bytes_remaining < dst_min_alignment)
- count = bytes_remaining;
- else
- count = dst_min_alignment;
- bytes_remaining -= count;
-
- /* Write one block to the PageWriteBuffer */
- buffer_pos = (pagen-first_page)*dst_min_alignment;
- wcount = DIV_ROUND_UP(count, 4);
- retval = target_write_memory(target, bank->base + pagen*dst_min_alignment, 4,
- wcount, buffer + buffer_pos);
- if (retval != ERROR_OK)
- return retval;
-
- /* Send Write Page command to Flash Controller */
- if (at91sam7_flash_command(bank, WP, pagen) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
- LOG_DEBUG("Write flash bank:%i page number:%" PRIi32 "", bank->bank_number, pagen);
- }
-
- return ERROR_OK;
-}
-
-static int at91sam7_probe(struct flash_bank *bank)
-{
- /* we can't probe on an at91sam7
- * if this is an at91sam7, it has the configured flash */
- int retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = at91sam7_read_part_info(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int get_at91sam7_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int printed;
- struct at91sam7_flash_bank *at91sam7_info = bank->driver_priv;
-
- if (at91sam7_info->cidr == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- printed = snprintf(buf, buf_size,
- "\n at91sam7 driver information: Chip is %s\n",
- at91sam7_info->target_name);
-
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf,
- buf_size,
- " Cidr: 0x%8.8" PRIx32 " | Arch: 0x%4.4x | Eproc: %s | Version: 0x%3.3x | "
- "Flashsize: 0x%8.8" PRIx32 "\n",
- at91sam7_info->cidr,
- at91sam7_info->cidr_arch,
- EPROC[at91sam7_info->cidr_eproc],
- at91sam7_info->cidr_version,
- bank->size);
-
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size,
- " Master clock (estimated): %u KHz | External clock: %u KHz\n",
- (unsigned)(at91sam7_info->mck_freq / 1000),
- (unsigned)(at91sam7_info->ext_freq / 1000));
-
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf,
- buf_size,
- " Pagesize: %i bytes | Lockbits(%i): %i 0x%4.4x | Pages in lock region: %i\n",
- at91sam7_info->pagesize,
- bank->num_sectors,
- at91sam7_info->num_lockbits_on,
- at91sam7_info->lockbits,
- at91sam7_info->pages_per_sector*at91sam7_info->num_lockbits_on);
-
- buf += printed;
- buf_size -= printed;
-
- snprintf(buf, buf_size,
- " Securitybit: %i | Nvmbits(%i): %i 0x%1.1x\n",
- at91sam7_info->securitybit, at91sam7_info->num_nvmbits,
- at91sam7_info->num_nvmbits_on, at91sam7_info->nvmbits);
-
- return ERROR_OK;
-}
-
-/*
-* On AT91SAM7S: When the gpnvm bits are set with
-* > at91sam7 gpnvm bitnr set
-* the changes are not visible in the flash controller status register MC_FSR
-* until the processor has been reset.
-* On the Olimex board this requires a power cycle.
-* Note that the AT91SAM7S has the following errata (doc6175.pdf sec 14.1.3):
-* The maximum number of write/erase cycles for Non volatile Memory bits is 100. this includes
-* Lock Bits (LOCKx), General Purpose NVM bits (GPNVMx) and the Security Bit.
-*/
-COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
-{
- struct flash_bank *bank;
- int bit;
- uint8_t flashcmd;
- uint32_t status;
- struct at91sam7_flash_bank *at91sam7_info;
- int retval;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- bank = get_flash_bank_by_num_noprobe(0);
- if (bank == NULL)
- return ERROR_FLASH_BANK_INVALID;
- if (strcmp(bank->driver->name, "at91sam7")) {
- command_print(CMD_CTX, "not an at91sam7 flash bank '%s'", CMD_ARGV[0]);
- return ERROR_FLASH_BANK_INVALID;
- }
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("target has to be halted to perform flash operation");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (strcmp(CMD_ARGV[1], "set") == 0)
- flashcmd = SGPB;
- else if (strcmp(CMD_ARGV[1], "clear") == 0)
- flashcmd = CGPB;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- at91sam7_info = bank->driver_priv;
- if (at91sam7_info->cidr == 0) {
- retval = at91sam7_read_part_info(bank);
- if (retval != ERROR_OK)
- return retval;
- }
-
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], bit);
- if ((bit < 0) || (bit >= at91sam7_info->num_nvmbits)) {
- command_print(CMD_CTX,
- "gpnvm bit '#%s' is out of bounds for target %s",
- CMD_ARGV[0],
- at91sam7_info->target_name);
- return ERROR_OK;
- }
-
- /* Configure the flash controller timing */
- at91sam7_read_clock_info(bank);
- at91sam7_set_flash_mode(bank, FMR_TIMING_NVBITS);
-
- if (at91sam7_flash_command(bank, flashcmd, bit) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* GPNVM and SECURITY bits apply only for MC_FSR of EFC0 */
- status = at91sam7_get_flash_status(bank->target, 0);
- LOG_DEBUG("at91sam7_handle_gpnvm_command: cmd 0x%x, value %d, status 0x%" PRIx32,
- flashcmd,
- bit,
- status);
-
- /* check protect state */
- at91sam7_protect_check(bank);
-
- return ERROR_OK;
-}
-
-static const struct command_registration at91sam7_exec_command_handlers[] = {
- {
- .name = "gpnvm",
- .handler = at91sam7_handle_gpnvm_command,
- .mode = COMMAND_EXEC,
- .help = "set or clear one General Purpose Non-Volatile Memory "
- "(gpnvm) bit",
- .usage = "bitnum ('set'|'clear')",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration at91sam7_command_handlers[] = {
- {
- .name = "at91sam7",
- .mode = COMMAND_ANY,
- .help = "at91sam7 flash command group",
- .usage = "",
- .chain = at91sam7_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver at91sam7_flash = {
- .name = "at91sam7",
- .usage = "gpnvm <bit> <set | clear>",
- .commands = at91sam7_command_handlers,
- .flash_bank_command = at91sam7_flash_bank_command,
- .erase = at91sam7_erase,
- .protect = at91sam7_protect,
- .write = at91sam7_write,
- .read = default_flash_read,
- .probe = at91sam7_probe,
- .auto_probe = at91sam7_probe,
- .erase_check = at91sam7_erase_check,
- .protect_check = at91sam7_protect_check,
- .info = get_at91sam7_info,
-};
diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c
deleted file mode 100644
index 58b367a..0000000
--- a/src/flash/nor/at91samd.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andrey Yurovsky *
- * Andrey Yurovsky <yurovsky@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "helper/binarybuffer.h"
-
-#include <target/cortex_m.h>
-
-#define SAMD_NUM_SECTORS 16
-#define SAMD_PAGE_SIZE_MAX 1024
-
-#define SAMD_FLASH ((uint32_t)0x00000000) /* physical Flash memory */
-#define SAMD_USER_ROW ((uint32_t)0x00804000) /* User Row of Flash */
-#define SAMD_PAC1 0x41000000 /* Peripheral Access Control 1 */
-#define SAMD_DSU 0x41002000 /* Device Service Unit */
-#define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
-
-#define SAMD_DSU_STATUSA 1 /* DSU status register */
-#define SAMD_DSU_DID 0x18 /* Device ID register */
-
-#define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
-#define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
-#define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
-#define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interupt Flag Status & Clear */
-#define SAMD_NVMCTRL_STATUS 0x18 /* NVM status register */
-#define SAMD_NVMCTRL_ADDR 0x1C /* NVM address register */
-#define SAMD_NVMCTRL_LOCK 0x20 /* NVM Lock section register */
-
-#define SAMD_CMDEX_KEY 0xA5UL
-#define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
-
-/* NVMCTRL commands. See Table 20-4 in 42129F–SAM–10/2013 */
-#define SAMD_NVM_CMD_ER 0x02 /* Erase Row */
-#define SAMD_NVM_CMD_WP 0x04 /* Write Page */
-#define SAMD_NVM_CMD_EAR 0x05 /* Erase Auxilary Row */
-#define SAMD_NVM_CMD_WAP 0x06 /* Write Auxilary Page */
-#define SAMD_NVM_CMD_LR 0x40 /* Lock Region */
-#define SAMD_NVM_CMD_UR 0x41 /* Unlock Region */
-#define SAMD_NVM_CMD_SPRM 0x42 /* Set Power Reduction Mode */
-#define SAMD_NVM_CMD_CPRM 0x43 /* Clear Power Reduction Mode */
-#define SAMD_NVM_CMD_PBC 0x44 /* Page Buffer Clear */
-#define SAMD_NVM_CMD_SSB 0x45 /* Set Security Bit */
-#define SAMD_NVM_CMD_INVALL 0x46 /* Invalidate all caches */
-
-/* NVMCTRL bits */
-#define SAMD_NVM_CTRLB_MANW 0x80
-
-/* Known identifiers */
-#define SAMD_PROCESSOR_M0 0x01
-#define SAMD_FAMILY_D 0x00
-#define SAMD_FAMILY_L 0x01
-#define SAMD_FAMILY_C 0x02
-#define SAMD_SERIES_20 0x00
-#define SAMD_SERIES_21 0x01
-#define SAMD_SERIES_22 0x02
-#define SAMD_SERIES_10 0x02
-#define SAMD_SERIES_11 0x03
-#define SAMD_SERIES_09 0x04
-
-/* Device ID macros */
-#define SAMD_GET_PROCESSOR(id) (id >> 28)
-#define SAMD_GET_FAMILY(id) (((id >> 23) & 0x1F))
-#define SAMD_GET_SERIES(id) (((id >> 16) & 0x3F))
-#define SAMD_GET_DEVSEL(id) (id & 0xFF)
-
-struct samd_part {
- uint8_t id;
- const char *name;
- uint32_t flash_kb;
- uint32_t ram_kb;
-};
-
-/* Known SAMD09 parts. DID reset values missing in RM, see
- * https://github.com/avrxml/asf/blob/master/sam0/utils/cmsis/samd09/include/ */
-static const struct samd_part samd09_parts[] = {
- { 0x0, "SAMD09D14A", 16, 4 },
- { 0x7, "SAMD09C13A", 8, 4 },
-};
-
-/* Known SAMD10 parts */
-static const struct samd_part samd10_parts[] = {
- { 0x0, "SAMD10D14AMU", 16, 4 },
- { 0x1, "SAMD10D13AMU", 8, 4 },
- { 0x2, "SAMD10D12AMU", 4, 4 },
- { 0x3, "SAMD10D14ASU", 16, 4 },
- { 0x4, "SAMD10D13ASU", 8, 4 },
- { 0x5, "SAMD10D12ASU", 4, 4 },
- { 0x6, "SAMD10C14A", 16, 4 },
- { 0x7, "SAMD10C13A", 8, 4 },
- { 0x8, "SAMD10C12A", 4, 4 },
-};
-
-/* Known SAMD11 parts */
-static const struct samd_part samd11_parts[] = {
- { 0x0, "SAMD11D14AMU", 16, 4 },
- { 0x1, "SAMD11D13AMU", 8, 4 },
- { 0x2, "SAMD11D12AMU", 4, 4 },
- { 0x3, "SAMD11D14ASU", 16, 4 },
- { 0x4, "SAMD11D13ASU", 8, 4 },
- { 0x5, "SAMD11D12ASU", 4, 4 },
- { 0x6, "SAMD11C14A", 16, 4 },
- { 0x7, "SAMD11C13A", 8, 4 },
- { 0x8, "SAMD11C12A", 4, 4 },
-};
-
-/* Known SAMD20 parts. See Table 12-8 in 42129F–SAM–10/2013 */
-static const struct samd_part samd20_parts[] = {
- { 0x0, "SAMD20J18A", 256, 32 },
- { 0x1, "SAMD20J17A", 128, 16 },
- { 0x2, "SAMD20J16A", 64, 8 },
- { 0x3, "SAMD20J15A", 32, 4 },
- { 0x4, "SAMD20J14A", 16, 2 },
- { 0x5, "SAMD20G18A", 256, 32 },
- { 0x6, "SAMD20G17A", 128, 16 },
- { 0x7, "SAMD20G16A", 64, 8 },
- { 0x8, "SAMD20G15A", 32, 4 },
- { 0x9, "SAMD20G14A", 16, 2 },
- { 0xA, "SAMD20E18A", 256, 32 },
- { 0xB, "SAMD20E17A", 128, 16 },
- { 0xC, "SAMD20E16A", 64, 8 },
- { 0xD, "SAMD20E15A", 32, 4 },
- { 0xE, "SAMD20E14A", 16, 2 },
-};
-
-/* Known SAMD21 parts. */
-static const struct samd_part samd21_parts[] = {
- { 0x0, "SAMD21J18A", 256, 32 },
- { 0x1, "SAMD21J17A", 128, 16 },
- { 0x2, "SAMD21J16A", 64, 8 },
- { 0x3, "SAMD21J15A", 32, 4 },
- { 0x4, "SAMD21J14A", 16, 2 },
- { 0x5, "SAMD21G18A", 256, 32 },
- { 0x6, "SAMD21G17A", 128, 16 },
- { 0x7, "SAMD21G16A", 64, 8 },
- { 0x8, "SAMD21G15A", 32, 4 },
- { 0x9, "SAMD21G14A", 16, 2 },
- { 0xA, "SAMD21E18A", 256, 32 },
- { 0xB, "SAMD21E17A", 128, 16 },
- { 0xC, "SAMD21E16A", 64, 8 },
- { 0xD, "SAMD21E15A", 32, 4 },
- { 0xE, "SAMD21E14A", 16, 2 },
- /* Below are B Variants (Table 3-7 from rev I of datasheet) */
- { 0x20, "SAMD21J16B", 64, 8 },
- { 0x21, "SAMD21J15B", 32, 4 },
- { 0x23, "SAMD21G16B", 64, 8 },
- { 0x24, "SAMD21G15B", 32, 4 },
- { 0x26, "SAMD21E16B", 64, 8 },
- { 0x27, "SAMD21E15B", 32, 4 },
-};
-
-/* Known SAMR21 parts. */
-static const struct samd_part samr21_parts[] = {
- { 0x19, "SAMR21G18A", 256, 32 },
- { 0x1A, "SAMR21G17A", 128, 32 },
- { 0x1B, "SAMR21G16A", 64, 32 },
- { 0x1C, "SAMR21E18A", 256, 32 },
- { 0x1D, "SAMR21E17A", 128, 32 },
- { 0x1E, "SAMR21E16A", 64, 32 },
-};
-
-/* Known SAML21 parts. */
-static const struct samd_part saml21_parts[] = {
- { 0x00, "SAML21J18A", 256, 32 },
- { 0x01, "SAML21J17A", 128, 16 },
- { 0x02, "SAML21J16A", 64, 8 },
- { 0x05, "SAML21G18A", 256, 32 },
- { 0x06, "SAML21G17A", 128, 16 },
- { 0x07, "SAML21G16A", 64, 8 },
- { 0x0A, "SAML21E18A", 256, 32 },
- { 0x0B, "SAML21E17A", 128, 16 },
- { 0x0C, "SAML21E16A", 64, 8 },
- { 0x0D, "SAML21E15A", 32, 4 },
- { 0x0F, "SAML21J18B", 256, 32 },
- { 0x10, "SAML21J17B", 128, 16 },
- { 0x11, "SAML21J16B", 64, 8 },
- { 0x14, "SAML21G18B", 256, 32 },
- { 0x15, "SAML21G17B", 128, 16 },
- { 0x16, "SAML21G16B", 64, 8 },
- { 0x19, "SAML21E18B", 256, 32 },
- { 0x1A, "SAML21E17B", 128, 16 },
- { 0x1B, "SAML21E16B", 64, 8 },
- { 0x1C, "SAML21E15B", 32, 4 },
-};
-
-/* Known SAML22 parts. */
-static const struct samd_part saml22_parts[] = {
- { 0x00, "SAML22N18A", 256, 32 },
- { 0x01, "SAML22N17A", 128, 16 },
- { 0x02, "SAML22N16A", 64, 8 },
- { 0x05, "SAML22J18A", 256, 32 },
- { 0x06, "SAML22J17A", 128, 16 },
- { 0x07, "SAML22J16A", 64, 8 },
- { 0x0A, "SAML22G18A", 256, 32 },
- { 0x0B, "SAML22G17A", 128, 16 },
- { 0x0C, "SAML22G16A", 64, 8 },
-};
-
-/* Known SAMC20 parts. */
-static const struct samd_part samc20_parts[] = {
- { 0x00, "SAMC20J18A", 256, 32 },
- { 0x01, "SAMC20J17A", 128, 16 },
- { 0x02, "SAMC20J16A", 64, 8 },
- { 0x03, "SAMC20J15A", 32, 4 },
- { 0x05, "SAMC20G18A", 256, 32 },
- { 0x06, "SAMC20G17A", 128, 16 },
- { 0x07, "SAMC20G16A", 64, 8 },
- { 0x08, "SAMC20G15A", 32, 4 },
- { 0x0A, "SAMC20E18A", 256, 32 },
- { 0x0B, "SAMC20E17A", 128, 16 },
- { 0x0C, "SAMC20E16A", 64, 8 },
- { 0x0D, "SAMC20E15A", 32, 4 },
-};
-
-/* Known SAMC21 parts. */
-static const struct samd_part samc21_parts[] = {
- { 0x00, "SAMC21J18A", 256, 32 },
- { 0x01, "SAMC21J17A", 128, 16 },
- { 0x02, "SAMC21J16A", 64, 8 },
- { 0x03, "SAMC21J15A", 32, 4 },
- { 0x05, "SAMC21G18A", 256, 32 },
- { 0x06, "SAMC21G17A", 128, 16 },
- { 0x07, "SAMC21G16A", 64, 8 },
- { 0x08, "SAMC21G15A", 32, 4 },
- { 0x0A, "SAMC21E18A", 256, 32 },
- { 0x0B, "SAMC21E17A", 128, 16 },
- { 0x0C, "SAMC21E16A", 64, 8 },
- { 0x0D, "SAMC21E15A", 32, 4 },
-};
-
-/* Each family of parts contains a parts table in the DEVSEL field of DID. The
- * processor ID, family ID, and series ID are used to determine which exact
- * family this is and then we can use the corresponding table. */
-struct samd_family {
- uint8_t processor;
- uint8_t family;
- uint8_t series;
- const struct samd_part *parts;
- size_t num_parts;
-};
-
-/* Known SAMD families */
-static const struct samd_family samd_families[] = {
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_20,
- samd20_parts, ARRAY_SIZE(samd20_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
- samd21_parts, ARRAY_SIZE(samd21_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
- samr21_parts, ARRAY_SIZE(samr21_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_09,
- samd09_parts, ARRAY_SIZE(samd09_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_10,
- samd10_parts, ARRAY_SIZE(samd10_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_11,
- samd11_parts, ARRAY_SIZE(samd11_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_21,
- saml21_parts, ARRAY_SIZE(saml21_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_22,
- saml22_parts, ARRAY_SIZE(saml22_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_20,
- samc20_parts, ARRAY_SIZE(samc20_parts) },
- { SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_21,
- samc21_parts, ARRAY_SIZE(samc21_parts) },
-};
-
-struct samd_info {
- uint32_t page_size;
- int num_pages;
- int sector_size;
-
- bool probed;
- struct target *target;
- struct samd_info *next;
-};
-
-static struct samd_info *samd_chips;
-
-
-
-static const struct samd_part *samd_find_part(uint32_t id)
-{
- uint8_t processor = SAMD_GET_PROCESSOR(id);
- uint8_t family = SAMD_GET_FAMILY(id);
- uint8_t series = SAMD_GET_SERIES(id);
- uint8_t devsel = SAMD_GET_DEVSEL(id);
-
- for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) {
- if (samd_families[i].processor == processor &&
- samd_families[i].series == series &&
- samd_families[i].family == family) {
- for (unsigned j = 0; j < samd_families[i].num_parts; j++) {
- if (samd_families[i].parts[j].id == devsel)
- return &samd_families[i].parts[j];
- }
- }
- }
-
- return NULL;
-}
-
-static int samd_protect_check(struct flash_bank *bank)
-{
- int res;
- uint16_t lock;
-
- res = target_read_u16(bank->target,
- SAMD_NVMCTRL + SAMD_NVMCTRL_LOCK, &lock);
- if (res != ERROR_OK)
- return res;
-
- /* Lock bits are active-low */
- for (int i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_protected = !(lock & (1<<i));
-
- return ERROR_OK;
-}
-
-static int samd_get_flash_page_info(struct target *target,
- uint32_t *sizep, int *nump)
-{
- int res;
- uint32_t param;
-
- res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_PARAM, &param);
- if (res == ERROR_OK) {
- /* The PSZ field (bits 18:16) indicate the page size bytes as 2^(3+n)
- * so 0 is 8KB and 7 is 1024KB. */
- if (sizep)
- *sizep = (8 << ((param >> 16) & 0x7));
- /* The NVMP field (bits 15:0) indicates the total number of pages */
- if (nump)
- *nump = param & 0xFFFF;
- } else {
- LOG_ERROR("Couldn't read NVM Parameters register");
- }
-
- return res;
-}
-
-static int samd_probe(struct flash_bank *bank)
-{
- uint32_t id;
- int res;
- struct samd_info *chip = (struct samd_info *)bank->driver_priv;
- const struct samd_part *part;
-
- if (chip->probed)
- return ERROR_OK;
-
- res = target_read_u32(bank->target, SAMD_DSU + SAMD_DSU_DID, &id);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read Device ID register");
- return res;
- }
-
- part = samd_find_part(id);
- if (part == NULL) {
- LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id);
- return ERROR_FAIL;
- }
-
- bank->size = part->flash_kb * 1024;
-
- chip->sector_size = bank->size / SAMD_NUM_SECTORS;
-
- res = samd_get_flash_page_info(bank->target, &chip->page_size,
- &chip->num_pages);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't determine Flash page size");
- return res;
- }
-
- /* Sanity check: the total flash size in the DSU should match the page size
- * multiplied by the number of pages. */
- if (bank->size != chip->num_pages * chip->page_size) {
- LOG_WARNING("SAMD: bank size doesn't match NVM parameters. "
- "Identified %" PRIu32 "KB Flash but NVMCTRL reports %u %" PRIu32 "B pages",
- part->flash_kb, chip->num_pages, chip->page_size);
- }
-
- /* Allocate the sector table */
- bank->num_sectors = SAMD_NUM_SECTORS;
- bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0]));
- if (!bank->sectors)
- return ERROR_FAIL;
-
- /* Fill out the sector information: all SAMD sectors are the same size and
- * there is always a fixed number of them. */
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].size = chip->sector_size;
- bank->sectors[i].offset = i * chip->sector_size;
- /* mark as unknown */
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- samd_protect_check(bank);
-
- /* Done */
- chip->probed = true;
-
- LOG_INFO("SAMD MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name,
- part->flash_kb, part->ram_kb);
-
- return ERROR_OK;
-}
-
-static bool samd_check_error(struct target *target)
-{
- int ret;
- bool error;
- uint16_t status;
-
- ret = target_read_u16(target,
- SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);
- if (ret != ERROR_OK) {
- LOG_ERROR("Can't read NVM status");
- return true;
- }
-
- if (status & 0x001C) {
- if (status & (1 << 4)) /* NVME */
- LOG_ERROR("SAMD: NVM Error");
- if (status & (1 << 3)) /* LOCKE */
- LOG_ERROR("SAMD: NVM lock error");
- if (status & (1 << 2)) /* PROGE */
- LOG_ERROR("SAMD: NVM programming error");
-
- error = true;
- } else {
- error = false;
- }
-
- /* Clear the error conditions by writing a one to them */
- ret = target_write_u16(target,
- SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status);
- if (ret != ERROR_OK)
- LOG_ERROR("Can't clear NVM error conditions");
-
- return error;
-}
-
-static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
-{
- int res;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Issue the NVM command */
- res = target_write_u16(target,
- SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLA, SAMD_NVM_CMD(cmd));
- if (res != ERROR_OK)
- return res;
-
- /* Check to see if the NVM command resulted in an error condition. */
- if (samd_check_error(target))
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int samd_erase_row(struct target *target, uint32_t address)
-{
- int res;
-
- /* Set an address contained in the row to be erased */
- res = target_write_u32(target,
- SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR, address >> 1);
-
- /* Issue the Erase Row command to erase that row. */
- if (res == ERROR_OK)
- res = samd_issue_nvmctrl_command(target,
- address == SAMD_USER_ROW ? SAMD_NVM_CMD_EAR : SAMD_NVM_CMD_ER);
-
- if (res != ERROR_OK) {
- LOG_ERROR("Failed to erase row containing %08" PRIx32, address);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static bool is_user_row_reserved_bit(uint8_t bit)
-{
- /* See Table 9-3 in the SAMD20 datasheet for more information. */
- switch (bit) {
- /* Reserved bits */
- case 3:
- case 7:
- /* Voltage regulator internal configuration with default value of 0x70,
- * may not be changed. */
- case 17 ... 24:
- /* 41 is voltage regulator internal configuration and must not be
- * changed. 42 through 47 are reserved. */
- case 41 ... 47:
- return true;
- default:
- break;
- }
-
- return false;
-}
-
-/* Modify the contents of the User Row in Flash. These are described in Table
- * 9-3 of the SAMD20 datasheet. The User Row itself has a size of one page
- * and contains a combination of "fuses" and calibration data in bits 24:17.
- * We therefore try not to erase the row's contents unless we absolutely have
- * to and we don't permit modifying reserved bits. */
-static int samd_modify_user_row(struct target *target, uint32_t value,
- uint8_t startb, uint8_t endb)
-{
- int res;
-
- if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) {
- LOG_ERROR("Can't modify bits in the requested range");
- return ERROR_FAIL;
- }
-
- /* Retrieve the MCU's page size, in bytes. This is also the size of the
- * entire User Row. */
- uint32_t page_size;
- res = samd_get_flash_page_info(target, &page_size, NULL);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't determine Flash page size");
- return res;
- }
-
- /* Make sure the size is sane before we allocate. */
- assert(page_size > 0 && page_size <= SAMD_PAGE_SIZE_MAX);
-
- /* Make sure we're within the single page that comprises the User Row. */
- if (startb >= (page_size * 8) || endb >= (page_size * 8)) {
- LOG_ERROR("Can't modify bits outside the User Row page range");
- return ERROR_FAIL;
- }
-
- uint8_t *buf = malloc(page_size);
- if (!buf)
- return ERROR_FAIL;
-
- /* Read the user row (comprising one page) by half-words. */
- res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf);
- if (res != ERROR_OK)
- goto out_user_row;
-
- /* We will need to erase before writing if the new value needs a '1' in any
- * position for which the current value had a '0'. Otherwise we can avoid
- * erasing. */
- uint32_t cur = buf_get_u32(buf, startb, endb - startb + 1);
- if ((~cur) & value) {
- res = samd_erase_row(target, SAMD_USER_ROW);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't erase user row");
- goto out_user_row;
- }
- }
-
- /* Modify */
- buf_set_u32(buf, startb, endb - startb + 1, value);
-
- /* Write the page buffer back out to the target. A Flash write will be
- * triggered automatically. */
- res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
- if (res != ERROR_OK)
- goto out_user_row;
-
- if (samd_check_error(target)) {
- res = ERROR_FAIL;
- goto out_user_row;
- }
-
- /* Success */
- res = ERROR_OK;
-
-out_user_row:
- free(buf);
-
- return res;
-}
-
-static int samd_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct samd_info *chip = (struct samd_info *)bank->driver_priv;
-
- /* We can issue lock/unlock region commands with the target running but
- * the settings won't persist unless we're able to modify the LOCK regions
- * and that requires the target to be halted. */
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int res = ERROR_OK;
-
- for (int s = first; s <= last; s++) {
- if (set != bank->sectors[s].is_protected) {
- /* Load an address that is within this sector (we use offset 0) */
- res = target_write_u32(bank->target,
- SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR,
- ((s * chip->sector_size) >> 1));
- if (res != ERROR_OK)
- goto exit;
-
- /* Tell the controller to lock that sector */
- res = samd_issue_nvmctrl_command(bank->target,
- set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR);
- if (res != ERROR_OK)
- goto exit;
- }
- }
-
- /* We've now applied our changes, however they will be undone by the next
- * reset unless we also apply them to the LOCK bits in the User Page. The
- * LOCK bits start at bit 48, corresponding to Sector 0 and end with bit 63,
- * corresponding to Sector 15. A '1' means unlocked and a '0' means
- * locked. See Table 9-3 in the SAMD20 datasheet for more details. */
-
- res = samd_modify_user_row(bank->target, set ? 0x0000 : 0xFFFF,
- 48 + first, 48 + last);
- if (res != ERROR_OK)
- LOG_WARNING("SAMD: protect settings were not made persistent!");
-
- res = ERROR_OK;
-
-exit:
- samd_protect_check(bank);
-
- return res;
-}
-
-static int samd_erase(struct flash_bank *bank, int first, int last)
-{
- int res;
- int rows_in_sector;
- struct samd_info *chip = (struct samd_info *)bank->driver_priv;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
-
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!chip->probed) {
- if (samd_probe(bank) != ERROR_OK)
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /* The SAMD NVM has row erase granularity. There are four pages in a row
- * and the number of rows in a sector depends on the sector size, which in
- * turn depends on the Flash capacity as there is a fixed number of
- * sectors. */
- rows_in_sector = chip->sector_size / (chip->page_size * 4);
-
- /* For each sector to be erased */
- for (int s = first; s <= last; s++) {
- if (bank->sectors[s].is_protected) {
- LOG_ERROR("SAMD: failed to erase sector %d. That sector is write-protected", s);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* For each row in that sector */
- for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) {
- res = samd_erase_row(bank->target, r * chip->page_size * 4);
- if (res != ERROR_OK) {
- LOG_ERROR("SAMD: failed to erase sector %d", s);
- return res;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-
-static int samd_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- int res;
- uint32_t nvm_ctrlb;
- uint32_t address;
- uint32_t pg_offset;
- uint32_t nb;
- uint32_t nw;
- struct samd_info *chip = (struct samd_info *)bank->driver_priv;
- uint8_t *pb = NULL;
- bool manual_wp;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!chip->probed) {
- if (samd_probe(bank) != ERROR_OK)
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /* Check if we need to do manual page write commands */
- res = target_read_u32(bank->target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &nvm_ctrlb);
-
- if (res != ERROR_OK)
- return res;
-
- if (nvm_ctrlb & SAMD_NVM_CTRLB_MANW)
- manual_wp = true;
- else
- manual_wp = false;
-
- res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_PBC);
- if (res != ERROR_OK) {
- LOG_ERROR("%s: %d", __func__, __LINE__);
- return res;
- }
-
- while (count) {
- nb = chip->page_size - offset % chip->page_size;
- if (count < nb)
- nb = count;
-
- address = bank->base + offset;
- pg_offset = offset % chip->page_size;
-
- if (offset % 4 || (offset + nb) % 4) {
- /* Either start or end of write is not word aligned */
- if (!pb) {
- pb = malloc(chip->page_size);
- if (!pb)
- return ERROR_FAIL;
- }
-
- /* Set temporary page buffer to 0xff and overwrite the relevant part */
- memset(pb, 0xff, chip->page_size);
- memcpy(pb + pg_offset, buffer, nb);
-
- /* Align start address to a word boundary */
- address -= offset % 4;
- pg_offset -= offset % 4;
- assert(pg_offset % 4 == 0);
-
- /* Extend length to whole words */
- nw = (nb + offset % 4 + 3) / 4;
- assert(pg_offset + 4 * nw <= chip->page_size);
-
- /* Now we have original data extended by 0xff bytes
- * to the nearest word boundary on both start and end */
- res = target_write_memory(bank->target, address, 4, nw, pb + pg_offset);
- } else {
- assert(nb % 4 == 0);
- nw = nb / 4;
- assert(pg_offset + 4 * nw <= chip->page_size);
-
- /* Word aligned data, use direct write from buffer */
- res = target_write_memory(bank->target, address, 4, nw, buffer);
- }
- if (res != ERROR_OK) {
- LOG_ERROR("%s: %d", __func__, __LINE__);
- goto free_pb;
- }
-
- /* Devices with errata 13134 have automatic page write enabled by default
- * For other devices issue a write page CMD to the NVM
- * If the page has not been written up to the last word
- * then issue CMD_WP always */
- if (manual_wp || pg_offset + 4 * nw < chip->page_size) {
- res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_WP);
- if (res != ERROR_OK) {
- LOG_ERROR("%s: %d", __func__, __LINE__);
- goto free_pb;
- }
- }
-
- /* Access through AHB is stalled while flash is being programmed */
- usleep(200);
-
- if (samd_check_error(bank->target)) {
- LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address);
- res = ERROR_FAIL;
- goto free_pb;
- }
-
- /* We're done with the page contents */
- count -= nb;
- offset += nb;
- buffer += nb;
- }
-
-free_pb:
- if (pb)
- free(pb);
-
- return res;
-}
-
-FLASH_BANK_COMMAND_HANDLER(samd_flash_bank_command)
-{
- struct samd_info *chip = samd_chips;
-
- while (chip) {
- if (chip->target == bank->target)
- break;
- chip = chip->next;
- }
-
- if (!chip) {
- /* Create a new chip */
- chip = calloc(1, sizeof(*chip));
- if (!chip)
- return ERROR_FAIL;
-
- chip->target = bank->target;
- chip->probed = false;
-
- bank->driver_priv = chip;
-
- /* Insert it into the chips list (at head) */
- chip->next = samd_chips;
- samd_chips = chip;
- }
-
- if (bank->base != SAMD_FLASH) {
- LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32
- "[at91samd series] )",
- bank->base, SAMD_FLASH);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(samd_handle_info_command)
-{
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(samd_handle_chip_erase_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- if (target) {
- /* Enable access to the DSU by disabling the write protect bit */
- target_write_u32(target, SAMD_PAC1, (1<<1));
- /* Tell the DSU to perform a full chip erase. It takes about 240ms to
- * perform the erase. */
- target_write_u8(target, SAMD_DSU, (1<<4));
-
- command_print(CMD_CTX, "chip erased");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(samd_handle_set_security_command)
-{
- int res = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
-
- if (CMD_ARGC < 1 || (CMD_ARGC >= 1 && (strcmp(CMD_ARGV[0], "enable")))) {
- command_print(CMD_CTX, "supply the \"enable\" argument to proceed.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (target) {
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_SSB);
-
- /* Check (and clear) error conditions */
- if (res == ERROR_OK)
- command_print(CMD_CTX, "chip secured on next power-cycle");
- else
- command_print(CMD_CTX, "failed to secure chip");
- }
-
- return res;
-}
-
-COMMAND_HANDLER(samd_handle_eeprom_command)
-{
- int res = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
-
- if (target) {
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (CMD_ARGC >= 1) {
- int val = atoi(CMD_ARGV[0]);
- uint32_t code;
-
- if (val == 0)
- code = 7;
- else {
- /* Try to match size in bytes with corresponding size code */
- for (code = 0; code <= 6; code++) {
- if (val == (2 << (13 - code)))
- break;
- }
-
- if (code > 6) {
- command_print(CMD_CTX, "Invalid EEPROM size. Please see "
- "datasheet for a list valid sizes.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- res = samd_modify_user_row(target, code, 4, 6);
- } else {
- uint16_t val;
- res = target_read_u16(target, SAMD_USER_ROW, &val);
- if (res == ERROR_OK) {
- uint32_t size = ((val >> 4) & 0x7); /* grab size code */
-
- if (size == 0x7)
- command_print(CMD_CTX, "EEPROM is disabled");
- else {
- /* Otherwise, 6 is 256B, 0 is 16KB */
- command_print(CMD_CTX, "EEPROM size is %u bytes",
- (2 << (13 - size)));
- }
- }
- }
- }
-
- return res;
-}
-
-COMMAND_HANDLER(samd_handle_bootloader_command)
-{
- int res = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
-
- if (target) {
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Retrieve the MCU's page size, in bytes. */
- uint32_t page_size;
- res = samd_get_flash_page_info(target, &page_size, NULL);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't determine Flash page size");
- return res;
- }
-
- if (CMD_ARGC >= 1) {
- int val = atoi(CMD_ARGV[0]);
- uint32_t code;
-
- if (val == 0)
- code = 7;
- else {
- /* Try to match size in bytes with corresponding size code */
- for (code = 0; code <= 6; code++) {
- if ((unsigned int)val == (2UL << (8UL - code)) * page_size)
- break;
- }
-
- if (code > 6) {
- command_print(CMD_CTX, "Invalid bootloader size. Please "
- "see datasheet for a list valid sizes.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- }
-
- res = samd_modify_user_row(target, code, 0, 2);
- } else {
- uint16_t val;
- res = target_read_u16(target, SAMD_USER_ROW, &val);
- if (res == ERROR_OK) {
- uint32_t size = (val & 0x7); /* grab size code */
- uint32_t nb;
-
- if (size == 0x7)
- nb = 0;
- else
- nb = (2 << (8 - size)) * page_size;
-
- /* There are 4 pages per row */
- command_print(CMD_CTX, "Bootloader size is %" PRIu32 " bytes (%" PRIu32 " rows)",
- nb, (uint32_t)(nb / (page_size * 4)));
- }
- }
- }
-
- return res;
-}
-
-
-
-COMMAND_HANDLER(samd_handle_reset_deassert)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- int retval = ERROR_OK;
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset()
- * so we just release reset held by DSU
- *
- * n_RESET (srst) clears the DP, so reenable debug and set vector catch here
- *
- * After vectreset DSU release is not needed however makes no harm
- */
- if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
- if (retval == ERROR_OK)
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR,
- TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
- /* do not return on error here, releasing DSU reset is more important */
- }
-
- /* clear CPU Reset Phase Extension bit */
- int retval2 = target_write_u8(target, SAMD_DSU + SAMD_DSU_STATUSA, (1<<1));
- if (retval2 != ERROR_OK)
- return retval2;
-
- return retval;
-}
-
-static const struct command_registration at91samd_exec_command_handlers[] = {
- {
- .name = "dsu_reset_deassert",
- .handler = samd_handle_reset_deassert,
- .mode = COMMAND_EXEC,
- .help = "deasert internal reset held by DSU"
- },
- {
- .name = "info",
- .handler = samd_handle_info_command,
- .mode = COMMAND_EXEC,
- .help = "Print information about the current at91samd chip"
- "and its flash configuration.",
- },
- {
- .name = "chip-erase",
- .handler = samd_handle_chip_erase_command,
- .mode = COMMAND_EXEC,
- .help = "Erase the entire Flash by using the Chip"
- "Erase feature in the Device Service Unit (DSU).",
- },
- {
- .name = "set-security",
- .handler = samd_handle_set_security_command,
- .mode = COMMAND_EXEC,
- .help = "Secure the chip's Flash by setting the Security Bit."
- "This makes it impossible to read the Flash contents."
- "The only way to undo this is to issue the chip-erase"
- "command.",
- },
- {
- .name = "eeprom",
- .usage = "[size_in_bytes]",
- .handler = samd_handle_eeprom_command,
- .mode = COMMAND_EXEC,
- .help = "Show or set the EEPROM size setting, stored in the User Row."
- "Please see Table 20-3 of the SAMD20 datasheet for allowed values."
- "Changes are stored immediately but take affect after the MCU is"
- "reset.",
- },
- {
- .name = "bootloader",
- .usage = "[size_in_bytes]",
- .handler = samd_handle_bootloader_command,
- .mode = COMMAND_EXEC,
- .help = "Show or set the bootloader size, stored in the User Row."
- "Please see Table 20-2 of the SAMD20 datasheet for allowed values."
- "Changes are stored immediately but take affect after the MCU is"
- "reset.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration at91samd_command_handlers[] = {
- {
- .name = "at91samd",
- .mode = COMMAND_ANY,
- .help = "at91samd flash command group",
- .usage = "",
- .chain = at91samd_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver at91samd_flash = {
- .name = "at91samd",
- .commands = at91samd_command_handlers,
- .flash_bank_command = samd_flash_bank_command,
- .erase = samd_erase,
- .protect = samd_protect,
- .write = samd_write,
- .read = default_flash_read,
- .probe = samd_probe,
- .auto_probe = samd_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = samd_protect_check,
-};
diff --git a/src/flash/nor/atsamv.c b/src/flash/nor/atsamv.c
deleted file mode 100644
index d21419d..0000000
--- a/src/flash/nor/atsamv.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Duane Ellis *
- * openocd@duaneellis.com *
- * *
- * Copyright (C) 2010 by Olaf Lüke (at91sam3s* support) *
- * olaf@uni-paderborn.de *
- * *
- * Copyright (C) 2011 by Olivier Schonken, Jim Norris *
- * (at91sam3x* & at91sam4 support)* *
- * *
- * Copyright (C) 2015 Morgan Quigley *
- * (atsamv, atsams, and atsame support) *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* Some of the the lower level code was based on code supplied by
- * ATMEL under this copyright. */
-
-/* BEGIN ATMEL COPYRIGHT */
-/* ----------------------------------------------------------------------------
- * ATMEL Microcontroller Software Support
- * ----------------------------------------------------------------------------
- * Copyright (c) 2009, Atmel Corporation
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the disclaimer below.
- *
- * Atmel's name may not be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * ----------------------------------------------------------------------------
- */
-/* END ATMEL COPYRIGHT */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/time_support.h>
-
-#define REG_NAME_WIDTH (12)
-
-#define SAMV_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
-#define SAMV_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
-#define SAMV_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
-#define SAMV_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */
-#define SAMV_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page, Write Page then Lock*/
-#define SAMV_EFC_FCMD_EA (0x5) /* (EFC) Erase All */
-#define SAMV_EFC_FCMD_EPA (0x7) /* (EFC) Erase pages */
-#define SAMV_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */
-#define SAMV_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */
-#define SAMV_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */
-#define SAMV_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
-#define SAMV_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
-#define SAMV_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
-
-#define OFFSET_EFC_FMR 0
-#define OFFSET_EFC_FCR 4
-#define OFFSET_EFC_FSR 8
-#define OFFSET_EFC_FRR 12
-
-#define SAMV_CHIPID_CIDR (0x400E0940)
-#define SAMV_NUM_GPNVM_BITS 9
-#define SAMV_CONTROLLER_ADDR (0x400e0c00)
-#define SAMV_SECTOR_SIZE 16384
-#define SAMV_PAGE_SIZE 512
-#define SAMV_FLASH_BASE 0x00400000
-
-extern struct flash_driver atsamv_flash;
-
-struct samv_flash_bank {
- int probed;
- unsigned size_bytes;
- unsigned gpnvm[SAMV_NUM_GPNVM_BITS];
-};
-
-/* The actual sector size of the SAMV7 flash memory is 128K bytes.
- * 16 sectors for a 2048KB device. The lock regions are 16KB per lock
- * region, with a 2048KB device having 128 lock regions.
- * For the best results, num_sectors is thus set to the number of lock
- * regions, and the sector_size set to the lock region size. Page
- * erases are used to erase 16KB sections when programming */
-
-static int samv_efc_get_status(struct target *target, uint32_t *v)
-{
- int r = target_read_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FSR, v);
- return r;
-}
-
-static int samv_efc_get_result(struct target *target, uint32_t *v)
-{
- uint32_t rv;
- int r = target_read_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FRR, &rv);
- if (v)
- *v = rv;
- return r;
-}
-
-static int samv_efc_start_command(struct target *target,
- unsigned command, unsigned argument)
-{
- uint32_t v;
- samv_efc_get_status(target, &v);
- if (!(v & 1)) {
- LOG_ERROR("flash controller is not ready");
- return ERROR_FAIL;
- }
-
- v = (0x5A << 24) | (argument << 8) | command;
- LOG_DEBUG("starting flash command: 0x%08x", (unsigned int)(v));
- int r = target_write_u32(target, SAMV_CONTROLLER_ADDR + OFFSET_EFC_FCR, v);
- if (r != ERROR_OK)
- LOG_DEBUG("write failed");
- return r;
-}
-
-static int samv_efc_perform_command(struct target *target,
- unsigned command, unsigned argument, uint32_t *status)
-{
- int r;
- uint32_t v;
- int64_t ms_now, ms_end;
-
- if (status)
- *status = 0;
-
- r = samv_efc_start_command(target, command, argument);
- if (r != ERROR_OK)
- return r;
-
- ms_end = 10000 + timeval_ms();
-
- do {
- r = samv_efc_get_status(target, &v);
- if (r != ERROR_OK)
- return r;
- ms_now = timeval_ms();
- if (ms_now > ms_end) {
- /* error */
- LOG_ERROR("Command timeout");
- return ERROR_FAIL;
- }
- } while ((v & 1) == 0);
-
- /* if requested, copy the flash controller error bits back to the caller */
- if (status)
- *status = (v & 0x6);
- return ERROR_OK;
-}
-
-static int samv_erase_pages(struct target *target,
- int first_page, int num_pages, uint32_t *status)
-{
- uint8_t erase_pages;
- switch (num_pages) {
- case 4:
- erase_pages = 0x00;
- break;
- case 8:
- erase_pages = 0x01;
- break;
- case 16:
- erase_pages = 0x02;
- break;
- case 32:
- erase_pages = 0x03;
- break;
- default:
- erase_pages = 0x00;
- break;
- }
-
- /* SAMV_EFC_FCMD_EPA
- * According to the datasheet FARG[15:2] defines the page from which
- * the erase will start.This page must be modulo 4, 8, 16 or 32
- * according to the number of pages to erase. FARG[1:0] defines the
- * number of pages to be erased. Previously (firstpage << 2) was used
- * to conform to this, seems it should not be shifted...
- */
- return samv_efc_perform_command(target, SAMV_EFC_FCMD_EPA,
- first_page | erase_pages, status);
-}
-
-static int samv_get_gpnvm(struct target *target, unsigned gpnvm, unsigned *out)
-{
- uint32_t v;
- int r;
-
- if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
- LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
- return ERROR_FAIL;
- }
-
- r = samv_efc_perform_command(target, SAMV_EFC_FCMD_GFB, 0, NULL);
- if (r != ERROR_OK) {
- LOG_ERROR("samv_get_gpnvm failed");
- return r;
- }
-
- r = samv_efc_get_result(target, &v);
-
- if (out)
- *out = (v >> gpnvm) & 1;
-
- return r;
-}
-
-static int samv_clear_gpnvm(struct target *target, unsigned gpnvm)
-{
- int r;
- unsigned v;
-
- if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
- LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
- return ERROR_FAIL;
- }
- r = samv_get_gpnvm(target, gpnvm, &v);
- if (r != ERROR_OK) {
- LOG_DEBUG("get gpnvm failed: %d", r);
- return r;
- }
- r = samv_efc_perform_command(target, SAMV_EFC_FCMD_CFB, gpnvm, NULL);
- LOG_DEBUG("clear gpnvm result: %d", r);
- return r;
-}
-
-static int samv_set_gpnvm(struct target *target, unsigned gpnvm)
-{
- int r;
- unsigned v;
- if (gpnvm >= SAMV_NUM_GPNVM_BITS) {
- LOG_ERROR("invalid gpnvm %d, max: %d", gpnvm, SAMV_NUM_GPNVM_BITS);
- return ERROR_FAIL;
- }
-
- r = samv_get_gpnvm(target, gpnvm, &v);
- if (r != ERROR_OK)
- return r;
- if (v) {
- r = ERROR_OK; /* the gpnvm bit is already set */
- } else {
- /* we need to set it */
- r = samv_efc_perform_command(target, SAMV_EFC_FCMD_SFB, gpnvm, NULL);
- }
- return r;
-}
-
-static int samv_flash_unlock(struct target *target,
- unsigned start_sector, unsigned end_sector)
-{
- int r;
- uint32_t status;
- uint32_t pg;
- uint32_t pages_per_sector;
-
- /* todo: look into this... i think this should be done on lock regions */
- pages_per_sector = SAMV_SECTOR_SIZE / SAMV_PAGE_SIZE;
- while (start_sector <= end_sector) {
- pg = start_sector * pages_per_sector;
- r = samv_efc_perform_command(target, SAMV_EFC_FCMD_CLB, pg, &status);
- if (r != ERROR_OK)
- return r;
- start_sector++;
- }
- return ERROR_OK;
-}
-
-static int samv_flash_lock(struct target *target,
- unsigned start_sector, unsigned end_sector)
-{
- uint32_t status;
- uint32_t pg;
- uint32_t pages_per_sector;
- int r;
-
- /* todo: look into this... i think this should be done on lock regions */
- pages_per_sector = SAMV_SECTOR_SIZE / SAMV_PAGE_SIZE;
- while (start_sector <= end_sector) {
- pg = start_sector * pages_per_sector;
- r = samv_efc_perform_command(target, SAMV_EFC_FCMD_SLB, pg, &status);
- if (r != ERROR_OK)
- return r;
- start_sector++;
- }
- return ERROR_OK;
-}
-
-static int samv_protect_check(struct flash_bank *bank)
-{
- int r;
- uint32_t v[4] = {0};
-
- r = samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_GLB, 0, NULL);
- if (r == ERROR_OK) {
- samv_efc_get_result(bank->target, &v[0]);
- samv_efc_get_result(bank->target, &v[1]);
- samv_efc_get_result(bank->target, &v[2]);
- r = samv_efc_get_result(bank->target, &v[3]);
- }
- if (r != ERROR_OK)
- return r;
-
- for (int x = 0; x < bank->num_sectors; x++)
- bank->sectors[x].is_protected = (!!(v[x >> 5] & (1 << (x % 32))));
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(samv_flash_bank_command)
-{
- LOG_INFO("flash bank command");
- struct samv_flash_bank *samv_info;
- samv_info = calloc(1, sizeof(struct samv_flash_bank));
- bank->driver_priv = samv_info;
- return ERROR_OK;
-}
-
-static int samv_get_device_id(struct flash_bank *bank, uint32_t *device_id)
-{
- return target_read_u32(bank->target, SAMV_CHIPID_CIDR, device_id);
-}
-
-static int samv_probe(struct flash_bank *bank)
-{
- uint32_t device_id;
- int r = samv_get_device_id(bank, &device_id);
- if (r != ERROR_OK)
- return r;
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
-
- uint8_t eproc = (device_id >> 5) & 0x7;
- if (eproc != 0) {
- LOG_ERROR("unexpected eproc code: %d was expecting 0 (Cortex-M7)", eproc);
- return ERROR_FAIL;
- }
-
- uint8_t nvm_size_code = (device_id >> 8) & 0xf;
- switch (nvm_size_code) {
- case 12:
- bank->size = 1024 * 1024;
- break;
- case 14:
- bank->size = 2048 * 1024;
- break;
- default:
- LOG_ERROR("unrecognized flash size code: %d", nvm_size_code);
- return ERROR_FAIL;
- break;
- }
-
- struct samv_flash_bank *samv_info = bank->driver_priv;
- samv_info->size_bytes = bank->size;
- samv_info->probed = 1;
-
- bank->base = SAMV_FLASH_BASE;
- bank->num_sectors = bank->size / SAMV_SECTOR_SIZE;
- bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
- for (int s = 0; s < (int)bank->num_sectors; s++) {
- bank->sectors[s].size = SAMV_SECTOR_SIZE;
- bank->sectors[s].offset = s * SAMV_SECTOR_SIZE;
- bank->sectors[s].is_erased = -1;
- bank->sectors[s].is_protected = -1;
- }
-
- r = samv_protect_check(bank);
- if (r != ERROR_OK)
- return r;
-
- return ERROR_OK;
-}
-
-static int samv_auto_probe(struct flash_bank *bank)
-{
- struct samv_flash_bank *samv_info = bank->driver_priv;
- if (samv_info->probed)
- return ERROR_OK;
- return samv_probe(bank);
-}
-
-static int samv_erase(struct flash_bank *bank, int first, int last)
-{
- const int page_count = 32; /* 32 pages equals 16 KB lock region */
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int r = samv_auto_probe(bank);
- if (r != ERROR_OK)
- return r;
-
- /* easy case: we've been requested to erase the entire flash */
- if ((first == 0) && ((last + 1) == (int)(bank->num_sectors)))
- return samv_efc_perform_command(bank->target, SAMV_EFC_FCMD_EA, 0, NULL);
-
- LOG_INFO("erasing lock regions %d-%d...", first, last);
-
- for (int i = first; i <= last; i++) {
- uint32_t status;
- r = samv_erase_pages(bank->target, (i * page_count), page_count, &status);
- LOG_INFO("erasing lock region %d", i);
- if (r != ERROR_OK)
- LOG_ERROR("error performing erase page @ lock region number %d",
- (unsigned int)(i));
- if (status & (1 << 2)) {
- LOG_ERROR("lock region %d is locked", (unsigned int)(i));
- return ERROR_FAIL;
- }
- if (status & (1 << 1)) {
- LOG_ERROR("flash command error @lock region %d", (unsigned int)(i));
- return ERROR_FAIL;
- }
- }
- return ERROR_OK;
-}
-
-static int samv_protect(struct flash_bank *bank, int set, int first, int last)
-{
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int r;
- if (set)
- r = samv_flash_lock(bank->target, (unsigned)(first), (unsigned)(last));
- else
- r = samv_flash_unlock(bank->target, (unsigned)(first), (unsigned)(last));
-
- return r;
-}
-
-static int samv_page_read(struct target *target,
- unsigned page_num, uint8_t *buf)
-{
- uint32_t addr = SAMV_FLASH_BASE + page_num * SAMV_PAGE_SIZE;
- int r = target_read_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
- if (r != ERROR_OK)
- LOG_ERROR("flash program failed to read page @ 0x%08x",
- (unsigned int)(addr));
- return r;
-}
-
-static int samv_page_write(struct target *target,
- unsigned pagenum, const uint8_t *buf)
-{
- uint32_t status;
- const uint32_t addr = SAMV_FLASH_BASE + pagenum * SAMV_PAGE_SIZE;
- int r;
-
- LOG_DEBUG("write page %u at address 0x%08x", pagenum, (unsigned int)addr);
- r = target_write_memory(target, addr, 4, SAMV_PAGE_SIZE / 4, buf);
- if (r != ERROR_OK) {
- LOG_ERROR("failed to buffer page at 0x%08x", (unsigned int)addr);
- return r;
- }
-
- r = samv_efc_perform_command(target, SAMV_EFC_FCMD_WP, pagenum, &status);
- if (r != ERROR_OK)
- LOG_ERROR("error performing write page at 0x%08x", (unsigned int)addr);
- if (status & (1 << 2)) {
- LOG_ERROR("page at 0x%08x is locked", (unsigned int)addr);
- return ERROR_FAIL;
- }
- if (status & (1 << 1)) {
- LOG_ERROR("flash command error at 0x%08x", (unsigned int)addr);
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int samv_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (count == 0)
- return ERROR_OK;
-
- if ((offset + count) > bank->size) {
- LOG_ERROR("flash write error - past end of bank");
- LOG_ERROR(" offset: 0x%08x, count 0x%08x, bank end: 0x%08x",
- (unsigned int)(offset),
- (unsigned int)(count),
- (unsigned int)(bank->size));
- return ERROR_FAIL;
- }
-
- uint8_t pagebuffer[SAMV_PAGE_SIZE] = {0};
- uint32_t page_cur = offset / SAMV_PAGE_SIZE;
- uint32_t page_end = (offset + count - 1) / SAMV_PAGE_SIZE;
-
- LOG_DEBUG("offset: 0x%08x, count: 0x%08x",
- (unsigned int)(offset), (unsigned int)(count));
- LOG_DEBUG("page start: %d, page end: %d", (int)(page_cur), (int)(page_end));
-
- /* Special case: all one page */
- /* Otherwise: */
- /* (1) non-aligned start */
- /* (2) body pages */
- /* (3) non-aligned end. */
-
- int r;
- uint32_t page_offset;
-
- /* handle special case - all one page. */
- if (page_cur == page_end) {
- LOG_DEBUG("special case, all in one page");
- r = samv_page_read(bank->target, page_cur, pagebuffer);
- if (r != ERROR_OK)
- return r;
-
- page_offset = offset & (SAMV_PAGE_SIZE-1);
- memcpy(pagebuffer + page_offset, buffer, count);
-
- r = samv_page_write(bank->target, page_cur, pagebuffer);
- if (r != ERROR_OK)
- return r;
- return ERROR_OK;
- }
-
- /* step 1) handle the non-aligned starting address */
- page_offset = offset & (SAMV_PAGE_SIZE - 1);
- if (page_offset) {
- LOG_DEBUG("non-aligned start");
- /* read the partial page */
- r = samv_page_read(bank->target, page_cur, pagebuffer);
- if (r != ERROR_OK)
- return r;
-
- /* over-write with new data */
- uint32_t n = SAMV_PAGE_SIZE - page_offset;
- memcpy(pagebuffer + page_offset, buffer, n);
-
- r = samv_page_write(bank->target, page_cur, pagebuffer);
- if (r != ERROR_OK)
- return r;
-
- count -= n;
- offset += n;
- buffer += n;
- page_cur++;
- }
-
- /* By checking that offset is correct here, we also fix a clang warning */
- assert(offset % SAMV_PAGE_SIZE == 0);
-
- /* step 2) handle the full pages */
- LOG_DEBUG("full page loop: cur=%d, end=%d, count = 0x%08x",
- (int)page_cur, (int)page_end, (unsigned int)(count));
-
- while ((page_cur < page_end) && (count >= SAMV_PAGE_SIZE)) {
- r = samv_page_write(bank->target, page_cur, buffer);
- if (r != ERROR_OK)
- return r;
- count -= SAMV_PAGE_SIZE;
- buffer += SAMV_PAGE_SIZE;
- page_cur += 1;
- }
-
- /* step 3) write final page, if it's partial (otherwise it's already done) */
- if (count) {
- LOG_DEBUG("final partial page, count = 0x%08x", (unsigned int)(count));
- /* we have a partial page */
- r = samv_page_read(bank->target, page_cur, pagebuffer);
- if (r != ERROR_OK)
- return r;
- memcpy(pagebuffer, buffer, count); /* data goes at start of page */
- r = samv_page_write(bank->target, page_cur, pagebuffer);
- if (r != ERROR_OK)
- return r;
- }
- return ERROR_OK;
-}
-
-static int samv_get_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct samv_flash_bank *samv_info = bank->driver_priv;
- if (!samv_info->probed) {
- int r = samv_probe(bank);
- if (ERROR_OK != r)
- return r;
- }
- snprintf(buf, buf_size, "Cortex-M7 detected with %d kB flash",
- bank->size / 1024);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(samv_handle_gpnvm_command)
-{
- struct flash_bank *bank = get_flash_bank_by_num_noprobe(0);
- if (!bank)
- return ERROR_FAIL;
- struct samv_flash_bank *samv_info = bank->driver_priv;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int r;
- if (!samv_info->probed) {
- r = samv_auto_probe(bank);
- if (r != ERROR_OK)
- return r;
- }
-
- int who = 0;
-
- switch (CMD_ARGC) {
- case 0:
- goto showall;
- break;
- case 1:
- who = -1;
- break;
- case 2:
- if (!strcmp(CMD_ARGV[0], "show") && !strcmp(CMD_ARGV[1], "all"))
- who = -1;
- else {
- uint32_t v32;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], v32);
- who = v32;
- }
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- }
-
- uint32_t v;
- if (!strcmp("show", CMD_ARGV[0])) {
- if (who == -1) {
-showall:
- r = ERROR_OK;
- for (int x = 0; x < SAMV_NUM_GPNVM_BITS; x++) {
- r = samv_get_gpnvm(target, x, &v);
- if (r != ERROR_OK)
- break;
- command_print(CMD_CTX, "samv-gpnvm%u: %u", x, v);
- }
- return r;
- }
- if ((who >= 0) && (((unsigned)who) < SAMV_NUM_GPNVM_BITS)) {
- r = samv_get_gpnvm(target, who, &v);
- command_print(CMD_CTX, "samv-gpnvm%u: %u", who, v);
- return r;
- } else {
- command_print(CMD_CTX, "invalid gpnvm: %u", who);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- if (who == -1) {
- command_print(CMD_CTX, "missing gpnvm number");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (!strcmp("set", CMD_ARGV[0]))
- r = samv_set_gpnvm(target, who);
- else if (!strcmp("clr", CMD_ARGV[0]) || !strcmp("clear", CMD_ARGV[0]))
- r = samv_clear_gpnvm(target, who);
- else {
- command_print(CMD_CTX, "unknown command: %s", CMD_ARGV[0]);
- r = ERROR_COMMAND_SYNTAX_ERROR;
- }
- return r;
-}
-
-static const struct command_registration atsamv_exec_command_handlers[] = {
- {
- .name = "gpnvm",
- .handler = samv_handle_gpnvm_command,
- .mode = COMMAND_EXEC,
- .usage = "[('clr'|'set'|'show') bitnum]",
- .help = "Without arguments, shows all bits in the gpnvm "
- "register. Otherwise, clears, sets, or shows one "
- "General Purpose Non-Volatile Memory (gpnvm) bit.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration atsamv_command_handlers[] = {
- {
- .name = "atsamv",
- .mode = COMMAND_ANY,
- .help = "atsamv flash command group",
- .usage = "",
- .chain = atsamv_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver atsamv_flash = {
- .name = "atsamv",
- .commands = atsamv_command_handlers,
- .flash_bank_command = samv_flash_bank_command,
- .erase = samv_erase,
- .protect = samv_protect,
- .write = samv_write,
- .read = default_flash_read,
- .probe = samv_probe,
- .auto_probe = samv_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = samv_protect_check,
- .info = samv_get_info,
-};
diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c
deleted file mode 100644
index 627418c..0000000
--- a/src/flash/nor/avrf.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Simon Qian *
- * SimonQian@SimonQian.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <target/avrt.h>
-
-/* AVR_JTAG_Instructions */
-#define AVR_JTAG_INS_LEN 4
-/* Public Instructions: */
-#define AVR_JTAG_INS_EXTEST 0x00
-#define AVR_JTAG_INS_IDCODE 0x01
-#define AVR_JTAG_INS_SAMPLE_PRELOAD 0x02
-#define AVR_JTAG_INS_BYPASS 0x0F
-/* AVR Specified Public Instructions: */
-#define AVR_JTAG_INS_AVR_RESET 0x0C
-#define AVR_JTAG_INS_PROG_ENABLE 0x04
-#define AVR_JTAG_INS_PROG_COMMANDS 0x05
-#define AVR_JTAG_INS_PROG_PAGELOAD 0x06
-#define AVR_JTAG_INS_PROG_PAGEREAD 0x07
-
-/* Data Registers: */
-#define AVR_JTAG_REG_Bypass_Len 1
-#define AVR_JTAG_REG_DeviceID_Len 32
-
-#define AVR_JTAG_REG_Reset_Len 1
-#define AVR_JTAG_REG_JTAGID_Len 32
-#define AVR_JTAG_REG_ProgrammingEnable_Len 16
-#define AVR_JTAG_REG_ProgrammingCommand_Len 15
-#define AVR_JTAG_REG_FlashDataByte_Len 16
-
-struct avrf_type {
- char name[15];
- uint16_t chip_id;
- int flash_page_size;
- int flash_page_num;
- int eeprom_page_size;
- int eeprom_page_num;
-};
-
-struct avrf_flash_bank {
- int ppage_size;
- int probed;
-};
-
-static const struct avrf_type avft_chips_info[] = {
-/* name, chip_id, flash_page_size, flash_page_num,
- * eeprom_page_size, eeprom_page_num
- */
- {"atmega128", 0x9702, 256, 512, 8, 512},
- {"at90can128", 0x9781, 256, 512, 8, 512},
- {"at90usb128", 0x9782, 256, 512, 8, 512},
- {"atmega164p", 0x940a, 128, 128, 4, 128},
- {"atmega324p", 0x9508, 128, 256, 4, 256},
- {"atmega324pa", 0x9511, 128, 256, 4, 256},
- {"atmega644p", 0x960a, 256, 256, 8, 256},
- {"atmega1284p", 0x9705, 256, 512, 8, 512},
-};
-
-/* avr program functions */
-static int avr_jtag_reset(struct avr_common *avr, uint32_t reset)
-{
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_AVR_RESET);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, reset, AVR_JTAG_REG_Reset_Len);
-
- return ERROR_OK;
-}
-
-static int avr_jtag_read_jtagid(struct avr_common *avr, uint32_t *id)
-{
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_IDCODE);
- avr_jtag_senddat(avr->jtag_info.tap, id, 0, AVR_JTAG_REG_JTAGID_Len);
-
- return ERROR_OK;
-}
-
-static int avr_jtagprg_enterprogmode(struct avr_common *avr)
-{
- avr_jtag_reset(avr, 1);
-
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_ENABLE);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xA370, AVR_JTAG_REG_ProgrammingEnable_Len);
-
- return ERROR_OK;
-}
-
-static int avr_jtagprg_leaveprogmode(struct avr_common *avr)
-{
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2300, AVR_JTAG_REG_ProgrammingCommand_Len);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3300, AVR_JTAG_REG_ProgrammingCommand_Len);
-
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_ENABLE);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0, AVR_JTAG_REG_ProgrammingEnable_Len);
-
- avr_jtag_reset(avr, 0);
-
- return ERROR_OK;
-}
-
-static int avr_jtagprg_chiperase(struct avr_common *avr)
-{
- uint32_t poll_value;
-
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2380, AVR_JTAG_REG_ProgrammingCommand_Len);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3180, AVR_JTAG_REG_ProgrammingCommand_Len);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3380, AVR_JTAG_REG_ProgrammingCommand_Len);
-
- do {
- poll_value = 0;
- avr_jtag_senddat(avr->jtag_info.tap,
- &poll_value,
- 0x3380,
- AVR_JTAG_REG_ProgrammingCommand_Len);
- if (ERROR_OK != mcu_execute_queue())
- return ERROR_FAIL;
- LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
- } while (!(poll_value & 0x0200));
-
- return ERROR_OK;
-}
-
-static int avr_jtagprg_writeflashpage(struct avr_common *avr,
- const uint8_t *page_buf,
- uint32_t buf_size,
- uint32_t addr,
- uint32_t page_size)
-{
- uint32_t i, poll_value;
-
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len);
-
- /* load addr high byte */
- avr_jtag_senddat(avr->jtag_info.tap,
- NULL,
- 0x0700 | ((addr >> 9) & 0xFF),
- AVR_JTAG_REG_ProgrammingCommand_Len);
-
- /* load addr low byte */
- avr_jtag_senddat(avr->jtag_info.tap,
- NULL,
- 0x0300 | ((addr >> 1) & 0xFF),
- AVR_JTAG_REG_ProgrammingCommand_Len);
-
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGELOAD);
-
- for (i = 0; i < page_size; i++) {
- if (i < buf_size)
- avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8);
- else
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xFF, 8);
- }
-
- avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
-
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3500, AVR_JTAG_REG_ProgrammingCommand_Len);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len);
- avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, AVR_JTAG_REG_ProgrammingCommand_Len);
-
- do {
- poll_value = 0;
- avr_jtag_senddat(avr->jtag_info.tap,
- &poll_value,
- 0x3700,
- AVR_JTAG_REG_ProgrammingCommand_Len);
- if (ERROR_OK != mcu_execute_queue())
- return ERROR_FAIL;
- LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
- } while (!(poll_value & 0x0200));
-
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command)
-{
- struct avrf_flash_bank *avrf_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- avrf_info = malloc(sizeof(struct avrf_flash_bank));
- bank->driver_priv = avrf_info;
-
- avrf_info->probed = 0;
-
- return ERROR_OK;
-}
-
-static int avrf_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct avr_common *avr = target->arch_info;
- int status;
-
- LOG_DEBUG("%s", __func__);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- status = avr_jtagprg_enterprogmode(avr);
- if (status != ERROR_OK)
- return status;
-
- status = avr_jtagprg_chiperase(avr);
- if (status != ERROR_OK)
- return status;
-
- return avr_jtagprg_leaveprogmode(avr);
-}
-
-static int avrf_protect(struct flash_bank *bank, int set, int first, int last)
-{
- LOG_INFO("%s", __func__);
- return ERROR_OK;
-}
-
-static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct avr_common *avr = target->arch_info;
- uint32_t cur_size, cur_buffer_size, page_size;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- page_size = bank->sectors[0].size;
- if ((offset % page_size) != 0) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
- offset,
- page_size);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- LOG_DEBUG("offset is 0x%08" PRIx32 "", offset);
- LOG_DEBUG("count is %" PRId32 "", count);
-
- if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
- return ERROR_FAIL;
-
- cur_size = 0;
- while (count > 0) {
- if (count > page_size)
- cur_buffer_size = page_size;
- else
- cur_buffer_size = count;
- avr_jtagprg_writeflashpage(avr,
- buffer + cur_size,
- cur_buffer_size,
- offset + cur_size,
- page_size);
- count -= cur_buffer_size;
- cur_size += cur_buffer_size;
-
- keep_alive();
- }
-
- return avr_jtagprg_leaveprogmode(avr);
-}
-
-#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
-#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
-#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
-
-static int avrf_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct avrf_flash_bank *avrf_info = bank->driver_priv;
- struct avr_common *avr = target->arch_info;
- const struct avrf_type *avr_info = NULL;
- int i;
- uint32_t device_id;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- avrf_info->probed = 0;
-
- avr_jtag_read_jtagid(avr, &device_id);
- if (ERROR_OK != mcu_execute_queue())
- return ERROR_FAIL;
-
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
- if (EXTRACT_MFG(device_id) != 0x1F)
- LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
- EXTRACT_MFG(device_id),
- 0x1F);
-
- for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
- if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
- avr_info = &avft_chips_info[i];
- LOG_INFO("target device is %s", avr_info->name);
- break;
- }
- }
-
- if (avr_info != NULL) {
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- /* chip found */
- bank->base = 0x00000000;
- bank->size = (avr_info->flash_page_size * avr_info->flash_page_num);
- bank->num_sectors = avr_info->flash_page_num;
- bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num);
-
- for (i = 0; i < avr_info->flash_page_num; i++) {
- bank->sectors[i].offset = i * avr_info->flash_page_size;
- bank->sectors[i].size = avr_info->flash_page_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- avrf_info->probed = 1;
- return ERROR_OK;
- } else {
- /* chip not supported */
- LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id));
-
- avrf_info->probed = 1;
- return ERROR_FAIL;
- }
-}
-
-static int avrf_auto_probe(struct flash_bank *bank)
-{
- struct avrf_flash_bank *avrf_info = bank->driver_priv;
- if (avrf_info->probed)
- return ERROR_OK;
- return avrf_probe(bank);
-}
-
-static int avrf_protect_check(struct flash_bank *bank)
-{
- LOG_INFO("%s", __func__);
- return ERROR_OK;
-}
-
-static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct target *target = bank->target;
- struct avr_common *avr = target->arch_info;
- const struct avrf_type *avr_info = NULL;
- int i;
- uint32_t device_id;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- avr_jtag_read_jtagid(avr, &device_id);
- if (ERROR_OK != mcu_execute_queue())
- return ERROR_FAIL;
-
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
- if (EXTRACT_MFG(device_id) != 0x1F)
- LOG_ERROR("0x%" PRIx32 " is invalid Manufacturer for avr, 0x%X is expected",
- EXTRACT_MFG(device_id),
- 0x1F);
-
- for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
- if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
- avr_info = &avft_chips_info[i];
- LOG_INFO("target device is %s", avr_info->name);
-
- break;
- }
- }
-
- if (avr_info != NULL) {
- /* chip found */
- snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", avr_info->name,
- EXTRACT_VER(device_id));
- return ERROR_OK;
- } else {
- /* chip not supported */
- snprintf(buf, buf_size, "Cannot identify target as a avr\n");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-}
-
-static int avrf_mass_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct avr_common *avr = target->arch_info;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((ERROR_OK != avr_jtagprg_enterprogmode(avr))
- || (ERROR_OK != avr_jtagprg_chiperase(avr))
- || (ERROR_OK != avr_jtagprg_leaveprogmode(avr)))
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(avrf_handle_mass_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (avrf_mass_erase(bank) == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "avr mass erase complete");
- } else
- command_print(CMD_CTX, "avr mass erase failed");
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static const struct command_registration avrf_exec_command_handlers[] = {
- {
- .name = "mass_erase",
- .usage = "<bank>",
- .handler = avrf_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .help = "erase entire device",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration avrf_command_handlers[] = {
- {
- .name = "avrf",
- .mode = COMMAND_ANY,
- .help = "AVR flash command group",
- .usage = "",
- .chain = avrf_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver avr_flash = {
- .name = "avr",
- .commands = avrf_command_handlers,
- .flash_bank_command = avrf_flash_bank_command,
- .erase = avrf_erase,
- .protect = avrf_protect,
- .write = avrf_write,
- .read = default_flash_read,
- .probe = avrf_probe,
- .auto_probe = avrf_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = avrf_protect_check,
- .info = avrf_info,
-};
diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c
deleted file mode 100644
index f7d8a90..0000000
--- a/src/flash/nor/cfi.c
+++ /dev/null
@@ -1,3131 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005, 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * Copyright (C) 2009 Michael Schwingen *
- * michael@schwingen.org *
- * Copyright (C) 2010 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "cfi.h"
-#include "non_cfi.h"
-#include <target/arm.h>
-#include <target/arm7_9_common.h>
-#include <target/armv7m.h>
-#include <target/mips32.h>
-#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
-
-/* some id-types with specific handling */
-#define AT49BV6416 0x00d6
-#define AT49BV6416T 0x00d2
-
-static const struct cfi_unlock_addresses cfi_unlock_addresses[] = {
- [CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa },
- [CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa },
-};
-
-static const int cfi_status_poll_mask_dq6_dq7 = CFI_STATUS_POLL_MASK_DQ6_DQ7;
-
-/* CFI fixups forward declarations */
-static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param);
-static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param);
-static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param);
-static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param);
-static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param);
-
-/* fixup after reading cmdset 0002 primary query table */
-static const struct cfi_fixup cfi_0002_fixups[] = {
- {CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
- {CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
- {CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
- {CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
- {CFI_MFR_SST, 0x2780, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
- {CFI_MFR_SST, 0x274b, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
- {CFI_MFR_SST, 0x235f, cfi_fixup_0002_polling_bits, /* 39VF3201C */
- &cfi_status_poll_mask_dq6_dq7},
- {CFI_MFR_SST, 0x236d, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
- {CFI_MFR_ATMEL, 0x00C8, cfi_fixup_reversed_erase_regions, NULL},
- {CFI_MFR_ST, 0x22C4, cfi_fixup_reversed_erase_regions, NULL}, /* M29W160ET */
- {CFI_MFR_FUJITSU, 0x22ea, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
- {CFI_MFR_FUJITSU, 0x226b, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
- {CFI_MFR_AMIC, 0xb31a, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
- {CFI_MFR_MX, 0x225b, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
- {CFI_MFR_EON, 0x225b, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
- {CFI_MFR_AMD, 0x225b, cfi_fixup_0002_unlock_addresses,
- &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
- {CFI_MFR_ANY, CFI_ID_ANY, cfi_fixup_0002_erase_regions, NULL},
- {CFI_MFR_ST, 0x227E, cfi_fixup_0002_write_buffer, NULL},/* M29W128G */
- {0, 0, NULL, NULL}
-};
-
-/* fixup after reading cmdset 0001 primary query table */
-static const struct cfi_fixup cfi_0001_fixups[] = {
- {0, 0, NULL, NULL}
-};
-
-static void cfi_fixup(struct flash_bank *bank, const struct cfi_fixup *fixups)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- const struct cfi_fixup *f;
-
- for (f = fixups; f->fixup; f++) {
- if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi_info->manufacturer)) &&
- ((f->id == CFI_ID_ANY) || (f->id == cfi_info->device_id)))
- f->fixup(bank, f->param);
- }
-}
-
-static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32_t offset)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- if (cfi_info->x16_as_x8)
- offset *= 2;
-
- /* while the sector list isn't built, only accesses to sector 0 work */
- if (sector == 0)
- return bank->base + offset * bank->bus_width;
- else {
- if (!bank->sectors) {
- LOG_ERROR("BUG: sector list not yet built");
- exit(-1);
- }
- return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;
- }
-}
-
-static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
-{
- int i;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- /* clear whole buffer, to ensure bits that exceed the bus_width
- * are set to zero
- */
- for (i = 0; i < CFI_MAX_BUS_WIDTH; i++)
- cmd_buf[i] = 0;
-
- if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) {
- for (i = bank->bus_width; i > 0; i--)
- *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
- } else {
- for (i = 1; i <= bank->bus_width; i++)
- *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
- }
-}
-
-static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t address)
-{
- uint8_t command[CFI_MAX_BUS_WIDTH];
-
- cfi_command(bank, cmd, command);
- return target_write_memory(bank->target, address, bank->bus_width, 1, command);
-}
-
-/* read unsigned 8-bit value from the bank
- * flash banks are expected to be made of similar chips
- * the query result should be the same for all
- */
-static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val)
-{
- struct target *target = bank->target;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- uint8_t data[CFI_MAX_BUS_WIDTH];
-
- int retval;
- retval = target_read_memory(target, flash_address(bank, sector, offset),
- bank->bus_width, 1, data);
- if (retval != ERROR_OK)
- return retval;
-
- if (cfi_info->endianness == TARGET_LITTLE_ENDIAN)
- *val = data[0];
- else
- *val = data[bank->bus_width - 1];
-
- return ERROR_OK;
-}
-
-/* read unsigned 8-bit value from the bank
- * in case of a bank made of multiple chips,
- * the individual values are ORed
- */
-static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val)
-{
- struct target *target = bank->target;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- uint8_t data[CFI_MAX_BUS_WIDTH];
- int i;
-
- int retval;
- retval = target_read_memory(target, flash_address(bank, sector, offset),
- bank->bus_width, 1, data);
- if (retval != ERROR_OK)
- return retval;
-
- if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) {
- for (i = 0; i < bank->bus_width / bank->chip_width; i++)
- data[0] |= data[i];
-
- *val = data[0];
- } else {
- uint8_t value = 0;
- for (i = 0; i < bank->bus_width / bank->chip_width; i++)
- value |= data[bank->bus_width - 1 - i];
-
- *val = value;
- }
- return ERROR_OK;
-}
-
-static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, uint16_t *val)
-{
- struct target *target = bank->target;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- uint8_t data[CFI_MAX_BUS_WIDTH * 2];
- int retval;
-
- if (cfi_info->x16_as_x8) {
- uint8_t i;
- for (i = 0; i < 2; i++) {
- retval = target_read_memory(target, flash_address(bank, sector, offset + i),
- bank->bus_width, 1, &data[i * bank->bus_width]);
- if (retval != ERROR_OK)
- return retval;
- }
- } else {
- retval = target_read_memory(target, flash_address(bank, sector, offset),
- bank->bus_width, 2, data);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (cfi_info->endianness == TARGET_LITTLE_ENDIAN)
- *val = data[0] | data[bank->bus_width] << 8;
- else
- *val = data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8;
-
- return ERROR_OK;
-}
-
-static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, uint32_t *val)
-{
- struct target *target = bank->target;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- uint8_t data[CFI_MAX_BUS_WIDTH * 4];
- int retval;
-
- if (cfi_info->x16_as_x8) {
- uint8_t i;
- for (i = 0; i < 4; i++) {
- retval = target_read_memory(target, flash_address(bank, sector, offset + i),
- bank->bus_width, 1, &data[i * bank->bus_width]);
- if (retval != ERROR_OK)
- return retval;
- }
- } else {
- retval = target_read_memory(target, flash_address(bank, sector, offset),
- bank->bus_width, 4, data);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (cfi_info->endianness == TARGET_LITTLE_ENDIAN)
- *val = data[0] | data[bank->bus_width] << 8 |
- data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24;
- else
- *val = data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8 |
- data[(3 * bank->bus_width) - 1] << 16 |
- data[(4 * bank->bus_width) - 1] << 24;
-
- return ERROR_OK;
-}
-
-static int cfi_reset(struct flash_bank *bank)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- int retval = ERROR_OK;
-
- retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- if (cfi_info->manufacturer == 0x20 &&
- (cfi_info->device_id == 0x227E || cfi_info->device_id == 0x7E)) {
- /* Numonix M29W128G is cmd 0xFF intolerant - causes internal undefined state
- * so we send an extra 0xF0 reset to fix the bug */
- retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x00));
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static void cfi_intel_clear_status_register(struct flash_bank *bank)
-{
- cfi_send_command(bank, 0x50, flash_address(bank, 0, 0x0));
-}
-
-static int cfi_intel_wait_status_busy(struct flash_bank *bank, int timeout, uint8_t *val)
-{
- uint8_t status;
-
- int retval = ERROR_OK;
-
- for (;; ) {
- if (timeout-- < 0) {
- LOG_ERROR("timeout while waiting for WSM to become ready");
- return ERROR_FAIL;
- }
-
- retval = cfi_get_u8(bank, 0, 0x0, &status);
- if (retval != ERROR_OK)
- return retval;
-
- if (status & 0x80)
- break;
-
- alive_sleep(1);
- }
-
- /* mask out bit 0 (reserved) */
- status = status & 0xfe;
-
- LOG_DEBUG("status: 0x%x", status);
-
- if (status != 0x80) {
- LOG_ERROR("status register: 0x%x", status);
- if (status & 0x2)
- LOG_ERROR("Block Lock-Bit Detected, Operation Abort");
- if (status & 0x4)
- LOG_ERROR("Program suspended");
- if (status & 0x8)
- LOG_ERROR("Low Programming Voltage Detected, Operation Aborted");
- if (status & 0x10)
- LOG_ERROR("Program Error / Error in Setting Lock-Bit");
- if (status & 0x20)
- LOG_ERROR("Error in Block Erasure or Clear Lock-Bits");
- if (status & 0x40)
- LOG_ERROR("Block Erase Suspended");
-
- cfi_intel_clear_status_register(bank);
-
- retval = ERROR_FAIL;
- }
-
- *val = status;
- return retval;
-}
-
-static 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;
- int retval;
-
- retval = cfi_get_u8(bank, 0, 0x0, &oldstatus);
- if (retval != ERROR_OK)
- return retval;
-
- do {
- retval = cfi_get_u8(bank, 0, 0x0, &status);
-
- if (retval != ERROR_OK)
- return retval;
-
- if ((status ^ oldstatus) & 0x40) {
- if (status & cfi_info->status_poll_mask & 0x20) {
- retval = cfi_get_u8(bank, 0, 0x0, &oldstatus);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_get_u8(bank, 0, 0x0, &status);
- if (retval != ERROR_OK)
- return retval;
- if ((status ^ oldstatus) & 0x40) {
- LOG_ERROR("dq5 timeout, status: 0x%x", status);
- return ERROR_FLASH_OPERATION_FAILED;
- } else {
- LOG_DEBUG("status: 0x%x", status);
- return ERROR_OK;
- }
- }
- } else {/* no toggle: finished, OK */
- LOG_DEBUG("status: 0x%x", status);
- return ERROR_OK;
- }
-
- oldstatus = status;
- alive_sleep(1);
- } while (timeout-- > 0);
-
- LOG_ERROR("timeout, status: 0x%x", status);
-
- return ERROR_FLASH_BUSY;
-}
-
-static int cfi_read_intel_pri_ext(struct flash_bank *bank)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_intel_pri_ext *pri_ext;
-
- if (cfi_info->pri_ext)
- free(cfi_info->pri_ext);
-
- pri_ext = malloc(sizeof(struct cfi_intel_pri_ext));
- if (pri_ext == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- cfi_info->pri_ext = pri_ext;
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0, &pri_ext->pri[0]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1, &pri_ext->pri[1]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2, &pri_ext->pri[2]);
- if (retval != ERROR_OK)
- return retval;
-
- if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I')) {
- retval = cfi_reset(bank);
- if (retval != ERROR_OK)
- return retval;
- LOG_ERROR("Could not read bank flash bank information");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3, &pri_ext->major_version);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4, &pri_ext->minor_version);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1],
- pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
-
- retval = cfi_query_u32(bank, 0, cfi_info->pri_addr + 5, &pri_ext->feature_support);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9, &pri_ext->suspend_cmd_support);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa, &pri_ext->blk_status_reg_mask);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("feature_support: 0x%" PRIx32 ", suspend_cmd_support: "
- "0x%x, blk_status_reg_mask: 0x%x",
- pri_ext->feature_support,
- pri_ext->suspend_cmd_support,
- pri_ext->blk_status_reg_mask);
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc, &pri_ext->vcc_optimal);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xd, &pri_ext->vpp_optimal);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("Vcc opt: %x.%x, Vpp opt: %u.%x",
- (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
- (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xe, &pri_ext->num_protection_fields);
- if (retval != ERROR_OK)
- return retval;
- if (pri_ext->num_protection_fields != 1) {
- LOG_WARNING("expected one protection register field, but found %i",
- pri_ext->num_protection_fields);
- }
-
- retval = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xf, &pri_ext->prot_reg_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x11, &pri_ext->fact_prot_reg_size);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x12, &pri_ext->user_prot_reg_size);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("protection_fields: %i, prot_reg_addr: 0x%x, "
- "factory pre-programmed: %i, user programmable: %i",
- pri_ext->num_protection_fields, pri_ext->prot_reg_addr,
- 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);
-
- return ERROR_OK;
-}
-
-static int cfi_read_spansion_pri_ext(struct flash_bank *bank)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext;
-
- if (cfi_info->pri_ext)
- free(cfi_info->pri_ext);
-
- pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
- if (pri_ext == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- cfi_info->pri_ext = pri_ext;
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0, &pri_ext->pri[0]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1, &pri_ext->pri[1]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2, &pri_ext->pri[2]);
- if (retval != ERROR_OK)
- return retval;
-
- /* default values for implementation specific workarounds */
- pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
- pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
- pri_ext->_reversed_geometry = 0;
-
- if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I')) {
- retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
- LOG_ERROR("Could not read spansion bank information");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3, &pri_ext->major_version);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4, &pri_ext->minor_version);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1],
- pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5, &pri_ext->SiliconRevision);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6, &pri_ext->EraseSuspend);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7, &pri_ext->BlkProt);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8, &pri_ext->TmpBlkUnprotect);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9, &pri_ext->BlkProtUnprot);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 10, &pri_ext->SimultaneousOps);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 11, &pri_ext->BurstMode);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 12, &pri_ext->PageMode);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 13, &pri_ext->VppMin);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 14, &pri_ext->VppMax);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 15, &pri_ext->TopBottom);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("Silicon Revision: 0x%x, Erase Suspend: 0x%x, Block protect: 0x%x",
- pri_ext->SiliconRevision, pri_ext->EraseSuspend, pri_ext->BlkProt);
-
- LOG_DEBUG("Temporary Unprotect: 0x%x, Block Protect Scheme: 0x%x, "
- "Simultaneous Ops: 0x%x", pri_ext->TmpBlkUnprotect,
- pri_ext->BlkProtUnprot, pri_ext->SimultaneousOps);
-
- LOG_DEBUG("Burst Mode: 0x%x, Page Mode: 0x%x, ", pri_ext->BurstMode, pri_ext->PageMode);
-
-
- LOG_DEBUG("Vpp min: %u.%x, Vpp max: %u.%x",
- (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,
- (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);
-
- LOG_DEBUG("WP# protection 0x%x", pri_ext->TopBottom);
-
- return ERROR_OK;
-}
-
-static int cfi_read_atmel_pri_ext(struct flash_bank *bank)
-{
- int retval;
- struct cfi_atmel_pri_ext atmel_pri_ext;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext;
-
- if (cfi_info->pri_ext)
- free(cfi_info->pri_ext);
-
- pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
- if (pri_ext == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- /* ATMEL devices use the same CFI primary command set (0x2) as AMD/Spansion,
- * but a different primary extended query table.
- * We read the atmel table, and prepare a valid AMD/Spansion query table.
- */
-
- memset(pri_ext, 0, sizeof(struct cfi_spansion_pri_ext));
-
- cfi_info->pri_ext = pri_ext;
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0, &atmel_pri_ext.pri[0]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1, &atmel_pri_ext.pri[1]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2, &atmel_pri_ext.pri[2]);
- if (retval != ERROR_OK)
- return retval;
-
- if ((atmel_pri_ext.pri[0] != 'P') || (atmel_pri_ext.pri[1] != 'R')
- || (atmel_pri_ext.pri[2] != 'I')) {
- retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
- LOG_ERROR("Could not read atmel bank information");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- pri_ext->pri[0] = atmel_pri_ext.pri[0];
- pri_ext->pri[1] = atmel_pri_ext.pri[1];
- pri_ext->pri[2] = atmel_pri_ext.pri[2];
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3, &atmel_pri_ext.major_version);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4, &atmel_pri_ext.minor_version);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("pri: '%c%c%c', version: %c.%c", atmel_pri_ext.pri[0],
- atmel_pri_ext.pri[1], atmel_pri_ext.pri[2],
- atmel_pri_ext.major_version, atmel_pri_ext.minor_version);
-
- pri_ext->major_version = atmel_pri_ext.major_version;
- pri_ext->minor_version = atmel_pri_ext.minor_version;
-
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5, &atmel_pri_ext.features);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6, &atmel_pri_ext.bottom_boot);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7, &atmel_pri_ext.burst_mode);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8, &atmel_pri_ext.page_mode);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG(
- "features: 0x%2.2x, bottom_boot: 0x%2.2x, burst_mode: 0x%2.2x, page_mode: 0x%2.2x",
- atmel_pri_ext.features,
- atmel_pri_ext.bottom_boot,
- atmel_pri_ext.burst_mode,
- atmel_pri_ext.page_mode);
-
- if (atmel_pri_ext.features & 0x02)
- pri_ext->EraseSuspend = 2;
-
- /* some chips got it backwards... */
- if (cfi_info->device_id == AT49BV6416 ||
- cfi_info->device_id == AT49BV6416T) {
- if (atmel_pri_ext.bottom_boot)
- pri_ext->TopBottom = 3;
- else
- pri_ext->TopBottom = 2;
- } else {
- if (atmel_pri_ext.bottom_boot)
- pri_ext->TopBottom = 2;
- else
- pri_ext->TopBottom = 3;
- }
-
- pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
- pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
-
- return ERROR_OK;
-}
-
-static int cfi_read_0002_pri_ext(struct flash_bank *bank)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- if (cfi_info->manufacturer == CFI_MFR_ATMEL)
- return cfi_read_atmel_pri_ext(bank);
- else
- return cfi_read_spansion_pri_ext(bank);
-}
-
-static int cfi_spansion_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int printed;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
-
- printed = snprintf(buf, buf_size, "\nSpansion primary algorithm extend information:\n");
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0],
- pri_ext->pri[1], pri_ext->pri[2],
- pri_ext->major_version, pri_ext->minor_version);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "Silicon Rev.: 0x%x, Address Sensitive unlock: 0x%x\n",
- (pri_ext->SiliconRevision) >> 2,
- (pri_ext->SiliconRevision) & 0x03);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "Erase Suspend: 0x%x, Sector Protect: 0x%x\n",
- pri_ext->EraseSuspend,
- pri_ext->BlkProt);
- buf += printed;
- buf_size -= printed;
-
- snprintf(buf, buf_size, "VppMin: %u.%x, VppMax: %u.%x\n",
- (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,
- (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);
-
- return ERROR_OK;
-}
-
-static int cfi_intel_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int printed;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext;
-
- printed = snprintf(buf, buf_size, "\nintel primary algorithm extend information:\n");
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf,
- buf_size,
- "pri: '%c%c%c', version: %c.%c\n",
- pri_ext->pri[0],
- pri_ext->pri[1],
- pri_ext->pri[2],
- pri_ext->major_version,
- pri_ext->minor_version);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf,
- buf_size,
- "feature_support: 0x%" PRIx32 ", "
- "suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x\n",
- pri_ext->feature_support,
- pri_ext->suspend_cmd_support,
- pri_ext->blk_status_reg_mask);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "Vcc opt: %x.%x, Vpp opt: %u.%x\n",
- (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
- (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);
- buf += printed;
- buf_size -= printed;
-
- snprintf(buf, buf_size, "protection_fields: %i, prot_reg_addr: 0x%x, "
- "factory pre-programmed: %i, user programmable: %i\n",
- pri_ext->num_protection_fields, pri_ext->prot_reg_addr,
- 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);
-
- return ERROR_OK;
-}
-
-/* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#> [options]
- */
-FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
-{
- struct cfi_flash_bank *cfi_info;
- int bus_swap = 0;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* both widths must:
- * - not exceed max value;
- * - not be null;
- * - be equal to a power of 2.
- * bus must be wide enough to hold one chip */
- if ((bank->chip_width > CFI_MAX_CHIP_WIDTH)
- || (bank->bus_width > CFI_MAX_BUS_WIDTH)
- || (bank->chip_width == 0)
- || (bank->bus_width == 0)
- || (bank->chip_width & (bank->chip_width - 1))
- || (bank->bus_width & (bank->bus_width - 1))
- || (bank->chip_width > bank->bus_width)) {
- LOG_ERROR("chip and bus width have to specified in bytes");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- cfi_info = malloc(sizeof(struct cfi_flash_bank));
- cfi_info->probed = 0;
- cfi_info->erase_region_info = NULL;
- cfi_info->pri_ext = NULL;
- bank->driver_priv = cfi_info;
-
- cfi_info->x16_as_x8 = 0;
- cfi_info->jedec_probe = 0;
- 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)
- cfi_info->x16_as_x8 = 1;
- else if (strcmp(CMD_ARGV[i], "data_swap") == 0)
- cfi_info->data_swap = 1;
- else if (strcmp(CMD_ARGV[i], "bus_swap") == 0)
- bus_swap = 1;
- else if (strcmp(CMD_ARGV[i], "jedec_probe") == 0)
- cfi_info->jedec_probe = 1;
- }
-
- if (bus_swap)
- cfi_info->endianness =
- bank->target->endianness == TARGET_LITTLE_ENDIAN ?
- TARGET_BIG_ENDIAN : TARGET_LITTLE_ENDIAN;
- else
- cfi_info->endianness = bank->target->endianness;
-
- /* bank wasn't probed yet */
- cfi_info->qry[0] = 0xff;
-
- return ERROR_OK;
-}
-
-static int cfi_intel_erase(struct flash_bank *bank, int first, int last)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- int i;
-
- cfi_intel_clear_status_register(bank);
-
- for (i = first; i <= last; i++) {
- retval = cfi_send_command(bank, 0x20, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0xd0, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- uint8_t status;
- retval = cfi_intel_wait_status_busy(bank, cfi_info->block_erase_timeout, &status);
- if (retval != ERROR_OK)
- return retval;
-
- if (status == 0x80)
- bank->sectors[i].is_erased = 1;
- else {
- retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR("couldn't erase block %i of flash bank at base 0x%"
- PRIx32, i, bank->base);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
-
- return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
-}
-
-static int cfi_spansion_erase(struct flash_bank *bank, int first, int last)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
- int i;
-
- for (i = first; i <= last; i++) {
- retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x80, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x30, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- if (cfi_spansion_wait_status_busy(bank, cfi_info->block_erase_timeout) == ERROR_OK)
- bank->sectors[i].is_erased = 1;
- else {
- retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR("couldn't erase block %i of flash bank at base 0x%"
- PRIx32, i, bank->base);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
-
- return cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
-}
-
-static int cfi_erase(struct flash_bank *bank, int first, int last)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first < 0) || (last < first) || (last >= bank->num_sectors))
- return ERROR_FLASH_SECTOR_INVALID;
-
- if (cfi_info->qry[0] != 'Q')
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_erase(bank, first, last);
- break;
- case 2:
- return cfi_spansion_erase(bank, first, last);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
- }
-
- return ERROR_OK;
-}
-
-static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext;
- int retry = 0;
- int i;
-
- /* if the device supports neither legacy lock/unlock (bit 3) nor
- * instant individual block locking (bit 5).
- */
- if (!(pri_ext->feature_support & 0x28)) {
- LOG_ERROR("lock/unlock not supported on flash");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- cfi_intel_clear_status_register(bank);
-
- for (i = first; i <= last; i++) {
- retval = cfi_send_command(bank, 0x60, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
- if (set) {
- retval = cfi_send_command(bank, 0x01, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
- bank->sectors[i].is_protected = 1;
- } else {
- retval = cfi_send_command(bank, 0xd0, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
- bank->sectors[i].is_protected = 0;
- }
-
- /* instant individual block locking doesn't require reading of the status register
- **/
- if (!(pri_ext->feature_support & 0x20)) {
- /* Clear lock bits operation may take up to 1.4s */
- uint8_t status;
- retval = cfi_intel_wait_status_busy(bank, 1400, &status);
- if (retval != ERROR_OK)
- return retval;
- } else {
- uint8_t block_status;
- /* read block lock bit, to verify status */
- retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, 0x55));
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_get_u8(bank, i, 0x2, &block_status);
- if (retval != ERROR_OK)
- return retval;
-
- if ((block_status & 0x1) != set) {
- LOG_ERROR(
- "couldn't change block lock status (set = %i, block_status = 0x%2.2x)",
- set, block_status);
- retval = cfi_send_command(bank, 0x70, flash_address(bank, 0, 0x55));
- if (retval != ERROR_OK)
- return retval;
- uint8_t status;
- retval = cfi_intel_wait_status_busy(bank, 10, &status);
- if (retval != ERROR_OK)
- return retval;
-
- if (retry > 10)
- return ERROR_FLASH_OPERATION_FAILED;
- else {
- i--;
- retry++;
- }
- }
- }
- }
-
- /* if the device doesn't support individual block lock bits set/clear,
- * all blocks have been unlocked in parallel, so we set those that should be protected
- */
- if ((!set) && (!(pri_ext->feature_support & 0x20))) {
- /* FIX!!! this code path is broken!!!
- *
- * The correct approach is:
- *
- * 1. read out current protection status
- *
- * 2. override read out protection status w/unprotected.
- *
- * 3. re-protect what should be protected.
- *
- */
- for (i = 0; i < bank->num_sectors; i++) {
- if (bank->sectors[i].is_protected == 1) {
- cfi_intel_clear_status_register(bank);
-
- retval = cfi_send_command(bank, 0x60, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x01, flash_address(bank, i, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- uint8_t status;
- retval = cfi_intel_wait_status_busy(bank, 100, &status);
- if (retval != ERROR_OK)
- return retval;
- }
- }
- }
-
- return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
-}
-
-static int cfi_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- if (bank->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("Invalid sector range");
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- if (cfi_info->qry[0] != 'Q')
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_protect(bank, set, first, last);
- break;
- default:
- LOG_WARNING("protect: cfi primary command set %i unsupported", cfi_info->pri_id);
- return ERROR_OK;
- }
-}
-
-static uint32_t cfi_command_val(struct flash_bank *bank, uint8_t cmd)
-{
- struct target *target = bank->target;
-
- uint8_t buf[CFI_MAX_BUS_WIDTH];
- cfi_command(bank, cmd, buf);
- switch (bank->bus_width) {
- case 1:
- return buf[0];
- break;
- case 2:
- return target_buffer_get_u16(target, buf);
- break;
- case 4:
- return target_buffer_get_u32(target, buf);
- break;
- default:
- LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes",
- bank->bus_width);
- return 0;
- }
-}
-
-static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t address, uint32_t count)
-{
- struct target *target = bank->target;
- struct reg_param reg_params[7];
- struct arm_algorithm arm_algo;
- struct working_area *write_algorithm;
- struct working_area *source = NULL;
- uint32_t buffer_size = 32768;
- uint32_t write_command_val, busy_pattern_val, error_pattern_val;
-
- /* algorithm register usage:
- * r0: source address (in RAM)
- * r1: target address (in Flash)
- * r2: count
- * r3: flash write command
- * r4: status byte (returned to host)
- * r5: busy test pattern
- * r6: error test pattern
- */
-
- /* see contib/loaders/flash/armv4_5_cfi_intel_32.s for src */
- static const uint32_t word_32_code[] = {
- 0xe4904004, /* loop: ldr r4, [r0], #4 */
- 0xe5813000, /* str r3, [r1] */
- 0xe5814000, /* str r4, [r1] */
- 0xe5914000, /* busy: ldr r4, [r1] */
- 0xe0047005, /* and r7, r4, r5 */
- 0xe1570005, /* cmp r7, r5 */
- 0x1afffffb, /* bne busy */
- 0xe1140006, /* tst r4, r6 */
- 0x1a000003, /* bne done */
- 0xe2522001, /* subs r2, r2, #1 */
- 0x0a000001, /* beq done */
- 0xe2811004, /* add r1, r1 #4 */
- 0xeafffff2, /* b loop */
- 0xeafffffe /* done: b -2 */
- };
-
- /* see contib/loaders/flash/armv4_5_cfi_intel_16.s for src */
- static const uint32_t word_16_code[] = {
- 0xe0d040b2, /* loop: ldrh r4, [r0], #2 */
- 0xe1c130b0, /* strh r3, [r1] */
- 0xe1c140b0, /* strh r4, [r1] */
- 0xe1d140b0, /* busy ldrh r4, [r1] */
- 0xe0047005, /* and r7, r4, r5 */
- 0xe1570005, /* cmp r7, r5 */
- 0x1afffffb, /* bne busy */
- 0xe1140006, /* tst r4, r6 */
- 0x1a000003, /* bne done */
- 0xe2522001, /* subs r2, r2, #1 */
- 0x0a000001, /* beq done */
- 0xe2811002, /* add r1, r1 #2 */
- 0xeafffff2, /* b loop */
- 0xeafffffe /* done: b -2 */
- };
-
- /* see contib/loaders/flash/armv4_5_cfi_intel_8.s for src */
- static const uint32_t word_8_code[] = {
- 0xe4d04001, /* loop: ldrb r4, [r0], #1 */
- 0xe5c13000, /* strb r3, [r1] */
- 0xe5c14000, /* strb r4, [r1] */
- 0xe5d14000, /* busy ldrb r4, [r1] */
- 0xe0047005, /* and r7, r4, r5 */
- 0xe1570005, /* cmp r7, r5 */
- 0x1afffffb, /* bne busy */
- 0xe1140006, /* tst r4, r6 */
- 0x1a000003, /* bne done */
- 0xe2522001, /* subs r2, r2, #1 */
- 0x0a000001, /* beq done */
- 0xe2811001, /* add r1, r1 #1 */
- 0xeafffff2, /* b loop */
- 0xeafffffe /* done: b -2 */
- };
- uint8_t target_code[4*CFI_MAX_INTEL_CODESIZE];
- const uint32_t *target_code_src;
- uint32_t target_code_size;
- int retval = ERROR_OK;
-
- /* check we have a supported arch */
- if (is_arm(target_to_arm(target))) {
- /* All other ARM CPUs have 32 bit instructions */
- arm_algo.common_magic = ARM_COMMON_MAGIC;
- arm_algo.core_mode = ARM_MODE_SVC;
- arm_algo.core_state = ARM_STATE_ARM;
- } else {
- LOG_ERROR("Unknown architecture");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- cfi_intel_clear_status_register(bank);
-
- /* If we are setting up the write_algorith, we need target_code_src
- * if not we only need target_code_size. */
-
- /* However, we don't want to create multiple code paths, so we
- * do the unnecessary evaluation of target_code_src, which the
- * compiler will probably nicely optimize away if not needed */
-
- /* prepare algorithm code for target endian */
- switch (bank->bus_width) {
- case 1:
- target_code_src = word_8_code;
- target_code_size = sizeof(word_8_code);
- break;
- case 2:
- target_code_src = word_16_code;
- target_code_size = sizeof(word_16_code);
- break;
- case 4:
- target_code_src = word_32_code;
- target_code_size = sizeof(word_32_code);
- break;
- default:
- LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes",
- bank->bus_width);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* flash write code */
- if (target_code_size > sizeof(target_code)) {
- LOG_WARNING("Internal error - target code buffer to small. "
- "Increase CFI_MAX_INTEL_CODESIZE and recompile.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src);
-
- /* Get memory for block write handler */
- retval = target_alloc_working_area(target,
- target_code_size,
- &write_algorithm);
- if (retval != ERROR_OK) {
- LOG_WARNING("No working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* write algorithm code to working area */
- retval = target_write_buffer(target, write_algorithm->address,
- target_code_size, target_code);
- if (retval != ERROR_OK) {
- LOG_ERROR("Unable to write block write code to target");
- goto cleanup;
- }
-
- /* Get a workspace buffer for the data to flash starting with 32k size.
- * Half size until buffer would be smaller 256 Bytes then fail back */
- /* FIXME Why 256 bytes, why not 32 bytes (smallest flash write page */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- LOG_WARNING(
- "no large enough working area available, can't do block memory writes");
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto cleanup;
- }
- }
-
- /* setup algo registers */
- 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);
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
- init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
- init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);
-
- /* prepare command and status register patterns */
- write_command_val = cfi_command_val(bank, 0x40);
- busy_pattern_val = cfi_command_val(bank, 0x80);
- error_pattern_val = cfi_command_val(bank, 0x7e);
-
- LOG_DEBUG("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32,
- source->address, buffer_size);
-
- /* Programming main loop */
- while (count > 0) {
- uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
- uint32_t wsm_error;
-
- retval = target_write_buffer(target, source->address, thisrun_count, buffer);
- if (retval != ERROR_OK)
- goto cleanup;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
-
- buf_set_u32(reg_params[3].value, 0, 32, write_command_val);
- buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val);
- buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val);
-
- LOG_DEBUG("Write 0x%04" PRIx32 " bytes to flash at 0x%08" PRIx32,
- thisrun_count, address);
-
- /* Execute algorithm, assume breakpoint for last instruction */
- retval = target_run_algorithm(target, 0, NULL, 7, reg_params,
- write_algorithm->address,
- write_algorithm->address + target_code_size -
- sizeof(uint32_t),
- 10000, /* 10s should be enough for max. 32k of data */
- &arm_algo);
-
- /* On failure try a fall back to direct word writes */
- if (retval != ERROR_OK) {
- cfi_intel_clear_status_register(bank);
- LOG_ERROR(
- "Execution of flash algorythm failed. Can't fall back. Please report.");
- retval = ERROR_FLASH_OPERATION_FAILED;
- /* retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; */
- /* FIXME To allow fall back or recovery, we must save the actual status
- * somewhere, so that a higher level code can start recovery. */
- goto cleanup;
- }
-
- /* Check return value from algo code */
- wsm_error = buf_get_u32(reg_params[4].value, 0, 32) & error_pattern_val;
- if (wsm_error) {
- /* read status register (outputs debug information) */
- uint8_t status;
- cfi_intel_wait_status_busy(bank, 100, &status);
- cfi_intel_clear_status_register(bank);
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto cleanup;
- }
-
- buffer += thisrun_count;
- address += thisrun_count;
- count -= thisrun_count;
-
- keep_alive();
- }
-
- /* free up resources */
-cleanup:
- if (source)
- target_free_working_area(target, source);
-
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
- destroy_reg_param(&reg_params[5]);
- destroy_reg_param(&reg_params[6]);
-
- return retval;
-}
-
-static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t address, uint32_t count)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
- struct target *target = bank->target;
- struct reg_param reg_params[10];
- struct mips32_algorithm mips32_info;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t buffer_size = 32768;
- uint32_t status;
- int retval = ERROR_OK;
-
- /* input parameters -
- * 4 A0 = source address
- * 5 A1 = destination address
- * 6 A2 = number of writes
- * 7 A3 = flash write command
- * 8 T0 = constant to mask DQ7 bits (also used for Dq5 with shift)
- * output parameters -
- * 9 T1 = 0x80 ok 0x00 bad
- * temp registers -
- * 10 T2 = value read from flash to test status
- * 11 T3 = holding register
- * unlock registers -
- * 12 T4 = unlock1_addr
- * 13 T5 = unlock1_cmd
- * 14 T6 = unlock2_addr
- * 15 T7 = unlock2_cmd */
-
- static const uint32_t mips_word_16_code[] = {
- /* start: */
- MIPS32_LHU(9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */
- MIPS32_ADDI(4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */
- MIPS32_SH(13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */
- MIPS32_SH(15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */
- MIPS32_SH(7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */
- MIPS32_SH(9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */
- MIPS32_NOP, /* nop */
- /* busy: */
- MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
- MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
- MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
- MIPS32_BNE(11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
- MIPS32_NOP, /* nop */
-
- MIPS32_SRL(10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */
- MIPS32_AND(11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */
- MIPS32_BNE(11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */
- MIPS32_NOP, /* nop */
-
- MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */
- MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */
- MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */
- MIPS32_BNE(11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */
- MIPS32_NOP, /* nop */
-
- MIPS32_XOR(9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */
- MIPS32_BEQ(9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */
- MIPS32_NOP, /* nop */
- /* cont: */
- MIPS32_ADDI(6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */
- MIPS32_BNE(6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */
- MIPS32_NOP, /* nop */
-
- MIPS32_LUI(9, 0), /* lui $t1, 0 */
- MIPS32_ORI(9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */
-
- MIPS32_B(4), /* b done ; goto done */
- MIPS32_NOP, /* nop */
- /* cont2: */
- MIPS32_ADDI(5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */
- MIPS32_B(NEG16(33)), /* b start ; goto start */
- MIPS32_NOP, /* nop */
- /* done: */
- MIPS32_SDBBP, /* sdbbp ; break(); */
- };
-
- mips32_info.common_magic = MIPS32_COMMON_MAGIC;
- mips32_info.isa_mode = MIPS32_ISA_MIPS32;
-
- int target_code_size = 0;
- const uint32_t *target_code_src = NULL;
-
- switch (bank->bus_width) {
- case 2:
- /* Check for DQ5 support */
- if (cfi_info->status_poll_mask & (1 << 5)) {
- target_code_src = mips_word_16_code;
- target_code_size = sizeof(mips_word_16_code);
- } else {
- LOG_ERROR("Need DQ5 support");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- /* target_code_src = mips_word_16_code_dq7only; */
- /* target_code_size = sizeof(mips_word_16_code_dq7only); */
- }
- break;
- default:
- LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes",
- bank->bus_width);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* flash write code */
- uint8_t *target_code;
-
- /* convert bus-width dependent algorithm code to correct endianness */
- target_code = malloc(target_code_size);
- if (target_code == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src);
-
- /* allocate working area */
- retval = target_alloc_working_area(target, target_code_size,
- &write_algorithm);
- if (retval != ERROR_OK) {
- free(target_code);
- return retval;
- }
-
- /* write algorithm code to working area */
- retval = target_write_buffer(target, write_algorithm->address,
- target_code_size, target_code);
- if (retval != ERROR_OK) {
- free(target_code);
- return retval;
- }
-
- free(target_code);
-
- /* the following code still assumes target code is fixed 24*4 bytes */
-
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING(
- "not enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
- init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
- init_reg_param(&reg_params[2], "r6", 32, PARAM_OUT);
- init_reg_param(&reg_params[3], "r7", 32, PARAM_OUT);
- init_reg_param(&reg_params[4], "r8", 32, PARAM_OUT);
- init_reg_param(&reg_params[5], "r9", 32, PARAM_IN);
- init_reg_param(&reg_params[6], "r12", 32, PARAM_OUT);
- init_reg_param(&reg_params[7], "r13", 32, PARAM_OUT);
- init_reg_param(&reg_params[8], "r14", 32, PARAM_OUT);
- init_reg_param(&reg_params[9], "r15", 32, PARAM_OUT);
-
- while (count > 0) {
- uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
-
- retval = target_write_buffer(target, source->address, thisrun_count, buffer);
- if (retval != ERROR_OK)
- break;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
- buf_set_u32(reg_params[3].value, 0, 32, cfi_command_val(bank, 0xA0));
- buf_set_u32(reg_params[4].value, 0, 32, cfi_command_val(bank, 0x80));
- buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1));
- buf_set_u32(reg_params[7].value, 0, 32, 0xaaaaaaaa);
- buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2));
- buf_set_u32(reg_params[9].value, 0, 32, 0x55555555);
-
- retval = target_run_algorithm(target, 0, NULL, 10, reg_params,
- write_algorithm->address,
- write_algorithm->address + ((target_code_size) - 4),
- 10000, &mips32_info);
- if (retval != ERROR_OK)
- break;
-
- status = buf_get_u32(reg_params[5].value, 0, 32);
- if (status != 0x80) {
- LOG_ERROR("flash write block failed status: 0x%" PRIx32, status);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- buffer += thisrun_count;
- address += thisrun_count;
- count -= thisrun_count;
- }
-
- target_free_all_working_areas(target);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
- destroy_reg_param(&reg_params[5]);
- destroy_reg_param(&reg_params[6]);
- destroy_reg_param(&reg_params[7]);
- destroy_reg_param(&reg_params[8]);
- destroy_reg_param(&reg_params[9]);
-
- return retval;
-}
-
-static int cfi_spansion_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t address, uint32_t count)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
- struct target *target = bank->target;
- struct reg_param reg_params[10];
- void *arm_algo;
- struct arm_algorithm armv4_5_algo;
- struct armv7m_algorithm armv7m_algo;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t buffer_size = 32768;
- uint32_t status;
- int retval = ERROR_OK;
-
- /* input parameters -
- * R0 = source address
- * R1 = destination address
- * R2 = number of writes
- * R3 = flash write command
- * R4 = constant to mask DQ7 bits (also used for Dq5 with shift)
- * output parameters -
- * R5 = 0x80 ok 0x00 bad
- * temp registers -
- * R6 = value read from flash to test status
- * R7 = holding register
- * unlock registers -
- * R8 = unlock1_addr
- * R9 = unlock1_cmd
- * R10 = unlock2_addr
- * R11 = unlock2_cmd */
-
- /* see contib/loaders/flash/armv4_5_cfi_span_32.s for src */
- static const uint32_t armv4_5_word_32_code[] = {
- /* 00008100 <sp_32_code>: */
- 0xe4905004, /* ldr r5, [r0], #4 */
- 0xe5889000, /* str r9, [r8] */
- 0xe58ab000, /* str r11, [r10] */
- 0xe5883000, /* str r3, [r8] */
- 0xe5815000, /* str r5, [r1] */
- 0xe1a00000, /* nop */
- /* 00008110 <sp_32_busy>: */
- 0xe5916000, /* ldr r6, [r1] */
- 0xe0257006, /* eor r7, r5, r6 */
- 0xe0147007, /* ands r7, r4, r7 */
- 0x0a000007, /* beq 8140 <sp_32_cont> ; b if DQ7 == Data7 */
- 0xe0166124, /* ands r6, r6, r4, lsr #2 */
- 0x0afffff9, /* beq 8110 <sp_32_busy> ; b if DQ5 low */
- 0xe5916000, /* ldr r6, [r1] */
- 0xe0257006, /* eor r7, r5, r6 */
- 0xe0147007, /* ands r7, r4, r7 */
- 0x0a000001, /* beq 8140 <sp_32_cont> ; b if DQ7 == Data7 */
- 0xe3a05000, /* mov r5, #0 ; 0x0 - return 0x00, error */
- 0x1a000004, /* bne 8154 <sp_32_done> */
- /* 00008140 <sp_32_cont>: */
- 0xe2522001, /* subs r2, r2, #1 ; 0x1 */
- 0x03a05080, /* moveq r5, #128 ; 0x80 */
- 0x0a000001, /* beq 8154 <sp_32_done> */
- 0xe2811004, /* add r1, r1, #4 ; 0x4 */
- 0xeaffffe8, /* b 8100 <sp_32_code> */
- /* 00008154 <sp_32_done>: */
- 0xeafffffe /* b 8154 <sp_32_done> */
- };
-
- /* see contib/loaders/flash/armv4_5_cfi_span_16.s for src */
- static const uint32_t armv4_5_word_16_code[] = {
- /* 00008158 <sp_16_code>: */
- 0xe0d050b2, /* ldrh r5, [r0], #2 */
- 0xe1c890b0, /* strh r9, [r8] */
- 0xe1cab0b0, /* strh r11, [r10] */
- 0xe1c830b0, /* strh r3, [r8] */
- 0xe1c150b0, /* strh r5, [r1] */
- 0xe1a00000, /* nop (mov r0,r0) */
- /* 00008168 <sp_16_busy>: */
- 0xe1d160b0, /* ldrh r6, [r1] */
- 0xe0257006, /* eor r7, r5, r6 */
- 0xe0147007, /* ands r7, r4, r7 */
- 0x0a000007, /* beq 8198 <sp_16_cont> */
- 0xe0166124, /* ands r6, r6, r4, lsr #2 */
- 0x0afffff9, /* beq 8168 <sp_16_busy> */
- 0xe1d160b0, /* ldrh r6, [r1] */
- 0xe0257006, /* eor r7, r5, r6 */
- 0xe0147007, /* ands r7, r4, r7 */
- 0x0a000001, /* beq 8198 <sp_16_cont> */
- 0xe3a05000, /* mov r5, #0 ; 0x0 */
- 0x1a000004, /* bne 81ac <sp_16_done> */
- /* 00008198 <sp_16_cont>: */
- 0xe2522001, /* subs r2, r2, #1 ; 0x1 */
- 0x03a05080, /* moveq r5, #128 ; 0x80 */
- 0x0a000001, /* beq 81ac <sp_16_done> */
- 0xe2811002, /* add r1, r1, #2 ; 0x2 */
- 0xeaffffe8, /* b 8158 <sp_16_code> */
- /* 000081ac <sp_16_done>: */
- 0xeafffffe /* b 81ac <sp_16_done> */
- };
-
- /* see contrib/loaders/flash/armv7m_cfi_span_16.s for src */
- static const uint32_t armv7m_word_16_code[] = {
- 0x5B02F830,
- 0x9000F8A8,
- 0xB000F8AA,
- 0x3000F8A8,
- 0xBF00800D,
- 0xEA85880E,
- 0x40270706,
- 0xEA16D00A,
- 0xD0F70694,
- 0xEA85880E,
- 0x40270706,
- 0xF04FD002,
- 0xD1070500,
- 0xD0023A01,
- 0x0102F101,
- 0xF04FE7E0,
- 0xE7FF0580,
- 0x0000BE00
- };
-
- /* see contrib/loaders/flash/armv7m_cfi_span_16_dq7.s for src */
- static const uint32_t armv7m_word_16_code_dq7only[] = {
- /* 00000000 <code>: */
- 0x5B02F830, /* ldrh.w r5, [r0], #2 */
- 0x9000F8A8, /* strh.w r9, [r8] */
- 0xB000F8AA, /* strh.w fp, [sl] */
- 0x3000F8A8, /* strh.w r3, [r8] */
- 0xBF00800D, /* strh r5, [r1, #0] */
- /* nop */
-
- /* 00000014 <busy>: */
- 0xEA85880E, /* ldrh r6, [r1, #0] */
- /* eor.w r7, r5, r6 */
- 0x40270706, /* ands r7, r4 */
- 0x3A01D1FA, /* bne.n 14 <busy> */
- /* subs r2, #1 */
- 0xF101D002, /* beq.n 28 <success> */
- 0xE7EB0102, /* add.w r1, r1, #2 */
- /* b.n 0 <code> */
-
- /* 00000028 <success>: */
- 0x0580F04F, /* mov.w r5, #128 */
- 0xBF00E7FF, /* b.n 30 <done> */
- /* nop (for alignment purposes) */
-
- /* 00000030 <done>: */
- 0x0000BE00 /* bkpt 0x0000 */
- };
-
- /* see contrib/loaders/flash/armv4_5_cfi_span_16_dq7.s for src */
- static const uint32_t armv4_5_word_16_code_dq7only[] = {
- /* <sp_16_code>: */
- 0xe0d050b2, /* ldrh r5, [r0], #2 */
- 0xe1c890b0, /* strh r9, [r8] */
- 0xe1cab0b0, /* strh r11, [r10] */
- 0xe1c830b0, /* strh r3, [r8] */
- 0xe1c150b0, /* strh r5, [r1] */
- 0xe1a00000, /* nop (mov r0,r0) */
- /* <sp_16_busy>: */
- 0xe1d160b0, /* ldrh r6, [r1] */
- 0xe0257006, /* eor r7, r5, r6 */
- 0xe2177080, /* ands r7, #0x80 */
- 0x1afffffb, /* bne 8168 <sp_16_busy> */
- /* */
- 0xe2522001, /* subs r2, r2, #1 ; 0x1 */
- 0x03a05080, /* moveq r5, #128 ; 0x80 */
- 0x0a000001, /* beq 81ac <sp_16_done> */
- 0xe2811002, /* add r1, r1, #2 ; 0x2 */
- 0xeafffff0, /* b 8158 <sp_16_code> */
- /* 000081ac <sp_16_done>: */
- 0xeafffffe /* b 81ac <sp_16_done> */
- };
-
- /* see contrib/loaders/flash/armv4_5_cfi_span_8.s for src */
- static const uint32_t armv4_5_word_8_code[] = {
- /* 000081b0 <sp_16_code_end>: */
- 0xe4d05001, /* ldrb r5, [r0], #1 */
- 0xe5c89000, /* strb r9, [r8] */
- 0xe5cab000, /* strb r11, [r10] */
- 0xe5c83000, /* strb r3, [r8] */
- 0xe5c15000, /* strb r5, [r1] */
- 0xe1a00000, /* nop (mov r0,r0) */
- /* 000081c0 <sp_8_busy>: */
- 0xe5d16000, /* ldrb r6, [r1] */
- 0xe0257006, /* eor r7, r5, r6 */
- 0xe0147007, /* ands r7, r4, r7 */
- 0x0a000007, /* beq 81f0 <sp_8_cont> */
- 0xe0166124, /* ands r6, r6, r4, lsr #2 */
- 0x0afffff9, /* beq 81c0 <sp_8_busy> */
- 0xe5d16000, /* ldrb r6, [r1] */
- 0xe0257006, /* eor r7, r5, r6 */
- 0xe0147007, /* ands r7, r4, r7 */
- 0x0a000001, /* beq 81f0 <sp_8_cont> */
- 0xe3a05000, /* mov r5, #0 ; 0x0 */
- 0x1a000004, /* bne 8204 <sp_8_done> */
- /* 000081f0 <sp_8_cont>: */
- 0xe2522001, /* subs r2, r2, #1 ; 0x1 */
- 0x03a05080, /* moveq r5, #128 ; 0x80 */
- 0x0a000001, /* beq 8204 <sp_8_done> */
- 0xe2811001, /* add r1, r1, #1 ; 0x1 */
- 0xeaffffe8, /* b 81b0 <sp_16_code_end> */
- /* 00008204 <sp_8_done>: */
- 0xeafffffe /* b 8204 <sp_8_done> */
- };
-
- if (strncmp(target_type_name(target), "mips_m4k", 8) == 0)
- return cfi_spansion_write_block_mips(bank, buffer, address, count);
-
- if (is_armv7m(target_to_armv7m(target))) { /* armv7m target */
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
- arm_algo = &armv7m_algo;
- } else if (is_arm(target_to_arm(target))) {
- /* All other ARM CPUs have 32 bit instructions */
- armv4_5_algo.common_magic = ARM_COMMON_MAGIC;
- armv4_5_algo.core_mode = ARM_MODE_SVC;
- armv4_5_algo.core_state = ARM_STATE_ARM;
- arm_algo = &armv4_5_algo;
- } else {
- LOG_ERROR("Unknown architecture");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- int target_code_size = 0;
- const uint32_t *target_code_src = NULL;
-
- switch (bank->bus_width) {
- case 1:
- if (is_armv7m(target_to_armv7m(target))) {
- LOG_ERROR("Unknown ARM architecture");
- return ERROR_FAIL;
- }
- target_code_src = armv4_5_word_8_code;
- target_code_size = sizeof(armv4_5_word_8_code);
- break;
- case 2:
- /* Check for DQ5 support */
- if (cfi_info->status_poll_mask & (1 << 5)) {
- if (is_armv7m(target_to_armv7m(target))) {
- /* armv7m target */
- target_code_src = armv7m_word_16_code;
- target_code_size = sizeof(armv7m_word_16_code);
- } else { /* armv4_5 target */
- target_code_src = armv4_5_word_16_code;
- target_code_size = sizeof(armv4_5_word_16_code);
- }
- } else {
- /* No DQ5 support. Use DQ7 DATA# polling only. */
- if (is_armv7m(target_to_armv7m(target))) {
- /* armv7m target */
- target_code_src = armv7m_word_16_code_dq7only;
- target_code_size = sizeof(armv7m_word_16_code_dq7only);
- } else { /* armv4_5 target */
- target_code_src = armv4_5_word_16_code_dq7only;
- target_code_size = sizeof(armv4_5_word_16_code_dq7only);
- }
- }
- break;
- case 4:
- if (is_armv7m(target_to_armv7m(target))) {
- LOG_ERROR("Unknown ARM architecture");
- return ERROR_FAIL;
- }
- target_code_src = armv4_5_word_32_code;
- target_code_size = sizeof(armv4_5_word_32_code);
- break;
- default:
- LOG_ERROR("Unsupported bank buswidth %d, can't do block memory writes",
- bank->bus_width);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* flash write code */
- uint8_t *target_code;
-
- /* convert bus-width dependent algorithm code to correct endianness */
- target_code = malloc(target_code_size);
- if (target_code == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src);
-
- /* allocate working area */
- retval = target_alloc_working_area(target, target_code_size,
- &write_algorithm);
- if (retval != ERROR_OK) {
- free(target_code);
- return retval;
- }
-
- /* write algorithm code to working area */
- retval = target_write_buffer(target, write_algorithm->address,
- target_code_size, target_code);
- if (retval != ERROR_OK) {
- free(target_code);
- return retval;
- }
-
- free(target_code);
-
- /* the following code still assumes target code is fixed 24*4 bytes */
-
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING(
- "not enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- 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);
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
- init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);
- init_reg_param(&reg_params[6], "r8", 32, PARAM_OUT);
- init_reg_param(&reg_params[7], "r9", 32, PARAM_OUT);
- init_reg_param(&reg_params[8], "r10", 32, PARAM_OUT);
- init_reg_param(&reg_params[9], "r11", 32, PARAM_OUT);
-
- while (count > 0) {
- uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
-
- retval = target_write_buffer(target, source->address, thisrun_count, buffer);
- if (retval != ERROR_OK)
- break;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
- buf_set_u32(reg_params[3].value, 0, 32, cfi_command_val(bank, 0xA0));
- buf_set_u32(reg_params[4].value, 0, 32, cfi_command_val(bank, 0x80));
- buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1));
- buf_set_u32(reg_params[7].value, 0, 32, 0xaaaaaaaa);
- buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2));
- buf_set_u32(reg_params[9].value, 0, 32, 0x55555555);
-
- retval = target_run_algorithm(target, 0, NULL, 10, reg_params,
- write_algorithm->address,
- write_algorithm->address + ((target_code_size) - 4),
- 10000, arm_algo);
- if (retval != ERROR_OK)
- break;
-
- status = buf_get_u32(reg_params[5].value, 0, 32);
- if (status != 0x80) {
- LOG_ERROR("flash write block failed status: 0x%" PRIx32, status);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- buffer += thisrun_count;
- address += thisrun_count;
- count -= thisrun_count;
- }
-
- target_free_all_working_areas(target);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
- destroy_reg_param(&reg_params[5]);
- destroy_reg_param(&reg_params[6]);
- destroy_reg_param(&reg_params[7]);
- destroy_reg_param(&reg_params[8]);
- destroy_reg_param(&reg_params[9]);
-
- return retval;
-}
-
-static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct target *target = bank->target;
-
- cfi_intel_clear_status_register(bank);
- retval = cfi_send_command(bank, 0x40, address);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_memory(target, address, bank->bus_width, 1, word);
- if (retval != ERROR_OK)
- return retval;
-
- uint8_t status;
- retval = cfi_intel_wait_status_busy(bank, cfi_info->word_write_timeout, &status);
- if (retval != ERROR_OK)
- return retval;
- if (status != 0x80) {
- retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR("couldn't write word at base 0x%" PRIx32 ", address 0x%" PRIx32,
- bank->base, address);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int cfi_intel_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 target *target = bank->target;
-
- /* Calculate buffer size and boundary mask
- * buffersize is (buffer size per chip) * (number of chips)
- * bufferwsize is buffersize in words */
- uint32_t buffersize =
- (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width);
- uint32_t buffermask = buffersize-1;
- uint32_t bufferwsize = buffersize / bank->bus_width;
-
- /* Check for valid range */
- if (address & buffermask) {
- LOG_ERROR("Write address at base 0x%" PRIx32 ", 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;
- }
-
- /* Write to flash buffer */
- cfi_intel_clear_status_register(bank);
-
- /* Initiate buffer operation _*/
- retval = cfi_send_command(bank, 0xe8, address);
- if (retval != ERROR_OK)
- return retval;
- uint8_t status;
- retval = cfi_intel_wait_status_busy(bank, cfi_info->buf_write_timeout, &status);
- if (retval != ERROR_OK)
- return retval;
- if (status != 0x80) {
- retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR(
- "couldn't start buffer write operation at base 0x%" PRIx32 ", address 0x%" PRIx32,
- bank->base,
- address);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* Write buffer wordcount-1 and data words */
- retval = cfi_send_command(bank, bufferwsize-1, address);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_memory(target, address, bank->bus_width, bufferwsize, word);
- if (retval != ERROR_OK)
- return retval;
-
- /* Commit write operation */
- retval = cfi_send_command(bank, 0xd0, address);
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_intel_wait_status_busy(bank, cfi_info->buf_write_timeout, &status);
- if (retval != ERROR_OK)
- return retval;
-
- if (status != 0x80) {
- retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR("Buffer write at base 0x%" PRIx32
- ", address 0x%" PRIx32 " failed.", bank->base, address);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, 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;
- struct target *target = bank->target;
-
- retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0xa0, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_memory(target, address, bank->bus_width, 1, word);
- 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, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR("couldn't write word at base 0x%" PRIx32
- ", address 0x%" PRIx32, bank->base, address);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int cfi_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 target *target = bank->target;
- 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 =
- (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width);
- uint32_t buffermask = buffersize-1;
- uint32_t bufferwsize = buffersize / bank->bus_width;
-
- /* Check for valid range */
- if (address & buffermask) {
- LOG_ERROR("Write address at base 0x%" PRIx32
- ", 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_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2));
- if (retval != ERROR_OK)
- return retval;
-
- /* Buffer load command */
- retval = cfi_send_command(bank, 0x25, address);
- if (retval != ERROR_OK)
- return retval;
-
- /* Write buffer wordcount-1 and data words */
- retval = cfi_send_command(bank, bufferwsize-1, address);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_memory(target, address, bank->bus_width, bufferwsize, word);
- if (retval != ERROR_OK)
- return retval;
-
- /* Commit write operation */
- retval = cfi_send_command(bank, 0x29, address);
- if (retval != ERROR_OK)
- return retval;
-
- if (cfi_spansion_wait_status_busy(bank, cfi_info->buf_write_timeout) != ERROR_OK) {
- retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR("couldn't write block at base 0x%" PRIx32
- ", address 0x%" PRIx32 ", size 0x%" PRIx32, bank->base, address,
- bufferwsize);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_write_word(bank, word, address);
- break;
- case 2:
- return cfi_spansion_write_word(bank, word, address);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
- }
-
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-static int cfi_write_words(struct flash_bank *bank, const uint8_t *word,
- uint32_t wordcount, uint32_t address)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- if (cfi_info->buf_write_timeout_typ == 0) {
- /* buffer writes are not supported */
- LOG_DEBUG("Buffer Writes Not Supported");
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_write_words(bank, word, wordcount, address);
- break;
- case 2:
- return cfi_spansion_write_words(bank, word, wordcount, address);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
- }
-
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-static int cfi_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;
- uint32_t address = bank->base + offset;
- uint32_t read_p;
- int align; /* number of unaligned bytes */
- uint8_t current_word[CFI_MAX_BUS_WIDTH];
- int i;
- int retval;
-
- LOG_DEBUG("reading buffer of %i byte at 0x%8.8x",
- (int)count, (unsigned)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;
-
- /* start at the first byte of the first word (bus_width size) */
- read_p = address & ~(bank->bus_width - 1);
- align = address - read_p;
- if (align != 0) {
- LOG_INFO("Fixup %d unaligned read head bytes", align);
-
- /* read a complete word from flash */
- retval = target_read_memory(target, read_p, bank->bus_width, 1, current_word);
- if (retval != ERROR_OK)
- return retval;
-
- /* take only bytes we need */
- for (i = align; (i < bank->bus_width) && (count > 0); i++, count--)
- *buffer++ = current_word[i];
-
- read_p += bank->bus_width;
- }
-
- align = count / bank->bus_width;
- if (align) {
- retval = target_read_memory(target, read_p, bank->bus_width, align, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- read_p += align * bank->bus_width;
- buffer += align * bank->bus_width;
- count -= align * bank->bus_width;
- }
-
- if (count) {
- LOG_INFO("Fixup %" PRIu32 " unaligned read tail bytes", count);
-
- /* read a complete word from flash */
- retval = target_read_memory(target, read_p, bank->bus_width, 1, current_word);
- if (retval != ERROR_OK)
- return retval;
-
- /* take only bytes we need */
- for (i = 0; (i < bank->bus_width) && (count > 0); i++, count--)
- *buffer++ = current_word[i];
- }
-
- return ERROR_OK;
-}
-
-static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t address = bank->base + offset; /* address of first byte to be programmed */
- uint32_t write_p;
- int align; /* number of unaligned bytes */
- int blk_count; /* number of bus_width bytes for block copy */
- uint8_t current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being
- *programmed */
- uint8_t *swapped_buffer = NULL;
- const uint8_t *real_buffer = NULL;
- 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 = target_read_memory(target, write_p, bank->bus_width, 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;
- }
-
- if (cfi_info->data_swap && count) {
- swapped_buffer = malloc(count & ~(bank->bus_width - 1));
- switch (bank->bus_width) {
- case 2:
- buf_bswap16(swapped_buffer, buffer,
- count & ~(bank->bus_width - 1));
- break;
- case 4:
- buf_bswap32(swapped_buffer, buffer,
- count & ~(bank->bus_width - 1));
- break;
- }
- real_buffer = buffer;
- buffer = swapped_buffer;
- }
-
- /* handle blocks of bus_size aligned bytes */
- blk_count = count & ~(bank->bus_width - 1); /* round down, leave tail bytes */
- switch (cfi_info->pri_id) {
- /* try block writes (fails without working area) */
- case 1:
- case 3:
- retval = cfi_intel_write_block(bank, buffer, write_p, blk_count);
- break;
- case 2:
- retval = cfi_spansion_write_block(bank, buffer, write_p, blk_count);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
- if (retval == ERROR_OK) {
- /* Increment pointers and decrease count on succesful block write */
- buffer += blk_count;
- write_p += blk_count;
- count -= blk_count;
- } else {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* Calculate buffer size and boundary mask
- * buffersize is (buffer size per chip) * (number of chips)
- * bufferwsize is buffersize in words */
- uint32_t buffersize =
- (1UL <<
- cfi_info->max_buf_write_size) *
- (bank->bus_width / bank->chip_width);
- 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 = cfi_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;
- }
- }
- } else
- return retval;
- }
-
- if (swapped_buffer) {
- buffer = real_buffer + (buffer - swapped_buffer);
- free(swapped_buffer);
- }
-
- /* 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 = target_read_memory(target, write_p, bank->bus_width, 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 void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param)
-{
- (void) param;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
-
- pri_ext->_reversed_geometry = 1;
-}
-
-static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param)
-{
- int i;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
- (void) param;
-
- if ((pri_ext->_reversed_geometry) || (pri_ext->TopBottom == 3)) {
- LOG_DEBUG("swapping reversed erase region information on cmdset 0002 device");
-
- for (i = 0; i < cfi_info->num_erase_regions / 2; i++) {
- int j = (cfi_info->num_erase_regions - 1) - i;
- uint32_t swap;
-
- swap = cfi_info->erase_region_info[i];
- cfi_info->erase_region_info[i] = cfi_info->erase_region_info[j];
- cfi_info->erase_region_info[j] = swap;
- }
- }
-}
-
-static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
- const struct cfi_unlock_addresses *unlock_addresses = param;
-
- pri_ext->_unlock1 = unlock_addresses->unlock1;
- pri_ext->_unlock2 = unlock_addresses->unlock2;
-}
-
-static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- const int *status_poll_mask = param;
-
- cfi_info->status_poll_mask = *status_poll_mask;
-}
-
-
-static int cfi_query_string(struct flash_bank *bank, int address)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- int retval;
-
- retval = cfi_send_command(bank, 0x98, flash_address(bank, 0, address));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_query_u8(bank, 0, 0x10, &cfi_info->qry[0]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x11, &cfi_info->qry[1]);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x12, &cfi_info->qry[2]);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x",
- cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
-
- if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y')) {
- retval = cfi_reset(bank);
- if (retval != ERROR_OK)
- return retval;
- LOG_ERROR("Could not probe bank: no QRY");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- return ERROR_OK;
-}
-
-static int cfi_probe(struct flash_bank *bank)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct target *target = bank->target;
- int num_sectors = 0;
- int i;
- int sector = 0;
- uint32_t unlock1 = 0x555;
- uint32_t unlock2 = 0x2aa;
- int retval;
- uint8_t value_buf0[CFI_MAX_BUS_WIDTH], value_buf1[CFI_MAX_BUS_WIDTH];
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- cfi_info->probed = 0;
- cfi_info->num_erase_regions = 0;
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
- if (cfi_info->erase_region_info) {
- free(cfi_info->erase_region_info);
- cfi_info->erase_region_info = NULL;
- }
-
- /* JEDEC standard JESD21C uses 0x5555 and 0x2aaa as unlock addresses,
- * while CFI compatible AMD/Spansion flashes use 0x555 and 0x2aa
- */
- if (cfi_info->jedec_probe) {
- unlock1 = 0x5555;
- unlock2 = 0x2aaa;
- }
-
- /* switch to read identifier codes mode ("AUTOSELECT") */
- retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, unlock1));
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, unlock2));
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_memory(target, flash_address(bank, 0, 0x00),
- bank->bus_width, 1, value_buf0);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_memory(target, flash_address(bank, 0, 0x01),
- bank->bus_width, 1, value_buf1);
- if (retval != ERROR_OK)
- return retval;
- switch (bank->chip_width) {
- case 1:
- cfi_info->manufacturer = *value_buf0;
- cfi_info->device_id = *value_buf1;
- break;
- case 2:
- cfi_info->manufacturer = target_buffer_get_u16(target, value_buf0);
- cfi_info->device_id = target_buffer_get_u16(target, value_buf1);
- break;
- case 4:
- cfi_info->manufacturer = target_buffer_get_u32(target, value_buf0);
- cfi_info->device_id = target_buffer_get_u32(target, value_buf1);
- break;
- default:
- LOG_ERROR("Unsupported bank chipwidth %d, can't probe memory",
- bank->chip_width);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- LOG_INFO("Flash Manufacturer/Device: 0x%04x 0x%04x",
- cfi_info->manufacturer, cfi_info->device_id);
- /* switch back to read array mode */
- retval = cfi_reset(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* check device/manufacturer ID for known non-CFI flashes. */
- cfi_fixup_non_cfi(bank);
-
- /* query only if this is a CFI compatible flash,
- * otherwise the relevant info has already been filled in
- */
- if (cfi_info->not_cfi == 0) {
- /* enter CFI query mode
- * according to JEDEC Standard No. 68.01,
- * a single bus sequence with address = 0x55, data = 0x98 should put
- * the device into CFI query mode.
- *
- * SST flashes clearly violate this, and we will consider them incompatible for now
- */
-
- retval = cfi_query_string(bank, 0x55);
- if (retval != ERROR_OK) {
- /*
- * Spansion S29WS-N CFI query fix is to try 0x555 if 0x55 fails. Should
- * be harmless enough:
- *
- * http://www.infradead.org/pipermail/linux-mtd/2005-September/013618.html
- */
- LOG_USER("Try workaround w/0x555 instead of 0x55 to get QRY.");
- retval = cfi_query_string(bank, 0x555);
- }
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_query_u16(bank, 0, 0x13, &cfi_info->pri_id);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u16(bank, 0, 0x15, &cfi_info->pri_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u16(bank, 0, 0x17, &cfi_info->alt_id);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u16(bank, 0, 0x19, &cfi_info->alt_addr);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: "
- "0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1],
- cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr,
- cfi_info->alt_id, cfi_info->alt_addr);
-
- retval = cfi_query_u8(bank, 0, 0x1b, &cfi_info->vcc_min);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x1c, &cfi_info->vcc_max);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x1d, &cfi_info->vpp_min);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x1e, &cfi_info->vpp_max);
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_query_u8(bank, 0, 0x1f, &cfi_info->word_write_timeout_typ);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x20, &cfi_info->buf_write_timeout_typ);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x21, &cfi_info->block_erase_timeout_typ);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x22, &cfi_info->chip_erase_timeout_typ);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x23, &cfi_info->word_write_timeout_max);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x24, &cfi_info->buf_write_timeout_max);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x25, &cfi_info->block_erase_timeout_max);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x26, &cfi_info->chip_erase_timeout_max);
- if (retval != ERROR_OK)
- return retval;
-
- uint8_t data;
- retval = cfi_query_u8(bank, 0, 0x27, &data);
- if (retval != ERROR_OK)
- return retval;
- cfi_info->dev_size = 1 << data;
-
- retval = cfi_query_u16(bank, 0, 0x28, &cfi_info->interface_desc);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u16(bank, 0, 0x2a, &cfi_info->max_buf_write_size);
- if (retval != ERROR_OK)
- return retval;
- retval = cfi_query_u8(bank, 0, 0x2c, &cfi_info->num_erase_regions);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("size: 0x%" PRIx32 ", interface desc: %i, max buffer write size: 0x%x",
- cfi_info->dev_size, cfi_info->interface_desc,
- (1 << cfi_info->max_buf_write_size));
-
- if (cfi_info->num_erase_regions) {
- cfi_info->erase_region_info = malloc(sizeof(*cfi_info->erase_region_info)
- * cfi_info->num_erase_regions);
- for (i = 0; i < cfi_info->num_erase_regions; i++) {
- retval = cfi_query_u32(bank,
- 0,
- 0x2d + (4 * i),
- &cfi_info->erase_region_info[i]);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG(
- "erase region[%i]: %" PRIu32 " blocks of size 0x%" PRIx32 "",
- i,
- (cfi_info->erase_region_info[i] & 0xffff) + 1,
- (cfi_info->erase_region_info[i] >> 16) * 256);
- }
- } else
- cfi_info->erase_region_info = NULL;
-
- /* We need to read the primary algorithm extended query table before calculating
- * the sector layout to be able to apply fixups
- */
- switch (cfi_info->pri_id) {
- /* Intel command set (standard and extended) */
- case 0x0001:
- case 0x0003:
- cfi_read_intel_pri_ext(bank);
- break;
- /* AMD/Spansion, Atmel, ... command set */
- case 0x0002:
- cfi_info->status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7; /*
- *default
- *for
- *all
- *CFI
- *flashs
- **/
- cfi_read_0002_pri_ext(bank);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
- }
-
- /* return to read array mode
- * we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command
- */
- retval = cfi_reset(bank);
- if (retval != ERROR_OK)
- return retval;
- } /* end CFI case */
-
- LOG_DEBUG("Vcc min: %x.%x, Vcc max: %x.%x, Vpp min: %u.%x, Vpp max: %u.%x",
- (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
- (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
- (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
- (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
-
- LOG_DEBUG("typ. word write timeout: %u us, typ. buf write timeout: %u us, "
- "typ. block erase timeout: %u ms, typ. chip erase timeout: %u ms",
- 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,
- 1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);
-
- LOG_DEBUG("max. word write timeout: %u us, max. buf write timeout: %u us, "
- "max. block erase timeout: %u ms, max. chip erase timeout: %u ms",
- (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
- (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
- (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),
- (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));
-
- /* convert timeouts to real values in ms */
- cfi_info->word_write_timeout = DIV_ROUND_UP((1L << cfi_info->word_write_timeout_typ) *
- (1L << cfi_info->word_write_timeout_max), 1000);
- cfi_info->buf_write_timeout = DIV_ROUND_UP((1L << cfi_info->buf_write_timeout_typ) *
- (1L << cfi_info->buf_write_timeout_max), 1000);
- cfi_info->block_erase_timeout = (1L << cfi_info->block_erase_timeout_typ) *
- (1L << cfi_info->block_erase_timeout_max);
- cfi_info->chip_erase_timeout = (1L << cfi_info->chip_erase_timeout_typ) *
- (1L << cfi_info->chip_erase_timeout_max);
-
- LOG_DEBUG("calculated word write timeout: %u ms, buf write timeout: %u ms, "
- "block erase timeout: %u ms, chip erase timeout: %u ms",
- cfi_info->word_write_timeout, cfi_info->buf_write_timeout,
- cfi_info->block_erase_timeout, cfi_info->chip_erase_timeout);
-
- /* apply fixups depending on the primary command set */
- switch (cfi_info->pri_id) {
- /* Intel command set (standard and extended) */
- case 0x0001:
- case 0x0003:
- cfi_fixup(bank, cfi_0001_fixups);
- break;
- /* AMD/Spansion, Atmel, ... command set */
- case 0x0002:
- cfi_fixup(bank, cfi_0002_fixups);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
- }
-
- if ((cfi_info->dev_size * bank->bus_width / bank->chip_width) != bank->size) {
- LOG_WARNING("configuration specifies 0x%" PRIx32 " size, but a 0x%" PRIx32
- " size flash was found", bank->size, cfi_info->dev_size);
- }
-
- if (cfi_info->num_erase_regions == 0) {
- /* a device might have only one erase block, spanning the whole device */
- bank->num_sectors = 1;
- bank->sectors = malloc(sizeof(struct flash_sector));
-
- bank->sectors[sector].offset = 0x0;
- bank->sectors[sector].size = bank->size;
- bank->sectors[sector].is_erased = -1;
- bank->sectors[sector].is_protected = -1;
- } else {
- uint32_t offset = 0;
-
- for (i = 0; i < cfi_info->num_erase_regions; i++)
- num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1;
-
- bank->num_sectors = num_sectors;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
-
- for (i = 0; i < cfi_info->num_erase_regions; i++) {
- uint32_t j;
- for (j = 0; j < (cfi_info->erase_region_info[i] & 0xffff) + 1; j++) {
- bank->sectors[sector].offset = offset;
- bank->sectors[sector].size =
- ((cfi_info->erase_region_info[i] >> 16) * 256)
- * bank->bus_width / bank->chip_width;
- offset += bank->sectors[sector].size;
- bank->sectors[sector].is_erased = -1;
- bank->sectors[sector].is_protected = -1;
- sector++;
- }
- }
- if (offset != (cfi_info->dev_size * bank->bus_width / bank->chip_width)) {
- LOG_WARNING(
- "CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32 "", \
- (cfi_info->dev_size * bank->bus_width / bank->chip_width),
- offset);
- }
- }
-
- cfi_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int cfi_auto_probe(struct flash_bank *bank)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- if (cfi_info->probed)
- return ERROR_OK;
- return cfi_probe(bank);
-}
-
-static int cfi_intel_protect_check(struct flash_bank *bank)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext;
- int i;
-
- /* check if block lock bits are supported on this device */
- if (!(pri_ext->blk_status_reg_mask & 0x1))
- return ERROR_FLASH_OPERATION_FAILED;
-
- retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, 0x55));
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint8_t block_status;
- retval = cfi_get_u8(bank, i, 0x2, &block_status);
- if (retval != ERROR_OK)
- return retval;
-
- if (block_status & 1)
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- }
-
- return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
-}
-
-static int cfi_spansion_protect_check(struct flash_bank *bank)
-{
- int retval;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
- int i;
-
- retval = cfi_send_command(bank, 0xaa, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x55, flash_address(bank, 0, pri_ext->_unlock2));
- if (retval != ERROR_OK)
- return retval;
-
- retval = cfi_send_command(bank, 0x90, flash_address(bank, 0, pri_ext->_unlock1));
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint8_t block_status;
- retval = cfi_get_u8(bank, i, 0x2, &block_status);
- if (retval != ERROR_OK)
- return retval;
-
- if (block_status & 1)
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- }
-
- return cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
-}
-
-static int cfi_protect_check(struct flash_bank *bank)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (cfi_info->qry[0] != 'Q')
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- switch (cfi_info->pri_id) {
- case 1:
- case 3:
- return cfi_intel_protect_check(bank);
- break;
- case 2:
- return cfi_spansion_protect_check(bank);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
- }
-
- return ERROR_OK;
-}
-
-static int get_cfi_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int printed;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- if (cfi_info->qry[0] == 0xff) {
- snprintf(buf, buf_size, "\ncfi flash bank not probed yet\n");
- return ERROR_OK;
- }
-
- if (cfi_info->not_cfi == 0)
- printed = snprintf(buf, buf_size, "\nCFI flash: ");
- else
- printed = snprintf(buf, buf_size, "\nnon-CFI flash: ");
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "mfr: 0x%4.4x, id:0x%4.4x\n\n",
- cfi_info->manufacturer, cfi_info->device_id);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: "
- "0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x\n",
- cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2],
- cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "Vcc min: %x.%x, Vcc max: %x.%x, "
- "Vpp min: %u.%x, Vpp max: %u.%x\n",
- (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
- (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
- (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
- (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "typ. word write timeout: %u us, "
- "typ. buf write timeout: %u us, "
- "typ. block erase timeout: %u ms, "
- "typ. chip erase timeout: %u ms\n",
- 1 << cfi_info->word_write_timeout_typ,
- 1 << cfi_info->buf_write_timeout_typ,
- 1 << cfi_info->block_erase_timeout_typ,
- 1 << cfi_info->chip_erase_timeout_typ);
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf,
- buf_size,
- "max. word write timeout: %u us, "
- "max. buf write timeout: %u us, max. "
- "block erase timeout: %u ms, max. chip erase timeout: %u ms\n",
- (1 <<
- cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
- (1 <<
- cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
- (1 <<
- cfi_info->block_erase_timeout_max) *
- (1 << cfi_info->block_erase_timeout_typ),
- (1 <<
- cfi_info->chip_erase_timeout_max) *
- (1 << cfi_info->chip_erase_timeout_typ));
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf, buf_size, "size: 0x%" PRIx32 ", interface desc: %i, "
- "max buffer write size: 0x%x\n",
- cfi_info->dev_size,
- cfi_info->interface_desc,
- 1 << cfi_info->max_buf_write_size);
- buf += printed;
- buf_size -= printed;
-
- switch (cfi_info->pri_id) {
- case 1:
- case 3:
- cfi_intel_info(bank, buf, buf_size);
- break;
- case 2:
- cfi_spansion_info(bank, buf, buf_size);
- break;
- default:
- LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
- break;
- }
-
- return ERROR_OK;
-}
-
-static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param)
-{
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
-
- /* disable write buffer for M29W128G */
- cfi_info->buf_write_timeout_typ = 0;
-}
-
-struct flash_driver cfi_flash = {
- .name = "cfi",
- .flash_bank_command = cfi_flash_bank_command,
- .erase = cfi_erase,
- .protect = cfi_protect,
- .write = cfi_write,
- .read = cfi_read,
- .probe = cfi_probe,
- .auto_probe = cfi_auto_probe,
- /* FIXME: access flash at bus_width size */
- .erase_check = default_flash_blank_check,
- .protect_check = cfi_protect_check,
- .info = get_cfi_info,
-};
diff --git a/src/flash/nor/cfi.h b/src/flash/nor/cfi.h
deleted file mode 100644
index ed858a9..0000000
--- a/src/flash/nor/cfi.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NOR_CFI_H
-#define OPENOCD_FLASH_NOR_CFI_H
-
-#define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */
-#define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */
-
-struct cfi_flash_bank {
- int x16_as_x8;
- int jedec_probe;
- int not_cfi;
- int probed;
-
- enum target_endianness endianness;
- int data_swap;
-
- uint16_t manufacturer;
- uint16_t device_id;
-
- uint8_t qry[3];
-
- /* identification string */
- uint16_t pri_id;
- uint16_t pri_addr;
- uint16_t alt_id;
- uint16_t alt_addr;
-
- /* device-system interface */
- uint8_t vcc_min;
- uint8_t vcc_max;
- uint8_t vpp_min;
- uint8_t vpp_max;
- uint8_t word_write_timeout_typ;
- uint8_t buf_write_timeout_typ;
- uint8_t block_erase_timeout_typ;
- uint8_t chip_erase_timeout_typ;
- uint8_t word_write_timeout_max;
- uint8_t buf_write_timeout_max;
- uint8_t block_erase_timeout_max;
- uint8_t chip_erase_timeout_max;
-
- uint8_t status_poll_mask;
-
- /* flash geometry */
- uint32_t dev_size;
- uint16_t interface_desc;
- uint16_t max_buf_write_size;
- uint8_t num_erase_regions;
- uint32_t *erase_region_info;
-
- void *pri_ext;
- void *alt_ext;
-
- /* calculated timeouts */
- unsigned word_write_timeout;
- unsigned buf_write_timeout;
- unsigned block_erase_timeout;
- unsigned chip_erase_timeout;
-};
-
-/* Intel primary extended query table
- * as defined for the Advanced+ Boot Block Flash Memory (C3)
- * and used by the linux kernel cfi driver (as of 2.6.14)
- */
-struct cfi_intel_pri_ext {
- uint8_t pri[3];
- uint8_t major_version;
- uint8_t minor_version;
- uint32_t feature_support;
- uint8_t suspend_cmd_support;
- uint16_t blk_status_reg_mask;
- uint8_t vcc_optimal;
- uint8_t vpp_optimal;
- uint8_t num_protection_fields;
- uint16_t prot_reg_addr;
- uint8_t fact_prot_reg_size;
- uint8_t user_prot_reg_size;
- uint8_t extra[0];
-};
-
-/* Spansion primary extended query table as defined for and used by
- * the linux kernel cfi driver (as of 2.6.15)
- */
-struct cfi_spansion_pri_ext {
- uint8_t pri[3];
- uint8_t major_version;
- uint8_t minor_version;
- uint8_t SiliconRevision; /* bits 1-0: Address Sensitive Unlock */
- uint8_t EraseSuspend;
- uint8_t BlkProt;
- uint8_t TmpBlkUnprotect;
- uint8_t BlkProtUnprot;
- uint8_t SimultaneousOps;
- uint8_t BurstMode;
- uint8_t PageMode;
- uint8_t VppMin;
- uint8_t VppMax;
- uint8_t TopBottom;
- int _reversed_geometry;
- uint32_t _unlock1;
- uint32_t _unlock2;
-};
-
-/* Atmel primary extended query table as defined for and used by
- * the linux kernel cfi driver (as of 2.6.20+)
- */
-struct cfi_atmel_pri_ext {
- uint8_t pri[3];
- uint8_t major_version;
- uint8_t minor_version;
- uint8_t features;
- uint8_t bottom_boot;
- uint8_t burst_mode;
- uint8_t page_mode;
-};
-
-enum {
- CFI_UNLOCK_555_2AA,
- CFI_UNLOCK_5555_2AAA,
-};
-
-struct cfi_unlock_addresses {
- uint32_t unlock1;
- uint32_t unlock2;
-};
-
-struct cfi_fixup {
- uint16_t mfr;
- uint16_t id;
- void (*fixup)(struct flash_bank *bank, const void *param);
- const void *param;
-};
-
-#define CFI_MFR_AMD 0x0001
-#define CFI_MFR_FUJITSU 0x0004
-#define CFI_MFR_ATMEL 0x001F
-#define CFI_MFR_ST 0x0020 /* STMicroelectronics */
-#define CFI_MFR_AMIC 0x0037
-#define CFI_MFR_SST 0x00BF
-#define CFI_MFR_MX 0x00C2
-#define CFI_MFR_EON 0x007F
-
-#define CFI_MFR_ANY 0xffff
-#define CFI_ID_ANY 0xffff
-
-#endif /* OPENOCD_FLASH_NOR_CFI_H */
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
deleted file mode 100644
index 7a62ba1..0000000
--- a/src/flash/nor/core.c
+++ /dev/null
@@ -1,797 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007-2010 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <flash/common.h>
-#include <flash/nor/core.h>
-#include <flash/nor/imp.h>
-#include <target/image.h>
-
-/**
- * @file
- * Upper level of NOR flash framework.
- * The lower level interfaces are to drivers. These upper level ones
- * primarily support access from Tcl scripts or from GDB.
- */
-
-static struct flash_bank *flash_banks;
-
-int flash_driver_erase(struct flash_bank *bank, int first, int last)
-{
- int retval;
-
- retval = bank->driver->erase(bank, first, last);
- if (retval != ERROR_OK)
- LOG_ERROR("failed erasing sectors %d to %d", first, last);
-
- return retval;
-}
-
-int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int retval;
-
- /* callers may not supply illegal parameters ... */
- if (first < 0 || first > last || last >= bank->num_sectors) {
- LOG_ERROR("illegal sector range");
- return ERROR_FAIL;
- }
-
- /* force "set" to 0/1 */
- set = !!set;
-
- /* DANGER!
- *
- * We must not use any cached information about protection state!!!!
- *
- * There are a million things that could change the protect state:
- *
- * the target could have reset, power cycled, been hot plugged,
- * the application could have run, etc.
- *
- * Drivers only receive valid sector range.
- */
- retval = bank->driver->protect(bank, set, first, last);
- if (retval != ERROR_OK)
- LOG_ERROR("failed setting protection for areas %d to %d", first, last);
-
- return retval;
-}
-
-int flash_driver_write(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- int retval;
-
- retval = bank->driver->write(bank, buffer, offset, count);
- if (retval != ERROR_OK) {
- LOG_ERROR(
- "error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
- bank->base,
- offset);
- }
-
- return retval;
-}
-
-int flash_driver_read(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- int retval;
-
- LOG_DEBUG("call flash_driver_read()");
-
- retval = bank->driver->read(bank, buffer, offset, count);
- if (retval != ERROR_OK) {
- LOG_ERROR(
- "error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
- bank->base,
- offset);
- }
-
- return retval;
-}
-
-int default_flash_read(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- return target_read_buffer(bank->target, offset + bank->base, count, buffer);
-}
-
-void flash_bank_add(struct flash_bank *bank)
-{
- /* put flash bank in linked list */
- unsigned bank_num = 0;
- if (flash_banks) {
- /* find last flash bank */
- struct flash_bank *p = flash_banks;
- while (NULL != p->next) {
- bank_num += 1;
- p = p->next;
- }
- p->next = bank;
- bank_num += 1;
- } else
- flash_banks = bank;
-
- bank->bank_number = bank_num;
-}
-
-struct flash_bank *flash_bank_list(void)
-{
- return flash_banks;
-}
-
-struct flash_bank *get_flash_bank_by_num_noprobe(int num)
-{
- struct flash_bank *p;
- int i = 0;
-
- for (p = flash_banks; p; p = p->next) {
- if (i++ == num)
- return p;
- }
- LOG_ERROR("flash bank %d does not exist", num);
- return NULL;
-}
-
-int flash_get_bank_count(void)
-{
- struct flash_bank *p;
- int i = 0;
- for (p = flash_banks; p; p = p->next)
- i++;
- return i;
-}
-
-struct flash_bank *get_flash_bank_by_name_noprobe(const char *name)
-{
- unsigned requested = get_flash_name_index(name);
- unsigned found = 0;
-
- struct flash_bank *bank;
- for (bank = flash_banks; NULL != bank; bank = bank->next) {
- if (strcmp(bank->name, name) == 0)
- return bank;
- if (!flash_driver_name_matches(bank->driver->name, name))
- continue;
- if (++found < requested)
- continue;
- return bank;
- }
- return NULL;
-}
-
-int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result)
-{
- struct flash_bank *bank;
- int retval;
-
- bank = get_flash_bank_by_name_noprobe(name);
- if (bank != NULL) {
- retval = bank->driver->auto_probe(bank);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("auto_probe failed");
- return retval;
- }
- }
-
- *bank_result = bank;
- return ERROR_OK;
-}
-
-int get_flash_bank_by_num(int num, struct flash_bank **bank)
-{
- struct flash_bank *p = get_flash_bank_by_num_noprobe(num);
- int retval;
-
- if (p == NULL)
- return ERROR_FAIL;
-
- retval = p->driver->auto_probe(p);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("auto_probe failed");
- return retval;
- }
- *bank = p;
- return ERROR_OK;
-}
-
-/* lookup flash bank by address, bank not found is success, but
- * result_bank is set to NULL. */
-int get_flash_bank_by_addr(struct target *target,
- uint32_t addr,
- bool check,
- struct flash_bank **result_bank)
-{
- struct flash_bank *c;
-
- /* cycle through bank list */
- for (c = flash_banks; c; c = c->next) {
- if (c->target != target)
- continue;
-
- int retval;
- retval = c->driver->auto_probe(c);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("auto_probe failed");
- return retval;
- }
- /* check whether address belongs to this flash bank */
- if ((addr >= c->base) && (addr <= c->base + (c->size - 1))) {
- *result_bank = c;
- return ERROR_OK;
- }
- }
- *result_bank = NULL;
- if (check) {
- LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int default_flash_mem_blank_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- const int buffer_size = 1024;
- int i;
- uint32_t nBytes;
- int retval = ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint8_t *buffer = malloc(buffer_size);
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t j;
- bank->sectors[i].is_erased = 1;
-
- for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
- uint32_t chunk;
- chunk = buffer_size;
- if (chunk > (j - bank->sectors[i].size))
- chunk = (j - bank->sectors[i].size);
-
- retval = target_read_memory(target,
- bank->base + bank->sectors[i].offset + j,
- 4,
- chunk/4,
- buffer);
- if (retval != ERROR_OK)
- goto done;
-
- for (nBytes = 0; nBytes < chunk; nBytes++) {
- if (buffer[nBytes] != 0xFF) {
- bank->sectors[i].is_erased = 0;
- break;
- }
- }
- }
- }
-
-done:
- free(buffer);
-
- return retval;
-}
-
-int default_flash_blank_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int i;
- int retval;
- int fast_check = 0;
- uint32_t blank;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t address = bank->base + bank->sectors[i].offset;
- uint32_t size = bank->sectors[i].size;
-
- retval = target_blank_check_memory(target, address, size, &blank);
- if (retval != ERROR_OK) {
- fast_check = 0;
- break;
- }
- if (blank == 0xFF)
- bank->sectors[i].is_erased = 1;
- else
- bank->sectors[i].is_erased = 0;
- fast_check = 1;
- }
-
- if (!fast_check) {
- LOG_USER("Running slow fallback erase check - add working memory");
- return default_flash_mem_blank_check(bank);
- }
-
- return ERROR_OK;
-}
-
-/* Manipulate given flash region, selecting the bank according to target
- * and address. Maps an address range to a set of sectors, and issues
- * the callback() on that set ... e.g. to erase or unprotect its members.
- *
- * Parameter iterate_protect_blocks switches iteration of protect block
- * instead of erase sectors. If there is no protect blocks array, sectors
- * are used in iteration, so compatibility for old flash drivers is retained.
- *
- * The "pad_reason" parameter is a kind of boolean: when it's NULL, the
- * range must fit those sectors exactly. This is clearly safe; it can't
- * erase data which the caller said to leave alone, for example. If it's
- * non-NULL, rather than failing, extra data in the first and/or last
- * sectors will be added to the range, and that reason string is used when
- * warning about those additions.
- */
-static int flash_iterate_address_range_inner(struct target *target,
- char *pad_reason, uint32_t addr, uint32_t length,
- bool iterate_protect_blocks,
- int (*callback)(struct flash_bank *bank, int first, int last))
-{
- struct flash_bank *c;
- struct flash_sector *block_array;
- uint32_t last_addr = addr + length; /* first address AFTER end */
- int first = -1;
- int last = -1;
- int i;
- int num_blocks;
-
- int retval = get_flash_bank_by_addr(target, addr, true, &c);
- if (retval != ERROR_OK)
- return retval;
-
- if (c->size == 0 || c->num_sectors == 0) {
- LOG_ERROR("Bank is invalid");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- if (length == 0) {
- /* special case, erase whole bank when length is zero */
- if (addr != c->base) {
- LOG_ERROR("Whole bank access must start at beginning of bank.");
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- return callback(c, 0, c->num_sectors - 1);
- }
-
- /* check whether it all fits in this bank */
- if (addr + length - 1 > c->base + c->size - 1) {
- LOG_ERROR("Flash access does not fit into bank.");
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- addr -= c->base;
- last_addr -= c->base;
-
- if (iterate_protect_blocks && c->prot_blocks && c->num_prot_blocks) {
- block_array = c->prot_blocks;
- num_blocks = c->num_prot_blocks;
- } else {
- block_array = c->sectors;
- num_blocks = c->num_sectors;
- iterate_protect_blocks = false;
- }
-
-
- for (i = 0; i < num_blocks; i++) {
- struct flash_sector *f = &block_array[i];
- uint32_t end = f->offset + f->size;
-
- /* start only on a sector boundary */
- if (first < 0) {
- /* scanned past the first sector? */
- if (addr < f->offset)
- break;
-
- /* is this the first sector? */
- if (addr == f->offset)
- first = i;
-
- /* Does this need head-padding? If so, pad and warn;
- * or else force an error.
- *
- * Such padding can make trouble, since *WE* can't
- * ever know if that data was in use. The warning
- * should help users sort out messes later.
- */
- else if (addr < end && pad_reason) {
- /* FIXME say how many bytes (e.g. 80 KB) */
- LOG_WARNING("Adding extra %s range, "
- "%#8.8x to %#8.8x",
- pad_reason,
- (unsigned) f->offset,
- (unsigned) addr - 1);
- first = i;
- } else
- continue;
- }
-
- /* is this (also?) the last sector? */
- if (last_addr == end) {
- last = i;
- break;
- }
-
- /* Does this need tail-padding? If so, pad and warn;
- * or else force an error.
- */
- if (last_addr < end && pad_reason) {
- /* FIXME say how many bytes (e.g. 80 KB) */
- LOG_WARNING("Adding extra %s range, "
- "%#8.8x to %#8.8x",
- pad_reason,
- (unsigned) last_addr,
- (unsigned) end - 1);
- last = i;
- break;
- }
-
- /* MUST finish on a sector boundary */
- if (last_addr <= f->offset)
- break;
- }
-
- /* invalid start or end address? */
- if (first == -1 || last == -1) {
- LOG_ERROR("address range 0x%8.8x .. 0x%8.8x "
- "is not sector-aligned",
- (unsigned) (c->base + addr),
- (unsigned) (c->base + last_addr - 1));
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* The NOR driver may trim this range down, based on what
- * sectors are already erased/unprotected. GDB currently
- * blocks such optimizations.
- */
- return callback(c, first, last);
-}
-
-/* The inner fn only handles a single bank, we could be spanning
- * multiple chips.
- */
-static int flash_iterate_address_range(struct target *target,
- char *pad_reason, uint32_t addr, uint32_t length,
- bool iterate_protect_blocks,
- int (*callback)(struct flash_bank *bank, int first, int last))
-{
- struct flash_bank *c;
- int retval = ERROR_OK;
-
- /* Danger! zero-length iterations means entire bank! */
- do {
- retval = get_flash_bank_by_addr(target, addr, true, &c);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t cur_length = length;
- /* check whether it all fits in this bank */
- if (addr + length - 1 > c->base + c->size - 1) {
- LOG_DEBUG("iterating over more than one flash bank.");
- cur_length = c->base + c->size - addr;
- }
- retval = flash_iterate_address_range_inner(target,
- pad_reason, addr, cur_length,
- iterate_protect_blocks,
- callback);
- if (retval != ERROR_OK)
- break;
-
- length -= cur_length;
- addr += cur_length;
- } while (length > 0);
-
- return retval;
-}
-
-int flash_erase_address_range(struct target *target,
- bool pad, uint32_t addr, uint32_t length)
-{
- return flash_iterate_address_range(target, pad ? "erase" : NULL,
- addr, length, false, &flash_driver_erase);
-}
-
-static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
-{
- return flash_driver_protect(bank, 0, first, last);
-}
-
-int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
-{
- /* By default, pad to sector boundaries ... the real issue here
- * is that our (only) caller *permanently* removes protection,
- * and doesn't restore it.
- */
- return flash_iterate_address_range(target, "unprotect",
- addr, length, true, &flash_driver_unprotect);
-}
-
-static int compare_section(const void *a, const void *b)
-{
- struct imagesection *b1, *b2;
- b1 = *((struct imagesection **)a);
- b2 = *((struct imagesection **)b);
-
- if (b1->base_address == b2->base_address)
- return 0;
- else if (b1->base_address > b2->base_address)
- return 1;
- else
- return -1;
-}
-
-int flash_write_unlock(struct target *target, struct image *image,
- uint32_t *written, int erase, bool unlock)
-{
- int retval = ERROR_OK;
-
- int section;
- uint32_t section_offset;
- struct flash_bank *c;
- int *padding;
-
- section = 0;
- section_offset = 0;
-
- if (written)
- *written = 0;
-
- if (erase) {
- /* assume all sectors need erasing - stops any problems
- * when flash_write is called multiple times */
-
- flash_set_dirty();
- }
-
- /* allocate padding array */
- padding = calloc(image->num_sections, sizeof(*padding));
-
- /* This fn requires all sections to be in ascending order of addresses,
- * whereas an image can have sections out of order. */
- struct imagesection **sections = malloc(sizeof(struct imagesection *) *
- image->num_sections);
- int i;
- for (i = 0; i < image->num_sections; i++)
- sections[i] = &image->sections[i];
-
- qsort(sections, image->num_sections, sizeof(struct imagesection *),
- compare_section);
-
- /* loop until we reach end of the image */
- while (section < image->num_sections) {
- uint32_t buffer_size;
- uint8_t *buffer;
- int section_last;
- uint32_t run_address = sections[section]->base_address + section_offset;
- uint32_t run_size = sections[section]->size - section_offset;
- int pad_bytes = 0;
-
- if (sections[section]->size == 0) {
- LOG_WARNING("empty section %d", section);
- section++;
- section_offset = 0;
- continue;
- }
-
- /* find the corresponding flash bank */
- retval = get_flash_bank_by_addr(target, run_address, false, &c);
- if (retval != ERROR_OK)
- goto done;
- if (c == NULL) {
- LOG_WARNING("no flash bank found for address %" PRIx32, run_address);
- section++; /* and skip it */
- section_offset = 0;
- continue;
- }
-
- /* collect consecutive sections which fall into the same bank */
- section_last = section;
- padding[section] = 0;
- while ((run_address + run_size - 1 < c->base + c->size - 1) &&
- (section_last + 1 < image->num_sections)) {
- /* sections are sorted */
- assert(sections[section_last + 1]->base_address >= c->base);
- if (sections[section_last + 1]->base_address >= (c->base + c->size)) {
- /* Done with this bank */
- break;
- }
-
- /* FIXME This needlessly touches sectors BETWEEN the
- * sections it's writing. Without auto erase, it just
- * writes ones. That WILL INVALIDATE data in cases
- * like Stellaris Tempest chips, corrupting internal
- * ECC codes; and at least FreeScale suggests issues
- * with that approach (in HC11 documentation).
- *
- * With auto erase enabled, data in those sectors will
- * be needlessly destroyed; and some of the limited
- * number of flash erase cycles will be wasted...
- *
- * In both cases, the extra writes slow things down.
- */
-
- /* if we have multiple sections within our image,
- * flash programming could fail due to alignment issues
- * attempt to rebuild a consecutive buffer for the flash loader */
- pad_bytes = (sections[section_last + 1]->base_address) - (run_address + run_size);
- padding[section_last] = pad_bytes;
- run_size += sections[++section_last]->size;
- run_size += pad_bytes;
-
- if (pad_bytes > 0)
- LOG_INFO("Padding image section %d with %d bytes",
- section_last-1,
- pad_bytes);
- }
-
- if (run_address + run_size - 1 > c->base + c->size - 1) {
- /* If we have more than one flash chip back to back, then we limit
- * the current write operation to the current chip.
- */
- LOG_DEBUG("Truncate flash run size to the current flash chip.");
-
- run_size = c->base + c->size - run_address;
- assert(run_size > 0);
- }
-
- /* If we're applying any sector automagic, then pad this
- * (maybe-combined) segment to the end of its last sector.
- */
- if (unlock || erase) {
- int sector;
- uint32_t offset_start = run_address - c->base;
- uint32_t offset_end = offset_start + run_size;
- uint32_t end = offset_end, delta;
-
- for (sector = 0; sector < c->num_sectors; sector++) {
- end = c->sectors[sector].offset
- + c->sectors[sector].size;
- if (offset_end <= end)
- break;
- }
-
- delta = end - offset_end;
- padding[section_last] += delta;
- run_size += delta;
- }
-
- /* allocate buffer */
- buffer = malloc(run_size);
- if (buffer == NULL) {
- LOG_ERROR("Out of memory for flash bank buffer");
- retval = ERROR_FAIL;
- goto done;
- }
- buffer_size = 0;
-
- /* read sections to the buffer */
- while (buffer_size < run_size) {
- size_t size_read;
-
- size_read = run_size - buffer_size;
- if (size_read > sections[section]->size - section_offset)
- size_read = sections[section]->size - section_offset;
-
- /* KLUDGE!
- *
- * #¤%#"%¤% we have to figure out the section # from the sorted
- * list of pointers to sections to invoke image_read_section()...
- */
- intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
- int t_section_num = diff / sizeof(struct imagesection);
-
- LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, "
- "section_offset = %d, buffer_size = %d, size_read = %d",
- (int)section, (int)t_section_num, (int)section_offset,
- (int)buffer_size, (int)size_read);
- retval = image_read_section(image, t_section_num, section_offset,
- size_read, buffer + buffer_size, &size_read);
- if (retval != ERROR_OK || size_read == 0) {
- free(buffer);
- goto done;
- }
-
- /* see if we need to pad the section */
- while (padding[section]--)
- (buffer + buffer_size)[size_read++] = c->default_padded_value;
-
- buffer_size += size_read;
- section_offset += size_read;
-
- if (section_offset >= sections[section]->size) {
- section++;
- section_offset = 0;
- }
- }
-
- retval = ERROR_OK;
-
- if (unlock)
- retval = flash_unlock_address_range(target, run_address, run_size);
- if (retval == ERROR_OK) {
- if (erase) {
- /* calculate and erase sectors */
- retval = flash_erase_address_range(target,
- true, run_address, run_size);
- }
- }
-
- if (retval == ERROR_OK) {
- /* write flash sectors */
- retval = flash_driver_write(c, buffer, run_address - c->base, run_size);
- }
-
- free(buffer);
-
- if (retval != ERROR_OK) {
- /* abort operation */
- goto done;
- }
-
- if (written != NULL)
- *written += run_size; /* add run size to total written counter */
- }
-
-done:
- free(sections);
- free(padding);
-
- return retval;
-}
-
-int flash_write(struct target *target, struct image *image,
- uint32_t *written, int erase)
-{
- return flash_write_unlock(target, image, written, erase, false);
-}
-
-struct flash_sector *alloc_block_array(uint32_t offset, uint32_t size, int num_blocks)
-{
- int i;
-
- struct flash_sector *array = calloc(num_blocks, sizeof(struct flash_sector));
- if (array == NULL)
- return NULL;
-
- for (i = 0; i < num_blocks; i++) {
- array[i].offset = offset;
- array[i].size = size;
- array[i].is_erased = -1;
- array[i].is_protected = -1;
- offset += size;
- }
-
- return array;
-}
diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h
deleted file mode 100644
index 60d4483..0000000
--- a/src/flash/nor/core.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NOR_CORE_H
-#define OPENOCD_FLASH_NOR_CORE_H
-
-#include <flash/common.h>
-
-/**
- * @file
- * Upper level NOR flash interfaces.
- */
-
-struct image;
-
-#define FLASH_MAX_ERROR_STR (128)
-
-/**
- * Describes the geometry and status of a single flash sector
- * within a flash bank. A single bank typically consists of multiple
- * sectors, each of which can be erased and protected independently.
- */
-struct flash_sector {
- /** Bus offset from start of the flash chip (in bytes). */
- uint32_t offset;
- /** Number of bytes in this flash sector. */
- uint32_t size;
- /**
- * Indication of erasure status: 0 = not erased, 1 = erased,
- * other = unknown. Set by @c flash_driver_s::erase_check.
- *
- * Flag is not used in protection block
- */
- int is_erased;
- /**
- * Indication of protection status: 0 = unprotected/unlocked,
- * 1 = protected/locked, other = unknown. Set by
- * @c flash_driver_s::protect_check.
- *
- * This information must be considered stale immediately.
- * A million things could make it stale: power cycle,
- * reset of target, code running on target, etc.
- *
- * If a flash_bank uses an extra array of protection blocks,
- * protection flag is not valid in sector array
- */
- int is_protected;
-};
-
-/**
- * Provides details of a flash bank, available either on-chip or through
- * a major interface.
- *
- * This structure will be passed as a parameter to the callbacks in the
- * flash_driver_s structure, some of which may modify the contents of
- * this structure of the area of flash that it defines. Driver writers
- * may use the @c driver_priv member to store additional data on a
- * per-bank basis, if required.
- */
-struct flash_bank {
- const char *name;
-
- struct target *target; /**< Target to which this bank belongs. */
-
- struct flash_driver *driver; /**< Driver for this bank. */
- void *driver_priv; /**< Private driver storage pointer */
-
- int bank_number; /**< The 'bank' (or chip number) of this instance. */
- uint32_t base; /**< The base address of this bank */
- uint32_t size; /**< The size of this chip bank, in bytes */
-
- int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */
- int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */
-
- /** Default padded value used, normally this matches the flash
- * erased value. Defaults to 0xFF. */
- uint8_t default_padded_value;
-
- /**
- * The number of sectors on this chip. This value will
- * be set intially to 0, and the flash driver must set this to
- * some non-zero value during "probe()" or "auto_probe()".
- */
- int num_sectors;
- /** Array of sectors, allocated and initialized by the flash driver */
- struct flash_sector *sectors;
-
- /**
- * The number of protection blocks in this bank. This value
- * is set intially to 0 and sectors are used as protection blocks.
- * Driver probe can set protection blocks array to work with
- * protection granularity different than sector size.
- */
- int num_prot_blocks;
- /** Array of protection blocks, allocated and initilized by the flash driver */
- struct flash_sector *prot_blocks;
-
- struct flash_bank *next; /**< The next flash bank on this chip */
-};
-
-/** Registers the 'flash' subsystem commands */
-int flash_register_commands(struct command_context *cmd_ctx);
-
-/**
- * Erases @a length bytes in the @a target flash, starting at @a addr.
- * The range @a addr to @a addr + @a length - 1 must be strictly
- * sector aligned, unless @a pad is true. Setting @a pad true extends
- * the range, at beginning and/or end, if needed for sector alignment.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
-int flash_erase_address_range(struct target *target,
- bool pad, uint32_t addr, uint32_t length);
-
-int flash_unlock_address_range(struct target *target, uint32_t addr,
- uint32_t length);
-
-/**
- * Writes @a image into the @a target flash. The @a written parameter
- * will contain the
- * @param target The target with the flash to be programmed.
- * @param image The image that will be programmed to flash.
- * @param written On return, contains the number of bytes written.
- * @param erase If non-zero, indicates the flash driver should first
- * erase the corresponding banks or sectors before programming.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
-int flash_write(struct target *target,
- struct image *image, uint32_t *written, int erase);
-
-/**
- * Forces targets to re-examine their erase/protection state.
- * This routine must be called when the system may modify the status.
- */
-void flash_set_dirty(void);
-/** @returns The number of flash banks currently defined. */
-int flash_get_bank_count(void);
-/**
- * Provides default read implementation for flash memory.
- * @param bank The bank to read.
- * @param buffer The data bytes read.
- * @param offset The offset into the chip to read.
- * @param count The number of bytes to read.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
-int default_flash_read(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count);
-/**
- * Provides default erased-bank check handling. Checks to see if
- * the flash driver knows they are erased; if things look uncertain,
- * this routine will call default_flash_mem_blank_check() to confirm.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
-int default_flash_blank_check(struct flash_bank *bank);
-
-/**
- * Returns the flash bank specified by @a name, which matches the
- * driver name and a suffix (option) specify the driver-specific
- * bank number. The suffix consists of the '.' and the driver-specific
- * bank number: when two str9x banks are defined, then 'str9x.1' refers
- * to the second.
- */
-int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result);
-/**
- * Returns the flash bank specified by @a name, which matches the
- * driver name and a suffix (option) specify the driver-specific
- * bank number. The suffix consists of the '.' and the driver-specific
- * bank number: when two str9x banks are defined, then 'str9x.1' refers
- * to the second.
- */
-struct flash_bank *get_flash_bank_by_name_noprobe(const char *name);
-/**
- * Returns the flash bank like get_flash_bank_by_name(), without probing.
- * @param num The flash bank number.
- * @param bank returned bank if fn returns ERROR_OK
- * @returns ERROR_OK if successful
- */
-int get_flash_bank_by_num(int num, struct flash_bank **bank);
-/**
- * Retreives @a bank from a command argument, reporting errors parsing
- * the bank identifier or retreiving the specified bank. The bank
- * may be identified by its bank number or by @c name.instance, where
- * @a instance is driver-specific.
- * @param name_index The index to the string in args containing the
- * bank identifier.
- * @param bank On output, contians a pointer to the bank or NULL.
- * @returns ERROR_OK on success, or an error indicating the problem.
- */
-COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
- struct flash_bank **bank);
-/**
- * Returns the flash bank like get_flash_bank_by_num(), without probing.
- * @param num The flash bank number.
- * @returns A struct flash_bank for flash bank @a num, or NULL.
- */
-struct flash_bank *get_flash_bank_by_num_noprobe(int num);
-/**
- * Returns the flash bank located at a specified address.
- * @param target The target, presumed to contain one or more banks.
- * @param addr An address that is within the range of the bank.
- * @param check return ERROR_OK and result_bank NULL if the bank does not exist
- * @returns The struct flash_bank located at @a addr, or NULL.
- */
-int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check,
- struct flash_bank **result_bank);
-/**
- * Allocate and fill an array of sectors or protection blocks.
- * @param offset Offset of first block.
- * @param size Size of each block.
- * @param num_blocks Number of blocks in array.
- * @returns A struct flash_sector pointer or NULL when allocation failed.
- */
-struct flash_sector *alloc_block_array(uint32_t offset, uint32_t size, int num_blocks);
-
-#endif /* OPENOCD_FLASH_NOR_CORE_H */
diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h
deleted file mode 100644
index 0ae4d8e..0000000
--- a/src/flash/nor/driver.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NOR_DRIVER_H
-#define OPENOCD_FLASH_NOR_DRIVER_H
-
-struct flash_bank;
-
-#define __FLASH_BANK_COMMAND(name) \
- COMMAND_HELPER(name, struct flash_bank *bank)
-
-/**
- * @brief Provides the implementation-independent structure that defines
- * all of the callbacks required by OpenOCD flash drivers.
- *
- * Driver authors must implement the routines defined here, providing an
- * instance with the fields filled out. After that, the instance must
- * be registered in flash.c, so it can be used by the driver lookup system.
- *
- * Specifically, the user can issue the command: @par
- * @code
- * flash bank DRIVERNAME ...parameters...
- * @endcode
- *
- * OpenOCD will search for the driver with a @c flash_driver_s::name
- * that matches @c DRIVERNAME.
- *
- * The flash subsystem calls some of the other drivers routines a using
- * corresponding static <code>flash_driver_<i>callback</i>()</code>
- * routine in flash.c.
- */
-struct flash_driver {
- /**
- * Gives a human-readable name of this flash driver,
- * This field is used to select and initialize the driver.
- */
- const char *name;
-
- /**
- * Gives a human-readable description of arguments.
- */
- const char *usage;
-
- /**
- * An array of driver-specific commands to register. When called
- * during the "flash bank" command, the driver can register addition
- * commands to support new flash chip functions.
- */
- const struct command_registration *commands;
-
- /**
- * Finish the "flash bank" command for @a bank. The
- * @a bank parameter will have been filled in by the core flash
- * layer when this routine is called, and the driver can store
- * additional information in its struct flash_bank::driver_priv field.
- *
- * The CMD_ARGV are: @par
- * @code
- * CMD_ARGV[0] = bank
- * CMD_ARGV[1] = drivername {name above}
- * CMD_ARGV[2] = baseaddress
- * CMD_ARGV[3] = lengthbytes
- * CMD_ARGV[4] = chip_width_in bytes
- * CMD_ARGV[5] = bus_width_in_bytes
- * CMD_ARGV[6] = driver-specific parameters
- * @endcode
- *
- * For example, CMD_ARGV[4] = 2 (for 16 bit flash),
- * CMD_ARGV[5] = 4 (for 32 bit bus).
- *
- * If extra arguments are provided (@a CMD_ARGC > 6), they will
- * start in @a CMD_ARGV[6]. These can be used to implement
- * driver-specific extensions.
- *
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- __FLASH_BANK_COMMAND((*flash_bank_command));
-
- /**
- * Bank/sector erase routine (target-specific). When
- * called, the flash driver should erase the specified sectors
- * using whatever means are at its disposal.
- *
- * @param bank The bank of flash to be erased.
- * @param first The number of the first sector to erase, typically 0.
- * @param last The number of the last sector to erase, typically N-1.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*erase)(struct flash_bank *bank, int first, int last);
-
- /**
- * Bank/sector protection routine (target-specific).
- *
- * When called, the driver should enable/disable protection
- * for MINIMUM the range covered by first..last sectors
- * inclusive. Some chips have alignment requirements will
- * cause the actual range to be protected / unprotected to
- * be larger than the first..last range.
- *
- * @param bank The bank to protect or unprotect.
- * @param set If non-zero, enable protection; if 0, disable it.
- * @param first The first sector to (un)protect, typicaly 0.
- * @param last The last sector to (un)project, typically N-1.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*protect)(struct flash_bank *bank, int set, int first, int last);
-
- /**
- * Program data into the flash. Note CPU address will be
- * "bank->base + offset", while the physical address is
- * dependent upon current target MMU mappings.
- *
- * @param bank The bank to program
- * @param buffer The data bytes to write.
- * @param offset The offset into the chip to program.
- * @param count The number of bytes to write.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*write)(struct flash_bank *bank,
- const uint8_t *buffer, uint32_t offset, uint32_t count);
-
- /**
- * Read data from the flash. Note CPU address will be
- * "bank->base + offset", while the physical address is
- * dependent upon current target MMU mappings.
- *
- * @param bank The bank to read.
- * @param buffer The data bytes read.
- * @param offset The offset into the chip to read.
- * @param count The number of bytes to read.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*read)(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count);
-
- /**
- * Probe to determine what kind of flash is present.
- * This is invoked by the "probe" script command.
- *
- * @param bank The bank to probe
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*probe)(struct flash_bank *bank);
-
- /**
- * Check the erasure status of a flash bank.
- * When called, the driver routine must perform the required
- * checks and then set the @c flash_sector_s::is_erased field
- * for each of the flash banks's sectors.
- *
- * @param bank The bank to check
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*erase_check)(struct flash_bank *bank);
-
- /**
- * Determine if the specific bank is "protected" or not.
- * When called, the driver routine must must perform the
- * required protection check(s) and then set the @c
- * flash_sector_s::is_protected field for each of the flash
- * bank's sectors.
- *
- * @param bank - the bank to check
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*protect_check)(struct flash_bank *bank);
-
- /**
- * Display human-readable information about the flash
- * bank into the given buffer. Drivers must be careful to avoid
- * overflowing the buffer.
- *
- * @param bank - the bank to get info about
- * @param char - where to put the text for the human to read
- * @param buf_size - the size of the human buffer.
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*info)(struct flash_bank *bank, char *buf, int buf_size);
-
- /**
- * A more gentle flavor of filash_driver_s::probe, performing
- * setup with less noise. Generally, driver routines should test
- * to see if the bank has already been probed; if it has, the
- * driver probably should not perform its probe a second time.
- *
- * This callback is often called from the inside of other
- * routines (e.g. GDB flash downloads) to autoprobe the flash as
- * it is programing the flash.
- *
- * @param bank - the bank to probe
- * @returns ERROR_OK if successful; otherwise, an error code.
- */
- int (*auto_probe)(struct flash_bank *bank);
-};
-
-#define FLASH_BANK_COMMAND_HANDLER(name) \
- static __FLASH_BANK_COMMAND(name)
-
-/**
- * Find a NOR flash driver by its name.
- * @param name The name of the requested driver.
- * @returns The flash_driver called @c name, or NULL if not found.
- */
-struct flash_driver *flash_driver_find_by_name(const char *name);
-
-#endif /* OPENOCD_FLASH_NOR_DRIVER_H */
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
deleted file mode 100644
index e7b6a88..0000000
--- a/src/flash/nor/drivers.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "imp.h"
-
-extern struct flash_driver aduc702x_flash;
-extern struct flash_driver aducm360_flash;
-extern struct flash_driver ambiqmicro_flash;
-extern struct flash_driver at91sam3_flash;
-extern struct flash_driver at91sam4_flash;
-extern struct flash_driver at91sam4l_flash;
-extern struct flash_driver at91sam7_flash;
-extern struct flash_driver at91samd_flash;
-extern struct flash_driver atsamv_flash;
-extern struct flash_driver avr_flash;
-extern struct flash_driver cfi_flash;
-extern struct flash_driver dsp5680xx_flash;
-extern struct flash_driver efm32_flash;
-extern struct flash_driver em357_flash;
-extern struct flash_driver faux_flash;
-extern struct flash_driver fm3_flash;
-extern struct flash_driver fm4_flash;
-extern struct flash_driver fespi_flash;
-extern struct flash_driver jtagspi_flash;
-extern struct flash_driver kinetis_flash;
-extern struct flash_driver kinetis_ke_flash;
-extern struct flash_driver lpc2000_flash;
-extern struct flash_driver lpc288x_flash;
-extern struct flash_driver lpc2900_flash;
-extern struct flash_driver lpcspifi_flash;
-extern struct flash_driver mdr_flash;
-extern struct flash_driver mrvlqspi_flash;
-extern struct flash_driver niietcm4_flash;
-extern struct flash_driver nrf51_flash;
-extern struct flash_driver numicro_flash;
-extern struct flash_driver ocl_flash;
-extern struct flash_driver pic32mx_flash;
-extern struct flash_driver psoc4_flash;
-extern struct flash_driver sim3x_flash;
-extern struct flash_driver stellaris_flash;
-extern struct flash_driver stm32f1x_flash;
-extern struct flash_driver stm32f2x_flash;
-extern struct flash_driver stm32lx_flash;
-extern struct flash_driver stm32l4x_flash;
-extern struct flash_driver stmsmi_flash;
-extern struct flash_driver str7x_flash;
-extern struct flash_driver str9x_flash;
-extern struct flash_driver str9xpec_flash;
-extern struct flash_driver tms470_flash;
-extern struct flash_driver virtual_flash;
-extern struct flash_driver xmc1xxx_flash;
-extern struct flash_driver xmc4xxx_flash;
-
-/**
- * The list of built-in flash drivers.
- * @todo Make this dynamically extendable with loadable modules.
- */
-static struct flash_driver *flash_drivers[] = {
- &aduc702x_flash,
- &aducm360_flash,
- &ambiqmicro_flash,
- &at91sam3_flash,
- &at91sam4_flash,
- &at91sam4l_flash,
- &at91sam7_flash,
- &at91samd_flash,
- &atsamv_flash,
- &avr_flash,
- &cfi_flash,
- &dsp5680xx_flash,
- &efm32_flash,
- &em357_flash,
- &faux_flash,
- &fm3_flash,
- &fm4_flash,
- &fespi_flash,
- &jtagspi_flash,
- &kinetis_flash,
- &kinetis_ke_flash,
- &lpc2000_flash,
- &lpc288x_flash,
- &lpc2900_flash,
- &lpcspifi_flash,
- &mdr_flash,
- &mrvlqspi_flash,
- &niietcm4_flash,
- &nrf51_flash,
- &numicro_flash,
- &ocl_flash,
- &pic32mx_flash,
- &psoc4_flash,
- &sim3x_flash,
- &stellaris_flash,
- &stm32f1x_flash,
- &stm32f2x_flash,
- &stm32lx_flash,
- &stm32l4x_flash,
- &stmsmi_flash,
- &str7x_flash,
- &str9x_flash,
- &str9xpec_flash,
- &tms470_flash,
- &virtual_flash,
- &xmc1xxx_flash,
- &xmc4xxx_flash,
- NULL,
-};
-
-struct flash_driver *flash_driver_find_by_name(const char *name)
-{
- for (unsigned i = 0; flash_drivers[i]; i++) {
- if (strcmp(name, flash_drivers[i]->name) == 0)
- return flash_drivers[i];
- }
- return NULL;
-}
diff --git a/src/flash/nor/dsp5680xx_flash.c b/src/flash/nor/dsp5680xx_flash.c
deleted file mode 100644
index 38649ff..0000000
--- a/src/flash/nor/dsp5680xx_flash.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Rodrigo L. Rosa *
- * rodrigorosa.LG@gmail.com *
- * *
- * Based on a file written by: *
- * Kevin McGuire *
- * Marcel Wijlaars *
- * Michael Ashton *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/**
- * @file dsp5680xx_flash.c
- * @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com>
- * @date Thu Jun 9 18:21:58 2011
- *
- * @brief This file implements the basic functions to run flashing commands
- * from the TCL interface.
- * It allows the user to flash the Freescale 5680xx DSP.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <helper/time_support.h>
-#include <target/algorithm.h>
-#include <target/dsp5680xx.h>
-
-static int dsp5680xx_build_sector_list(struct flash_bank *bank)
-{
- uint32_t offset = HFM_FLASH_BASE_ADDR;
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- int i;
-
- for (i = 0; i < bank->num_sectors; ++i) {
- bank->sectors[i].offset = i * HFM_SECTOR_SIZE;
- bank->sectors[i].size = HFM_SECTOR_SIZE;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
- LOG_USER("%s not tested yet.", __func__);
- return ERROR_OK;
-
-}
-
-/* flash bank dsp5680xx 0 0 0 0 <target#> */
-FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command)
-{
- bank->base = HFM_FLASH_BASE_ADDR;
- bank->size = HFM_SIZE_BYTES; /* top 4k not accessible */
- bank->num_sectors = HFM_SECTOR_COUNT;
- dsp5680xx_build_sector_list(bank);
-
- return ERROR_OK;
-}
-
-/**
- * A memory mapped register (PROT) holds information regarding sector protection.
- * Protection refers to undesired core access.
- * The value in this register is loaded from flash upon reset.
- *
- * @param bank
- *
- * @return
- */
-static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
-{
- int retval = ERROR_OK;
-
- uint16_t protected = 0;
-
- retval = dsp5680xx_f_protect_check(bank->target, &protected);
- if (retval != ERROR_OK) {
- for (int i = 0; i < HFM_SECTOR_COUNT; i++)
- bank->sectors[i].is_protected = -1;
- return ERROR_OK;
- }
- for (int i = 0; i < HFM_SECTOR_COUNT / 2; i++) {
- if (protected & 1) {
- bank->sectors[2 * i].is_protected = 1;
- bank->sectors[2 * i + 1].is_protected = 1;
- } else {
- bank->sectors[2 * i].is_protected = 0;
- bank->sectors[2 * i + 1].is_protected = 0;
- }
- protected = (protected >> 1);
- }
- return retval;
-}
-
-/**
- * Protection funcionality is not implemented.
- * The current implementation applies/removes security on the chip.
- * The chip is effectively secured/unsecured after the first reset
- * following the execution of this function.
- *
- * @param bank
- * @param set Apply or remove security on the chip.
- * @param first This parameter is ignored.
- * @param last This parameter is ignored.
- *
- * @return
- */
-static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
- int last)
-{
-/**
- * This applies security to flash module after next reset, it does
- * not actually apply protection (protection refers to undesired access from the core)
- */
- int retval;
-
- if (set)
- retval = dsp5680xx_f_lock(bank->target);
- else {
- retval = dsp5680xx_f_unlock(bank->target);
- if (retval == ERROR_OK) {
- /* mark all as erased */
- for (int i = 0; i <= (HFM_SECTOR_COUNT - 1); i++)
- /* FM does not recognize it as erased if erased via JTAG. */
- bank->sectors[i].is_erased = 1;
- }
- }
- return retval;
-}
-
-/**
- * The dsp5680xx use word addressing. The "/2" that appear in the following code
- * are a workaround for the fact that OpenOCD uses byte addressing.
- *
- * @param bank
- * @param buffer Data to write to flash.
- * @param offset
- * @param count In bytes (2 bytes per address).
- *
- * @return
- */
-static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t* buffer,
- uint32_t offset, uint32_t count)
-{
- int retval;
-
- if ((offset + count / 2) > bank->size) {
- LOG_ERROR("%s: Flash bank cannot fit data.", __func__);
- return ERROR_FAIL;
- }
- if (offset % 2) {
- /**
- * Writing to odd addresses not supported.
- * This chip uses word addressing, Openocd only supports byte addressing.
- * The workaround results in disabling writing to odd byte addresses
- */
- LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
- return ERROR_FAIL;
- }
- retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
- uint32_t addr_word;
-
- for (addr_word = bank->base + offset / 2; addr_word < count / 2;
- addr_word += (HFM_SECTOR_SIZE / 2)) {
- if (retval == ERROR_OK)
- bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0;
- else
- bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1;
- }
- return retval;
-}
-
-static int dsp5680xx_probe(struct flash_bank *bank)
-{
- LOG_DEBUG("%s not implemented", __func__);
- return ERROR_OK;
-}
-
-/**
- * The flash module (FM) on the dsp5680xx supports both individual sector
- * and mass erase of the flash memory.
- * If this function is called with @first == @last == 0 or if @first is the
- * first sector (#0) and @last is the last sector then the mass erase command
- * is executed (much faster than erasing each sector individually).
- *
- * @param bank
- * @param first
- * @param last
- *
- * @return
- */
-static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
-{
- int retval;
-
- retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
- if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
- last = HFM_SECTOR_COUNT - 1;
- if (retval == ERROR_OK)
- for (int i = first; i <= last; i++)
- bank->sectors[i].is_erased = 1;
- else
- /**
- * If an error occurred unknown status
- *is set even though some sector could have been correctly erased.
- */
- for (int i = first; i <= last; i++)
- bank->sectors[i].is_erased = -1;
- return retval;
-}
-
-/**
- * The flash module (FM) on the dsp5680xx support a blank check function.
- * This function executes the FM's blank check functionality on each and every sector.
- *
- * @param bank
- *
- * @return
- */
-static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
-{
- int retval = ERROR_OK;
-
- uint8_t erased = 0;
-
- uint32_t i;
-
- for (i = 0; i < HFM_SECTOR_COUNT; i++) {
- if (bank->sectors[i].is_erased == -1) {
- retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
- if (retval != ERROR_OK) {
- bank->sectors[i].is_erased = -1;
- } else {
- if (erased)
- bank->sectors[i].is_erased = 1;
- else
- bank->sectors[i].is_erased = 0;
- }
- }
- }
- return retval;
-}
-
-struct flash_driver dsp5680xx_flash = {
- .name = "dsp5680xx_flash",
- .flash_bank_command = dsp5680xx_flash_bank_command,
- .erase = dsp5680xx_flash_erase,
- .protect = dsp5680xx_flash_protect,
- .write = dsp5680xx_flash_write,
- /* .read = default_flash_read, */
- .probe = dsp5680xx_probe,
- .auto_probe = dsp5680xx_probe,
- .erase_check = dsp5680xx_flash_erase_check,
- .protect_check = dsp5680xx_flash_protect_check,
-};
diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c
deleted file mode 100644
index 0b33829..0000000
--- a/src/flash/nor/efm32.c
+++ /dev/null
@@ -1,1069 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * Copyright (C) 2013 by Roman Dmitrienko *
- * me@iamroman.org *
- * *
- * Copyright (C) 2014 Nemui Trinomius *
- * nemuisan_kawausogasuki@live.jp *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-#include <target/cortex_m.h>
-
-/* keep family IDs in decimal */
-#define EFM_FAMILY_ID_GECKO 71
-#define EFM_FAMILY_ID_GIANT_GECKO 72
-#define EFM_FAMILY_ID_TINY_GECKO 73
-#define EFM_FAMILY_ID_LEOPARD_GECKO 74
-#define EFM_FAMILY_ID_WONDER_GECKO 75
-#define EFM_FAMILY_ID_ZERO_GECKO 76
-#define EFM_FAMILY_ID_HAPPY_GECKO 77
-#define EZR_FAMILY_ID_WONDER_GECKO 120
-#define EZR_FAMILY_ID_LEOPARD_GECKO 121
-
-#define EFM32_FLASH_ERASE_TMO 100
-#define EFM32_FLASH_WDATAREADY_TMO 100
-#define EFM32_FLASH_WRITE_TMO 100
-
-/* size in bytes, not words; must fit all Gecko devices */
-#define LOCKBITS_PAGE_SZ 512
-
-#define EFM32_MSC_INFO_BASE 0x0fe00000
-
-#define EFM32_MSC_USER_DATA EFM32_MSC_INFO_BASE
-#define EFM32_MSC_LOCK_BITS (EFM32_MSC_INFO_BASE+0x4000)
-#define EFM32_MSC_DEV_INFO (EFM32_MSC_INFO_BASE+0x8000)
-
-/* PAGE_SIZE is only present in Leopard, Giant and Wonder Gecko MCUs */
-#define EFM32_MSC_DI_PAGE_SIZE (EFM32_MSC_DEV_INFO+0x1e7)
-#define EFM32_MSC_DI_FLASH_SZ (EFM32_MSC_DEV_INFO+0x1f8)
-#define EFM32_MSC_DI_RAM_SZ (EFM32_MSC_DEV_INFO+0x1fa)
-#define EFM32_MSC_DI_PART_NUM (EFM32_MSC_DEV_INFO+0x1fc)
-#define EFM32_MSC_DI_PART_FAMILY (EFM32_MSC_DEV_INFO+0x1fe)
-#define EFM32_MSC_DI_PROD_REV (EFM32_MSC_DEV_INFO+0x1ff)
-
-#define EFM32_MSC_REGBASE 0x400c0000
-#define EFM32_MSC_WRITECTRL (EFM32_MSC_REGBASE+0x008)
-#define EFM32_MSC_WRITECTRL_WREN_MASK 0x1
-#define EFM32_MSC_WRITECMD (EFM32_MSC_REGBASE+0x00c)
-#define EFM32_MSC_WRITECMD_LADDRIM_MASK 0x1
-#define EFM32_MSC_WRITECMD_ERASEPAGE_MASK 0x2
-#define EFM32_MSC_WRITECMD_WRITEONCE_MASK 0x8
-#define EFM32_MSC_ADDRB (EFM32_MSC_REGBASE+0x010)
-#define EFM32_MSC_WDATA (EFM32_MSC_REGBASE+0x018)
-#define EFM32_MSC_STATUS (EFM32_MSC_REGBASE+0x01c)
-#define EFM32_MSC_STATUS_BUSY_MASK 0x1
-#define EFM32_MSC_STATUS_LOCKED_MASK 0x2
-#define EFM32_MSC_STATUS_INVADDR_MASK 0x4
-#define EFM32_MSC_STATUS_WDATAREADY_MASK 0x8
-#define EFM32_MSC_STATUS_WORDTIMEOUT_MASK 0x10
-#define EFM32_MSC_STATUS_ERASEABORTED_MASK 0x20
-#define EFM32_MSC_LOCK (EFM32_MSC_REGBASE+0x03c)
-#define EFM32_MSC_LOCK_LOCKKEY 0x1b71
-
-struct efm32x_flash_bank {
- int probed;
- uint32_t lb_page[LOCKBITS_PAGE_SZ/4];
-};
-
-struct efm32_info {
- uint16_t flash_sz_kib;
- uint16_t ram_sz_kib;
- uint16_t part_num;
- uint8_t part_family;
- uint8_t prod_rev;
- uint16_t page_size;
-};
-
-static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count);
-
-static int efm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_sz)
-{
- return target_read_u16(bank->target, EFM32_MSC_DI_FLASH_SZ, flash_sz);
-}
-
-static int efm32x_get_ram_size(struct flash_bank *bank, uint16_t *ram_sz)
-{
- return target_read_u16(bank->target, EFM32_MSC_DI_RAM_SZ, ram_sz);
-}
-
-static int efm32x_get_part_num(struct flash_bank *bank, uint16_t *pnum)
-{
- return target_read_u16(bank->target, EFM32_MSC_DI_PART_NUM, pnum);
-}
-
-static int efm32x_get_part_family(struct flash_bank *bank, uint8_t *pfamily)
-{
- return target_read_u8(bank->target, EFM32_MSC_DI_PART_FAMILY, pfamily);
-}
-
-static int efm32x_get_prod_rev(struct flash_bank *bank, uint8_t *prev)
-{
- return target_read_u8(bank->target, EFM32_MSC_DI_PROD_REV, prev);
-}
-
-static int efm32x_read_info(struct flash_bank *bank,
- struct efm32_info *efm32_info)
-{
- int ret;
- uint32_t cpuid = 0;
-
- memset(efm32_info, 0, sizeof(struct efm32_info));
-
- ret = target_read_u32(bank->target, CPUID, &cpuid);
- if (ERROR_OK != ret)
- return ret;
-
- if (((cpuid >> 4) & 0xfff) == 0xc23) {
- /* Cortex-M3 device */
- } else if (((cpuid >> 4) & 0xfff) == 0xc24) {
- /* Cortex-M4 device (WONDER GECKO) */
- } else if (((cpuid >> 4) & 0xfff) == 0xc60) {
- /* Cortex-M0+ device */
- } else {
- LOG_ERROR("Target is not Cortex-Mx Device");
- return ERROR_FAIL;
- }
-
- ret = efm32x_get_flash_size(bank, &(efm32_info->flash_sz_kib));
- if (ERROR_OK != ret)
- return ret;
-
- ret = efm32x_get_ram_size(bank, &(efm32_info->ram_sz_kib));
- if (ERROR_OK != ret)
- return ret;
-
- ret = efm32x_get_part_num(bank, &(efm32_info->part_num));
- if (ERROR_OK != ret)
- return ret;
-
- ret = efm32x_get_part_family(bank, &(efm32_info->part_family));
- if (ERROR_OK != ret)
- return ret;
-
- ret = efm32x_get_prod_rev(bank, &(efm32_info->prod_rev));
- if (ERROR_OK != ret)
- return ret;
-
- if (EFM_FAMILY_ID_GECKO == efm32_info->part_family ||
- EFM_FAMILY_ID_TINY_GECKO == efm32_info->part_family)
- efm32_info->page_size = 512;
- else if (EFM_FAMILY_ID_ZERO_GECKO == efm32_info->part_family ||
- EFM_FAMILY_ID_HAPPY_GECKO == efm32_info->part_family)
- efm32_info->page_size = 1024;
- else if (EFM_FAMILY_ID_GIANT_GECKO == efm32_info->part_family ||
- EFM_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) {
- if (efm32_info->prod_rev >= 18) {
- uint8_t pg_size = 0;
- ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE,
- &pg_size);
- if (ERROR_OK != ret)
- return ret;
-
- efm32_info->page_size = (1 << ((pg_size+10) & 0xff));
- } else {
- /* EFM32 GG/LG errata: MEM_INFO_PAGE_SIZE is invalid
- for MCUs with PROD_REV < 18 */
- if (efm32_info->flash_sz_kib < 512)
- efm32_info->page_size = 2048;
- else
- efm32_info->page_size = 4096;
- }
-
- if ((2048 != efm32_info->page_size) &&
- (4096 != efm32_info->page_size)) {
- LOG_ERROR("Invalid page size %u", efm32_info->page_size);
- return ERROR_FAIL;
- }
- } else if (EFM_FAMILY_ID_WONDER_GECKO == efm32_info->part_family ||
- EZR_FAMILY_ID_WONDER_GECKO == efm32_info->part_family ||
- EZR_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) {
- uint8_t pg_size = 0;
- ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE,
- &pg_size);
- if (ERROR_OK != ret)
- return ret;
-
- efm32_info->page_size = (1 << ((pg_size+10) & 0xff));
- if (2048 != efm32_info->page_size) {
- LOG_ERROR("Invalid page size %u", efm32_info->page_size);
- return ERROR_FAIL;
- }
- } else {
- LOG_ERROR("Unknown MCU family %d", efm32_info->part_family);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-/*
- * Helper to create a human friendly string describing a part
- */
-static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size)
-{
- int printed = 0;
-
- switch (info->part_family) {
- case EZR_FAMILY_ID_WONDER_GECKO:
- case EZR_FAMILY_ID_LEOPARD_GECKO:
- printed = snprintf(buf, buf_size, "EZR32 ");
- break;
- default:
- printed = snprintf(buf, buf_size, "EFM32 ");
- }
-
- buf += printed;
- buf_size -= printed;
-
- if (0 >= buf_size)
- return ERROR_BUF_TOO_SMALL;
-
- switch (info->part_family) {
- case EFM_FAMILY_ID_GECKO:
- printed = snprintf(buf, buf_size, "Gecko");
- break;
- case EFM_FAMILY_ID_GIANT_GECKO:
- printed = snprintf(buf, buf_size, "Giant Gecko");
- break;
- case EFM_FAMILY_ID_TINY_GECKO:
- printed = snprintf(buf, buf_size, "Tiny Gecko");
- break;
- case EFM_FAMILY_ID_LEOPARD_GECKO:
- case EZR_FAMILY_ID_LEOPARD_GECKO:
- printed = snprintf(buf, buf_size, "Leopard Gecko");
- break;
- case EFM_FAMILY_ID_WONDER_GECKO:
- case EZR_FAMILY_ID_WONDER_GECKO:
- printed = snprintf(buf, buf_size, "Wonder Gecko");
- break;
- case EFM_FAMILY_ID_ZERO_GECKO:
- printed = snprintf(buf, buf_size, "Zero Gecko");
- break;
- case EFM_FAMILY_ID_HAPPY_GECKO:
- printed = snprintf(buf, buf_size, "Happy Gecko");
- break;
- }
-
- buf += printed;
- buf_size -= printed;
-
- if (0 >= buf_size)
- return ERROR_BUF_TOO_SMALL;
-
- printed = snprintf(buf, buf_size, " - Rev: %d", info->prod_rev);
- buf += printed;
- buf_size -= printed;
-
- if (0 >= buf_size)
- return ERROR_BUF_TOO_SMALL;
-
- return ERROR_OK;
-}
-
-/* flash bank efm32 <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(efm32x_flash_bank_command)
-{
- struct efm32x_flash_bank *efm32x_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- efm32x_info = malloc(sizeof(struct efm32x_flash_bank));
-
- bank->driver_priv = efm32x_info;
- efm32x_info->probed = 0;
- memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
-
- return ERROR_OK;
-}
-
-/* set or reset given bits in a register */
-static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg,
- uint32_t bitmask, int set)
-{
- int ret = 0;
- uint32_t reg_val = 0;
-
- ret = target_read_u32(bank->target, reg, &reg_val);
- if (ERROR_OK != ret)
- return ret;
-
- if (set)
- reg_val |= bitmask;
- else
- reg_val &= ~bitmask;
-
- return target_write_u32(bank->target, reg, reg_val);
-}
-
-static int efm32x_set_wren(struct flash_bank *bank, int write_enable)
-{
- return efm32x_set_reg_bits(bank, EFM32_MSC_WRITECTRL,
- EFM32_MSC_WRITECTRL_WREN_MASK, write_enable);
-}
-
-static int efm32x_msc_lock(struct flash_bank *bank, int lock)
-{
- return target_write_u32(bank->target, EFM32_MSC_LOCK,
- (lock ? 0 : EFM32_MSC_LOCK_LOCKKEY));
-}
-
-static int efm32x_wait_status(struct flash_bank *bank, int timeout,
- uint32_t wait_mask, int wait_for_set)
-{
- int ret = 0;
- uint32_t status = 0;
-
- while (1) {
- ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status);
- if (ERROR_OK != ret)
- break;
-
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
-
- if (((status & wait_mask) == 0) && (0 == wait_for_set))
- break;
- else if (((status & wait_mask) != 0) && wait_for_set)
- break;
-
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for MSC status");
- return ERROR_FAIL;
- }
-
- alive_sleep(1);
- }
-
- if (status & EFM32_MSC_STATUS_ERASEABORTED_MASK)
- LOG_WARNING("page erase was aborted");
-
- return ret;
-}
-
-static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
-{
- /* this function DOES NOT set WREN; must be set already */
- /* 1. write address to ADDRB
- 2. write LADDRIM
- 3. check status (INVADDR, LOCKED)
- 4. write ERASEPAGE
- 5. wait until !STATUS_BUSY
- */
- int ret = 0;
- uint32_t status = 0;
-
- LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr);
-
- ret = target_write_u32(bank->target, EFM32_MSC_ADDRB, addr);
- if (ERROR_OK != ret)
- return ret;
-
- ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD,
- EFM32_MSC_WRITECMD_LADDRIM_MASK, 1);
- if (ERROR_OK != ret)
- return ret;
-
- ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status);
- if (ERROR_OK != ret)
- return ret;
-
- LOG_DEBUG("status 0x%" PRIx32, status);
-
- if (status & EFM32_MSC_STATUS_LOCKED_MASK) {
- LOG_ERROR("Page is locked");
- return ERROR_FAIL;
- } else if (status & EFM32_MSC_STATUS_INVADDR_MASK) {
- LOG_ERROR("Invalid address 0x%" PRIx32, addr);
- return ERROR_FAIL;
- }
-
- ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD,
- EFM32_MSC_WRITECMD_ERASEPAGE_MASK, 1);
- if (ERROR_OK != ret)
- return ret;
-
- return efm32x_wait_status(bank, EFM32_FLASH_ERASE_TMO,
- EFM32_MSC_STATUS_BUSY_MASK, 0);
-}
-
-static int efm32x_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- int i = 0;
- int ret = 0;
-
- if (TARGET_HALTED != target->state) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- efm32x_msc_lock(bank, 0);
- ret = efm32x_set_wren(bank, 1);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to enable MSC write");
- return ret;
- }
-
- for (i = first; i <= last; i++) {
- ret = efm32x_erase_page(bank, bank->sectors[i].offset);
- if (ERROR_OK != ret)
- LOG_ERROR("Failed to erase page %d", i);
- }
-
- ret = efm32x_set_wren(bank, 0);
- efm32x_msc_lock(bank, 1);
-
- return ret;
-}
-
-static int efm32x_read_lock_data(struct flash_bank *bank)
-{
- struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
- struct target *target = bank->target;
- int i = 0;
- int data_size = 0;
- uint32_t *ptr = NULL;
- int ret = 0;
-
- assert(!(bank->num_sectors & 0x1f));
-
- data_size = bank->num_sectors / 8; /* number of data bytes */
- data_size /= 4; /* ...and data dwords */
-
- ptr = efm32x_info->lb_page;
-
- for (i = 0; i < data_size; i++, ptr++) {
- ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+i*4, ptr);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to read PLW %d", i);
- return ret;
- }
- }
-
- /* also, read ULW, DLW and MLW */
-
- /* ULW, word 126 */
- ptr = efm32x_info->lb_page + 126;
- ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+126*4, ptr);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to read ULW");
- return ret;
- }
-
- /* DLW, word 127 */
- ptr = efm32x_info->lb_page + 127;
- ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+127*4, ptr);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to read DLW");
- return ret;
- }
-
- /* MLW, word 125, present in GG and LG */
- ptr = efm32x_info->lb_page + 125;
- ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+125*4, ptr);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to read MLW");
- return ret;
- }
-
- return ERROR_OK;
-}
-
-static int efm32x_write_lock_data(struct flash_bank *bank)
-{
- struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
- int ret = 0;
-
- ret = efm32x_erase_page(bank, EFM32_MSC_LOCK_BITS);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to erase LB page");
- return ret;
- }
-
- return efm32x_write(bank, (uint8_t *)efm32x_info->lb_page, EFM32_MSC_LOCK_BITS,
- LOCKBITS_PAGE_SZ);
-}
-
-static int efm32x_get_page_lock(struct flash_bank *bank, size_t page)
-{
- struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
- uint32_t dw = efm32x_info->lb_page[page >> 5];
- uint32_t mask = 0;
-
- mask = 1 << (page & 0x1f);
-
- return (dw & mask) ? 0 : 1;
-}
-
-static int efm32x_set_page_lock(struct flash_bank *bank, size_t page, int set)
-{
- struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
- uint32_t *dw = &efm32x_info->lb_page[page >> 5];
- uint32_t mask = 0;
-
- mask = 1 << (page & 0x1f);
-
- if (!set)
- *dw |= mask;
- else
- *dw &= ~mask;
-
- return ERROR_OK;
-}
-
-static int efm32x_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct target *target = bank->target;
- int i = 0;
- int ret = 0;
-
- if (!set) {
- LOG_ERROR("Erase device data to reset page locks");
- return ERROR_FAIL;
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- for (i = first; i <= last; i++) {
- ret = efm32x_set_page_lock(bank, i, set);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to set lock on page %d", i);
- return ret;
- }
- }
-
- ret = efm32x_write_lock_data(bank);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to write LB page");
- return ret;
- }
-
- return ERROR_OK;
-}
-
-static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- int ret = ERROR_OK;
-
- /* see contrib/loaders/flash/efm32.S for src */
- static const uint8_t efm32x_flash_write_code[] = {
- /* #define EFM32_MSC_WRITECTRL_OFFSET 0x008 */
- /* #define EFM32_MSC_WRITECMD_OFFSET 0x00c */
- /* #define EFM32_MSC_ADDRB_OFFSET 0x010 */
- /* #define EFM32_MSC_WDATA_OFFSET 0x018 */
- /* #define EFM32_MSC_STATUS_OFFSET 0x01c */
- /* #define EFM32_MSC_LOCK_OFFSET 0x03c */
-
- 0x15, 0x4e, /* ldr r6, =#0x1b71 */
- 0xc6, 0x63, /* str r6, [r0, #EFM32_MSC_LOCK_OFFSET] */
- 0x01, 0x26, /* movs r6, #1 */
- 0x86, 0x60, /* str r6, [r0, #EFM32_MSC_WRITECTRL_OFFSET] */
-
- /* wait_fifo: */
- 0x16, 0x68, /* ldr r6, [r2, #0] */
- 0x00, 0x2e, /* cmp r6, #0 */
- 0x22, 0xd0, /* beq exit */
- 0x55, 0x68, /* ldr r5, [r2, #4] */
- 0xb5, 0x42, /* cmp r5, r6 */
- 0xf9, 0xd0, /* beq wait_fifo */
-
- 0x04, 0x61, /* str r4, [r0, #EFM32_MSC_ADDRB_OFFSET] */
- 0x01, 0x26, /* movs r6, #1 */
- 0xc6, 0x60, /* str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET] */
- 0xc6, 0x69, /* ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] */
- 0x06, 0x27, /* movs r7, #6 */
- 0x3e, 0x42, /* tst r6, r7 */
- 0x16, 0xd1, /* bne error */
-
- /* wait_wdataready: */
- 0xc6, 0x69, /* ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] */
- 0x08, 0x27, /* movs r7, #8 */
- 0x3e, 0x42, /* tst r6, r7 */
- 0xfb, 0xd0, /* beq wait_wdataready */
-
- 0x2e, 0x68, /* ldr r6, [r5] */
- 0x86, 0x61, /* str r6, [r0, #EFM32_MSC_WDATA_OFFSET] */
- 0x08, 0x26, /* movs r6, #8 */
- 0xc6, 0x60, /* str r6, [r0, #EFM32_MSC_WRITECMD_OFFSET] */
-
- 0x04, 0x35, /* adds r5, #4 */
- 0x04, 0x34, /* adds r4, #4 */
-
- /* busy: */
- 0xc6, 0x69, /* ldr r6, [r0, #EFM32_MSC_STATUS_OFFSET] */
- 0x01, 0x27, /* movs r7, #1 */
- 0x3e, 0x42, /* tst r6, r7 */
- 0xfb, 0xd1, /* bne busy */
-
- 0x9d, 0x42, /* cmp r5, r3 */
- 0x01, 0xd3, /* bcc no_wrap */
- 0x15, 0x46, /* mov r5, r2 */
- 0x08, 0x35, /* adds r5, #8 */
-
- /* no_wrap: */
- 0x55, 0x60, /* str r5, [r2, #4] */
- 0x01, 0x39, /* subs r1, r1, #1 */
- 0x00, 0x29, /* cmp r1, #0 */
- 0x02, 0xd0, /* beq exit */
- 0xdb, 0xe7, /* b wait_fifo */
-
- /* error: */
- 0x00, 0x20, /* movs r0, #0 */
- 0x50, 0x60, /* str r0, [r2, #4] */
-
- /* exit: */
- 0x30, 0x46, /* mov r0, r6 */
- 0x00, 0xbe, /* bkpt #0 */
-
- /* LOCKKEY */
- 0x71, 0x1b, 0x00, 0x00
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(efm32x_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- ret = target_write_buffer(target, write_algorithm->address,
- sizeof(efm32x_flash_write_code), efm32x_flash_write_code);
- if (ret != ERROR_OK)
- return ret;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (word-32bit) */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
-
- buf_set_u32(reg_params[0].value, 0, 32, EFM32_MSC_REGBASE);
- buf_set_u32(reg_params[1].value, 0, 32, count);
- buf_set_u32(reg_params[2].value, 0, 32, source->address);
- buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
- buf_set_u32(reg_params[4].value, 0, 32, address);
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- ret = target_run_flash_async_algorithm(target, buf, count, 4,
- 0, NULL,
- 5, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (ret == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("flash write failed at address 0x%"PRIx32,
- buf_get_u32(reg_params[4].value, 0, 32));
-
- if (buf_get_u32(reg_params[0].value, 0, 32) &
- EFM32_MSC_STATUS_LOCKED_MASK) {
- LOG_ERROR("flash memory write protected");
- }
-
- if (buf_get_u32(reg_params[0].value, 0, 32) &
- EFM32_MSC_STATUS_INVADDR_MASK) {
- LOG_ERROR("invalid flash memory write address");
- }
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return ret;
-}
-
-static int efm32x_write_word(struct flash_bank *bank, uint32_t addr,
- uint32_t val)
-{
- /* this function DOES NOT set WREN; must be set already */
- /* 1. write address to ADDRB
- 2. write LADDRIM
- 3. check status (INVADDR, LOCKED)
- 4. wait for WDATAREADY
- 5. write data to WDATA
- 6. write WRITECMD_WRITEONCE to WRITECMD
- 7. wait until !STATUS_BUSY
- */
-
- /* FIXME: EFM32G ref states (7.3.2) that writes should be
- * performed twice per dword */
-
- int ret = 0;
- uint32_t status = 0;
-
- /* if not called, GDB errors will be reported during large writes */
- keep_alive();
-
- ret = target_write_u32(bank->target, EFM32_MSC_ADDRB, addr);
- if (ERROR_OK != ret)
- return ret;
-
- ret = efm32x_set_reg_bits(bank, EFM32_MSC_WRITECMD,
- EFM32_MSC_WRITECMD_LADDRIM_MASK, 1);
- if (ERROR_OK != ret)
- return ret;
-
- ret = target_read_u32(bank->target, EFM32_MSC_STATUS, &status);
- if (ERROR_OK != ret)
- return ret;
-
- LOG_DEBUG("status 0x%" PRIx32, status);
-
- if (status & EFM32_MSC_STATUS_LOCKED_MASK) {
- LOG_ERROR("Page is locked");
- return ERROR_FAIL;
- } else if (status & EFM32_MSC_STATUS_INVADDR_MASK) {
- LOG_ERROR("Invalid address 0x%" PRIx32, addr);
- return ERROR_FAIL;
- }
-
- ret = efm32x_wait_status(bank, EFM32_FLASH_WDATAREADY_TMO,
- EFM32_MSC_STATUS_WDATAREADY_MASK, 1);
- if (ERROR_OK != ret) {
- LOG_ERROR("Wait for WDATAREADY failed");
- return ret;
- }
-
- ret = target_write_u32(bank->target, EFM32_MSC_WDATA, val);
- if (ERROR_OK != ret) {
- LOG_ERROR("WDATA write failed");
- return ret;
- }
-
- ret = target_write_u32(bank->target, EFM32_MSC_WRITECMD,
- EFM32_MSC_WRITECMD_WRITEONCE_MASK);
- if (ERROR_OK != ret) {
- LOG_ERROR("WRITECMD write failed");
- return ret;
- }
-
- ret = efm32x_wait_status(bank, EFM32_FLASH_WRITE_TMO,
- EFM32_MSC_STATUS_BUSY_MASK, 0);
- if (ERROR_OK != ret) {
- LOG_ERROR("Wait for BUSY failed");
- return ret;
- }
-
- return ERROR_OK;
-}
-
-static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint8_t *new_buffer = NULL;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x3) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte "
- "alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- if (count & 0x3) {
- uint32_t old_count = count;
- count = (old_count | 3) + 1;
- new_buffer = malloc(count);
- if (new_buffer == NULL) {
- LOG_ERROR("odd number of bytes to write and no memory "
- "for padding buffer");
- return ERROR_FAIL;
- }
- LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " "
- "and padding with 0xff", old_count, count);
- memset(new_buffer, 0xff, count);
- buffer = memcpy(new_buffer, buffer, old_count);
- }
-
- uint32_t words_remaining = count / 4;
- int retval, retval2;
-
- /* unlock flash registers */
- efm32x_msc_lock(bank, 0);
- retval = efm32x_set_wren(bank, 1);
- if (retval != ERROR_OK)
- goto cleanup;
-
- /* try using a block write */
- retval = efm32x_write_block(bank, buffer, offset, words_remaining);
-
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single word accesses */
- LOG_WARNING("couldn't use block writes, falling back to single "
- "memory accesses");
-
- while (words_remaining > 0) {
- uint32_t value;
- memcpy(&value, buffer, sizeof(uint32_t));
-
- retval = efm32x_write_word(bank, offset, value);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- words_remaining--;
- buffer += 4;
- offset += 4;
- }
- }
-
-reset_pg_and_lock:
- retval2 = efm32x_set_wren(bank, 0);
- efm32x_msc_lock(bank, 1);
- if (retval == ERROR_OK)
- retval = retval2;
-
-cleanup:
- if (new_buffer)
- free(new_buffer);
-
- return retval;
-}
-
-static int efm32x_probe(struct flash_bank *bank)
-{
- struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
- struct efm32_info efm32_mcu_info;
- int ret;
- int i;
- uint32_t base_address = 0x00000000;
- char buf[256];
-
- efm32x_info->probed = 0;
- memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
-
- ret = efm32x_read_info(bank, &efm32_mcu_info);
- if (ERROR_OK != ret)
- return ret;
-
- ret = efm32x_decode_info(&efm32_mcu_info, buf, sizeof(buf));
- if (ERROR_OK != ret)
- return ret;
-
- LOG_INFO("detected part: %s", buf);
- LOG_INFO("flash size = %dkbytes", efm32_mcu_info.flash_sz_kib);
- LOG_INFO("flash page size = %dbytes", efm32_mcu_info.page_size);
-
- assert(0 != efm32_mcu_info.page_size);
-
- int num_pages = efm32_mcu_info.flash_sz_kib * 1024 /
- efm32_mcu_info.page_size;
-
- assert(num_pages > 0);
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->base = base_address;
- bank->size = (num_pages * efm32_mcu_info.page_size);
- bank->num_sectors = num_pages;
-
- ret = efm32x_read_lock_data(bank);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to read LB data");
- return ret;
- }
-
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
-
- for (i = 0; i < num_pages; i++) {
- bank->sectors[i].offset = i * efm32_mcu_info.page_size;
- bank->sectors[i].size = efm32_mcu_info.page_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- efm32x_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int efm32x_auto_probe(struct flash_bank *bank)
-{
- struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
- if (efm32x_info->probed)
- return ERROR_OK;
- return efm32x_probe(bank);
-}
-
-static int efm32x_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int ret = 0;
- int i = 0;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- ret = efm32x_read_lock_data(bank);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to read LB data");
- return ret;
- }
-
- assert(NULL != bank->sectors);
-
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_protected = efm32x_get_page_lock(bank, i);
-
- return ERROR_OK;
-}
-
-static int get_efm32x_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct efm32_info info;
- int ret = 0;
-
- ret = efm32x_read_info(bank, &info);
- if (ERROR_OK != ret) {
- LOG_ERROR("Failed to read EFM32 info");
- return ret;
- }
-
- return efm32x_decode_info(&info, buf, buf_size);
-}
-
-COMMAND_HANDLER(efm32x_handle_debuglock_command)
-{
- struct target *target = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t *ptr;
- ptr = efm32x_info->lb_page + 127;
- *ptr = 0;
-
- retval = efm32x_write_lock_data(bank);
- if (ERROR_OK != retval) {
- LOG_ERROR("Failed to write LB page");
- return retval;
- }
-
- command_print(CMD_CTX, "efm32x debug interface locked, reset the device to apply");
-
- return ERROR_OK;
-}
-
-static const struct command_registration efm32x_exec_command_handlers[] = {
- {
- .name = "debuglock",
- .handler = efm32x_handle_debuglock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Lock the debug interface of the device.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration efm32x_command_handlers[] = {
- {
- .name = "efm32",
- .mode = COMMAND_ANY,
- .help = "efm32 flash command group",
- .usage = "",
- .chain = efm32x_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver efm32_flash = {
- .name = "efm32",
- .commands = efm32x_command_handlers,
- .flash_bank_command = efm32x_flash_bank_command,
- .erase = efm32x_erase,
- .protect = efm32x_protect,
- .write = efm32x_write,
- .read = default_flash_read,
- .probe = efm32x_probe,
- .auto_probe = efm32x_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = efm32x_protect_check,
- .info = get_efm32x_info,
-};
diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c
deleted file mode 100644
index 1501562..0000000
--- a/src/flash/nor/em357.c
+++ /dev/null
@@ -1,939 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- *
- * Copyright (C) 2011 by Erik Botö
- * erik.boto@pelagicore.com
- *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-/* em357 register locations */
-
-#define EM357_FLASH_ACR 0x40008000
-#define EM357_FLASH_KEYR 0x40008004
-#define EM357_FLASH_OPTKEYR 0x40008008
-#define EM357_FLASH_SR 0x4000800C
-#define EM357_FLASH_CR 0x40008010
-#define EM357_FLASH_AR 0x40008014
-#define EM357_FLASH_OBR 0x4000801C
-#define EM357_FLASH_WRPR 0x40008020
-
-#define EM357_FPEC_CLK 0x4000402c
-/* option byte location */
-
-#define EM357_OB_RDP 0x08040800
-#define EM357_OB_WRP0 0x08040808
-#define EM357_OB_WRP1 0x0804080A
-#define EM357_OB_WRP2 0x0804080C
-
-/* FLASH_CR register bits */
-
-#define FLASH_PG (1 << 0)
-#define FLASH_PER (1 << 1)
-#define FLASH_MER (1 << 2)
-#define FLASH_OPTPG (1 << 4)
-#define FLASH_OPTER (1 << 5)
-#define FLASH_STRT (1 << 6)
-#define FLASH_LOCK (1 << 7)
-#define FLASH_OPTWRE (1 << 9)
-
-/* FLASH_SR register bits */
-
-#define FLASH_BSY (1 << 0)
-#define FLASH_PGERR (1 << 2)
-#define FLASH_WRPRTERR (1 << 4)
-#define FLASH_EOP (1 << 5)
-
-/* EM357_FLASH_OBR bit definitions (reading) */
-
-#define OPT_ERROR 0
-#define OPT_READOUT 1
-
-/* register unlock keys */
-
-#define KEY1 0x45670123
-#define KEY2 0xCDEF89AB
-
-struct em357_options {
- uint16_t RDP;
- uint16_t user_options;
- uint16_t protection[3];
-};
-
-struct em357_flash_bank {
- struct em357_options option_bytes;
- int ppage_size;
- int probed;
-};
-
-static int em357_mass_erase(struct flash_bank *bank);
-
-/* flash bank em357 <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(em357_flash_bank_command)
-{
- struct em357_flash_bank *em357_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- em357_info = malloc(sizeof(struct em357_flash_bank));
- bank->driver_priv = em357_info;
-
- em357_info->probed = 0;
-
- return ERROR_OK;
-}
-
-static inline int em357_get_flash_status(struct flash_bank *bank, uint32_t *status)
-{
- struct target *target = bank->target;
- return target_read_u32(target, EM357_FLASH_SR, status);
-}
-
-static int em357_wait_status_busy(struct flash_bank *bank, int timeout)
-{
- struct target *target = bank->target;
- uint32_t status;
- int retval = ERROR_OK;
-
- /* wait for busy to clear */
- for (;; ) {
- retval = em357_get_flash_status(bank, &status);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if ((status & FLASH_BSY) == 0)
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
- if (status & FLASH_WRPRTERR) {
- LOG_ERROR("em357 device protected");
- retval = ERROR_FAIL;
- }
-
- if (status & FLASH_PGERR) {
- LOG_ERROR("em357 device programming failed");
- retval = ERROR_FAIL;
- }
-
- /* Clear but report errors */
- if (status & (FLASH_WRPRTERR | FLASH_PGERR)) {
- /* If this operation fails, we ignore it and report the original
- * retval
- */
- target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR | FLASH_PGERR);
- }
- return retval;
-}
-
-static int em357_read_options(struct flash_bank *bank)
-{
- uint32_t optiondata;
- struct em357_flash_bank *em357_info = NULL;
- struct target *target = bank->target;
-
- em357_info = bank->driver_priv;
-
- /* read current option bytes */
- int retval = target_read_u32(target, EM357_FLASH_OBR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- em357_info->option_bytes.user_options = (uint16_t)0xFFFC | ((optiondata >> 2) & 0x03);
- em357_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5;
-
- if (optiondata & (1 << OPT_READOUT))
- LOG_INFO("Device Security Bit Set");
-
- /* each bit refers to a 4bank protection */
- retval = target_read_u32(target, EM357_FLASH_WRPR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- em357_info->option_bytes.protection[0] = (uint16_t)optiondata;
- em357_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8);
- em357_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16);
-
- return ERROR_OK;
-}
-
-static int em357_erase_options(struct flash_bank *bank)
-{
- struct em357_flash_bank *em357_info = NULL;
- struct target *target = bank->target;
-
- em357_info = bank->driver_priv;
-
- /* read current options */
- em357_read_options(bank);
-
- /* unlock flash registers */
- int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* unlock option flash registers */
- retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* erase option bytes */
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_OPTWRE);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 10);
- if (retval != ERROR_OK)
- return retval;
-
- /* clear readout protection and complementary option bytes
- * this will also force a device unlock if set */
- em357_info->option_bytes.RDP = 0x5AA5;
-
- return ERROR_OK;
-}
-
-static int em357_write_options(struct flash_bank *bank)
-{
- struct em357_flash_bank *em357_info = NULL;
- struct target *target = bank->target;
-
- em357_info = bank->driver_priv;
-
- /* unlock flash registers */
- int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* unlock option flash registers */
- retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* program option bytes */
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTPG | FLASH_OPTWRE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 10);
- if (retval != ERROR_OK)
- return retval;
-
- /* write protection byte 1 */
- retval = target_write_u16(target, EM357_OB_WRP0, em357_info->option_bytes.protection[0]);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 10);
- if (retval != ERROR_OK)
- return retval;
-
- /* write protection byte 2 */
- retval = target_write_u16(target, EM357_OB_WRP1, em357_info->option_bytes.protection[1]);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 10);
- if (retval != ERROR_OK)
- return retval;
-
- /* write protection byte 3 */
- retval = target_write_u16(target, EM357_OB_WRP2, em357_info->option_bytes.protection[2]);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 10);
- if (retval != ERROR_OK)
- return retval;
-
- /* write readout protection bit */
- retval = target_write_u16(target, EM357_OB_RDP, em357_info->option_bytes.RDP);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 10);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int em357_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct em357_flash_bank *em357_info = bank->driver_priv;
-
- uint32_t protection;
- int i, s;
- int num_bits;
- int set;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* each bit refers to a 4bank protection (bit 0-23) */
- int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection);
- if (retval != ERROR_OK)
- return retval;
-
- /* each protection bit is for 4 * 2K pages */
- num_bits = (bank->num_sectors / em357_info->ppage_size);
-
- for (i = 0; i < num_bits; i++) {
- set = 1;
- if (protection & (1 << i))
- set = 0;
-
- for (s = 0; s < em357_info->ppage_size; s++)
- bank->sectors[(i * em357_info->ppage_size) + s].is_protected = set;
- }
-
- return ERROR_OK;
-}
-
-static int em357_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");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first == 0) && (last == (bank->num_sectors - 1)))
- return em357_mass_erase(bank);
-
- /* Enable FPEC clock */
- target_write_u32(target, EM357_FPEC_CLK, 0x00000001);
-
- /* unlock flash registers */
- int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = first; i <= last; i++) {
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_AR,
- bank->base + bank->sectors[i].offset);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER | FLASH_STRT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 100);
- if (retval != ERROR_OK)
- return retval;
-
- bank->sectors[i].is_erased = 1;
- }
-
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int em357_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct em357_flash_bank *em357_info = NULL;
- struct target *target = bank->target;
- uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
- int i, reg, bit;
- int status;
- uint32_t protection;
-
- em357_info = bank->driver_priv;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first % em357_info->ppage_size) != 0) {
- LOG_WARNING("aligned start protect sector to a %d sector boundary",
- em357_info->ppage_size);
- first = first - (first % em357_info->ppage_size);
- }
- if (((last + 1) % em357_info->ppage_size) != 0) {
- LOG_WARNING("aligned end protect sector to a %d sector boundary",
- em357_info->ppage_size);
- last++;
- last = last - (last % em357_info->ppage_size);
- last--;
- }
-
- /* each bit refers to a 4bank protection */
- int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection);
- if (retval != ERROR_OK)
- return retval;
-
- prot_reg[0] = (uint16_t)protection;
- prot_reg[1] = (uint16_t)(protection >> 8);
- prot_reg[2] = (uint16_t)(protection >> 16);
-
- for (i = first; i <= last; i++) {
- reg = (i / em357_info->ppage_size) / 8;
- bit = (i / em357_info->ppage_size) - (reg * 8);
-
- LOG_WARNING("reg, bit: %d, %d", reg, bit);
- if (set)
- prot_reg[reg] &= ~(1 << bit);
- else
- prot_reg[reg] |= (1 << bit);
- }
-
- status = em357_erase_options(bank);
- if (retval != ERROR_OK)
- return status;
-
- em357_info->option_bytes.protection[0] = prot_reg[0];
- em357_info->option_bytes.protection[1] = prot_reg[1];
- em357_info->option_bytes.protection[2] = prot_reg[2];
-
- return em357_write_options(bank);
-}
-
-static int em357_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[4];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* see contib/loaders/flash/stm32x.s for src, the same is used here except for
- * a modified *_FLASH_BASE */
-
- static const uint8_t em357_flash_write_code[] = {
- /* #define EM357_FLASH_CR_OFFSET 0x10
- * #define EM357_FLASH_SR_OFFSET 0x0C
- * write: */
- 0x08, 0x4c, /* ldr r4, EM357_FLASH_BASE */
- 0x1c, 0x44, /* add r4, r3 */
- /* write_half_word: */
- 0x01, 0x23, /* movs r3, #0x01 */
- 0x23, 0x61, /* str r3, [r4,
- *#EM357_FLASH_CR_OFFSET] */
- 0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
- 0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
- /* busy: */
- 0xe3, 0x68, /* ldr r3, [r4,
- *#EM357_FLASH_SR_OFFSET] */
- 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
- 0xfb, 0xd0, /* beq busy */
- 0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
- 0x01, 0xd1, /* bne exit */
- 0x01, 0x3a, /* subs r2, r2, #0x01 */
- 0xf0, 0xd1, /* bne write_half_word */
- /* exit: */
- 0x00, 0xbe, /* bkpt #0x00 */
- 0x00, 0x80, 0x00, 0x40, /* EM357_FLASH_BASE: .word 0x40008000 */
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(em357_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(em357_flash_write_code), em357_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING(
- "no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- 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_IN_OUT);
-
- while (count > 0) {
- uint32_t thisrun_count = (count > (buffer_size / 2)) ?
- (buffer_size / 2) : count;
-
- retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
- if (retval != ERROR_OK)
- break;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
- buf_set_u32(reg_params[3].value, 0, 32, 0);
-
- retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
- write_algorithm->address, 0, 10000, &armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("error executing em357 flash write algorithm");
- break;
- }
-
- if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR) {
- LOG_ERROR("flash memory not erased before writing");
- /* Clear but report errors */
- target_write_u32(target, EM357_FLASH_SR, FLASH_PGERR);
- retval = ERROR_FAIL;
- break;
- }
-
- if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR) {
- LOG_ERROR("flash memory write protected");
- /* Clear but report errors */
- target_write_u32(target, EM357_FLASH_SR, FLASH_WRPRTERR);
- retval = ERROR_FAIL;
- break;
- }
-
- buffer += thisrun_count * 2;
- address += thisrun_count * 2;
- count -= thisrun_count;
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- 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 retval;
-}
-
-static int em357_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t words_remaining = (count / 2);
- uint32_t bytes_remaining = (count & 0x00000001);
- uint32_t address = bank->base + offset;
- uint32_t bytes_written = 0;
- int retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x1) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* unlock flash registers */
- retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- target_write_u32(target, EM357_FPEC_CLK, 0x00000001);
-
- /* multiple half words (2-byte) to be programmed? */
- if (words_remaining > 0) {
- /* try using a block write */
- retval = em357_write_block(bank, buffer, offset, words_remaining);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single dword accesses */
- LOG_WARNING(
- "couldn't use block writes, falling back to single memory accesses");
- }
- } else {
- buffer += words_remaining * 2;
- address += words_remaining * 2;
- words_remaining = 0;
- }
- }
-
- if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
- return retval;
-
- while (words_remaining > 0) {
- uint16_t value;
- memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
-
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u16(target, address, value);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 5);
- if (retval != ERROR_OK)
- return retval;
-
- bytes_written += 2;
- words_remaining--;
- address += 2;
- }
-
- if (bytes_remaining) {
- uint16_t value = 0xffff;
- memcpy(&value, buffer + bytes_written, bytes_remaining);
-
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u16(target, address, value);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 5);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
-}
-
-static int em357_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct em357_flash_bank *em357_info = bank->driver_priv;
- int i;
- uint16_t num_pages;
- int page_size;
- uint32_t base_address = 0x08000000;
-
- em357_info->probed = 0;
-
- switch (bank->size) {
- case 0x10000:
- /* 64k -- 64 1k pages */
- num_pages = 64;
- page_size = 1024;
- break;
- case 0x20000:
- /* 128k -- 128 1k pages */
- num_pages = 128;
- page_size = 1024;
- break;
- case 0x30000:
- /* 192k -- 96 2k pages */
- num_pages = 96;
- page_size = 2048;
- break;
- case 0x40000:
- /* 256k -- 128 2k pages */
- num_pages = 128;
- page_size = 2048;
- break;
- default:
- LOG_WARNING("No size specified for em357 flash driver, assuming 192k!");
- num_pages = 96;
- page_size = 2048;
- break;
- }
-
- /* Enable FPEC CLK */
- int retval = target_write_u32(target, EM357_FPEC_CLK, 0x00000001);
- if (retval != ERROR_OK)
- return retval;
-
- em357_info->ppage_size = 4;
-
- LOG_INFO("flash size = %dkbytes", num_pages*page_size/1024);
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->base = base_address;
- bank->size = (num_pages * page_size);
- bank->num_sectors = num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
-
- for (i = 0; i < num_pages; i++) {
- bank->sectors[i].offset = i * page_size;
- bank->sectors[i].size = page_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- em357_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int em357_auto_probe(struct flash_bank *bank)
-{
- struct em357_flash_bank *em357_info = bank->driver_priv;
- if (em357_info->probed)
- return ERROR_OK;
- return em357_probe(bank);
-}
-
-COMMAND_HANDLER(em357_handle_lock_command)
-{
- struct target *target = NULL;
- struct em357_flash_bank *em357_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- em357_info = bank->driver_priv;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (em357_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "em357 failed to erase options");
- return ERROR_OK;
- }
-
- /* set readout protection */
- em357_info->option_bytes.RDP = 0;
-
- if (em357_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "em357 failed to lock device");
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "em357 locked");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(em357_handle_unlock_command)
-{
- struct target *target = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (em357_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "em357 failed to unlock device");
- return ERROR_OK;
- }
-
- if (em357_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "em357 failed to lock device");
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "em357 unlocked.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.");
-
- return ERROR_OK;
-}
-
-static int em357_mass_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Make sure the flash clock is on */
- target_write_u32(target, EM357_FPEC_CLK, 0x00000001);
-
- /* unlock option flash registers */
- int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* mass erase flash memory */
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER | FLASH_STRT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = em357_wait_status_busy(bank, 100);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(em357_handle_mass_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = em357_mass_erase(bank);
- if (retval == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "em357 mass erase complete");
- } else
- command_print(CMD_CTX, "em357 mass erase failed");
-
- return retval;
-}
-
-static const struct command_registration em357_exec_command_handlers[] = {
- {
- .name = "lock",
- .usage = "<bank>",
- .handler = em357_handle_lock_command,
- .mode = COMMAND_EXEC,
- .help = "Lock entire flash device.",
- },
- {
- .name = "unlock",
- .usage = "<bank>",
- .handler = em357_handle_unlock_command,
- .mode = COMMAND_EXEC,
- .help = "Unlock entire protected flash device.",
- },
- {
- .name = "mass_erase",
- .usage = "<bank>",
- .handler = em357_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .help = "Erase entire flash device.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration em357_command_handlers[] = {
- {
- .name = "em357",
- .mode = COMMAND_ANY,
- .help = "em357 flash command group",
- .usage = "",
- .chain = em357_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver em357_flash = {
- .name = "em357",
- .commands = em357_command_handlers,
- .flash_bank_command = em357_flash_bank_command,
- .erase = em357_erase,
- .protect = em357_protect,
- .write = em357_write,
- .read = default_flash_read,
- .probe = em357_probe,
- .auto_probe = em357_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = em357_protect_check,
-};
diff --git a/src/flash/nor/faux.c b/src/flash/nor/faux.c
deleted file mode 100644
index 203eb6f..0000000
--- a/src/flash/nor/faux.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <target/image.h>
-#include "hello.h"
-
-struct faux_flash_bank {
- struct target *target;
- uint8_t *memory;
- uint32_t start_address;
-};
-
-static const int sectorSize = 0x10000;
-
-
-/* flash bank faux <base> <size> <chip_width> <bus_width> <target#> <driverPath>
- */
-FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command)
-{
- struct faux_flash_bank *info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- info = malloc(sizeof(struct faux_flash_bank));
- if (info == NULL) {
- LOG_ERROR("no memory for flash bank info");
- return ERROR_FAIL;
- }
- info->memory = malloc(bank->size);
- if (info->memory == NULL) {
- free(info);
- LOG_ERROR("no memory for flash bank info");
- return ERROR_FAIL;
- }
- bank->driver_priv = info;
-
- /* Use 0x10000 as a fixed sector size. */
- int i = 0;
- uint32_t offset = 0;
- bank->num_sectors = bank->size/sectorSize;
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- for (i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = sectorSize;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 0;
- }
-
- info->target = get_target(CMD_ARGV[5]);
- if (info->target == NULL) {
- LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
- free(info->memory);
- free(info);
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int faux_erase(struct flash_bank *bank, int first, int last)
-{
- struct faux_flash_bank *info = bank->driver_priv;
- memset(info->memory + first*sectorSize, 0xff, sectorSize*(last-first + 1));
- return ERROR_OK;
-}
-
-static int faux_protect(struct flash_bank *bank, int set, int first, int last)
-{
- LOG_USER("set protection sector %d to %d to %s", first, last, set ? "on" : "off");
- return ERROR_OK;
-}
-
-static int faux_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct faux_flash_bank *info = bank->driver_priv;
- memcpy(info->memory + offset, buffer, count);
- return ERROR_OK;
-}
-
-static int faux_protect_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-static int faux_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- snprintf(buf, buf_size, "faux flash driver");
- return ERROR_OK;
-}
-
-static int faux_probe(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-static const struct command_registration faux_command_handlers[] = {
- {
- .name = "faux",
- .mode = COMMAND_ANY,
- .help = "faux flash command group",
- .chain = hello_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver faux_flash = {
- .name = "faux",
- .commands = faux_command_handlers,
- .flash_bank_command = faux_flash_bank_command,
- .erase = faux_erase,
- .protect = faux_protect,
- .write = faux_write,
- .read = default_flash_read,
- .probe = faux_probe,
- .auto_probe = faux_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = faux_protect_check,
- .info = faux_info
-};
diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c
deleted file mode 100644
index 55c2920..0000000
--- a/src/flash/nor/fespi.c
+++ /dev/null
@@ -1,1127 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
- * Modified by Megan Wachs <megan@sifive.com> from the original stmsmi.c *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* The Freedom E SPI controller is a SPI bus controller
- * specifically designed for SPI Flash Memories on Freedom E platforms.
- *
- * Two working modes are available:
- * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
- * on the bus. Writes are only possible in this mode.
- * - HW mode: Memory content is directly
- * accessible in CPU memory space. CPU can read, write and execute memory
- * content. */
-
-/* ATTENTION:
- * To have flash memory mapped in CPU memory space, the controller
- * must have "HW mode" enabled.
- * 1) The command "reset init" has to initialize the controller and put
- * it in HW mode (this is actually the default out of reset for Freedom E systems).
- * 2) every command in this file have to return to prompt in HW mode. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "spi.h"
-#include <jtag/jtag.h>
-#include <helper/time_support.h>
-#include <target/algorithm.h>
-
-/* Register offsets */
-
-#define FESPI_REG_SCKDIV 0x00
-#define FESPI_REG_SCKMODE 0x04
-#define FESPI_REG_CSID 0x10
-#define FESPI_REG_CSDEF 0x14
-#define FESPI_REG_CSMODE 0x18
-
-#define FESPI_REG_DCSSCK 0x28
-#define FESPI_REG_DSCKCS 0x2a
-#define FESPI_REG_DINTERCS 0x2c
-#define FESPI_REG_DINTERXFR 0x2e
-
-#define FESPI_REG_FMT 0x40
-#define FESPI_REG_TXFIFO 0x48
-#define FESPI_REG_RXFIFO 0x4c
-#define FESPI_REG_TXCTRL 0x50
-#define FESPI_REG_RXCTRL 0x54
-
-#define FESPI_REG_FCTRL 0x60
-#define FESPI_REG_FFMT 0x64
-
-#define FESPI_REG_IE 0x70
-#define FESPI_REG_IP 0x74
-
-/* Fields */
-
-#define FESPI_SCK_POL 0x1
-#define FESPI_SCK_PHA 0x2
-
-#define FESPI_FMT_PROTO(x) ((x) & 0x3)
-#define FESPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
-#define FESPI_FMT_DIR(x) (((x) & 0x1) << 3)
-#define FESPI_FMT_LEN(x) (((x) & 0xf) << 16)
-
-/* TXCTRL register */
-#define FESPI_TXWM(x) ((x) & 0xffff)
-/* RXCTRL register */
-#define FESPI_RXWM(x) ((x) & 0xffff)
-
-#define FESPI_IP_TXWM 0x1
-#define FESPI_IP_RXWM 0x2
-
-#define FESPI_FCTRL_EN 0x1
-
-#define FESPI_INSN_CMD_EN 0x1
-#define FESPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
-#define FESPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
-#define FESPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
-#define FESPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
-#define FESPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
-#define FESPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
-#define FESPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
-
-/* Values */
-
-#define FESPI_CSMODE_AUTO 0
-#define FESPI_CSMODE_HOLD 2
-#define FESPI_CSMODE_OFF 3
-
-#define FESPI_DIR_RX 0
-#define FESPI_DIR_TX 1
-
-#define FESPI_PROTO_S 0
-#define FESPI_PROTO_D 1
-#define FESPI_PROTO_Q 2
-
-#define FESPI_ENDIAN_MSB 0
-#define FESPI_ENDIAN_LSB 1
-
-
-/* Timeout in ms */
-#define FESPI_CMD_TIMEOUT (100)
-#define FESPI_PROBE_TIMEOUT (100)
-#define FESPI_MAX_TIMEOUT (3000)
-
-
-#define FESPI_READ_REG(a) (_FESPI_READ_REG(a))
-#define _FESPI_READ_REG(a) \
-{ \
- int __a; \
- uint32_t __v; \
- \
- __a = target_read_u32(target, ctrl_base + (a), &__v); \
- if (__a != ERROR_OK) \
- return __a; \
- __v; \
-}
-
-#define FESPI_WRITE_REG(a, v) \
-{ \
- int __r; \
- \
- __r = target_write_u32(target, ctrl_base + (a), (v)); \
- if (__r != ERROR_OK) \
- return __r; \
-}
-
-#define FESPI_DISABLE_HW_MODE() FESPI_WRITE_REG(FESPI_REG_FCTRL, \
- FESPI_READ_REG(FESPI_REG_FCTRL) & ~FESPI_FCTRL_EN)
-#define FESPI_ENABLE_HW_MODE() FESPI_WRITE_REG(FESPI_REG_FCTRL, \
- FESPI_READ_REG(FESPI_REG_FCTRL) | FESPI_FCTRL_EN)
-
-struct fespi_flash_bank {
- int probed;
- uint32_t ctrl_base;
- const struct flash_device *dev;
-};
-
-struct fespi_target {
- char *name;
- uint32_t tap_idcode;
- uint32_t ctrl_base;
-};
-
-//TODO !!! What is the right naming convention here?
-static const struct fespi_target target_devices[] = {
- /* name, tap_idcode, ctrl_base */
- { "Freedom E300 SPI Flash", 0x10e31913 , 0x10014000 },
- { "whatever", 0x00000001, 0x10014000 },
- { NULL, 0, 0 }
-};
-
-FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command)
-{
- struct fespi_flash_bank *fespi_info;
-
- LOG_DEBUG("%s", __func__);
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- fespi_info = malloc(sizeof(struct fespi_flash_bank));
- if (fespi_info == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- bank->driver_priv = fespi_info;
- fespi_info->probed = 0;
-
- return ERROR_OK;
-}
-
-static int fespi_set_dir (struct flash_bank * bank, bool dir) {
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
-
- FESPI_WRITE_REG(FESPI_REG_FMT,
- (FESPI_READ_REG(FESPI_REG_FMT) & ~(FESPI_FMT_DIR(0xFFFFFFFF))) |
- FESPI_FMT_DIR(dir));
-
- return ERROR_OK;
-
-}
-
-static int fespi_txwm_wait(struct flash_bank *bank) {
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
-
- int64_t start = timeval_ms();
-
- while (1) {
- if (FESPI_READ_REG(FESPI_REG_IP) & FESPI_IP_TXWM) {
- break;
- }
- int64_t now = timeval_ms();
- if (now - start > 1000) {
- LOG_ERROR("ip.txwm didn't get set.");
- return ERROR_TARGET_TIMEOUT;
- }
- }
-
- return ERROR_OK;
-
-}
-
-static int fespi_tx(struct flash_bank *bank, uint8_t in){
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
-
- int64_t start = timeval_ms();
-
- while (1) {
- if ((int32_t) FESPI_READ_REG(FESPI_REG_TXFIFO) >= 0) {
- break;
- }
- int64_t now = timeval_ms();
- if (now - start > 1000) {
- LOG_ERROR("txfifo stayed negative.");
- return ERROR_TARGET_TIMEOUT;
- }
- }
-
- FESPI_WRITE_REG(FESPI_REG_TXFIFO, in);
-
- return ERROR_OK;
-}
-
-static int fespi_rx(struct flash_bank *bank, uint8_t *out)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
-
- int64_t start = timeval_ms();
- int32_t value;
-
- while (1) {
- value = (int32_t) FESPI_READ_REG(FESPI_REG_RXFIFO);
- if (value >= 0)
- break;
- int64_t now = timeval_ms();
- if (now - start > 1000) {
- LOG_ERROR("rxfifo didn't go positive (value=0x%x).", value);
- return ERROR_TARGET_TIMEOUT;
- }
- }
-
- if (out) {
- *out = value & 0xff;
- }
- return ERROR_OK;
-}
-
-//TODO!!! Why don't we need to call this after writing?
-static int fespi_wip (struct flash_bank * bank, int timeout)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
-
- int64_t endtime;
-
- fespi_set_dir(bank, FESPI_DIR_RX);
-
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
- endtime = timeval_ms() + timeout;
-
- fespi_tx(bank, SPIFLASH_READ_STATUS);
- if (fespi_rx(bank, NULL) != ERROR_OK)
- return ERROR_FAIL;
-
- do {
- alive_sleep(1);
-
- fespi_tx(bank, 0);
- uint8_t rx;
- if (fespi_rx(bank, &rx) != ERROR_OK)
- return ERROR_FAIL;
- if ((rx & SPIFLASH_BSY_BIT) == 0) {
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
- fespi_set_dir(bank, FESPI_DIR_TX);
- return ERROR_OK;
- }
- } while (timeval_ms() < endtime);
-
- LOG_ERROR("timeout");
- return ERROR_FAIL;
-}
-
-static int fespi_erase_sector(struct flash_bank *bank, int sector)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
- int retval;
-
- fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
- fespi_txwm_wait(bank);
-
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
- fespi_tx(bank, fespi_info->dev->erase_cmd);
- sector = bank->sectors[sector].offset;
- fespi_tx(bank, sector >> 16);
- fespi_tx(bank, sector >> 8);
- fespi_tx(bank, sector);
- fespi_txwm_wait(bank);
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
-
- retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int fespi_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
- 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 (!(fespi_info->probed)) {
- LOG_ERROR("Flash bank not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- for (sector = first; sector <= last; sector++) {
- if (bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- fespi_txwm_wait(bank);
-
- /* Disable Hardware accesses*/
- FESPI_DISABLE_HW_MODE();
-
- /* poll WIP */
- retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- for (sector = first; sector <= last; sector++) {
- retval = fespi_erase_sector(bank, sector);
- if (retval != ERROR_OK)
- break;
- keep_alive();
- }
-
- /* Switch to HW mode before return to prompt */
- FESPI_ENABLE_HW_MODE();
- return retval;
-}
-
-static int fespi_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 slow_fespi_write_buffer(struct flash_bank *bank,
- const uint8_t *buffer, uint32_t offset, uint32_t len)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
- uint32_t ii;
-
- //TODO!!! assert that len < page size
-
- fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
- fespi_txwm_wait(bank);
-
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
-
- fespi_tx(bank, SPIFLASH_PAGE_PROGRAM);
-
- fespi_tx(bank, offset >> 16);
- fespi_tx(bank, offset >> 8);
- fespi_tx(bank, offset);
-
- for (ii = 0; ii < len; ii++) {
- fespi_tx(bank, buffer[ii]);
- }
-
- fespi_txwm_wait(bank);
-
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
-
- keep_alive();
-
- return ERROR_OK;
-}
-
-/*
- * Here's the source for the algorithm.
- * You can turn it into the array below using:
- sed -n '/ALGO_START$/,/ALGO_END/ p' fespi.c | \
- riscv32-unknown-elf-gcc -x assembler-with-cpp - -nostdlib -nostartfiles -o tmp.o && \
- riscv32-unknown-elf-objcopy -O binary tmp.o algorithm.bin && \
- xxd -i algorithm.bin
-
-// ALGO_START
-#define SPIFLASH_READ_STATUS 0x05 // Read Status Register
-#define SPIFLASH_BSY_BIT 0x00000001 // WIP Bit of SPI SR on SMI SR
-
-// Register offsets
-#define FESPI_REG_FMT 0x40
-#define FESPI_REG_TXFIFO 0x48
-#define FESPI_REG_RXFIFO 0x4c
-#define FESPI_REG_IP 0x74
-
-// Fields
-#define FESPI_IP_TXWM 0x1
-#define FESPI_FMT_DIR(x) (((x) & 0x1) << 3)
-
-// To enter, jump to the start of command_table (ie. offset 0).
-// a0 - FESPI base address
-// a1 - start address of buffer
-
-// The buffer contains a "program" in byte sequences. The first byte in a
-// sequence determines the operation. Some operation will read more data from
-// the program, while some will not. The operation byte is the offset into
-// command_table, so eg. 4 means exit, 8 means transmit, and so on.
-
- .global _start
-_start:
-command_table:
- j main // 0
- ebreak // 4
- j tx // 8
- j txwm_wait // 12
- j write_reg // 16
- j wip_wait // 20
- j set_dir // 24
-
-// Execute the program.
-main:
- lbu t0, 0(a1)
- addi a1, a1, 1
- la t1, command_table
- add t0, t0, t1
- jr t0
-
-// Read 1 byte the contains the number of bytes to transmit. Then read those
-// bytes from the program and transmit them one by one.
-tx:
- lbu t1, 0(a1) // read number of bytes to transmit
- addi a1, a1, 1
-1: lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
- bltz t0, 1b
- lbu t0, 0(a1) // Load byte to write
- sw t0, FESPI_REG_TXFIFO(a0)
- addi a1, a1, 1
- addi t1, t1, -1
- bgtz t1, 1b
- j main
-
-// Wait until TXWM is set.
-txwm_wait:
-1: lw t0, FESPI_REG_IP(a0)
- andi t0, t0, FESPI_IP_TXWM
- beqz t0, 1b
- j main
-
-// Read 1 byte that contains the offset of the register to write, and 1 byte
-// that contains the data to write.
-write_reg:
- lbu t0, 0(a1) // read register to write
- add t0, t0, a0
- lbu t1, 1(a1) // read value to write
- addi a1, a1, 2
- sw t1, 0(t0)
- j main
-
-wip_wait:
- li a2, SPIFLASH_READ_STATUS
- jal txrx_byte
- // discard first result
-1: li a2, 0
- jal txrx_byte
- andi t0, a2, SPIFLASH_BSY_BIT
- bnez t0, 1b
- j main
-
-txrx_byte: // transmit the byte in a2, receive a bit into a2
- lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
- bltz t0, txrx_byte
- sw a2, FESPI_REG_TXFIFO(a0)
-1: lw a2, FESPI_REG_RXFIFO(a0)
- bltz a2, 1b
- ret
-
-set_dir:
- lw t0, FESPI_REG_FMT(a0)
- li t1, ~(FESPI_FMT_DIR(0xFFFFFFFF))
- and t0, t0, t1
- lbu t1, 0(a1) // read value to OR in
- addi a1, a1, 1
- or t0, t0, t1
- sw t0, FESPI_REG_FMT(a0)
- j main
-
-// ALGO_END
- */
-static const uint8_t algorithm_bin[] = {
- 0x6f, 0x00, 0xc0, 0x01, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0xc0, 0x02,
- 0x6f, 0x00, 0x00, 0x05, 0x6f, 0x00, 0xc0, 0x05, 0x6f, 0x00, 0x00, 0x07,
- 0x6f, 0x00, 0x00, 0x0a, 0x83, 0xc2, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
- 0x17, 0x03, 0x00, 0x00, 0x13, 0x03, 0xc3, 0xfd, 0xb3, 0x82, 0x62, 0x00,
- 0x67, 0x80, 0x02, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
- 0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x83, 0xc2, 0x05, 0x00,
- 0x23, 0x24, 0x55, 0x04, 0x93, 0x85, 0x15, 0x00, 0x13, 0x03, 0xf3, 0xff,
- 0xe3, 0x44, 0x60, 0xfe, 0x6f, 0xf0, 0x5f, 0xfc, 0x83, 0x22, 0x45, 0x07,
- 0x93, 0xf2, 0x12, 0x00, 0xe3, 0x8c, 0x02, 0xfe, 0x6f, 0xf0, 0x5f, 0xfb,
- 0x83, 0xc2, 0x05, 0x00, 0xb3, 0x82, 0xa2, 0x00, 0x03, 0xc3, 0x15, 0x00,
- 0x93, 0x85, 0x25, 0x00, 0x23, 0xa0, 0x62, 0x00, 0x6f, 0xf0, 0xdf, 0xf9,
- 0x13, 0x06, 0x50, 0x00, 0xef, 0x00, 0x80, 0x01, 0x13, 0x06, 0x00, 0x00,
- 0xef, 0x00, 0x00, 0x01, 0x93, 0x72, 0x16, 0x00, 0xe3, 0x9a, 0x02, 0xfe,
- 0x6f, 0xf0, 0x1f, 0xf8, 0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe,
- 0x23, 0x24, 0xc5, 0x04, 0x03, 0x26, 0xc5, 0x04, 0xe3, 0x4e, 0x06, 0xfe,
- 0x67, 0x80, 0x00, 0x00, 0x83, 0x22, 0x05, 0x04, 0x13, 0x03, 0x70, 0xff,
- 0xb3, 0xf2, 0x62, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
- 0xb3, 0xe2, 0x62, 0x00, 0x23, 0x20, 0x55, 0x04, 0x6f, 0xf0, 0x9f, 0xf4
-};
-#define STEP_EXIT 4
-#define STEP_TX 8
-#define STEP_TXWM_WAIT 12
-#define STEP_WRITE_REG 16
-#define STEP_WIP_WAIT 20
-#define STEP_SET_DIR 24
-#define STEP_NOP 0xff
-
-struct algorithm_steps {
- unsigned size;
- unsigned used;
- uint8_t **steps;
-};
-
-struct algorithm_steps *as_new(unsigned size)
-{
- struct algorithm_steps *as = calloc(1, sizeof(struct algorithm_steps));
- as->size = size;
- as->steps = calloc(size, sizeof(as->steps[0]));
- return as;
-}
-
-struct algorithm_steps *as_delete(struct algorithm_steps *as)
-{
- for (unsigned step = 0; step < as->used; step++) {
- free(as->steps[step]);
- as->steps[step] = NULL;
- }
- free(as);
- return NULL;
-}
-
-int as_empty(struct algorithm_steps *as)
-{
- for (unsigned s = 0; s < as->used; s++) {
- if (as->steps[s][0] != STEP_NOP)
- return 0;
- }
- return 1;
-}
-
-// Return size of compiled program.
-unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
- unsigned target_size)
-{
- unsigned offset = 0;
- bool finish_early = false;
- for (unsigned s = 0; s < as->used && !finish_early; s++) {
- unsigned bytes_left = target_size - offset;
- switch (as->steps[s][0]) {
- case STEP_NOP:
- break;
- case STEP_TX:
- {
- unsigned size = as->steps[s][1];
- if (size + 3 > bytes_left) {
- finish_early = true;
- break;
- }
- memcpy(target + offset, as->steps[s], size + 2);
- offset += size + 2;
- break;
- }
- case STEP_WRITE_REG:
- if (4 > bytes_left) {
- finish_early = true;
- break;
- }
- memcpy(target + offset, as->steps[s], 3);
- offset += 3;
- break;
- case STEP_SET_DIR:
- if (3 > bytes_left) {
- finish_early = true;
- break;
- }
- memcpy(target + offset, as->steps[s], 2);
- offset += 2;
- break;
- case STEP_TXWM_WAIT:
- case STEP_WIP_WAIT:
- if (2 > bytes_left) {
- finish_early = true;
- break;
- }
- memcpy(target + offset, as->steps[s], 1);
- offset += 1;
- break;
- default:
- assert(0);
- }
- if (!finish_early)
- as->steps[s][0] = STEP_NOP;
- }
- assert(offset + 1 <= target_size);
- target[offset++] = STEP_EXIT;
-
- LOG_DEBUG("%d-byte program:", offset);
- for (unsigned i = 0; i < offset;) {
- char buf[80];
- for (unsigned x = 0; i < offset && x < 16; x++, i++) {
- sprintf(buf + x*3, "%02x ", target[i]);
- }
- LOG_DEBUG("%s", buf);
- }
-
- return offset;
-}
-
-void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data)
-{
- LOG_DEBUG("count=%d", count);
- while (count > 0) {
- unsigned step_count = MIN(count, 255);
- assert(as->used < as->size);
- as->steps[as->used] = malloc(step_count + 2);
- as->steps[as->used][0] = STEP_TX;
- as->steps[as->used][1] = step_count;
- memcpy(as->steps[as->used] + 2, data, step_count);
- as->used++;
- data += step_count;
- count -= step_count;
- }
-}
-
-void as_add_tx1(struct algorithm_steps *as, uint8_t byte)
-{
- uint8_t data[1];
- data[0] = byte;
- as_add_tx(as, 1, data);
-}
-
-void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data)
-{
- assert(as->used < as->size);
- as->steps[as->used] = malloc(3);
- as->steps[as->used][0] = STEP_WRITE_REG;
- as->steps[as->used][1] = offset;
- as->steps[as->used][2] = data;
- as->used++;
-}
-
-void as_add_txwm_wait(struct algorithm_steps *as)
-{
- assert(as->used < as->size);
- as->steps[as->used] = malloc(1);
- as->steps[as->used][0] = STEP_TXWM_WAIT;
- as->used++;
-}
-
-void as_add_wip_wait(struct algorithm_steps *as)
-{
- assert(as->used < as->size);
- as->steps[as->used] = malloc(1);
- as->steps[as->used][0] = STEP_WIP_WAIT;
- as->used++;
-}
-
-void as_add_set_dir(struct algorithm_steps *as, bool dir)
-{
- assert(as->used < as->size);
- as->steps[as->used] = malloc(2);
- as->steps[as->used][0] = STEP_SET_DIR;
- as->steps[as->used][1] = FESPI_FMT_DIR(dir);
- as->used++;
-}
-
-/* This should write something less than or equal to a page.*/
-static int steps_add_buffer_write(struct algorithm_steps *as,
- const uint8_t *buffer, uint32_t chip_offset, uint32_t len)
-{
- as_add_tx1(as, SPIFLASH_WRITE_ENABLE);
- as_add_txwm_wait(as);
- as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
-
- uint8_t setup[] = {
- SPIFLASH_PAGE_PROGRAM,
- chip_offset >> 16,
- chip_offset >> 8,
- chip_offset,
- };
- as_add_tx(as, sizeof(setup), setup);
-
- as_add_tx(as, len, buffer);
- as_add_txwm_wait(as);
- as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
-
- // fespi_wip()
- as_add_set_dir(as, FESPI_DIR_RX);
- as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
- as_add_wip_wait(as);
- as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
- as_add_set_dir(as, FESPI_DIR_TX);
-
- return ERROR_OK;
-}
-
-static int steps_execute(struct algorithm_steps *as,
- struct flash_bank *bank, struct working_area *algorithm_wa,
- struct working_area *data_wa)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
- uint8_t *data_buf = malloc(data_wa->size);
-
- struct reg_param reg_params[2];
- init_reg_param(&reg_params[0], "x10", 64, PARAM_OUT);
- init_reg_param(&reg_params[1], "x11", 64, PARAM_OUT);
- buf_set_u64(reg_params[0].value, 0, 64, ctrl_base);
- buf_set_u64(reg_params[1].value, 0, 64, data_wa->address);
- while (!as_empty(as)) {
- keep_alive();
- unsigned bytes = as_compile(as, data_buf, data_wa->size);
- int retval = target_write_buffer(target, data_wa->address, bytes,
- data_buf);
- if (retval != ERROR_OK) {
- LOG_ERROR("Failed to write data to 0x%x: %d", data_wa->address,
- retval);
- return retval;
- }
-
- retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
- algorithm_wa->address, algorithm_wa->address + 4,
- 10000, NULL);
- if (retval != ERROR_OK) {
- LOG_ERROR("Failed to execute algorithm at 0x%x: %d", algorithm_wa->address,
- retval);
- return retval;
- }
- }
-
- return ERROR_OK;
-}
-
-static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
- uint32_t cur_count, page_size, page_offset;
- int sector;
- int retval = 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 > fespi_info->dev->size_in_bytes) {
- LOG_WARNING("Write past end of flash. Extra data discarded.");
- count = fespi_info->dev->size_in_bytes - offset;
- }
-
- /* 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? */
- if ((offset <
- (bank->sectors[sector].offset + bank->sectors[sector].size))
- && ((offset + count - 1) >= bank->sectors[sector].offset)
- && bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- struct working_area *algorithm_wa;
- if (target_alloc_working_area(target, sizeof(algorithm_bin),
- &algorithm_wa) != ERROR_OK) {
- LOG_WARNING("Couldn't allocate %zd-byte working area.",
- sizeof(algorithm_bin));
- algorithm_wa = NULL;
- } else {
- retval = target_write_buffer(target, algorithm_wa->address,
- sizeof(algorithm_bin), algorithm_bin);
- if (retval != ERROR_OK) {
- LOG_ERROR("Failed to write code to 0x%x: %d", algorithm_wa->address,
- retval);
- target_free_working_area(target, algorithm_wa);
- algorithm_wa = NULL;
- }
- }
-
- struct working_area *data_wa = NULL;
- unsigned data_wa_size = 2 * count;
- while (1) {
- if (data_wa_size < 128) {
- LOG_WARNING("Couldn't allocate data working area.");
- target_free_working_area(target, algorithm_wa);
- algorithm_wa = NULL;
- }
- if (target_alloc_working_area_try(target, data_wa_size, &data_wa) ==
- ERROR_OK) {
- break;
- }
-
- data_wa_size /= 2;
- }
-
- page_size = fespi_info->dev->pagesize;
-
- fespi_txwm_wait(bank);
-
- /* Disable Hardware accesses*/
- FESPI_DISABLE_HW_MODE();
-
- /* poll WIP */
- retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- struct algorithm_steps *as = as_new(count / 4);
-
- /* unaligned buffer head */
- if (count > 0 && (offset & 3) != 0) {
- cur_count = 4 - (offset & 3);
- if (cur_count > count)
- cur_count = count;
- if (algorithm_wa) {
- retval = steps_add_buffer_write(as, buffer, offset, cur_count);
- } else {
- retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
- }
- if (retval != ERROR_OK)
- goto err;
- offset += cur_count;
- buffer += cur_count;
- count -= cur_count;
- }
-
- page_offset = offset % page_size;
- /* central part, aligned words */
- while (count >= 4) {
- /* clip block at page boundary */
- if (page_offset + count > page_size)
- cur_count = page_size - page_offset;
- else
- cur_count = count & ~3;
-
- if (algorithm_wa) {
- retval = steps_add_buffer_write(as, buffer, offset, cur_count);
- } else {
- retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
- }
- if (retval != ERROR_OK)
- goto err;
-
- page_offset = 0;
- buffer += cur_count;
- offset += cur_count;
- count -= cur_count;
- }
-
- /* buffer tail */
- if (count > 0) {
- if (algorithm_wa) {
- retval = steps_add_buffer_write(as, buffer, offset, count);
- } else {
- retval = slow_fespi_write_buffer(bank, buffer, offset, count);
- }
- if (retval != ERROR_OK)
- goto err;
- }
-
- if (algorithm_wa) {
- retval = steps_execute(as, bank, algorithm_wa, data_wa);
- }
-
-err:
- if (algorithm_wa) {
- target_free_working_area(target, data_wa);
- target_free_working_area(target, algorithm_wa);
- }
-
- /* Switch to HW mode before return to prompt */
- FESPI_ENABLE_HW_MODE();
- return retval;
-}
-
-/* Return ID of flash device */
-/* On exit, SW mode is kept */
-static int fespi_read_flash_id(struct flash_bank *bank, uint32_t *id)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base = fespi_info->ctrl_base;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- fespi_txwm_wait(bank);
-
- /* Disable Hardware accesses*/
- FESPI_DISABLE_HW_MODE();
-
- /* poll WIP */
- retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- fespi_set_dir(bank, FESPI_DIR_RX);
-
- /* Send SPI command "read ID" */
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
-
- fespi_tx(bank, SPIFLASH_READ_ID);
- /* Send dummy bytes to actually read the ID.*/
- fespi_tx(bank, 0);
- fespi_tx(bank, 0);
- fespi_tx(bank, 0);
-
- /* read ID from Receive Register */
- *id = 0;
- if (fespi_rx(bank, NULL) != ERROR_OK)
- return ERROR_FAIL;
- uint8_t rx;
- if (fespi_rx(bank, &rx) != ERROR_OK)
- return ERROR_FAIL;
- *id = rx;
- if (fespi_rx(bank, &rx) != ERROR_OK)
- return ERROR_FAIL;
- *id |= (rx << 8);
- if (fespi_rx(bank, &rx) != ERROR_OK)
- return ERROR_FAIL;
- *id |= (rx << 16);
-
- FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
-
- fespi_set_dir(bank, FESPI_DIR_TX);
-
- return ERROR_OK;
-}
-
-static int fespi_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- uint32_t ctrl_base;
- struct flash_sector *sectors;
- uint32_t id = 0; /* silence uninitialized warning */
- const struct fespi_target *target_device;
- int retval;
-
- if (fespi_info->probed)
- free(bank->sectors);
- fespi_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 as FESPI capable",
- target->tap->idcode);
- return ERROR_FAIL;
- }
-
- ctrl_base = target_device->ctrl_base;
- fespi_info->ctrl_base = ctrl_base;
-
- LOG_DEBUG("Valid FESPI on device %s at address 0x%" PRIx32,
- target_device->name, bank->base);
-
- /* read and decode flash ID; returns in SW mode */
- FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1));
- fespi_set_dir(bank, FESPI_DIR_TX);
-
- retval = fespi_read_flash_id(bank, &id);
-
- FESPI_ENABLE_HW_MODE();
- if (retval != ERROR_OK)
- return retval;
-
- fespi_info->dev = NULL;
- for (const struct flash_device *p = flash_devices; p->name ; p++)
- if (p->device_id == id) {
- fespi_info->dev = p;
- break;
- }
-
- if (!fespi_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 ")",
- fespi_info->dev->name, fespi_info->dev->device_id);
-
- /* Set correct size value */
- bank->size = fespi_info->dev->size_in_bytes;
-
- /* create and fill sectors array */
- bank->num_sectors =
- fespi_info->dev->size_in_bytes / fespi_info->dev->sectorsize;
- sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- if (sectors == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- for (int sector = 0; sector < bank->num_sectors; sector++) {
- sectors[sector].offset = sector * fespi_info->dev->sectorsize;
- sectors[sector].size = fespi_info->dev->sectorsize;
- sectors[sector].is_erased = -1;
- sectors[sector].is_protected = 1;
- }
-
- bank->sectors = sectors;
- fespi_info->probed = 1;
- return ERROR_OK;
-}
-
-static int fespi_auto_probe(struct flash_bank *bank)
-{
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
- if (fespi_info->probed)
- return ERROR_OK;
- return fespi_probe(bank);
-}
-
-static int fespi_protect_check(struct flash_bank *bank)
-{
- /* Nothing to do. Protection is only handled in SW. */
- return ERROR_OK;
-}
-
-static int get_fespi_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct fespi_flash_bank *fespi_info = bank->driver_priv;
-
- if (!(fespi_info->probed)) {
- snprintf(buf, buf_size,
- "\nFESPI flash bank not probed yet\n");
- return ERROR_OK;
- }
-
- snprintf(buf, buf_size, "\nFESPI flash information:\n"
- " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
- fespi_info->dev->name, fespi_info->dev->device_id);
-
- return ERROR_OK;
-}
-
-struct flash_driver fespi_flash = {
- .name = "fespi",
- .flash_bank_command = fespi_flash_bank_command,
- .erase = fespi_erase,
- .protect = fespi_protect,
- .write = fespi_write,
- .read = default_flash_read,
- .probe = fespi_probe,
- .auto_probe = fespi_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = fespi_protect_check,
- .info = get_fespi_info
-};
diff --git a/src/flash/nor/fm3.c b/src/flash/nor/fm3.c
deleted file mode 100644
index 6269a65..0000000
--- a/src/flash/nor/fm3.c
+++ /dev/null
@@ -1,1000 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Marc Willam, Holger Wech *
- * openOCD.fseu(AT)de.fujitsu.com *
- * Copyright (C) 2011 Ronny Strutz *
- * *
- * Copyright (C) 2013 Nemui Trinomius *
- * nemuisan_kawausogasuki@live.jp *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-#define FLASH_DQ6 0x40 /* Data toggle flag bit (TOGG) position */
-#define FLASH_DQ5 0x20 /* Time limit exceeding flag bit (TLOV) position */
-
-enum fm3_variant {
- mb9bfxx1, /* Flash Type '1' */
- mb9bfxx2,
- mb9bfxx3,
- mb9bfxx4,
- mb9bfxx5,
- mb9bfxx6,
- mb9bfxx7,
- mb9bfxx8,
-
- mb9afxx1, /* Flash Type '2' */
- mb9afxx2,
- mb9afxx3,
- mb9afxx4,
- mb9afxx5,
- mb9afxx6,
- mb9afxx7,
- mb9afxx8,
-};
-
-enum fm3_flash_type {
- fm3_no_flash_type = 0,
- fm3_flash_type1 = 1,
- fm3_flash_type2 = 2
-};
-
-struct fm3_flash_bank {
- enum fm3_variant variant;
- enum fm3_flash_type flashtype;
- int probed;
-};
-
-FLASH_BANK_COMMAND_HANDLER(fm3_flash_bank_command)
-{
- struct fm3_flash_bank *fm3_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- fm3_info = malloc(sizeof(struct fm3_flash_bank));
- bank->driver_priv = fm3_info;
-
- /* Flash type '1' */
- if (strcmp(CMD_ARGV[5], "mb9bfxx1.cpu") == 0) {
- fm3_info->variant = mb9bfxx1;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9bfxx2.cpu") == 0) {
- fm3_info->variant = mb9bfxx2;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9bfxx3.cpu") == 0) {
- fm3_info->variant = mb9bfxx3;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9bfxx4.cpu") == 0) {
- fm3_info->variant = mb9bfxx4;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9bfxx5.cpu") == 0) {
- fm3_info->variant = mb9bfxx5;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9bfxx6.cpu") == 0) {
- fm3_info->variant = mb9bfxx6;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9bfxx7.cpu") == 0) {
- fm3_info->variant = mb9bfxx7;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9bfxx8.cpu") == 0) {
- fm3_info->variant = mb9bfxx8;
- fm3_info->flashtype = fm3_flash_type1;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx1.cpu") == 0) { /* Flash type '2' */
- fm3_info->variant = mb9afxx1;
- fm3_info->flashtype = fm3_flash_type2;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx2.cpu") == 0) {
- fm3_info->variant = mb9afxx2;
- fm3_info->flashtype = fm3_flash_type2;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx3.cpu") == 0) {
- fm3_info->variant = mb9afxx3;
- fm3_info->flashtype = fm3_flash_type2;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx4.cpu") == 0) {
- fm3_info->variant = mb9afxx4;
- fm3_info->flashtype = fm3_flash_type2;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx5.cpu") == 0) {
- fm3_info->variant = mb9afxx5;
- fm3_info->flashtype = fm3_flash_type2;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx6.cpu") == 0) {
- fm3_info->variant = mb9afxx6;
- fm3_info->flashtype = fm3_flash_type2;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx7.cpu") == 0) {
- fm3_info->variant = mb9afxx7;
- fm3_info->flashtype = fm3_flash_type2;
- } else if (strcmp(CMD_ARGV[5], "mb9afxx8.cpu") == 0) {
- fm3_info->variant = mb9afxx8;
- fm3_info->flashtype = fm3_flash_type2;
- }
-
- /* unknown Flash type */
- else {
- LOG_ERROR("unknown fm3 variant: %s", CMD_ARGV[5]);
- free(fm3_info);
- return ERROR_FLASH_BANK_INVALID;
- }
-
- fm3_info->probed = 0;
-
- return ERROR_OK;
-}
-
-/* Data polling algorithm */
-static int fm3_busy_wait(struct target *target, uint32_t offset, int timeout_ms)
-{
- int retval = ERROR_OK;
- uint8_t state1, state2;
- int ms = 0;
-
- /* While(1) loop exit via "break" and "return" on error */
- while (1) {
- /* dummy-read - see flash manual */
- retval = target_read_u8(target, offset, &state1);
- if (retval != ERROR_OK)
- return retval;
-
- /* Data polling 1 */
- retval = target_read_u8(target, offset, &state1);
- if (retval != ERROR_OK)
- return retval;
-
- /* Data polling 2 */
- retval = target_read_u8(target, offset, &state2);
- if (retval != ERROR_OK)
- return retval;
-
- /* Flash command finished via polled data equal? */
- if ((state1 & FLASH_DQ6) == (state2 & FLASH_DQ6))
- break;
- /* Timeout Flag? */
- else if (state1 & FLASH_DQ5) {
- /* Retry data polling */
-
- /* Data polling 1 */
- retval = target_read_u8(target, offset, &state1);
- if (retval != ERROR_OK)
- return retval;
-
- /* Data polling 2 */
- retval = target_read_u8(target, offset, &state2);
- if (retval != ERROR_OK)
- return retval;
-
- /* Flash command finished via polled data equal? */
- if ((state1 & FLASH_DQ6) != (state2 & FLASH_DQ6))
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* finish anyway */
- break;
- }
- usleep(1000);
- ++ms;
-
- /* Polling time exceeded? */
- if (ms > timeout_ms) {
- LOG_ERROR("Polling data reading timed out!");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
-
- if (retval == ERROR_OK)
- LOG_DEBUG("fm3_busy_wait(%" PRIx32 ") needs about %d ms", offset, ms);
-
- return retval;
-}
-
-static int fm3_erase(struct flash_bank *bank, int first, int last)
-{
- struct fm3_flash_bank *fm3_info = bank->driver_priv;
- struct target *target = bank->target;
- int retval = ERROR_OK;
- uint32_t u32DummyRead;
- int sector, odd;
- uint32_t u32FlashType;
- uint32_t u32FlashSeqAddress1;
- uint32_t u32FlashSeqAddress2;
-
- struct working_area *write_algorithm;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
-
- u32FlashType = (uint32_t) fm3_info->flashtype;
-
- if (u32FlashType == fm3_flash_type1) {
- u32FlashSeqAddress1 = 0x00001550;
- u32FlashSeqAddress2 = 0x00000AA8;
- } else if (u32FlashType == fm3_flash_type2) {
- u32FlashSeqAddress1 = 0x00000AA8;
- u32FlashSeqAddress2 = 0x00000554;
- } else {
- LOG_ERROR("Flash/Device type unknown!");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* RAMCODE used for fm3 Flash sector erase: */
- /* R0 keeps Flash Sequence address 1 (u32FlashSeq1) */
- /* R1 keeps Flash Sequence address 2 (u32FlashSeq2) */
- /* R2 keeps Flash Offset address (ofs) */
- static const uint8_t fm3_flash_erase_sector_code[] = {
- /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
- 0xAA, 0x24, /* MOVS R4, #0xAA */
- 0x04, 0x80, /* STRH R4, [R0, #0] */
- /* *(uint16_t*)u32FlashSeq2 = 0x55; */
- 0x55, 0x23, /* MOVS R3, #0x55 */
- 0x0B, 0x80, /* STRH R3, [R1, #0] */
- /* *(uint16_t*)u32FlashSeq1 = 0x80; */
- 0x80, 0x25, /* MOVS R5, #0x80 */
- 0x05, 0x80, /* STRH R5, [R0, #0] */
- /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
- 0x04, 0x80, /* STRH R4, [R0, #0] */
- /* *(uint16_t*)u32FlashSeq2 = 0x55; */
- 0x0B, 0x80, /* STRH R3, [R1, #0] */
- /* Sector_Erase Command (0x30) */
- /* *(uint16_t*)ofs = 0x30; */
- 0x30, 0x20, /* MOVS R0, #0x30 */
- 0x10, 0x80, /* STRH R0, [R2, #0] */
- /* End Code */
- 0x00, 0xBE, /* BKPT #0 */
- };
-
- LOG_INFO("Fujitsu MB9[A/B]FXXX: Sector Erase ... (%d to %d)", first, last);
-
- /* disable HW watchdog */
- retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, 0x40011008, 0x00000000);
- if (retval != ERROR_OK)
- return retval;
-
- /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash acccess) */
- retval = target_write_u32(target, 0x40000000, 0x0001);
- if (retval != ERROR_OK)
- return retval;
-
- /* dummy read of FASZR */
- retval = target_read_u32(target, 0x40000000, &u32DummyRead);
- if (retval != ERROR_OK)
- return retval;
-
- /* allocate working area with flash sector erase code */
- if (target_alloc_working_area(target, sizeof(fm3_flash_erase_sector_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(fm3_flash_erase_sector_code), fm3_flash_erase_sector_code);
- if (retval != ERROR_OK)
- return retval;
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* u32FlashSeqAddress1 */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* u32FlashSeqAddress2 */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* offset */
-
- /* write code buffer and use Flash sector erase code within fm3 */
- for (sector = first ; sector <= last ; sector++) {
- uint32_t offset = bank->sectors[sector].offset;
-
- for (odd = 0; odd < 2 ; odd++) {
- if (odd)
- offset += 4;
-
- buf_set_u32(reg_params[0].value, 0, 32, u32FlashSeqAddress1);
- buf_set_u32(reg_params[1].value, 0, 32, u32FlashSeqAddress2);
- buf_set_u32(reg_params[2].value, 0, 32, offset);
-
- retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- write_algorithm->address, 0, 100000, &armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing flash erase programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- return retval;
- }
-
- retval = fm3_busy_wait(target, offset, 500);
- if (retval != ERROR_OK)
- return retval;
- }
- bank->sectors[sector].is_erased = 1;
- }
-
- target_free_working_area(target, write_algorithm);
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- /* FASZR = 0x02, Enables CPU Run Mode (32-bit Flash acccess) */
- retval = target_write_u32(target, 0x40000000, 0x0002);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
-
- return retval;
-}
-
-static int fm3_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct fm3_flash_bank *fm3_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t buffer_size = 2048; /* Default minimum value */
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[6];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
- uint32_t u32FlashType;
- uint32_t u32FlashSeqAddress1;
- uint32_t u32FlashSeqAddress2;
-
- /* Increase buffer_size if needed */
- if (buffer_size < (target->working_area_size / 2))
- buffer_size = (target->working_area_size / 2);
-
- u32FlashType = (uint32_t) fm3_info->flashtype;
-
- if (u32FlashType == fm3_flash_type1) {
- u32FlashSeqAddress1 = 0x00001550;
- u32FlashSeqAddress2 = 0x00000AA8;
- } else if (u32FlashType == fm3_flash_type2) {
- u32FlashSeqAddress1 = 0x00000AA8;
- u32FlashSeqAddress2 = 0x00000554;
- } else {
- LOG_ERROR("Flash/Device type unknown!");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* RAMCODE used for fm3 Flash programming: */
- /* R0 keeps source start address (u32Source) */
- /* R1 keeps target start address (u32Target) */
- /* R2 keeps number of halfwords to write (u32Count) */
- /* R3 keeps Flash Sequence address 1 (u32FlashSeq1) */
- /* R4 keeps Flash Sequence address 2 (u32FlashSeq2) */
- /* R5 returns result value (u32FlashResult) */
-
- static const uint8_t fm3_flash_write_code[] = {
- /* fm3_FLASH_IF->FASZ &= 0xFFFD; */
- 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
- 0x2D, 0x68, /* LDR R5, [R5] */
- 0x4F, 0xF6, 0xFD, 0x76, /* MOVW R6, #0xFFFD */
- 0x35, 0x40, /* ANDS R5, R5, R6 */
- 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
- 0x35, 0x60, /* STR R5, [R6] */
- /* fm3_FLASH_IF->FASZ |= 1; */
- 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
- 0x2D, 0x68, /* LDR R5, [R3] */
- 0x55, 0xF0, 0x01, 0x05, /* ORRS.W R5, R5, #1 */
- 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
- 0x35, 0x60, /* STR R5, [R6] */
- /* u32DummyRead = fm3_FLASH_IF->FASZ; */
- 0x28, 0x4D, /* LDR.N R5, ??u32DummyRead */
- 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
- 0x36, 0x68, /* LDR R6, [R6] */
- 0x2E, 0x60, /* STR R6, [R5] */
- /* u32FlashResult = FLASH_WRITE_NO_RESULT */
- 0x26, 0x4D, /* LDR.N R5, ??u32FlashResult */
- 0x00, 0x26, /* MOVS R6, #0 */
- 0x2E, 0x60, /* STR R6, [R5] */
- /* while ((u32Count > 0 ) */
- /* && (u32FlashResult */
- /* == FLASH_WRITE_NO_RESULT)) */
- 0x01, 0x2A, /* L0: CMP R2, #1 */
- 0x2C, 0xDB, /* BLT.N L1 */
- 0x24, 0x4D, /* LDR.N R5, ??u32FlashResult */
- 0x2D, 0x68, /* LDR R5, [R5] */
- 0x00, 0x2D, /* CMP R5, #0 */
- 0x28, 0xD1, /* BNE.N L1 */
- /* *u32FlashSeq1 = FLASH_WRITE_1; */
- 0xAA, 0x25, /* MOVS R5, #0xAA */
- 0x1D, 0x60, /* STR R5, [R3] */
- /* *u32FlashSeq2 = FLASH_WRITE_2; */
- 0x55, 0x25, /* MOVS R5, #0x55 */
- 0x25, 0x60, /* STR R5, [R4] */
- /* *u32FlashSeq1 = FLASH_WRITE_3; */
- 0xA0, 0x25, /* MOVS R5, #0xA0 */
- 0x1D, 0x60, /* STRH R5, [R3] */
- /* *(volatile uint16_t*)u32Target */
- /* = *(volatile uint16_t*)u32Source; */
- 0x05, 0x88, /* LDRH R5, [R0] */
- 0x0D, 0x80, /* STRH R5, [R1] */
- /* while (u32FlashResult */
- /* == FLASH_WRITE_NO_RESTULT) */
- 0x1E, 0x4D, /* L2: LDR.N R5, ??u32FlashResult */
- 0x2D, 0x68, /* LDR R5, [R5] */
- 0x00, 0x2D, /* CMP R5, #0 */
- 0x11, 0xD1, /* BNE.N L3 */
- /* if ((*(volatile uint16_t*)u32Target */
- /* & FLASH_DQ5) == FLASH_DQ5) */
- 0x0D, 0x88, /* LDRH R5, [R1] */
- 0xAD, 0x06, /* LSLS R5, R5, #0x1A */
- 0x02, 0xD5, /* BPL.N L4 */
- /* u32FlashResult = FLASH_WRITE_TIMEOUT */
- 0x1A, 0x4D, /* LDR.N R5, ??u32FlashResult */
- 0x02, 0x26, /* MOVS R6, #2 */
- 0x2E, 0x60, /* STR R6, [R5] */
- /* if ((*(volatile uint16_t *)u32Target */
- /* & FLASH_DQ7) */
- /* == (*(volatile uint16_t*)u32Source */
- /* & FLASH_DQ7)) */
- 0x0D, 0x88, /* L4: LDRH R5, [R1] */
- 0x15, 0xF0, 0x80, 0x05, /* ANDS.W R5, R5, #0x80 */
- 0x06, 0x88, /* LDRH R6, [R0] */
- 0x16, 0xF0, 0x80, 0x06, /* ANDS.W R6, R6, #0x80 */
- 0xB5, 0x42, /* CMP R5, R6 */
- 0xED, 0xD1, /* BNE.N L2 */
- /* u32FlashResult = FLASH_WRITE_OKAY */
- 0x15, 0x4D, /* LDR.N R5, ??u32FlashResult */
- 0x01, 0x26, /* MOVS R6, #1 */
- 0x2E, 0x60, /* STR R6, [R5] */
- 0xE9, 0xE7, /* B.N L2 */
- /* if (u32FlashResult */
- /* != FLASH_WRITE_TIMEOUT) */
- 0x13, 0x4D, /* LDR.N R5, ??u32FlashResult */
- 0x2D, 0x68, /* LDR R5, [R5] */
- 0x02, 0x2D, /* CMP R5, #2 */
- 0x02, 0xD0, /* BEQ.N L5 */
- /* u32FlashResult = FLASH_WRITE_NO_RESULT */
- 0x11, 0x4D, /* LDR.N R5, ??u32FlashResult */
- 0x00, 0x26, /* MOVS R6, #0 */
- 0x2E, 0x60, /* STR R6, [R5] */
- /* u32Count--; */
- 0x52, 0x1E, /* L5: SUBS R2, R2, #1 */
- /* u32Source += 2; */
- 0x80, 0x1C, /* ADDS R0, R0, #2 */
- /* u32Target += 2; */
- 0x89, 0x1C, /* ADDS R1, R1, #2 */
- 0xD0, 0xE7, /* B.N L0 */
- /* fm3_FLASH_IF->FASZ &= 0xFFFE; */
- 0x5F, 0xF0, 0x80, 0x45, /* L1: MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
- 0x2D, 0x68, /* LDR R5, [R5] */
- 0x4F, 0xF6, 0xFE, 0x76, /* MOVW R6, #0xFFFE */
- 0x35, 0x40, /* ANDS R5, R5, R6 */
- 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
- 0x35, 0x60, /* STR R5, [R6] */
- /* fm3_FLASH_IF->FASZ |= 2; */
- 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
- 0x2D, 0x68, /* LDR R5, [R5] */
- 0x55, 0xF0, 0x02, 0x05, /* ORRS.W R5, R5, #2 */
- 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
- 0x35, 0x60, /* STR R5, [R6] */
- /* u32DummyRead = fm3_FLASH_IF->FASZ; */
- 0x04, 0x4D, /* LDR.N R5, ??u32DummyRead */
- 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
- 0x36, 0x68, /* LDR R6, [R6] */
- 0x2E, 0x60, /* STR R6, [R5] */
- /* copy u32FlashResult to R3 for return */
- /* value */
- 0xDF, 0xF8, 0x08, 0x50, /* LDR.W R5, ??u32FlashResult */
- 0x2D, 0x68, /* LDR R5, [R5] */
- /* Breakpoint here */
- 0x00, 0xBE, /* BKPT #0 */
-
- /* The following address pointers assume, that the code is running from */
- /* SRAM basic-address + 8.These address pointers will be patched, if a */
- /* different start address in RAM is used (e.g. for Flash type 2)! */
- /* Default SRAM basic-address is 0x20000000. */
- 0x00, 0x00, 0x00, 0x20, /* u32DummyRead address in RAM (0x20000000) */
- 0x04, 0x00, 0x00, 0x20 /* u32FlashResult address in RAM (0x20000004) */
- };
-
- LOG_INFO("Fujitsu MB9[A/B]FXXX: FLASH Write ...");
-
- /* disable HW watchdog */
- retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, 0x40011008, 0x00000000);
- if (retval != ERROR_OK)
- return retval;
-
- count = count / 2; /* number bytes -> number halfwords */
-
- /* check code alignment */
- if (offset & 0x1) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* allocate working area and variables with flash programming code */
- if (target_alloc_working_area(target, sizeof(fm3_flash_write_code) + 8,
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address + 8,
- sizeof(fm3_flash_write_code), fm3_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* Patching 'local variable address' */
- /* Algorithm: u32DummyRead: */
- retval = target_write_u32(target, (write_algorithm->address + 8)
- + sizeof(fm3_flash_write_code) - 8, (write_algorithm->address));
- if (retval != ERROR_OK)
- return retval;
- /* Algorithm: u32FlashResult: */
- retval = target_write_u32(target, (write_algorithm->address + 8)
- + sizeof(fm3_flash_write_code) - 4, (write_algorithm->address) + 4);
- if (retval != ERROR_OK)
- return retval;
-
-
-
- /* memory buffer */
- while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* free working area, write algorithm already allocated */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("No large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* source start address */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* target start address */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of halfwords to program */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Flash Sequence address 1 */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* Flash Sequence address 1 */
- init_reg_param(&reg_params[5], "r5", 32, PARAM_IN); /* result */
-
- /* write code buffer and use Flash programming code within fm3 */
- /* Set breakpoint to 0 with time-out of 1000 ms */
- while (count > 0) {
- uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
-
- retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
- if (retval != ERROR_OK)
- break;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
- buf_set_u32(reg_params[3].value, 0, 32, u32FlashSeqAddress1);
- buf_set_u32(reg_params[4].value, 0, 32, u32FlashSeqAddress2);
-
- retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
- (write_algorithm->address + 8), 0, 1000, &armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing fm3 Flash programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- if (buf_get_u32(reg_params[5].value, 0, 32) != ERROR_OK) {
- LOG_ERROR("Fujitsu MB9[A/B]FXXX: Flash programming ERROR (Timeout) -> Reg R3: %" PRIx32,
- buf_get_u32(reg_params[5].value, 0, 32));
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- buffer += thisrun_count * 2;
- address += thisrun_count * 2;
- count -= thisrun_count;
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
- destroy_reg_param(&reg_params[5]);
-
- return retval;
-}
-
-static int fm3_probe(struct flash_bank *bank)
-{
- struct fm3_flash_bank *fm3_info = bank->driver_priv;
- uint16_t num_pages;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
-/*
- -- page-- start -- blocksize - mpu - totalFlash --
- page0 0x00000 16k
- page1 0x04000 16k
- page2 0x08000 96k ___ fxx3 128k Flash
- page3 0x20000 128k ___ fxx4 256k Flash
- page4 0x40000 128k ___ fxx5 384k Flash
- page5 0x60000 128k ___ fxx6 512k Flash
------------------------
- page6 0x80000 128k
- page7 0xa0000 128k ___ fxx7 256k Flash
- page8 0xc0000 128k
- page9 0xe0000 128k ___ fxx8 256k Flash
- */
-
- num_pages = 10; /* max number of Flash pages for malloc */
- fm3_info->probed = 0;
-
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
- bank->base = 0x00000000;
- bank->size = 32 * 1024; /* bytes */
-
- bank->sectors[0].offset = 0;
- bank->sectors[0].size = 16 * 1024;
- bank->sectors[0].is_erased = -1;
- bank->sectors[0].is_protected = -1;
-
- bank->sectors[1].offset = 0x4000;
- bank->sectors[1].size = 16 * 1024;
- bank->sectors[1].is_erased = -1;
- bank->sectors[1].is_protected = -1;
-
- if ((fm3_info->variant == mb9bfxx1)
- || (fm3_info->variant == mb9afxx1)) {
- num_pages = 3;
- bank->size = 64 * 1024; /* bytes */
- bank->num_sectors = num_pages;
-
- bank->sectors[2].offset = 0x8000;
- bank->sectors[2].size = 32 * 1024;
- bank->sectors[2].is_erased = -1;
- bank->sectors[2].is_protected = -1;
- }
-
- if ((fm3_info->variant == mb9bfxx2)
- || (fm3_info->variant == mb9bfxx4)
- || (fm3_info->variant == mb9bfxx5)
- || (fm3_info->variant == mb9bfxx6)
- || (fm3_info->variant == mb9bfxx7)
- || (fm3_info->variant == mb9bfxx8)
- || (fm3_info->variant == mb9afxx2)
- || (fm3_info->variant == mb9afxx4)
- || (fm3_info->variant == mb9afxx5)
- || (fm3_info->variant == mb9afxx6)
- || (fm3_info->variant == mb9afxx7)
- || (fm3_info->variant == mb9afxx8)) {
- num_pages = 3;
- bank->size = 128 * 1024; /* bytes */
- bank->num_sectors = num_pages;
-
- bank->sectors[2].offset = 0x8000;
- bank->sectors[2].size = 96 * 1024;
- bank->sectors[2].is_erased = -1;
- bank->sectors[2].is_protected = -1;
- }
-
- if ((fm3_info->variant == mb9bfxx4)
- || (fm3_info->variant == mb9bfxx5)
- || (fm3_info->variant == mb9bfxx6)
- || (fm3_info->variant == mb9bfxx7)
- || (fm3_info->variant == mb9bfxx8)
- || (fm3_info->variant == mb9afxx4)
- || (fm3_info->variant == mb9afxx5)
- || (fm3_info->variant == mb9afxx6)
- || (fm3_info->variant == mb9afxx7)
- || (fm3_info->variant == mb9afxx8)) {
- num_pages = 4;
- bank->size = 256 * 1024; /* bytes */
- bank->num_sectors = num_pages;
-
- bank->sectors[3].offset = 0x20000;
- bank->sectors[3].size = 128 * 1024;
- bank->sectors[3].is_erased = -1;
- bank->sectors[3].is_protected = -1;
- }
-
- if ((fm3_info->variant == mb9bfxx5)
- || (fm3_info->variant == mb9bfxx6)
- || (fm3_info->variant == mb9bfxx7)
- || (fm3_info->variant == mb9bfxx8)
- || (fm3_info->variant == mb9afxx5)
- || (fm3_info->variant == mb9afxx6)
- || (fm3_info->variant == mb9afxx7)
- || (fm3_info->variant == mb9afxx8)) {
- num_pages = 5;
- bank->size = 384 * 1024; /* bytes */
- bank->num_sectors = num_pages;
-
- bank->sectors[4].offset = 0x40000;
- bank->sectors[4].size = 128 * 1024;
- bank->sectors[4].is_erased = -1;
- bank->sectors[4].is_protected = -1;
- }
-
- if ((fm3_info->variant == mb9bfxx6)
- || (fm3_info->variant == mb9bfxx7)
- || (fm3_info->variant == mb9bfxx8)
- || (fm3_info->variant == mb9afxx6)
- || (fm3_info->variant == mb9afxx7)
- || (fm3_info->variant == mb9afxx8)) {
- num_pages = 6;
- bank->size = 512 * 1024; /* bytes */
- bank->num_sectors = num_pages;
-
- bank->sectors[5].offset = 0x60000;
- bank->sectors[5].size = 128 * 1024;
- bank->sectors[5].is_erased = -1;
- bank->sectors[5].is_protected = -1;
- }
-
- if ((fm3_info->variant == mb9bfxx7)
- || (fm3_info->variant == mb9bfxx8)
- || (fm3_info->variant == mb9afxx7)
- || (fm3_info->variant == mb9afxx8)) {
- num_pages = 8;
- bank->size = 768 * 1024; /* bytes */
- bank->num_sectors = num_pages;
-
- bank->sectors[6].offset = 0x80000;
- bank->sectors[6].size = 128 * 1024;
- bank->sectors[6].is_erased = -1;
- bank->sectors[6].is_protected = -1;
-
- bank->sectors[7].offset = 0xa0000;
- bank->sectors[7].size = 128 * 1024;
- bank->sectors[7].is_erased = -1;
- bank->sectors[7].is_protected = -1;
- }
-
- if ((fm3_info->variant == mb9bfxx8)
- || (fm3_info->variant == mb9afxx8)) {
- num_pages = 10;
- bank->size = 1024 * 1024; /* bytes */
- bank->num_sectors = num_pages;
-
- bank->sectors[8].offset = 0xc0000;
- bank->sectors[8].size = 128 * 1024;
- bank->sectors[8].is_erased = -1;
- bank->sectors[8].is_protected = -1;
-
- bank->sectors[9].offset = 0xe0000;
- bank->sectors[9].size = 128 * 1024;
- bank->sectors[9].is_erased = -1;
- bank->sectors[9].is_protected = -1;
- }
-
- fm3_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int fm3_auto_probe(struct flash_bank *bank)
-{
- struct fm3_flash_bank *fm3_info = bank->driver_priv;
- if (fm3_info->probed)
- return ERROR_OK;
- return fm3_probe(bank);
-}
-
-/* Chip erase */
-static int fm3_chip_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct fm3_flash_bank *fm3_info2 = bank->driver_priv;
- int retval = ERROR_OK;
- uint32_t u32DummyRead;
- uint32_t u32FlashType;
- uint32_t u32FlashSeqAddress1;
- uint32_t u32FlashSeqAddress2;
-
- struct working_area *write_algorithm;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
-
- u32FlashType = (uint32_t) fm3_info2->flashtype;
-
- if (u32FlashType == fm3_flash_type1) {
- LOG_INFO("*** Erasing mb9bfxxx type");
- u32FlashSeqAddress1 = 0x00001550;
- u32FlashSeqAddress2 = 0x00000AA8;
- } else if (u32FlashType == fm3_flash_type2) {
- LOG_INFO("*** Erasing mb9afxxx type");
- u32FlashSeqAddress1 = 0x00000AA8;
- u32FlashSeqAddress2 = 0x00000554;
- } else {
- LOG_ERROR("Flash/Device type unknown!");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* RAMCODE used for fm3 Flash chip erase: */
- /* R0 keeps Flash Sequence address 1 (u32FlashSeq1) */
- /* R1 keeps Flash Sequence address 2 (u32FlashSeq2) */
- static const uint8_t fm3_flash_erase_chip_code[] = {
- /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
- 0xAA, 0x22, /* MOVS R2, #0xAA */
- 0x02, 0x80, /* STRH R2, [R0, #0] */
- /* *(uint16_t*)u32FlashSeq2 = 0x55; */
- 0x55, 0x23, /* MOVS R3, #0x55 */
- 0x0B, 0x80, /* STRH R3, [R1, #0] */
- /* *(uint16_t*)u32FlashSeq1 = 0x80; */
- 0x80, 0x24, /* MOVS R4, #0x80 */
- 0x04, 0x80, /* STRH R4, [R0, #0] */
- /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
- 0x02, 0x80, /* STRH R2, [R0, #0] */
- /* *(uint16_t*)u32FlashSeq2 = 0x55; */
- 0x0B, 0x80, /* STRH R3, [R1, #0] */
- /* Chip_Erase Command 0x10 */
- /* *(uint16_t*)u32FlashSeq1 = 0x10; */
- 0x10, 0x21, /* MOVS R1, #0x10 */
- 0x01, 0x80, /* STRH R1, [R0, #0] */
- /* End Code */
- 0x00, 0xBE, /* BKPT #0 */
- };
-
- LOG_INFO("Fujitsu MB9[A/B]xxx: Chip Erase ... (may take several seconds)");
-
- /* disable HW watchdog */
- retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, 0x40011008, 0x00000000);
- if (retval != ERROR_OK)
- return retval;
-
- /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */
- retval = target_write_u32(target, 0x40000000, 0x0001);
- if (retval != ERROR_OK)
- return retval;
-
- /* dummy read of FASZR */
- retval = target_read_u32(target, 0x40000000, &u32DummyRead);
- if (retval != ERROR_OK)
- return retval;
-
- /* allocate working area with flash chip erase code */
- if (target_alloc_working_area(target, sizeof(fm3_flash_erase_chip_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(fm3_flash_erase_chip_code), fm3_flash_erase_chip_code);
- if (retval != ERROR_OK)
- return retval;
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* u32FlashSeqAddress1 */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* u32FlashSeqAddress2 */
-
- buf_set_u32(reg_params[0].value, 0, 32, u32FlashSeqAddress1);
- buf_set_u32(reg_params[1].value, 0, 32, u32FlashSeqAddress2);
-
- retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
- write_algorithm->address, 0, 100000, &armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing flash erase programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- return retval;
- }
-
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
-
- retval = fm3_busy_wait(target, u32FlashSeqAddress2, 20000); /* 20s timeout */
- if (retval != ERROR_OK)
- return retval;
-
- /* FASZR = 0x02, Re-enables CPU Run Mode (32-bit Flash access) */
- retval = target_write_u32(target, 0x40000000, 0x0002);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
-
- return retval;
-}
-
-COMMAND_HANDLER(fm3_handle_chip_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (fm3_chip_erase(bank) == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "fm3 chip erase complete");
- } else {
- command_print(CMD_CTX, "fm3 chip erase failed");
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration fm3_exec_command_handlers[] = {
- {
- .name = "chip_erase",
- .usage = "<bank>",
- .handler = fm3_handle_chip_erase_command,
- .mode = COMMAND_EXEC,
- .help = "Erase entire Flash device.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration fm3_command_handlers[] = {
- {
- .name = "fm3",
- .mode = COMMAND_ANY,
- .help = "fm3 Flash command group",
- .usage = "",
- .chain = fm3_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver fm3_flash = {
- .name = "fm3",
- .commands = fm3_command_handlers,
- .flash_bank_command = fm3_flash_bank_command,
- .erase = fm3_erase,
- .write = fm3_write_block,
- .probe = fm3_probe,
- .auto_probe = fm3_auto_probe,
- .erase_check = default_flash_blank_check,
-};
diff --git a/src/flash/nor/fm4.c b/src/flash/nor/fm4.c
deleted file mode 100644
index c348c1d..0000000
--- a/src/flash/nor/fm4.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * Spansion FM4 flash
- *
- * Copyright (c) 2015 Andreas Färber
- *
- * Based on S6E2DH_MN709-00013 for S6E2DH/DF/D5/D3 series
- * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
- * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
- * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-#define FLASH_BASE 0x40000000
-#define FASZR (FLASH_BASE + 0x000)
-#define DFCTRLR (FLASH_BASE + 0x030)
-#define DFCTRLR_DFE (1UL << 0)
-
-#define WDG_BASE 0x40011000
-#define WDG_CTL (WDG_BASE + 0x008)
-#define WDG_LCK (WDG_BASE + 0xC00)
-
-enum fm4_variant {
- mb9bfx64,
- mb9bfx65,
- mb9bfx66,
- mb9bfx67,
- mb9bfx68,
-
- s6e2cx8,
- s6e2cx9,
- s6e2cxa,
-
- s6e2dx,
-};
-
-struct fm4_flash_bank {
- enum fm4_variant variant;
- int macro_nr;
- bool probed;
-};
-
-static int fm4_disable_hw_watchdog(struct target *target)
-{
- int retval;
-
- retval = target_write_u32(target, WDG_LCK, 0x1ACCE551);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, WDG_LCK, 0xE5331AAE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, WDG_CTL, 0);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int fm4_enter_flash_cpu_programming_mode(struct target *target)
-{
- uint32_t u32_value;
- int retval;
-
- /* FASZR ASZ = CPU programming mode */
- retval = target_write_u32(target, FASZR, 0x00000001);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, FASZR, &u32_value);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int fm4_enter_flash_cpu_rom_mode(struct target *target)
-{
- uint32_t u32_value;
- int retval;
-
- /* FASZR ASZ = CPU ROM mode */
- retval = target_write_u32(target, FASZR, 0x00000002);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, FASZR, &u32_value);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int fm4_flash_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct working_area *workarea;
- struct reg_param reg_params[4];
- struct armv7m_algorithm armv7m_algo;
- unsigned i;
- int retval, sector;
- const uint8_t erase_sector_code[] = {
-#include "../../../contrib/loaders/flash/fm4/erase.inc"
- };
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first, last);
-
- retval = fm4_disable_hw_watchdog(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = fm4_enter_flash_cpu_programming_mode(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_alloc_working_area(target, sizeof(erase_sector_code),
- &workarea);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available.");
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto err_alloc_code;
- }
- retval = target_write_buffer(target, workarea->address,
- sizeof(erase_sector_code), erase_sector_code);
- if (retval != ERROR_OK)
- goto err_write_code;
-
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
-
- 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_IN);
-
- for (sector = first; sector <= last; sector++) {
- uint32_t addr = bank->base + bank->sectors[sector].offset;
- uint32_t result;
-
- buf_set_u32(reg_params[0].value, 0, 32, (addr & ~0xffff) | 0xAA8);
- buf_set_u32(reg_params[1].value, 0, 32, (addr & ~0xffff) | 0x554);
- buf_set_u32(reg_params[2].value, 0, 32, addr);
-
- retval = target_run_algorithm(target,
- 0, NULL,
- ARRAY_SIZE(reg_params), reg_params,
- workarea->address, 0,
- 1000, &armv7m_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing flash sector erase "
- "programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run;
- }
-
- result = buf_get_u32(reg_params[3].value, 0, 32);
- if (result == 2) {
- LOG_ERROR("Timeout error from flash sector erase programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run_ret;
- } else if (result != 0) {
- LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result);
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run_ret;
- } else
- retval = ERROR_OK;
-
- bank->sectors[sector].is_erased = 1;
- }
-
-err_run_ret:
-err_run:
- for (i = 0; i < ARRAY_SIZE(reg_params); i++)
- destroy_reg_param(&reg_params[i]);
-
-err_write_code:
- target_free_working_area(target, workarea);
-
-err_alloc_code:
- if (retval != ERROR_OK)
- fm4_enter_flash_cpu_rom_mode(target);
- else
- retval = fm4_enter_flash_cpu_rom_mode(target);
-
- return retval;
-}
-
-static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t byte_count)
-{
- struct target *target = bank->target;
- struct working_area *code_workarea, *data_workarea;
- struct reg_param reg_params[6];
- struct armv7m_algorithm armv7m_algo;
- uint32_t halfword_count = DIV_ROUND_UP(byte_count, 2);
- uint32_t result;
- unsigned i;
- int retval;
- const uint8_t write_block_code[] = {
-#include "../../../contrib/loaders/flash/fm4/write.inc"
- };
-
- LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32 " (%" PRId32 " bytes)",
- offset, byte_count);
-
- if (offset & 0x1) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment",
- offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
- if (byte_count & 0x1) {
- LOG_WARNING("length %" PRId32 " is not 2-byte aligned, rounding up",
- byte_count);
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = fm4_disable_hw_watchdog(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_alloc_working_area(target, sizeof(write_block_code),
- &code_workarea);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available for write code.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- retval = target_write_buffer(target, code_workarea->address,
- sizeof(write_block_code), write_block_code);
- if (retval != ERROR_OK)
- goto err_write_code;
-
- retval = target_alloc_working_area(target,
- MIN(halfword_count * 2, target_get_working_area_avail(target)),
- &data_workarea);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available for write data.");
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto err_alloc_data;
- }
-
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
-
- 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);
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
- init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);
-
- retval = fm4_enter_flash_cpu_programming_mode(target);
- if (retval != ERROR_OK)
- goto err_flash_mode;
-
- while (byte_count > 0) {
- uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2);
- uint32_t addr = bank->base + offset;
-
- LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32,
- MIN(halfwords * 2, byte_count), data_workarea->address);
-
- retval = target_write_buffer(target, data_workarea->address,
- MIN(halfwords * 2, byte_count), buffer);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error writing data buffer");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_write_data;
- }
-
- LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRId32 "x)",
- addr, addr + halfwords * 2 - 1, halfwords);
-
- buf_set_u32(reg_params[0].value, 0, 32, (addr & ~0xffff) | 0xAA8);
- buf_set_u32(reg_params[1].value, 0, 32, (addr & ~0xffff) | 0x554);
- buf_set_u32(reg_params[2].value, 0, 32, addr);
- buf_set_u32(reg_params[3].value, 0, 32, data_workarea->address);
- buf_set_u32(reg_params[4].value, 0, 32, halfwords);
-
- retval = target_run_algorithm(target,
- 0, NULL,
- ARRAY_SIZE(reg_params), reg_params,
- code_workarea->address, 0,
- 5 * 60 * 1000, &armv7m_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing flash sector erase "
- "programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run;
- }
-
- result = buf_get_u32(reg_params[5].value, 0, 32);
- if (result == 2) {
- LOG_ERROR("Timeout error from flash write "
- "programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run_ret;
- } else if (result != 0) {
- LOG_ERROR("Unexpected error %d from flash write "
- "programming algorithm", result);
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run_ret;
- } else
- retval = ERROR_OK;
-
- halfword_count -= halfwords;
- offset += halfwords * 2;
- buffer += halfwords * 2;
- byte_count -= MIN(halfwords * 2, byte_count);
- }
-
-err_run_ret:
-err_run:
-err_write_data:
- retval = fm4_enter_flash_cpu_rom_mode(target);
-
-err_flash_mode:
- for (i = 0; i < ARRAY_SIZE(reg_params); i++)
- destroy_reg_param(&reg_params[i]);
-
- target_free_working_area(target, data_workarea);
-err_alloc_data:
-err_write_code:
- target_free_working_area(target, code_workarea);
-
- return retval;
-}
-
-static int mb9bf_probe(struct flash_bank *bank)
-{
- struct fm4_flash_bank *fm4_bank = bank->driver_priv;
- uint32_t flash_addr = bank->base;
- int i;
-
- switch (fm4_bank->variant) {
- case mb9bfx64:
- bank->num_sectors = 8;
- break;
- case mb9bfx65:
- bank->num_sectors = 10;
- break;
- case mb9bfx66:
- bank->num_sectors = 12;
- break;
- case mb9bfx67:
- bank->num_sectors = 16;
- break;
- case mb9bfx68:
- bank->num_sectors = 20;
- break;
- default:
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- LOG_DEBUG("%d sectors", bank->num_sectors);
- bank->sectors = calloc(bank->num_sectors,
- sizeof(struct flash_sector));
- for (i = 0; i < bank->num_sectors; i++) {
- if (i < 4)
- bank->sectors[i].size = 8 * 1024;
- else if (i == 4)
- bank->sectors[i].size = 32 * 1024;
- else
- bank->sectors[i].size = 64 * 1024;
- bank->sectors[i].offset = flash_addr - bank->base;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
-
- bank->size += bank->sectors[i].size;
- flash_addr += bank->sectors[i].size;
- }
-
- return ERROR_OK;
-}
-
-static void s6e2cc_init_sector(struct flash_sector *sector, int sa)
-{
- if (sa < 8)
- sector->size = 8 * 1024;
- else if (sa == 8)
- sector->size = 32 * 1024;
- else
- sector->size = 64 * 1024;
-
- sector->is_erased = -1;
- sector->is_protected = -1;
-}
-
-static int s6e2cc_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct fm4_flash_bank *fm4_bank = bank->driver_priv;
- uint32_t u32_value;
- uint32_t flash_addr = bank->base;
- int i, retval, num_sectors, num_extra_sectors;
-
- retval = target_read_u32(target, DFCTRLR, &u32_value);
- if (retval != ERROR_OK)
- return retval;
- if (u32_value & DFCTRLR_DFE) {
- LOG_WARNING("Dual Flash mode is not implemented.");
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- switch (fm4_bank->variant) {
- case s6e2cx8:
- num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 0;
- break;
- case s6e2cx9:
- num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 12;
- break;
- case s6e2cxa:
- num_sectors = 20;
- break;
- default:
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
- num_extra_sectors = (fm4_bank->macro_nr == 0) ? 1 : 4;
- bank->num_sectors = num_sectors + num_extra_sectors;
-
- LOG_DEBUG("%d sectors", bank->num_sectors);
- bank->sectors = calloc(bank->num_sectors,
- sizeof(struct flash_sector));
- for (i = 0; i < num_sectors; i++) {
- int sa = 4 + i;
- bank->sectors[i].offset = flash_addr - bank->base;
- s6e2cc_init_sector(&bank->sectors[i], sa);
-
- bank->size += bank->sectors[i].size;
- flash_addr += bank->sectors[i].size;
- }
-
- flash_addr = (fm4_bank->macro_nr == 0) ? 0x00406000 : 0x00408000;
- for (; i < bank->num_sectors; i++) {
- int sa = 4 - num_extra_sectors + (i - num_sectors);
- bank->sectors[i].offset = flash_addr - bank->base;
- s6e2cc_init_sector(&bank->sectors[i], sa);
-
- /*
- * Don't increase bank->size for these sectors
- * to avoid an overlap between Flash Macros #0 and #1.
- */
- flash_addr += bank->sectors[i].size;
- }
-
- return ERROR_OK;
-}
-
-static int s6e2dh_probe(struct flash_bank *bank)
-{
- uint32_t flash_addr = bank->base;
- int i;
-
- bank->num_sectors = 10;
- bank->sectors = calloc(bank->num_sectors,
- sizeof(struct flash_sector));
- for (i = 0; i < bank->num_sectors; i++) {
- if (i < 4)
- bank->sectors[i].size = 8 * 1024;
- else if (i == 4)
- bank->sectors[i].size = 32 * 1024;
- else
- bank->sectors[i].size = 64 * 1024;
- bank->sectors[i].offset = flash_addr - bank->base;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
-
- bank->size += bank->sectors[i].size;
- flash_addr += bank->sectors[i].size;
- }
-
- return ERROR_OK;
-}
-
-static int fm4_probe(struct flash_bank *bank)
-{
- struct fm4_flash_bank *fm4_bank = bank->driver_priv;
- int retval;
-
- if (fm4_bank->probed)
- return ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- switch (fm4_bank->variant) {
- case mb9bfx64:
- case mb9bfx65:
- case mb9bfx66:
- case mb9bfx67:
- case mb9bfx68:
- retval = mb9bf_probe(bank);
- break;
- case s6e2cx8:
- case s6e2cx9:
- case s6e2cxa:
- retval = s6e2cc_probe(bank);
- break;
- case s6e2dx:
- retval = s6e2dh_probe(bank);
- break;
- default:
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
- if (retval != ERROR_OK)
- return retval;
-
- fm4_bank->probed = true;
-
- return ERROR_OK;
-}
-
-static int fm4_auto_probe(struct flash_bank *bank)
-{
- struct fm4_flash_bank *fm4_bank = bank->driver_priv;
-
- if (fm4_bank->probed)
- return ERROR_OK;
-
- return fm4_probe(bank);
-}
-
-static int fm4_protect_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct fm4_flash_bank *fm4_bank = bank->driver_priv;
- const char *name;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- switch (fm4_bank->variant) {
- case mb9bfx64:
- name = "MB9BFx64";
- break;
- case mb9bfx65:
- name = "MB9BFx65";
- break;
- case mb9bfx66:
- name = "MB9BFx66";
- break;
- case mb9bfx67:
- name = "MB9BFx67";
- break;
- case mb9bfx68:
- name = "MB9BFx68";
- break;
- case s6e2cx8:
- name = "S6E2Cx8";
- break;
- case s6e2cx9:
- name = "S6E2Cx9";
- break;
- case s6e2cxa:
- name = "S6E2CxA";
- break;
- case s6e2dx:
- name = "S6E2Dx";
- break;
- default:
- name = "unknown";
- break;
- }
-
- switch (fm4_bank->variant) {
- case s6e2cx8:
- case s6e2cx9:
- case s6e2cxa:
- snprintf(buf, buf_size, "%s MainFlash Macro #%i",
- name, fm4_bank->macro_nr);
- break;
- default:
- snprintf(buf, buf_size, "%s MainFlash", name);
- break;
- }
-
- return ERROR_OK;
-}
-
-static bool fm4_name_match(const char *s, const char *pattern)
-{
- int i = 0;
-
- while (s[i]) {
- /* If the match string is shorter, ignore excess */
- if (!pattern[i])
- return true;
- /* Use x as wildcard */
- if (pattern[i] != 'x' && tolower(s[i]) != tolower(pattern[i]))
- return false;
- i++;
- }
- return true;
-}
-
-static int mb9bf_bank_setup(struct flash_bank *bank, const char *variant)
-{
- struct fm4_flash_bank *fm4_bank = bank->driver_priv;
-
- if (fm4_name_match(variant, "MB9BFx64")) {
- fm4_bank->variant = mb9bfx64;
- } else if (fm4_name_match(variant, "MB9BFx65")) {
- fm4_bank->variant = mb9bfx65;
- } else if (fm4_name_match(variant, "MB9BFx66")) {
- fm4_bank->variant = mb9bfx66;
- } else if (fm4_name_match(variant, "MB9BFx67")) {
- fm4_bank->variant = mb9bfx67;
- } else if (fm4_name_match(variant, "MB9BFx68")) {
- fm4_bank->variant = mb9bfx68;
- } else {
- LOG_WARNING("MB9BF variant %s not recognized.", variant);
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- return ERROR_OK;
-}
-
-static int s6e2cc_bank_setup(struct flash_bank *bank, const char *variant)
-{
- struct fm4_flash_bank *fm4_bank = bank->driver_priv;
-
- if (fm4_name_match(variant, "S6E2Cx8")) {
- fm4_bank->variant = s6e2cx8;
- } else if (fm4_name_match(variant, "S6E2Cx9")) {
- fm4_bank->variant = s6e2cx9;
- } else if (fm4_name_match(variant, "S6E2CxA")) {
- fm4_bank->variant = s6e2cxa;
- } else {
- LOG_WARNING("S6E2CC variant %s not recognized.", variant);
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command)
-{
- struct fm4_flash_bank *fm4_bank;
- const char *variant;
- int ret;
-
- if (CMD_ARGC < 7)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- variant = CMD_ARGV[6];
-
- fm4_bank = malloc(sizeof(struct fm4_flash_bank));
- if (!fm4_bank)
- return ERROR_FLASH_OPERATION_FAILED;
-
- fm4_bank->probed = false;
- fm4_bank->macro_nr = (bank->base == 0x00000000) ? 0 : 1;
-
- bank->driver_priv = fm4_bank;
-
- if (fm4_name_match(variant, "MB9BF"))
- ret = mb9bf_bank_setup(bank, variant);
- else if (fm4_name_match(variant, "S6E2Cx"))
- ret = s6e2cc_bank_setup(bank, variant);
- else if (fm4_name_match(variant, "S6E2Dx")) {
- fm4_bank->variant = s6e2dx;
- ret = ERROR_OK;
- } else {
- LOG_WARNING("Family %s not recognized.", variant);
- ret = ERROR_FLASH_OPER_UNSUPPORTED;
- }
- if (ret != ERROR_OK)
- free(fm4_bank);
- return ret;
-}
-
-static const struct command_registration fm4_exec_command_handlers[] = {
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration fm4_command_handlers[] = {
- {
- .name = "fm4",
- .mode = COMMAND_ANY,
- .help = "fm4 flash command group",
- .usage = "",
- .chain = fm4_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver fm4_flash = {
- .name = "fm4",
- .commands = fm4_command_handlers,
- .flash_bank_command = fm4_flash_bank_command,
- .info = fm4_get_info_command,
- .probe = fm4_probe,
- .auto_probe = fm4_auto_probe,
- .protect_check = fm4_protect_check,
- .read = default_flash_read,
- .erase = fm4_flash_erase,
- .erase_check = default_flash_blank_check,
- .write = fm4_flash_write,
-};
diff --git a/src/flash/nor/imp.h b/src/flash/nor/imp.h
deleted file mode 100644
index 87475a3..0000000
--- a/src/flash/nor/imp.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NOR_IMP_H
-#define OPENOCD_FLASH_NOR_IMP_H
-
-/* this is an internal header */
-#include "core.h"
-#include "driver.h"
-/* almost all drivers will need this file */
-#include <target/target.h>
-
-/**
- * Adds a new NOR bank to the global list of banks.
- * @param bank The bank that should be added.
- */
-void flash_bank_add(struct flash_bank *bank);
-
-/**
- * @return The first bank in the global list.
- */
-struct flash_bank *flash_bank_list(void);
-
-int flash_driver_erase(struct flash_bank *bank, int first, int last);
-int flash_driver_protect(struct flash_bank *bank, int set, int first, int last);
-int flash_driver_write(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count);
-int flash_driver_read(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count);
-
-/* write (optional verify) an image to flash memory of the given target */
-int flash_write_unlock(struct target *target, struct image *image,
- uint32_t *written, int erase, bool unlock);
-
-#endif /* OPENOCD_FLASH_NOR_IMP_H */
diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c
deleted file mode 100644
index a995fc7..0000000
--- a/src/flash/nor/jtagspi.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 Robert Jordens <jordens@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <jtag/jtag.h>
-#include <flash/nor/spi.h>
-#include <helper/time_support.h>
-
-#define JTAGSPI_MAX_TIMEOUT 3000
-
-
-struct jtagspi_flash_bank {
- struct jtag_tap *tap;
- const struct flash_device *dev;
- int probed;
- uint32_t ir;
- uint32_t dr_len;
-};
-
-FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
-{
- struct jtagspi_flash_bank *info;
-
- if (CMD_ARGC < 8)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- info = malloc(sizeof(struct jtagspi_flash_bank));
- if (info == NULL) {
- LOG_ERROR("no memory for flash bank info");
- return ERROR_FAIL;
- }
- bank->driver_priv = info;
-
- info->tap = NULL;
- info->probed = 0;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[7], info->dr_len);
-
- return ERROR_OK;
-}
-
-static void jtagspi_set_ir(struct flash_bank *bank)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
- struct scan_field field;
- uint8_t buf[4];
-
- if (buf_get_u32(info->tap->cur_instr, 0, info->tap->ir_length) == info->ir)
- return;
-
- LOG_DEBUG("loading jtagspi ir");
- buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
- field.num_bits = info->tap->ir_length;
- field.out_value = buf;
- field.in_value = NULL;
- jtag_add_ir_scan(info->tap, &field, TAP_IDLE);
-}
-
-static void flip_u8(uint8_t *in, uint8_t *out, int len)
-{
- for (int i = 0; i < len; i++)
- out[i] = flip_u32(in[i], 8);
-}
-
-static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
- uint32_t *addr, uint8_t *data, int len)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
- struct scan_field fields[3];
- uint8_t cmd_buf[4];
- uint8_t *data_buf;
- int is_read, lenb, n;
-
- /* LOG_DEBUG("cmd=0x%02x len=%i", cmd, len); */
-
- n = 0;
- fields[n].num_bits = 8;
- cmd_buf[0] = cmd;
- if (addr) {
- h_u24_to_be(cmd_buf + 1, *addr);
- fields[n].num_bits += 24;
- }
- flip_u8(cmd_buf, cmd_buf, 4);
- fields[n].out_value = cmd_buf;
- fields[n].in_value = NULL;
- n++;
-
- is_read = (len < 0);
- if (is_read)
- len = -len;
- lenb = DIV_ROUND_UP(len, 8);
- data_buf = malloc(lenb);
- if (lenb > 0) {
- if (data_buf == NULL) {
- LOG_ERROR("no memory for spi buffer");
- return ERROR_FAIL;
- }
- if (is_read) {
- fields[n].num_bits = info->dr_len;
- fields[n].out_value = NULL;
- fields[n].in_value = NULL;
- n++;
- fields[n].out_value = NULL;
- fields[n].in_value = data_buf;
- } else {
- flip_u8(data, data_buf, lenb);
- fields[n].out_value = data_buf;
- fields[n].in_value = NULL;
- }
- fields[n].num_bits = len;
- n++;
- }
-
- jtagspi_set_ir(bank);
- jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
- jtag_execute_queue();
-
- if (is_read)
- flip_u8(data_buf, data, lenb);
- free(data_buf);
- return ERROR_OK;
-}
-
-static int jtagspi_probe(struct flash_bank *bank)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
- struct flash_sector *sectors;
- uint8_t in_buf[3];
- uint32_t id;
-
- if (info->probed)
- free(bank->sectors);
- info->probed = 0;
-
- if (bank->target->tap == NULL) {
- LOG_ERROR("Target has no JTAG tap");
- return ERROR_FAIL;
- }
- info->tap = bank->target->tap;
-
- jtagspi_cmd(bank, SPIFLASH_READ_ID, NULL, in_buf, -24);
- /* the table in spi.c has the manufacturer byte (first) as the lsb */
- id = le_to_h_u24(in_buf);
-
- 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;
-
- /* create and fill sectors array */
- bank->num_sectors =
- info->dev->size_in_bytes / info->dev->sectorsize;
- sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- if (sectors == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- for (int sector = 0; sector < bank->num_sectors; sector++) {
- sectors[sector].offset = sector * info->dev->sectorsize;
- sectors[sector].size = info->dev->sectorsize;
- sectors[sector].is_erased = -1;
- sectors[sector].is_protected = 0;
- }
-
- bank->sectors = sectors;
- info->probed = 1;
- return ERROR_OK;
-}
-
-static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
-{
- uint8_t buf;
- jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8);
- *status = buf;
- /* LOG_DEBUG("status=0x%08" PRIx32, *status); */
-}
-
-static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
-{
- uint32_t status;
- int64_t t0 = timeval_ms();
- int64_t dt;
-
- do {
- dt = timeval_ms() - t0;
- jtagspi_read_status(bank, &status);
- if ((status & SPIFLASH_BSY_BIT) == 0) {
- LOG_DEBUG("waited %" PRId64 " ms", dt);
- return ERROR_OK;
- }
- alive_sleep(1);
- } while (dt <= timeout_ms);
-
- LOG_ERROR("timeout, device still busy");
- return ERROR_FAIL;
-}
-
-static int jtagspi_write_enable(struct flash_bank *bank)
-{
- uint32_t status;
-
- jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
- jtagspi_read_status(bank, &status);
- if ((status & SPIFLASH_WE_BIT) == 0) {
- LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int jtagspi_bulk_erase(struct flash_bank *bank)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
- int retval;
- int64_t t0 = timeval_ms();
-
- retval = jtagspi_write_enable(bank);
- if (retval != ERROR_OK)
- return retval;
- jtagspi_cmd(bank, info->dev->chip_erase_cmd, NULL, NULL, 0);
- retval = jtagspi_wait(bank, bank->num_sectors*JTAGSPI_MAX_TIMEOUT);
- LOG_INFO("took %" PRId64 " ms", timeval_ms() - t0);
- return retval;
-}
-
-static int jtagspi_sector_erase(struct flash_bank *bank, int sector)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
- int retval;
- int64_t t0 = timeval_ms();
-
- retval = jtagspi_write_enable(bank);
- if (retval != ERROR_OK)
- return retval;
- jtagspi_cmd(bank, info->dev->erase_cmd, &bank->sectors[sector].offset, NULL, 0);
- retval = jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
- LOG_INFO("sector %d took %" PRId64 " ms", sector, timeval_ms() - t0);
- return retval;
-}
-
-static int jtagspi_erase(struct flash_bank *bank, int first, int last)
-{
- int sector;
- struct jtagspi_flash_bank *info = bank->driver_priv;
- int retval = ERROR_OK;
-
- LOG_DEBUG("erase from sector %d to sector %d", first, last);
-
- 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;
- }
-
- for (sector = first; sector <= last; sector++) {
- if (bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- if (first == 0 && last == (bank->num_sectors - 1)
- && info->dev->chip_erase_cmd != info->dev->erase_cmd) {
- LOG_DEBUG("Trying bulk erase.");
- retval = jtagspi_bulk_erase(bank);
- if (retval == ERROR_OK)
- return retval;
- else
- LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
- }
-
- for (sector = first; sector <= last; sector++) {
- retval = jtagspi_sector_erase(bank, sector);
- if (retval != ERROR_OK) {
- LOG_ERROR("Sector erase failed.");
- break;
- }
- }
-
- return retval;
-}
-
-static int jtagspi_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int sector;
-
- if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
- LOG_ERROR("Flash sector invalid");
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- for (sector = first; sector <= last; sector++)
- bank->sectors[sector].is_protected = set;
- return ERROR_OK;
-}
-
-static int jtagspi_protect_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-static int jtagspi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
-
- if (!(info->probed)) {
- LOG_ERROR("Flash bank not yet probed.");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- jtagspi_cmd(bank, SPIFLASH_READ, &offset, buffer, -count*8);
- return ERROR_OK;
-}
-
-static int jtagspi_page_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- int retval;
-
- retval = jtagspi_write_enable(bank);
- if (retval != ERROR_OK)
- return retval;
- jtagspi_cmd(bank, SPIFLASH_PAGE_PROGRAM, &offset, (uint8_t *) buffer, count*8);
- return jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
-}
-
-static int jtagspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
- int retval;
- uint32_t n;
-
- if (!(info->probed)) {
- LOG_ERROR("Flash bank not yet probed.");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- for (n = 0; n < count; n += info->dev->pagesize) {
- retval = jtagspi_page_write(bank, buffer + n, offset + n,
- MIN(count - n, info->dev->pagesize));
- if (retval != ERROR_OK) {
- LOG_ERROR("page write error");
- return retval;
- }
- LOG_DEBUG("wrote page at 0x%08" PRIx32, offset + n);
- }
- return ERROR_OK;
-}
-
-static int jtagspi_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct jtagspi_flash_bank *info = bank->driver_priv;
-
- if (!(info->probed)) {
- snprintf(buf, buf_size, "\nJTAGSPI flash bank not probed yet\n");
- return ERROR_OK;
- }
-
- snprintf(buf, buf_size, "\nSPIFI flash information:\n"
- " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
- info->dev->name, info->dev->device_id);
-
- return ERROR_OK;
-}
-
-struct flash_driver jtagspi_flash = {
- .name = "jtagspi",
- .flash_bank_command = jtagspi_flash_bank_command,
- .erase = jtagspi_erase,
- .protect = jtagspi_protect,
- .write = jtagspi_write,
- .read = jtagspi_read,
- .probe = jtagspi_probe,
- .auto_probe = jtagspi_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = jtagspi_protect_check,
- .info = jtagspi_info
-};
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
deleted file mode 100644
index e9cf8fa..0000000
--- a/src/flash/nor/kinetis.c
+++ /dev/null
@@ -1,2423 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * kesmtp@freenet.de *
- * *
- * Copyright (C) 2011 sleep(5) ltd *
- * tomas@sleepfive.com *
- * *
- * Copyright (C) 2012 by Christopher D. Kilgour *
- * techie at whiterocker.com *
- * *
- * Copyright (C) 2013 Nemui Trinomius *
- * nemuisan_kawausogasuki@live.jp *
- * *
- * Copyright (C) 2015 Tomas Vanek *
- * vanekt@fbl.cz *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <helper/time_support.h>
-#include <target/target_type.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-#include <target/cortex_m.h>
-
-/*
- * Implementation Notes
- *
- * The persistent memories in the Kinetis chip families K10 through
- * K70 are all manipulated with the Flash Memory Module. Some
- * variants call this module the FTFE, others call it the FTFL. To
- * indicate that both are considered here, we use FTFX.
- *
- * Within the module, according to the chip variant, the persistent
- * memory is divided into what Freescale terms Program Flash, FlexNVM,
- * and FlexRAM. All chip variants have Program Flash. Some chip
- * variants also have FlexNVM and FlexRAM, which always appear
- * together.
- *
- * A given Kinetis chip may have 1, 2 or 4 blocks of flash. Here we map
- * each block to a separate bank. Each block size varies by chip and
- * may be determined by the read-only SIM_FCFG1 register. The sector
- * size within each bank/block varies by chip, and may be 1, 2 or 4k.
- * The sector size may be different for flash and FlexNVM.
- *
- * The first half of the flash (1 or 2 blocks) is always Program Flash
- * and always starts at address 0x00000000. The "PFLSH" flag, bit 23
- * of the read-only SIM_FCFG2 register, determines whether the second
- * half of the flash is also Program Flash or FlexNVM+FlexRAM. When
- * PFLSH is set, the second from the first half. When PFLSH is clear,
- * the second half of flash is FlexNVM and always starts at address
- * 0x10000000. FlexRAM, which is also present when PFLSH is clear,
- * always starts at address 0x14000000.
- *
- * The Flash Memory Module provides a register set where flash
- * commands are loaded to perform flash operations like erase and
- * program. Different commands are available depending on whether
- * Program Flash or FlexNVM/FlexRAM is being manipulated. Although
- * the commands used are quite consistent between flash blocks, the
- * parameters they accept differ according to the flash sector size.
- *
- */
-
-/* Addressess */
-#define FCF_ADDRESS 0x00000400
-#define FCF_FPROT 0x8
-#define FCF_FSEC 0xc
-#define FCF_FOPT 0xd
-#define FCF_FDPROT 0xf
-#define FCF_SIZE 0x10
-
-#define FLEXRAM 0x14000000
-
-#define FMC_PFB01CR 0x4001f004
-#define FTFx_FSTAT 0x40020000
-#define FTFx_FCNFG 0x40020001
-#define FTFx_FCCOB3 0x40020004
-#define FTFx_FPROT3 0x40020010
-#define FTFx_FDPROT 0x40020017
-#define SIM_SDID 0x40048024
-#define SIM_SOPT1 0x40047000
-#define SIM_FCFG1 0x4004804c
-#define SIM_FCFG2 0x40048050
-#define WDOG_STCTRH 0x40052000
-#define SMC_PMCTRL 0x4007E001
-#define SMC_PMSTAT 0x4007E003
-
-/* Values */
-#define PM_STAT_RUN 0x01
-#define PM_STAT_VLPR 0x04
-#define PM_CTRL_RUNM_RUN 0x00
-
-/* Commands */
-#define FTFx_CMD_BLOCKSTAT 0x00
-#define FTFx_CMD_SECTSTAT 0x01
-#define FTFx_CMD_LWORDPROG 0x06
-#define FTFx_CMD_SECTERASE 0x09
-#define FTFx_CMD_SECTWRITE 0x0b
-#define FTFx_CMD_MASSERASE 0x44
-#define FTFx_CMD_PGMPART 0x80
-#define FTFx_CMD_SETFLEXRAM 0x81
-
-/* The older Kinetis K series uses the following SDID layout :
- * Bit 31-16 : 0
- * Bit 15-12 : REVID
- * Bit 11-7 : DIEID
- * Bit 6-4 : FAMID
- * Bit 3-0 : PINID
- *
- * The newer Kinetis series uses the following SDID layout :
- * Bit 31-28 : FAMID
- * Bit 27-24 : SUBFAMID
- * Bit 23-20 : SERIESID
- * Bit 19-16 : SRAMSIZE
- * Bit 15-12 : REVID
- * Bit 6-4 : Reserved (0)
- * Bit 3-0 : PINID
- *
- * We assume that if bits 31-16 are 0 then it's an older
- * K-series MCU.
- */
-
-#define KINETIS_SOPT1_RAMSIZE_MASK 0x0000F000
-#define KINETIS_SOPT1_RAMSIZE_K24FN1M 0x0000B000
-
-#define KINETIS_SDID_K_SERIES_MASK 0x0000FFFF
-
-#define KINETIS_SDID_DIEID_MASK 0x00000F80
-
-#define KINETIS_SDID_DIEID_K22FN128 0x00000680 /* smaller pflash with FTFA */
-#define KINETIS_SDID_DIEID_K22FN256 0x00000A80
-#define KINETIS_SDID_DIEID_K22FN512 0x00000E80
-#define KINETIS_SDID_DIEID_K24FN256 0x00000700
-
-#define KINETIS_SDID_DIEID_K24FN1M 0x00000300 /* Detect Errata 7534 */
-
-/* We can't rely solely on the FAMID field to determine the MCU
- * type since some FAMID values identify multiple MCUs with
- * different flash sector sizes (K20 and K22 for instance).
- * Therefore we combine it with the DIEID bits which may possibly
- * break if Freescale bumps the DIEID for a particular MCU. */
-#define KINETIS_K_SDID_TYPE_MASK 0x00000FF0
-#define KINETIS_K_SDID_K10_M50 0x00000000
-#define KINETIS_K_SDID_K10_M72 0x00000080
-#define KINETIS_K_SDID_K10_M100 0x00000100
-#define KINETIS_K_SDID_K10_M120 0x00000180
-#define KINETIS_K_SDID_K11 0x00000220
-#define KINETIS_K_SDID_K12 0x00000200
-#define KINETIS_K_SDID_K20_M50 0x00000010
-#define KINETIS_K_SDID_K20_M72 0x00000090
-#define KINETIS_K_SDID_K20_M100 0x00000110
-#define KINETIS_K_SDID_K20_M120 0x00000190
-#define KINETIS_K_SDID_K21_M50 0x00000230
-#define KINETIS_K_SDID_K21_M120 0x00000330
-#define KINETIS_K_SDID_K22_M50 0x00000210
-#define KINETIS_K_SDID_K22_M120 0x00000310
-#define KINETIS_K_SDID_K30_M72 0x000000A0
-#define KINETIS_K_SDID_K30_M100 0x00000120
-#define KINETIS_K_SDID_K40_M72 0x000000B0
-#define KINETIS_K_SDID_K40_M100 0x00000130
-#define KINETIS_K_SDID_K50_M72 0x000000E0
-#define KINETIS_K_SDID_K51_M72 0x000000F0
-#define KINETIS_K_SDID_K53 0x00000170
-#define KINETIS_K_SDID_K60_M100 0x00000140
-#define KINETIS_K_SDID_K60_M150 0x000001C0
-#define KINETIS_K_SDID_K70_M150 0x000001D0
-
-#define KINETIS_SDID_SERIESID_MASK 0x00F00000
-#define KINETIS_SDID_SERIESID_K 0x00000000
-#define KINETIS_SDID_SERIESID_KL 0x00100000
-#define KINETIS_SDID_SERIESID_KW 0x00500000
-#define KINETIS_SDID_SERIESID_KV 0x00600000
-
-#define KINETIS_SDID_SUBFAMID_MASK 0x0F000000
-#define KINETIS_SDID_SUBFAMID_KX0 0x00000000
-#define KINETIS_SDID_SUBFAMID_KX1 0x01000000
-#define KINETIS_SDID_SUBFAMID_KX2 0x02000000
-#define KINETIS_SDID_SUBFAMID_KX3 0x03000000
-#define KINETIS_SDID_SUBFAMID_KX4 0x04000000
-#define KINETIS_SDID_SUBFAMID_KX5 0x05000000
-#define KINETIS_SDID_SUBFAMID_KX6 0x06000000
-
-#define KINETIS_SDID_FAMILYID_MASK 0xF0000000
-#define KINETIS_SDID_FAMILYID_K0X 0x00000000
-#define KINETIS_SDID_FAMILYID_K1X 0x10000000
-#define KINETIS_SDID_FAMILYID_K2X 0x20000000
-#define KINETIS_SDID_FAMILYID_K3X 0x30000000
-#define KINETIS_SDID_FAMILYID_K4X 0x40000000
-#define KINETIS_SDID_FAMILYID_K6X 0x60000000
-#define KINETIS_SDID_FAMILYID_K7X 0x70000000
-
-struct kinetis_flash_bank {
- bool probed;
- uint32_t sector_size;
- uint32_t max_flash_prog_size;
- uint32_t protection_size;
- uint32_t prog_base; /* base address for FTFx operations */
- /* same as bank->base for pflash, differs for FlexNVM */
- uint32_t protection_block; /* number of first protection block in this bank */
-
- uint32_t sim_sdid;
- uint32_t sim_fcfg1;
- uint32_t sim_fcfg2;
-
- enum {
- FC_AUTO = 0,
- FC_PFLASH,
- FC_FLEX_NVM,
- FC_FLEX_RAM,
- } flash_class;
-
- enum {
- FS_PROGRAM_SECTOR = 1,
- FS_PROGRAM_LONGWORD = 2,
- FS_PROGRAM_PHRASE = 4, /* Unsupported */
- FS_INVALIDATE_CACHE = 8,
- } flash_support;
-};
-
-#define MDM_AP 1
-
-#define MDM_REG_STAT 0x00
-#define MDM_REG_CTRL 0x04
-#define MDM_REG_ID 0xfc
-
-#define MDM_STAT_FMEACK (1<<0)
-#define MDM_STAT_FREADY (1<<1)
-#define MDM_STAT_SYSSEC (1<<2)
-#define MDM_STAT_SYSRES (1<<3)
-#define MDM_STAT_FMEEN (1<<5)
-#define MDM_STAT_BACKDOOREN (1<<6)
-#define MDM_STAT_LPEN (1<<7)
-#define MDM_STAT_VLPEN (1<<8)
-#define MDM_STAT_LLSMODEXIT (1<<9)
-#define MDM_STAT_VLLSXMODEXIT (1<<10)
-#define MDM_STAT_CORE_HALTED (1<<16)
-#define MDM_STAT_CORE_SLEEPDEEP (1<<17)
-#define MDM_STAT_CORESLEEPING (1<<18)
-
-#define MDM_CTRL_FMEIP (1<<0)
-#define MDM_CTRL_DBG_DIS (1<<1)
-#define MDM_CTRL_DBG_REQ (1<<2)
-#define MDM_CTRL_SYS_RES_REQ (1<<3)
-#define MDM_CTRL_CORE_HOLD_RES (1<<4)
-#define MDM_CTRL_VLLSX_DBG_REQ (1<<5)
-#define MDM_CTRL_VLLSX_DBG_ACK (1<<6)
-#define MDM_CTRL_VLLSX_STAT_ACK (1<<7)
-
-#define MDM_ACCESS_TIMEOUT 500 /* msec */
-
-
-static bool allow_fcf_writes;
-static uint8_t fcf_fopt = 0xff;
-
-
-struct flash_driver kinetis_flash;
-static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count);
-static int kinetis_auto_probe(struct flash_bank *bank);
-
-
-static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
-{
- int retval;
- LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value);
-
- retval = dap_queue_ap_write(dap_ap(dap, MDM_AP), reg, value);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: failed to queue a write request");
- return retval;
- }
-
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: dap_run failed");
- return retval;
- }
-
-
- return ERROR_OK;
-}
-
-static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
-{
- int retval;
-
- retval = dap_queue_ap_read(dap_ap(dap, MDM_AP), reg, result);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: failed to queue a read request");
- return retval;
- }
-
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: dap_run failed");
- return retval;
- }
-
- LOG_DEBUG("MDM_REG[0x%02x]: %08" PRIX32, reg, *result);
- return ERROR_OK;
-}
-
-static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned reg,
- uint32_t mask, uint32_t value, uint32_t timeout_ms)
-{
- uint32_t val;
- int retval;
- int64_t ms_timeout = timeval_ms() + timeout_ms;
-
- do {
- retval = kinetis_mdm_read_register(dap, reg, &val);
- if (retval != ERROR_OK || (val & mask) == value)
- return retval;
-
- alive_sleep(1);
- } while (timeval_ms() < ms_timeout);
-
- LOG_DEBUG("MDM: polling timed out");
- return ERROR_FAIL;
-}
-
-/*
- * This command can be used to break a watchdog reset loop when
- * connecting to an unsecured target. Unlike other commands, halt will
- * automatically retry as it does not know how far into the boot process
- * it is when the command is called.
- */
-COMMAND_HANDLER(kinetis_mdm_halt)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
- int retval;
- int tries = 0;
- uint32_t stat;
- int64_t ms_timeout = timeval_ms() + MDM_ACCESS_TIMEOUT;
-
- if (!dap) {
- LOG_ERROR("Cannot perform halt with a high-level adapter");
- return ERROR_FAIL;
- }
-
- while (true) {
- tries++;
-
- kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_CORE_HOLD_RES);
-
- alive_sleep(1);
-
- retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &stat);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: failed to read MDM_REG_STAT");
- continue;
- }
-
- /* Repeat setting MDM_CTRL_CORE_HOLD_RES until system is out of
- * reset with flash ready and without security
- */
- if ((stat & (MDM_STAT_FREADY | MDM_STAT_SYSSEC | MDM_STAT_SYSRES))
- == (MDM_STAT_FREADY | MDM_STAT_SYSRES))
- break;
-
- if (timeval_ms() >= ms_timeout) {
- LOG_ERROR("MDM: halt timed out");
- return ERROR_FAIL;
- }
- }
-
- LOG_DEBUG("MDM: halt succeded after %d attempts.", tries);
-
- target_poll(target);
- /* enable polling in case kinetis_check_flash_security_status disabled it */
- jtag_poll_set_enabled(true);
-
- alive_sleep(100);
-
- target->reset_halt = true;
- target->type->assert_reset(target);
-
- retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to clear MDM_REG_CTRL");
- return retval;
- }
-
- target->type->deassert_reset(target);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(kinetis_mdm_reset)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
- int retval;
-
- if (!dap) {
- LOG_ERROR("Cannot perform reset with a high-level adapter");
- return ERROR_FAIL;
- }
-
- retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_SYS_RES_REQ);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to write MDM_REG_CTRL");
- return retval;
- }
-
- retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, MDM_STAT_SYSRES, 0, 500);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to assert reset");
- return retval;
- }
-
- retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to clear MDM_REG_CTRL");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-/*
- * This function implements the procedure to mass erase the flash via
- * SWD/JTAG on Kinetis K and L series of devices as it is described in
- * AN4835 "Production Flash Programming Best Practices for Kinetis K-
- * and L-series MCUs" Section 4.2.1. To prevent a watchdog reset loop,
- * the core remains halted after this function completes as suggested
- * by the application note.
- */
-COMMAND_HANDLER(kinetis_mdm_mass_erase)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
-
- if (!dap) {
- LOG_ERROR("Cannot perform mass erase with a high-level adapter");
- return ERROR_FAIL;
- }
-
- int retval;
-
- /*
- * ... Power on the processor, or if power has already been
- * applied, assert the RESET pin to reset the processor. For
- * devices that do not have a RESET pin, write the System
- * Reset Request bit in the MDM-AP control register after
- * establishing communication...
- */
-
- /* assert SRST if configured */
- bool has_srst = jtag_get_reset_config() & RESET_HAS_SRST;
- if (has_srst)
- adapter_assert_reset();
-
- retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_SYS_RES_REQ);
- if (retval != ERROR_OK && !has_srst) {
- LOG_ERROR("MDM: failed to assert reset");
- goto deassert_reset_and_exit;
- }
-
- /*
- * ... Read the MDM-AP status register repeatedly and wait for
- * stable conditions suitable for mass erase:
- * - mass erase is enabled
- * - flash is ready
- * - reset is finished
- *
- * Mass erase is started as soon as all conditions are met in 32
- * subsequent status reads.
- *
- * In case of not stable conditions (RESET/WDOG loop in secured device)
- * the user is asked for manual pressing of RESET button
- * as a last resort.
- */
- int cnt_mass_erase_disabled = 0;
- int cnt_ready = 0;
- int64_t ms_start = timeval_ms();
- bool man_reset_requested = false;
-
- do {
- uint32_t stat = 0;
- int64_t ms_elapsed = timeval_ms() - ms_start;
-
- if (!man_reset_requested && ms_elapsed > 100) {
- LOG_INFO("MDM: Press RESET button now if possible.");
- man_reset_requested = true;
- }
-
- if (ms_elapsed > 3000) {
- LOG_ERROR("MDM: waiting for mass erase conditions timed out.");
- LOG_INFO("Mass erase of a secured MCU is not possible without hardware reset.");
- LOG_INFO("Connect SRST, use 'reset_config srst_only' and retry.");
- goto deassert_reset_and_exit;
- }
- retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &stat);
- if (retval != ERROR_OK) {
- cnt_ready = 0;
- continue;
- }
-
- if (!(stat & MDM_STAT_FMEEN)) {
- cnt_ready = 0;
- cnt_mass_erase_disabled++;
- if (cnt_mass_erase_disabled > 10) {
- LOG_ERROR("MDM: mass erase is disabled");
- goto deassert_reset_and_exit;
- }
- continue;
- }
-
- if ((stat & (MDM_STAT_FREADY | MDM_STAT_SYSRES)) == MDM_STAT_FREADY)
- cnt_ready++;
- else
- cnt_ready = 0;
-
- } while (cnt_ready < 32);
-
- /*
- * ... Write the MDM-AP control register to set the Flash Mass
- * Erase in Progress bit. This will start the mass erase
- * process...
- */
- retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_SYS_RES_REQ | MDM_CTRL_FMEIP);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to start mass erase");
- goto deassert_reset_and_exit;
- }
-
- /*
- * ... Read the MDM-AP control register until the Flash Mass
- * Erase in Progress bit clears...
- * Data sheed defines erase time <3.6 sec/512kB flash block.
- * The biggest device has 4 pflash blocks => timeout 16 sec.
- */
- retval = kinetis_mdm_poll_register(dap, MDM_REG_CTRL, MDM_CTRL_FMEIP, 0, 16000);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: mass erase timeout");
- goto deassert_reset_and_exit;
- }
-
- target_poll(target);
- /* enable polling in case kinetis_check_flash_security_status disabled it */
- jtag_poll_set_enabled(true);
-
- alive_sleep(100);
-
- target->reset_halt = true;
- target->type->assert_reset(target);
-
- /*
- * ... Negate the RESET signal or clear the System Reset Request
- * bit in the MDM-AP control register.
- */
- retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0);
- if (retval != ERROR_OK)
- LOG_ERROR("MDM: failed to clear MDM_REG_CTRL");
-
- target->type->deassert_reset(target);
-
- return retval;
-
-deassert_reset_and_exit:
- kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0);
- if (has_srst)
- adapter_deassert_reset();
- return retval;
-}
-
-static const uint32_t kinetis_known_mdm_ids[] = {
- 0x001C0000, /* Kinetis-K Series */
- 0x001C0020, /* Kinetis-L/M/V/E Series */
-};
-
-/*
- * This function implements the procedure to connect to
- * SWD/JTAG on Kinetis K and L series of devices as it is described in
- * AN4835 "Production Flash Programming Best Practices for Kinetis K-
- * and L-series MCUs" Section 4.1.1
- */
-COMMAND_HANDLER(kinetis_check_flash_security_status)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
-
- if (!dap) {
- LOG_WARNING("Cannot check flash security status with a high-level adapter");
- return ERROR_OK;
- }
-
- uint32_t val;
- int retval;
-
- /*
- * ... The MDM-AP ID register can be read to verify that the
- * connection is working correctly...
- */
- retval = kinetis_mdm_read_register(dap, MDM_REG_ID, &val);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to read ID register");
- return ERROR_OK;
- }
-
- if (val == 0)
- return ERROR_OK;
-
- bool found = false;
- for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) {
- if (val == kinetis_known_mdm_ids[i]) {
- found = true;
- break;
- }
- }
-
- if (!found)
- LOG_WARNING("MDM: unknown ID %08" PRIX32, val);
-
- /*
- * ... Read the System Security bit to determine if security is enabled.
- * If System Security = 0, then proceed. If System Security = 1, then
- * communication with the internals of the processor, including the
- * flash, will not be possible without issuing a mass erase command or
- * unsecuring the part through other means (backdoor key unlock)...
- */
- retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &val);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to read MDM_REG_STAT");
- return ERROR_OK;
- }
-
- /*
- * System Security bit is also active for short time during reset.
- * If a MCU has blank flash and runs in RESET/WDOG loop,
- * System Security bit is active most of time!
- * We should observe Flash Ready bit and read status several times
- * to avoid false detection of secured MCU
- */
- int secured_score = 0, flash_not_ready_score = 0;
-
- if ((val & (MDM_STAT_SYSSEC | MDM_STAT_FREADY)) != MDM_STAT_FREADY) {
- uint32_t stats[32];
- int i;
-
- for (i = 0; i < 32; i++) {
- stats[i] = MDM_STAT_FREADY;
- dap_queue_ap_read(dap_ap(dap, MDM_AP), MDM_REG_STAT, &stats[i]);
- }
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: dap_run failed when validating secured state");
- return ERROR_OK;
- }
- for (i = 0; i < 32; i++) {
- if (stats[i] & MDM_STAT_SYSSEC)
- secured_score++;
- if (!(stats[i] & MDM_STAT_FREADY))
- flash_not_ready_score++;
- }
- }
-
- if (flash_not_ready_score <= 8 && secured_score > 24) {
- jtag_poll_set_enabled(false);
-
- LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
- LOG_WARNING("**** ****");
- LOG_WARNING("**** Your Kinetis MCU is in secured state, which means that, ****");
- LOG_WARNING("**** with exception for very basic communication, JTAG/SWD ****");
- LOG_WARNING("**** interface will NOT work. In order to restore its ****");
- LOG_WARNING("**** functionality please issue 'kinetis mdm mass_erase' ****");
- LOG_WARNING("**** command, power cycle the MCU and restart OpenOCD. ****");
- LOG_WARNING("**** ****");
- LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
-
- } else if (flash_not_ready_score > 24) {
- jtag_poll_set_enabled(false);
- LOG_WARNING("**** Your Kinetis MCU is probably locked-up in RESET/WDOG loop. ****");
- LOG_WARNING("**** Common reason is a blank flash (at least a reset vector). ****");
- LOG_WARNING("**** Issue 'kinetis mdm halt' command or if SRST is connected ****");
- LOG_WARNING("**** and configured, use 'reset halt' ****");
- LOG_WARNING("**** If MCU cannot be halted, it is likely secured and running ****");
- LOG_WARNING("**** in RESET/WDOG loop. Issue 'kinetis mdm mass_erase' ****");
-
- } else {
- LOG_INFO("MDM: Chip is unsecured. Continuing.");
- jtag_poll_set_enabled(true);
- }
-
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command)
-{
- struct kinetis_flash_bank *bank_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_INFO("add flash_bank kinetis %s", bank->name);
-
- bank_info = malloc(sizeof(struct kinetis_flash_bank));
-
- memset(bank_info, 0, sizeof(struct kinetis_flash_bank));
-
- bank->driver_priv = bank_info;
-
- return ERROR_OK;
-}
-
-/* Disable the watchdog on Kinetis devices */
-int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid)
-{
- struct working_area *wdog_algorithm;
- struct armv7m_algorithm armv7m_info;
- uint16_t wdog;
- int retval;
-
- static const uint8_t kinetis_unlock_wdog_code[] = {
-#include "../../../contrib/loaders/watchdog/armv7m_kinetis_wdog.inc"
- };
-
- /* Decide whether the connected device needs watchdog disabling.
- * Disable for all Kx and KVx devices, return if it is a KLx */
-
- if ((sim_sdid & KINETIS_SDID_SERIESID_MASK) == KINETIS_SDID_SERIESID_KL)
- return ERROR_OK;
-
- /* The connected device requires watchdog disabling. */
- retval = target_read_u16(target, WDOG_STCTRH, &wdog);
- if (retval != ERROR_OK)
- return retval;
-
- if ((wdog & 0x1) == 0) {
- /* watchdog already disabled */
- return ERROR_OK;
- }
- LOG_INFO("Disabling Kinetis watchdog (initial WDOG_STCTRLH = 0x%x)", wdog);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = target_alloc_working_area(target, sizeof(kinetis_unlock_wdog_code), &wdog_algorithm);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_buffer(target, wdog_algorithm->address,
- sizeof(kinetis_unlock_wdog_code), (uint8_t *)kinetis_unlock_wdog_code);
- if (retval != ERROR_OK) {
- target_free_working_area(target, wdog_algorithm);
- return retval;
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- retval = target_run_algorithm(target, 0, NULL, 0, NULL, wdog_algorithm->address,
- wdog_algorithm->address + (sizeof(kinetis_unlock_wdog_code) - 2),
- 10000, &armv7m_info);
-
- if (retval != ERROR_OK)
- LOG_ERROR("error executing kinetis wdog unlock algorithm");
-
- retval = target_read_u16(target, WDOG_STCTRH, &wdog);
- if (retval != ERROR_OK)
- return retval;
- LOG_INFO("WDOG_STCTRLH = 0x%x", wdog);
-
- target_free_working_area(target, wdog_algorithm);
-
- return retval;
-}
-
-COMMAND_HANDLER(kinetis_disable_wdog_handler)
-{
- int result;
- uint32_t sim_sdid;
- struct target *target = get_current_target(CMD_CTX);
-
- if (CMD_ARGC > 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- result = target_read_u32(target, SIM_SDID, &sim_sdid);
- if (result != ERROR_OK) {
- LOG_ERROR("Failed to read SIMSDID");
- return result;
- }
-
- result = kinetis_disable_wdog(target, sim_sdid);
- return result;
-}
-
-
-static int kinetis_ftfx_decode_error(uint8_t fstat)
-{
- if (fstat & 0x20) {
- LOG_ERROR("Flash operation failed, illegal command");
- return ERROR_FLASH_OPER_UNSUPPORTED;
-
- } else if (fstat & 0x10)
- LOG_ERROR("Flash operation failed, protection violated");
-
- else if (fstat & 0x40)
- LOG_ERROR("Flash operation failed, read collision");
-
- else if (fstat & 0x80)
- return ERROR_OK;
-
- else
- LOG_ERROR("Flash operation timed out");
-
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-
-static int kinetis_ftfx_prepare(struct target *target)
-{
- int result, i;
- uint8_t fstat;
-
- /* wait until busy */
- for (i = 0; i < 50; i++) {
- result = target_read_u8(target, FTFx_FSTAT, &fstat);
- if (result != ERROR_OK)
- return result;
-
- if (fstat & 0x80)
- break;
- }
-
- if ((fstat & 0x80) == 0) {
- LOG_ERROR("Flash controller is busy");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- if (fstat != 0x80) {
- /* reset error flags */
- result = target_write_u8(target, FTFx_FSTAT, 0x70);
- }
- return result;
-}
-
-/* Kinetis Program-LongWord Microcodes */
-static const uint8_t kinetis_flash_write_code[] = {
- /* Params:
- * r0 - workarea buffer
- * r1 - target address
- * r2 - wordcount
- * Clobbered:
- * r4 - tmp
- * r5 - tmp
- * r6 - tmp
- * r7 - tmp
- */
-
- /* .L1: */
- /* for(register uint32_t i=0;i<wcount;i++){ */
- 0x04, 0x1C, /* mov r4, r0 */
- 0x00, 0x23, /* mov r3, #0 */
- /* .L2: */
- 0x0E, 0x1A, /* sub r6, r1, r0 */
- 0xA6, 0x19, /* add r6, r4, r6 */
- 0x93, 0x42, /* cmp r3, r2 */
- 0x16, 0xD0, /* beq .L9 */
- /* .L5: */
- /* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
- 0x0B, 0x4D, /* ldr r5, .L10 */
- 0x2F, 0x78, /* ldrb r7, [r5] */
- 0x7F, 0xB2, /* sxtb r7, r7 */
- 0x00, 0x2F, /* cmp r7, #0 */
- 0xFA, 0xDA, /* bge .L5 */
- /* FTFx_FSTAT = FTFA_FSTAT_ACCERR_MASK|FTFA_FSTAT_FPVIOL_MASK|FTFA_FSTAT_RDCO */
- 0x70, 0x27, /* mov r7, #112 */
- 0x2F, 0x70, /* strb r7, [r5] */
- /* FTFx_FCCOB3 = faddr; */
- 0x09, 0x4F, /* ldr r7, .L10+4 */
- 0x3E, 0x60, /* str r6, [r7] */
- 0x06, 0x27, /* mov r7, #6 */
- /* FTFx_FCCOB0 = 0x06; */
- 0x08, 0x4E, /* ldr r6, .L10+8 */
- 0x37, 0x70, /* strb r7, [r6] */
- /* FTFx_FCCOB7 = *pLW; */
- 0x80, 0xCC, /* ldmia r4!, {r7} */
- 0x08, 0x4E, /* ldr r6, .L10+12 */
- 0x37, 0x60, /* str r7, [r6] */
- /* FTFx_FSTAT = FTFA_FSTAT_CCIF_MASK; */
- 0x80, 0x27, /* mov r7, #128 */
- 0x2F, 0x70, /* strb r7, [r5] */
- /* .L4: */
- /* while((FTFx_FSTAT&FTFA_FSTAT_CCIF_MASK) != FTFA_FSTAT_CCIF_MASK){}; */
- 0x2E, 0x78, /* ldrb r6, [r5] */
- 0x77, 0xB2, /* sxtb r7, r6 */
- 0x00, 0x2F, /* cmp r7, #0 */
- 0xFB, 0xDA, /* bge .L4 */
- 0x01, 0x33, /* add r3, r3, #1 */
- 0xE4, 0xE7, /* b .L2 */
- /* .L9: */
- 0x00, 0xBE, /* bkpt #0 */
- /* .L10: */
- 0x00, 0x00, 0x02, 0x40, /* .word 1073872896 */
- 0x04, 0x00, 0x02, 0x40, /* .word 1073872900 */
- 0x07, 0x00, 0x02, 0x40, /* .word 1073872903 */
- 0x08, 0x00, 0x02, 0x40, /* .word 1073872904 */
-};
-
-/* Program LongWord Block Write */
-static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t wcount)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 2048; /* Default minimum value */
- struct working_area *write_algorithm;
- struct working_area *source;
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
- uint32_t address = kinfo->prog_base + offset;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* Params:
- * r0 - workarea buffer
- * r1 - target address
- * r2 - wordcount
- * Clobbered:
- * r4 - tmp
- * r5 - tmp
- * r6 - tmp
- * r7 - tmp
- */
-
- /* Increase buffer_size if needed */
- if (buffer_size < (target->working_area_size/2))
- buffer_size = (target->working_area_size/2);
-
- /* allocate working area with flash programming code */
- if (target_alloc_working_area(target, sizeof(kinetis_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(kinetis_flash_write_code), kinetis_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 4;
- if (buffer_size <= 256) {
- /* free working area, write algorithm already allocated */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("No large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* faddr */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of words to program */
-
- /* write code buffer and use Flash programming code within kinetis */
- /* Set breakpoint to 0 with time-out of 1000 ms */
- while (wcount > 0) {
- uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
-
- retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
- if (retval != ERROR_OK)
- break;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
-
- retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- write_algorithm->address, 0, 100000, &armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing kinetis Flash programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- buffer += thisrun_count * 4;
- address += thisrun_count * 4;
- wcount -= thisrun_count;
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- return retval;
-}
-
-static int kinetis_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int i;
-
- if (allow_fcf_writes) {
- LOG_ERROR("Protection setting is possible with 'kinetis fcf_source protection' only!");
- return ERROR_FAIL;
- }
-
- if (!bank->prot_blocks || bank->num_prot_blocks == 0) {
- LOG_ERROR("No protection possible for current bank!");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- for (i = first; i < bank->num_prot_blocks && i <= last; i++)
- bank->prot_blocks[i].is_protected = set;
-
- LOG_INFO("Protection bits will be written at the next FCF sector erase or write.");
- LOG_INFO("Do not issue 'flash info' command until protection is written,");
- LOG_INFO("doing so would re-read protection status from MCU.");
-
- return ERROR_OK;
-}
-
-static int kinetis_protect_check(struct flash_bank *bank)
-{
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
- int result;
- int i, b;
- uint32_t fprot;
-
- if (kinfo->flash_class == FC_PFLASH) {
-
- /* read protection register */
- result = target_read_u32(bank->target, FTFx_FPROT3, &fprot);
- if (result != ERROR_OK)
- return result;
-
- /* Every bit protects 1/32 of the full flash (not necessarily just this bank) */
-
- } else if (kinfo->flash_class == FC_FLEX_NVM) {
- uint8_t fdprot;
-
- /* read protection register */
- result = target_read_u8(bank->target, FTFx_FDPROT, &fdprot);
- if (result != ERROR_OK)
- return result;
-
- fprot = fdprot;
-
- } else {
- LOG_ERROR("Protection checks for FlexRAM not supported");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- b = kinfo->protection_block;
- for (i = 0; i < bank->num_prot_blocks; i++) {
- if ((fprot >> b) & 1)
- bank->prot_blocks[i].is_protected = 0;
- else
- bank->prot_blocks[i].is_protected = 1;
-
- b++;
- }
-
- return ERROR_OK;
-}
-
-
-static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf)
-{
- uint32_t fprot = 0xffffffff;
- uint8_t fsec = 0xfe; /* set MCU unsecure */
- uint8_t fdprot = 0xff;
- int i;
- uint32_t pflash_bit;
- uint8_t dflash_bit;
- struct flash_bank *bank_iter;
- struct kinetis_flash_bank *kinfo;
-
- memset(fcf, 0xff, FCF_SIZE);
-
- pflash_bit = 1;
- dflash_bit = 1;
-
- /* iterate over all kinetis banks */
- /* current bank is bank 0, it contains FCF */
- for (bank_iter = bank; bank_iter; bank_iter = bank_iter->next) {
- if (bank_iter->driver != &kinetis_flash
- || bank_iter->target != bank->target)
- continue;
-
- kinetis_auto_probe(bank_iter);
-
- kinfo = bank->driver_priv;
- if (!kinfo)
- continue;
-
- if (kinfo->flash_class == FC_PFLASH) {
- for (i = 0; i < bank_iter->num_prot_blocks; i++) {
- if (bank_iter->prot_blocks[i].is_protected == 1)
- fprot &= ~pflash_bit;
-
- pflash_bit <<= 1;
- }
-
- } else if (kinfo->flash_class == FC_FLEX_NVM) {
- for (i = 0; i < bank_iter->num_prot_blocks; i++) {
- if (bank_iter->prot_blocks[i].is_protected == 1)
- fdprot &= ~dflash_bit;
-
- dflash_bit <<= 1;
- }
-
- }
- }
-
- target_buffer_set_u32(bank->target, fcf + FCF_FPROT, fprot);
- fcf[FCF_FSEC] = fsec;
- fcf[FCF_FOPT] = fcf_fopt;
- fcf[FCF_FDPROT] = fdprot;
- return ERROR_OK;
-}
-
-static int kinetis_ftfx_command(struct target *target, uint8_t fcmd, uint32_t faddr,
- uint8_t fccob4, uint8_t fccob5, uint8_t fccob6, uint8_t fccob7,
- uint8_t fccob8, uint8_t fccob9, uint8_t fccoba, uint8_t fccobb,
- uint8_t *ftfx_fstat)
-{
- uint8_t command[12] = {faddr & 0xff, (faddr >> 8) & 0xff, (faddr >> 16) & 0xff, fcmd,
- fccob7, fccob6, fccob5, fccob4,
- fccobb, fccoba, fccob9, fccob8};
- int result;
- uint8_t fstat;
- int64_t ms_timeout = timeval_ms() + 250;
-
- result = target_write_memory(target, FTFx_FCCOB3, 4, 3, command);
- if (result != ERROR_OK)
- return result;
-
- /* start command */
- result = target_write_u8(target, FTFx_FSTAT, 0x80);
- if (result != ERROR_OK)
- return result;
-
- /* wait for done */
- do {
- result = target_read_u8(target, FTFx_FSTAT, &fstat);
-
- if (result != ERROR_OK)
- return result;
-
- if (fstat & 0x80)
- break;
-
- } while (timeval_ms() < ms_timeout);
-
- if (ftfx_fstat)
- *ftfx_fstat = fstat;
-
- if ((fstat & 0xf0) != 0x80) {
- LOG_DEBUG("ftfx command failed FSTAT: %02X FCCOB: %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X",
- fstat, command[3], command[2], command[1], command[0],
- command[7], command[6], command[5], command[4],
- command[11], command[10], command[9], command[8]);
-
- return kinetis_ftfx_decode_error(fstat);
- }
-
- return ERROR_OK;
-}
-
-
-static int kinetis_check_run_mode(struct target *target)
-{
- int result, i;
- uint8_t pmctrl, pmstat;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- result = target_read_u8(target, SMC_PMSTAT, &pmstat);
- if (result != ERROR_OK)
- return result;
-
- if (pmstat == PM_STAT_RUN)
- return ERROR_OK;
-
- if (pmstat == PM_STAT_VLPR) {
- /* It is safe to switch from VLPR to RUN mode without changing clock */
- LOG_INFO("Switching from VLPR to RUN mode.");
- pmctrl = PM_CTRL_RUNM_RUN;
- result = target_write_u8(target, SMC_PMCTRL, pmctrl);
- if (result != ERROR_OK)
- return result;
-
- for (i = 100; i; i--) {
- result = target_read_u8(target, SMC_PMSTAT, &pmstat);
- if (result != ERROR_OK)
- return result;
-
- if (pmstat == PM_STAT_RUN)
- return ERROR_OK;
- }
- }
-
- LOG_ERROR("Flash operation not possible in current run mode: SMC_PMSTAT: 0x%x", pmstat);
- LOG_ERROR("Issue a 'reset init' command.");
- return ERROR_TARGET_NOT_HALTED;
-}
-
-
-static void kinetis_invalidate_flash_cache(struct flash_bank *bank)
-{
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
- uint8_t pfb01cr_byte2 = 0xf0;
-
- if (!(kinfo->flash_support & FS_INVALIDATE_CACHE))
- return;
-
- target_write_memory(bank->target, FMC_PFB01CR + 2, 1, 1, &pfb01cr_byte2);
- return;
-}
-
-
-static int kinetis_erase(struct flash_bank *bank, int first, int last)
-{
- int result, i;
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
-
- result = kinetis_check_run_mode(bank->target);
- if (result != ERROR_OK)
- return result;
-
- /* reset error flags */
- result = kinetis_ftfx_prepare(bank->target);
- if (result != ERROR_OK)
- return result;
-
- if ((first > bank->num_sectors) || (last > bank->num_sectors))
- return ERROR_FLASH_OPERATION_FAILED;
-
- /*
- * FIXME: TODO: use the 'Erase Flash Block' command if the
- * requested erase is PFlash or NVM and encompasses the entire
- * block. Should be quicker.
- */
- for (i = first; i <= last; i++) {
- /* set command and sector address */
- result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTERASE, kinfo->prog_base + bank->sectors[i].offset,
- 0, 0, 0, 0, 0, 0, 0, 0, NULL);
-
- if (result != ERROR_OK) {
- LOG_WARNING("erase sector %d failed", i);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- bank->sectors[i].is_erased = 1;
-
- if (bank->base == 0
- && bank->sectors[i].offset <= FCF_ADDRESS
- && bank->sectors[i].offset + bank->sectors[i].size > FCF_ADDRESS + FCF_SIZE) {
- if (allow_fcf_writes) {
- LOG_WARNING("Flash Configuration Field erased, DO NOT reset or power off the device");
- LOG_WARNING("until correct FCF is programmed or MCU gets security lock.");
- } else {
- uint8_t fcf_buffer[FCF_SIZE];
-
- kinetis_fill_fcf(bank, fcf_buffer);
- result = kinetis_write_inner(bank, fcf_buffer, FCF_ADDRESS, FCF_SIZE);
- if (result != ERROR_OK)
- LOG_WARNING("Flash Configuration Field write failed");
- bank->sectors[i].is_erased = 0;
- }
- }
- }
-
- kinetis_invalidate_flash_cache(bank);
-
- return ERROR_OK;
-}
-
-static int kinetis_make_ram_ready(struct target *target)
-{
- int result;
- uint8_t ftfx_fcnfg;
-
- /* check if ram ready */
- result = target_read_u8(target, FTFx_FCNFG, &ftfx_fcnfg);
- if (result != ERROR_OK)
- return result;
-
- if (ftfx_fcnfg & (1 << 1))
- return ERROR_OK; /* ram ready */
-
- /* make flex ram available */
- result = kinetis_ftfx_command(target, FTFx_CMD_SETFLEXRAM, 0x00ff0000,
- 0, 0, 0, 0, 0, 0, 0, 0, NULL);
- if (result != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* check again */
- result = target_read_u8(target, FTFx_FCNFG, &ftfx_fcnfg);
- if (result != ERROR_OK)
- return result;
-
- if (ftfx_fcnfg & (1 << 1))
- return ERROR_OK; /* ram ready */
-
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-
-static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- int result = ERROR_OK;
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
- uint8_t *buffer_aligned = NULL;
- /*
- * Kinetis uses different terms for the granularity of
- * sector writes, e.g. "phrase" or "128 bits". We use
- * the generic term "chunk". The largest possible
- * Kinetis "chunk" is 16 bytes (128 bits).
- */
- uint32_t prog_section_chunk_bytes = kinfo->sector_size >> 8;
- uint32_t prog_size_bytes = kinfo->max_flash_prog_size;
-
- while (count > 0) {
- uint32_t size = prog_size_bytes - offset % prog_size_bytes;
- uint32_t align_begin = offset % prog_section_chunk_bytes;
- uint32_t align_end;
- uint32_t size_aligned;
- uint16_t chunk_count;
- uint8_t ftfx_fstat;
-
- if (size > count)
- size = count;
-
- align_end = (align_begin + size) % prog_section_chunk_bytes;
- if (align_end)
- align_end = prog_section_chunk_bytes - align_end;
-
- size_aligned = align_begin + size + align_end;
- chunk_count = size_aligned / prog_section_chunk_bytes;
-
- if (size != size_aligned) {
- /* aligned section: the first, the last or the only */
- if (!buffer_aligned)
- buffer_aligned = malloc(prog_size_bytes);
-
- memset(buffer_aligned, 0xff, size_aligned);
- memcpy(buffer_aligned + align_begin, buffer, size);
-
- result = target_write_memory(bank->target, FLEXRAM,
- 4, size_aligned / 4, buffer_aligned);
-
- LOG_DEBUG("section @ %08" PRIx32 " aligned begin %" PRIu32 ", end %" PRIu32,
- bank->base + offset, align_begin, align_end);
- } else
- result = target_write_memory(bank->target, FLEXRAM,
- 4, size_aligned / 4, buffer);
-
- LOG_DEBUG("write section @ %08" PRIx32 " with length %" PRIu32 " bytes",
- bank->base + offset, size);
-
- if (result != ERROR_OK) {
- LOG_ERROR("target_write_memory failed");
- break;
- }
-
- /* execute section-write command */
- result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTWRITE,
- kinfo->prog_base + offset - align_begin,
- chunk_count>>8, chunk_count, 0, 0,
- 0, 0, 0, 0, &ftfx_fstat);
-
- if (result != ERROR_OK) {
- LOG_ERROR("Error writing section at %08" PRIx32, bank->base + offset);
- break;
- }
-
- if (ftfx_fstat & 0x01)
- LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset);
-
- buffer += size;
- offset += size;
- count -= size;
- }
-
- free(buffer_aligned);
- return result;
-}
-
-
-static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- int result, fallback = 0;
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
-
- if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) {
- /* fallback to longword write */
- fallback = 1;
- LOG_WARNING("This device supports Program Longword execution only.");
- } else {
- result = kinetis_make_ram_ready(bank->target);
- if (result != ERROR_OK) {
- fallback = 1;
- LOG_WARNING("FlexRAM not ready, fallback to slow longword write.");
- }
- }
-
- LOG_DEBUG("flash write @08%" PRIx32, bank->base + offset);
-
- if (fallback == 0) {
- /* program section command */
- kinetis_write_sections(bank, buffer, offset, count);
- }
- else if (kinfo->flash_support & FS_PROGRAM_LONGWORD) {
- /* program longword command, not supported in FTFE */
- uint8_t *new_buffer = NULL;
-
- /* check word alignment */
- if (offset & 0x3) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks the required alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- if (count & 0x3) {
- uint32_t old_count = count;
- count = (old_count | 3) + 1;
- new_buffer = malloc(count);
- if (new_buffer == NULL) {
- LOG_ERROR("odd number of bytes to write and no memory "
- "for padding buffer");
- return ERROR_FAIL;
- }
- LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " "
- "and padding with 0xff", old_count, count);
- memset(new_buffer + old_count, 0xff, count - old_count);
- buffer = memcpy(new_buffer, buffer, old_count);
- }
-
- uint32_t words_remaining = count / 4;
-
- kinetis_disable_wdog(bank->target, kinfo->sim_sdid);
-
- /* try using a block write */
- result = kinetis_write_block(bank, buffer, offset, words_remaining);
-
- if (result == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single word accesses */
- LOG_WARNING("couldn't use block writes, falling back to single "
- "memory accesses");
-
- while (words_remaining) {
- uint8_t ftfx_fstat;
-
- LOG_DEBUG("write longword @ %08" PRIx32, (uint32_t)(bank->base + offset));
-
- result = kinetis_ftfx_command(bank->target, FTFx_CMD_LWORDPROG, kinfo->prog_base + offset,
- buffer[3], buffer[2], buffer[1], buffer[0],
- 0, 0, 0, 0, &ftfx_fstat);
-
- if (result != ERROR_OK) {
- LOG_ERROR("Error writing longword at %08" PRIx32, bank->base + offset);
- break;
- }
-
- if (ftfx_fstat & 0x01)
- LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset);
-
- buffer += 4;
- offset += 4;
- words_remaining--;
- }
- }
- free(new_buffer);
- } else {
- LOG_ERROR("Flash write strategy not implemented");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- kinetis_invalidate_flash_cache(bank);
- return result;
-}
-
-
-static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- int result;
- bool set_fcf = false;
- int sect = 0;
-
- result = kinetis_check_run_mode(bank->target);
- if (result != ERROR_OK)
- return result;
-
- /* reset error flags */
- result = kinetis_ftfx_prepare(bank->target);
- if (result != ERROR_OK)
- return result;
-
- if (bank->base == 0 && !allow_fcf_writes) {
- if (bank->sectors[1].offset <= FCF_ADDRESS)
- sect = 1; /* 1kb sector, FCF in 2nd sector */
-
- if (offset < bank->sectors[sect].offset + bank->sectors[sect].size
- && offset + count > bank->sectors[sect].offset)
- set_fcf = true; /* write to any part of sector with FCF */
- }
-
- if (set_fcf) {
- uint8_t fcf_buffer[FCF_SIZE];
- uint8_t fcf_current[FCF_SIZE];
-
- kinetis_fill_fcf(bank, fcf_buffer);
-
- if (offset < FCF_ADDRESS) {
- /* write part preceding FCF */
- result = kinetis_write_inner(bank, buffer, offset, FCF_ADDRESS - offset);
- if (result != ERROR_OK)
- return result;
- }
-
- result = target_read_memory(bank->target, FCF_ADDRESS, 4, FCF_SIZE / 4, fcf_current);
- if (result == ERROR_OK && memcmp(fcf_current, fcf_buffer, FCF_SIZE) == 0)
- set_fcf = false;
-
- if (set_fcf) {
- /* write FCF if differs from flash - eliminate multiple writes */
- result = kinetis_write_inner(bank, fcf_buffer, FCF_ADDRESS, FCF_SIZE);
- if (result != ERROR_OK)
- return result;
- }
-
- LOG_WARNING("Flash Configuration Field written.");
- LOG_WARNING("Reset or power off the device to make settings effective.");
-
- if (offset + count > FCF_ADDRESS + FCF_SIZE) {
- uint32_t delta = FCF_ADDRESS + FCF_SIZE - offset;
- /* write part after FCF */
- result = kinetis_write_inner(bank, buffer + delta, FCF_ADDRESS + FCF_SIZE, count - delta);
- }
- return result;
-
- } else
- /* no FCF fiddling, normal write */
- return kinetis_write_inner(bank, buffer, offset, count);
-}
-
-
-static int kinetis_probe(struct flash_bank *bank)
-{
- int result, i;
- uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg1_depart;
- uint8_t fcfg2_maxaddr0, fcfg2_pflsh, fcfg2_maxaddr1;
- uint32_t nvm_size = 0, pf_size = 0, df_size = 0, ee_size = 0;
- unsigned num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0, first_nvm_bank = 0,
- pflash_sector_size_bytes = 0, nvm_sector_size_bytes = 0;
- struct target *target = bank->target;
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
-
- kinfo->probed = false;
-
- result = target_read_u32(target, SIM_SDID, &kinfo->sim_sdid);
- if (result != ERROR_OK)
- return result;
-
- if ((kinfo->sim_sdid & (~KINETIS_SDID_K_SERIES_MASK)) == 0) {
- /* older K-series MCU */
- uint32_t mcu_type = kinfo->sim_sdid & KINETIS_K_SDID_TYPE_MASK;
-
- switch (mcu_type) {
- case KINETIS_K_SDID_K10_M50:
- case KINETIS_K_SDID_K20_M50:
- /* 1kB sectors */
- pflash_sector_size_bytes = 1<<10;
- nvm_sector_size_bytes = 1<<10;
- num_blocks = 2;
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- break;
- case KINETIS_K_SDID_K10_M72:
- case KINETIS_K_SDID_K20_M72:
- case KINETIS_K_SDID_K30_M72:
- case KINETIS_K_SDID_K30_M100:
- case KINETIS_K_SDID_K40_M72:
- case KINETIS_K_SDID_K40_M100:
- case KINETIS_K_SDID_K50_M72:
- /* 2kB sectors, 1kB FlexNVM sectors */
- pflash_sector_size_bytes = 2<<10;
- nvm_sector_size_bytes = 1<<10;
- num_blocks = 2;
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- kinfo->max_flash_prog_size = 1<<10;
- break;
- case KINETIS_K_SDID_K10_M100:
- case KINETIS_K_SDID_K20_M100:
- case KINETIS_K_SDID_K11:
- case KINETIS_K_SDID_K12:
- case KINETIS_K_SDID_K21_M50:
- case KINETIS_K_SDID_K22_M50:
- case KINETIS_K_SDID_K51_M72:
- case KINETIS_K_SDID_K53:
- case KINETIS_K_SDID_K60_M100:
- /* 2kB sectors */
- pflash_sector_size_bytes = 2<<10;
- nvm_sector_size_bytes = 2<<10;
- num_blocks = 2;
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- break;
- case KINETIS_K_SDID_K21_M120:
- case KINETIS_K_SDID_K22_M120:
- /* 4kB sectors (MK21FN1M0, MK21FX512, MK22FN1M0, MK22FX512) */
- pflash_sector_size_bytes = 4<<10;
- kinfo->max_flash_prog_size = 1<<10;
- nvm_sector_size_bytes = 4<<10;
- num_blocks = 2;
- kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- break;
- case KINETIS_K_SDID_K10_M120:
- case KINETIS_K_SDID_K20_M120:
- case KINETIS_K_SDID_K60_M150:
- case KINETIS_K_SDID_K70_M150:
- /* 4kB sectors */
- pflash_sector_size_bytes = 4<<10;
- nvm_sector_size_bytes = 4<<10;
- num_blocks = 4;
- kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- break;
- default:
- LOG_ERROR("Unsupported K-family FAMID");
- }
- } else {
- /* Newer K-series or KL series MCU */
- switch (kinfo->sim_sdid & KINETIS_SDID_SERIESID_MASK) {
- case KINETIS_SDID_SERIESID_K:
- switch (kinfo->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) {
- case KINETIS_SDID_FAMILYID_K0X | KINETIS_SDID_SUBFAMID_KX2:
- /* K02FN64, K02FN128: FTFA, 2kB sectors */
- pflash_sector_size_bytes = 2<<10;
- num_blocks = 1;
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
- break;
-
- case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: {
- /* MK24FN1M reports as K22, this should detect it (according to errata note 1N83J) */
- uint32_t sopt1;
- result = target_read_u32(target, SIM_SOPT1, &sopt1);
- if (result != ERROR_OK)
- return result;
-
- if (((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN1M) &&
- ((sopt1 & KINETIS_SOPT1_RAMSIZE_MASK) == KINETIS_SOPT1_RAMSIZE_K24FN1M)) {
- /* MK24FN1M */
- pflash_sector_size_bytes = 4<<10;
- num_blocks = 2;
- kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- kinfo->max_flash_prog_size = 1<<10;
- break;
- }
- if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN128
- || (kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN256
- || (kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN512) {
- /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */
- pflash_sector_size_bytes = 2<<10;
- /* autodetect 1 or 2 blocks */
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
- break;
- }
- LOG_ERROR("Unsupported Kinetis K22 DIEID");
- break;
- }
- case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX4:
- pflash_sector_size_bytes = 4<<10;
- if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) {
- /* K24FN256 - smaller pflash with FTFA */
- num_blocks = 1;
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
- break;
- }
- /* K24FN1M without errata 7534 */
- num_blocks = 2;
- kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- kinfo->max_flash_prog_size = 1<<10;
- break;
-
- case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX3:
- case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX1: /* errata 7534 - should be K63 */
- /* K63FN1M0 */
- case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX4:
- case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX2: /* errata 7534 - should be K64 */
- /* K64FN1M0, K64FX512 */
- pflash_sector_size_bytes = 4<<10;
- nvm_sector_size_bytes = 4<<10;
- kinfo->max_flash_prog_size = 1<<10;
- num_blocks = 2;
- kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- break;
-
- case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6:
- /* K26FN2M0 */
- case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX6:
- /* K66FN2M0, K66FX1M0 */
- pflash_sector_size_bytes = 4<<10;
- nvm_sector_size_bytes = 4<<10;
- kinfo->max_flash_prog_size = 1<<10;
- num_blocks = 4;
- kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE;
- break;
- default:
- LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID");
- }
- break;
-
- case KINETIS_SDID_SERIESID_KL:
- /* KL-series */
- pflash_sector_size_bytes = 1<<10;
- nvm_sector_size_bytes = 1<<10;
- /* autodetect 1 or 2 blocks */
- kinfo->flash_support = FS_PROGRAM_LONGWORD;
- break;
-
- case KINETIS_SDID_SERIESID_KV:
- /* KV-series */
- switch (kinfo->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) {
- case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX0:
- /* KV10: FTFA, 1kB sectors */
- pflash_sector_size_bytes = 1<<10;
- num_blocks = 1;
- kinfo->flash_support = FS_PROGRAM_LONGWORD;
- break;
-
- case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1:
- /* KV11: FTFA, 2kB sectors */
- pflash_sector_size_bytes = 2<<10;
- num_blocks = 1;
- kinfo->flash_support = FS_PROGRAM_LONGWORD;
- break;
-
- case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0:
- /* KV30: FTFA, 2kB sectors, 1 block */
- case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX1:
- /* KV31: FTFA, 2kB sectors, 2 blocks */
- pflash_sector_size_bytes = 2<<10;
- /* autodetect 1 or 2 blocks */
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
- break;
-
- case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2:
- case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX4:
- case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX6:
- /* KV4x: FTFA, 4kB sectors */
- pflash_sector_size_bytes = 4<<10;
- num_blocks = 1;
- kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE;
- break;
-
- default:
- LOG_ERROR("Unsupported KV FAMILYID SUBFAMID");
- }
- break;
-
- default:
- LOG_ERROR("Unsupported K-series");
- }
- }
-
- if (pflash_sector_size_bytes == 0) {
- LOG_ERROR("MCU is unsupported, SDID 0x%08" PRIx32, kinfo->sim_sdid);
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- result = target_read_u32(target, SIM_FCFG1, &kinfo->sim_fcfg1);
- if (result != ERROR_OK)
- return result;
-
- result = target_read_u32(target, SIM_FCFG2, &kinfo->sim_fcfg2);
- if (result != ERROR_OK)
- return result;
-
- LOG_DEBUG("SDID: 0x%08" PRIX32 " FCFG1: 0x%08" PRIX32 " FCFG2: 0x%08" PRIX32, kinfo->sim_sdid,
- kinfo->sim_fcfg1, kinfo->sim_fcfg2);
-
- fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f);
- fcfg1_pfsize = (uint8_t)((kinfo->sim_fcfg1 >> 24) & 0x0f);
- fcfg1_eesize = (uint8_t)((kinfo->sim_fcfg1 >> 16) & 0x0f);
- fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f);
-
- fcfg2_pflsh = (uint8_t)((kinfo->sim_fcfg2 >> 23) & 0x01);
- fcfg2_maxaddr0 = (uint8_t)((kinfo->sim_fcfg2 >> 24) & 0x7f);
- fcfg2_maxaddr1 = (uint8_t)((kinfo->sim_fcfg2 >> 16) & 0x7f);
-
- if (num_blocks == 0)
- num_blocks = fcfg2_maxaddr1 ? 2 : 1;
- else if (fcfg2_maxaddr1 == 0 && num_blocks >= 2) {
- num_blocks = 1;
- LOG_WARNING("MAXADDR1 is zero, number of flash banks adjusted to 1");
- } else if (fcfg2_maxaddr1 != 0 && num_blocks == 1) {
- num_blocks = 2;
- LOG_WARNING("MAXADDR1 is non zero, number of flash banks adjusted to 2");
- }
-
- /* when the PFLSH bit is set, there is no FlexNVM/FlexRAM */
- if (!fcfg2_pflsh) {
- switch (fcfg1_nvmsize) {
- case 0x03:
- case 0x05:
- case 0x07:
- case 0x09:
- case 0x0b:
- nvm_size = 1 << (14 + (fcfg1_nvmsize >> 1));
- break;
- case 0x0f:
- if (pflash_sector_size_bytes >= 4<<10)
- nvm_size = 512<<10;
- else
- /* K20_100 */
- nvm_size = 256<<10;
- break;
- default:
- nvm_size = 0;
- break;
- }
-
- switch (fcfg1_eesize) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- case 0x08:
- case 0x09:
- ee_size = (16 << (10 - fcfg1_eesize));
- break;
- default:
- ee_size = 0;
- break;
- }
-
- switch (fcfg1_depart) {
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- df_size = nvm_size - (4096 << fcfg1_depart);
- break;
- case 0x08:
- df_size = 0;
- break;
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- df_size = 4096 << (fcfg1_depart & 0x7);
- break;
- default:
- df_size = nvm_size;
- break;
- }
- }
-
- switch (fcfg1_pfsize) {
- case 0x03:
- case 0x05:
- case 0x07:
- case 0x09:
- case 0x0b:
- case 0x0d:
- pf_size = 1 << (14 + (fcfg1_pfsize >> 1));
- break;
- case 0x0f:
- /* a peculiar case: Freescale states different sizes for 0xf
- * K02P64M100SFARM 128 KB ... duplicate of code 0x7
- * K22P121M120SF8RM 256 KB ... duplicate of code 0x9
- * K22P121M120SF7RM 512 KB ... duplicate of code 0xb
- * K22P100M120SF5RM 1024 KB ... duplicate of code 0xd
- * K26P169M180SF5RM 2048 KB ... the only unique value
- * fcfg2_maxaddr0 seems to be the only clue to pf_size
- * Checking fcfg2_maxaddr0 later in this routine is pointless then
- */
- if (fcfg2_pflsh)
- pf_size = ((uint32_t)fcfg2_maxaddr0 << 13) * num_blocks;
- else
- pf_size = ((uint32_t)fcfg2_maxaddr0 << 13) * num_blocks / 2;
- if (pf_size != 2048<<10)
- LOG_WARNING("SIM_FCFG1 PFSIZE = 0xf: please check if pflash is %u KB", pf_size>>10);
-
- break;
- default:
- pf_size = 0;
- break;
- }
-
- LOG_DEBUG("FlexNVM: %" PRIu32 " PFlash: %" PRIu32 " FlexRAM: %" PRIu32 " PFLSH: %d",
- nvm_size, pf_size, ee_size, fcfg2_pflsh);
-
- num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh);
- first_nvm_bank = num_pflash_blocks;
- num_nvm_blocks = num_blocks - num_pflash_blocks;
-
- LOG_DEBUG("%d blocks total: %d PFlash, %d FlexNVM",
- num_blocks, num_pflash_blocks, num_nvm_blocks);
-
- LOG_INFO("Probing flash info for bank %d", bank->bank_number);
-
- if ((unsigned)bank->bank_number < num_pflash_blocks) {
- /* pflash, banks start at address zero */
- kinfo->flash_class = FC_PFLASH;
- bank->size = (pf_size / num_pflash_blocks);
- bank->base = 0x00000000 + bank->size * bank->bank_number;
- kinfo->prog_base = bank->base;
- kinfo->sector_size = pflash_sector_size_bytes;
- /* pflash is divided into 32 protection areas for
- * parts with more than 32K of PFlash. For parts with
- * less the protection unit is set to 1024 bytes */
- kinfo->protection_size = MAX(pf_size / 32, 1024);
- bank->num_prot_blocks = 32 / num_pflash_blocks;
- kinfo->protection_block = bank->num_prot_blocks * bank->bank_number;
-
- } else if ((unsigned)bank->bank_number < num_blocks) {
- /* nvm, banks start at address 0x10000000 */
- unsigned nvm_ord = bank->bank_number - first_nvm_bank;
- uint32_t limit;
-
- kinfo->flash_class = FC_FLEX_NVM;
- bank->size = (nvm_size / num_nvm_blocks);
- bank->base = 0x10000000 + bank->size * nvm_ord;
- kinfo->prog_base = 0x00800000 + bank->size * nvm_ord;
- kinfo->sector_size = nvm_sector_size_bytes;
- if (df_size == 0) {
- kinfo->protection_size = 0;
- } else {
- for (i = df_size; ~i & 1; i >>= 1)
- ;
- if (i == 1)
- kinfo->protection_size = df_size / 8; /* data flash size = 2^^n */
- else
- kinfo->protection_size = nvm_size / 8; /* TODO: verify on SF1, not documented in RM */
- }
- bank->num_prot_blocks = 8 / num_nvm_blocks;
- kinfo->protection_block = bank->num_prot_blocks * nvm_ord;
-
- /* EEPROM backup part of FlexNVM is not accessible, use df_size as a limit */
- if (df_size > bank->size * nvm_ord)
- limit = df_size - bank->size * nvm_ord;
- else
- limit = 0;
-
- if (bank->size > limit) {
- bank->size = limit;
- LOG_DEBUG("FlexNVM bank %d limited to 0x%08" PRIx32 " due to active EEPROM backup",
- bank->bank_number, limit);
- }
-
- } else if ((unsigned)bank->bank_number == num_blocks) {
- LOG_ERROR("FlexRAM support not yet implemented");
- return ERROR_FLASH_OPER_UNSUPPORTED;
- } else {
- LOG_ERROR("Cannot determine parameters for bank %d, only %d banks on device",
- bank->bank_number, num_blocks);
- return ERROR_FLASH_BANK_INVALID;
- }
-
- if (bank->bank_number == 0 && ((uint32_t)fcfg2_maxaddr0 << 13) != bank->size)
- LOG_WARNING("MAXADDR0 0x%02" PRIx8 " check failed,"
- " please report to OpenOCD mailing list", fcfg2_maxaddr0);
- if (fcfg2_pflsh) {
- if (bank->bank_number == 1 && ((uint32_t)fcfg2_maxaddr1 << 13) != bank->size)
- LOG_WARNING("MAXADDR1 0x%02" PRIx8 " check failed,"
- " please report to OpenOCD mailing list", fcfg2_maxaddr1);
- } else {
- if ((unsigned)bank->bank_number == first_nvm_bank
- && ((uint32_t)fcfg2_maxaddr1 << 13) != df_size)
- LOG_WARNING("FlexNVM MAXADDR1 0x%02" PRIx8 " check failed,"
- " please report to OpenOCD mailing list", fcfg2_maxaddr1);
- }
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
- if (bank->prot_blocks) {
- free(bank->prot_blocks);
- bank->prot_blocks = NULL;
- }
-
- if (kinfo->sector_size == 0) {
- LOG_ERROR("Unknown sector size for bank %d", bank->bank_number);
- return ERROR_FLASH_BANK_INVALID;
- }
-
- if (kinfo->flash_support & FS_PROGRAM_SECTOR
- && kinfo->max_flash_prog_size == 0) {
- kinfo->max_flash_prog_size = kinfo->sector_size;
- /* Program section size is equal to sector size by default */
- }
-
- bank->num_sectors = bank->size / kinfo->sector_size;
-
- if (bank->num_sectors > 0) {
- /* FlexNVM bank can be used for EEPROM backup therefore zero sized */
- bank->sectors = alloc_block_array(0, kinfo->sector_size, bank->num_sectors);
- if (!bank->sectors)
- return ERROR_FAIL;
-
- bank->prot_blocks = alloc_block_array(0, kinfo->protection_size, bank->num_prot_blocks);
- if (!bank->prot_blocks)
- return ERROR_FAIL;
-
- } else {
- bank->num_prot_blocks = 0;
- }
-
- kinfo->probed = true;
-
- return ERROR_OK;
-}
-
-static int kinetis_auto_probe(struct flash_bank *bank)
-{
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
-
- if (kinfo && kinfo->probed)
- return ERROR_OK;
-
- return kinetis_probe(bank);
-}
-
-static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- const char *bank_class_names[] = {
- "(ANY)", "PFlash", "FlexNVM", "FlexRAM"
- };
-
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
-
- (void) snprintf(buf, buf_size,
- "%s driver for %s flash bank %s at 0x%8.8" PRIx32 "",
- bank->driver->name, bank_class_names[kinfo->flash_class],
- bank->name, bank->base);
-
- return ERROR_OK;
-}
-
-static int kinetis_blank_check(struct flash_bank *bank)
-{
- struct kinetis_flash_bank *kinfo = bank->driver_priv;
- int result;
-
- /* suprisingly blank check does not work in VLPR and HSRUN modes */
- result = kinetis_check_run_mode(bank->target);
- if (result != ERROR_OK)
- return result;
-
- /* reset error flags */
- result = kinetis_ftfx_prepare(bank->target);
- if (result != ERROR_OK)
- return result;
-
- if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) {
- bool block_dirty = false;
- uint8_t ftfx_fstat;
-
- if (kinfo->flash_class == FC_FLEX_NVM) {
- uint8_t fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f);
- /* block operation cannot be used on FlexNVM when EEPROM backup partition is set */
- if (fcfg1_depart != 0xf && fcfg1_depart != 0)
- block_dirty = true;
- }
-
- if (!block_dirty) {
- /* check if whole bank is blank */
- result = kinetis_ftfx_command(bank->target, FTFx_CMD_BLOCKSTAT, kinfo->prog_base,
- 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
-
- if (result != ERROR_OK || (ftfx_fstat & 0x01))
- block_dirty = true;
- }
-
- if (block_dirty) {
- /* the whole bank is not erased, check sector-by-sector */
- int i;
- for (i = 0; i < bank->num_sectors; i++) {
- /* normal margin */
- result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTSTAT,
- kinfo->prog_base + bank->sectors[i].offset,
- 1, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat);
-
- if (result == ERROR_OK) {
- bank->sectors[i].is_erased = !(ftfx_fstat & 0x01);
- } else {
- LOG_DEBUG("Ignoring errored PFlash sector blank-check");
- bank->sectors[i].is_erased = -1;
- }
- }
- } else {
- /* the whole bank is erased, update all sectors */
- int i;
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
- }
- } else {
- LOG_WARNING("kinetis_blank_check not supported yet for FlexRAM");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-
-COMMAND_HANDLER(kinetis_nvm_partition)
-{
- int result, i;
- unsigned long par, log2 = 0, ee1 = 0, ee2 = 0;
- enum { SHOW_INFO, DF_SIZE, EEBKP_SIZE } sz_type = SHOW_INFO;
- bool enable;
- uint8_t load_flex_ram = 1;
- uint8_t ee_size_code = 0x3f;
- uint8_t flex_nvm_partition_code = 0;
- uint8_t ee_split = 3;
- struct target *target = get_current_target(CMD_CTX);
- struct flash_bank *bank;
- struct kinetis_flash_bank *kinfo;
- uint32_t sim_fcfg1;
-
- if (CMD_ARGC >= 2) {
- if (strcmp(CMD_ARGV[0], "dataflash") == 0)
- sz_type = DF_SIZE;
- else if (strcmp(CMD_ARGV[0], "eebkp") == 0)
- sz_type = EEBKP_SIZE;
-
- par = strtoul(CMD_ARGV[1], NULL, 10);
- while (par >> (log2 + 3))
- log2++;
- }
- switch (sz_type) {
- case SHOW_INFO:
- result = target_read_u32(target, SIM_FCFG1, &sim_fcfg1);
- if (result != ERROR_OK)
- return result;
-
- flex_nvm_partition_code = (uint8_t)((sim_fcfg1 >> 8) & 0x0f);
- switch (flex_nvm_partition_code) {
- case 0:
- command_print(CMD_CTX, "No EEPROM backup, data flash only");
- break;
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- command_print(CMD_CTX, "EEPROM backup %d KB", 4 << flex_nvm_partition_code);
- break;
- case 8:
- command_print(CMD_CTX, "No data flash, EEPROM backup only");
- break;
- case 0x9:
- case 0xA:
- case 0xB:
- case 0xC:
- case 0xD:
- case 0xE:
- command_print(CMD_CTX, "data flash %d KB", 4 << (flex_nvm_partition_code & 7));
- break;
- case 0xf:
- command_print(CMD_CTX, "No EEPROM backup, data flash only (DEPART not set)");
- break;
- default:
- command_print(CMD_CTX, "Unsupported EEPROM backup size code 0x%02" PRIx8, flex_nvm_partition_code);
- }
- return ERROR_OK;
-
- case DF_SIZE:
- flex_nvm_partition_code = 0x8 | log2;
- break;
-
- case EEBKP_SIZE:
- flex_nvm_partition_code = log2;
- break;
- }
-
- if (CMD_ARGC == 3)
- ee1 = ee2 = strtoul(CMD_ARGV[2], NULL, 10) / 2;
- else if (CMD_ARGC >= 4) {
- ee1 = strtoul(CMD_ARGV[2], NULL, 10);
- ee2 = strtoul(CMD_ARGV[3], NULL, 10);
- }
-
- enable = ee1 + ee2 > 0;
- if (enable) {
- for (log2 = 2; ; log2++) {
- if (ee1 + ee2 == (16u << 10) >> log2)
- break;
- if (ee1 + ee2 > (16u << 10) >> log2 || log2 >= 9) {
- LOG_ERROR("Unsupported EEPROM size");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
-
- if (ee1 * 3 == ee2)
- ee_split = 1;
- else if (ee1 * 7 == ee2)
- ee_split = 0;
- else if (ee1 != ee2) {
- LOG_ERROR("Unsupported EEPROM sizes ratio");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- ee_size_code = log2 | ee_split << 4;
- }
-
- if (CMD_ARGC >= 5)
- COMMAND_PARSE_ON_OFF(CMD_ARGV[4], enable);
- if (enable)
- load_flex_ram = 0;
-
- LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8,
- flex_nvm_partition_code, ee_size_code);
-
- result = kinetis_check_run_mode(target);
- if (result != ERROR_OK)
- return result;
-
- /* reset error flags */
- result = kinetis_ftfx_prepare(target);
- if (result != ERROR_OK)
- return result;
-
- result = kinetis_ftfx_command(target, FTFx_CMD_PGMPART, load_flex_ram,
- ee_size_code, flex_nvm_partition_code, 0, 0,
- 0, 0, 0, 0, NULL);
- if (result != ERROR_OK)
- return result;
-
- command_print(CMD_CTX, "FlexNVM partition set. Please reset MCU.");
-
- for (i = 1; i < 4; i++) {
- bank = get_flash_bank_by_num_noprobe(i);
- if (bank == NULL)
- break;
-
- kinfo = bank->driver_priv;
- if (kinfo && kinfo->flash_class == FC_FLEX_NVM)
- kinfo->probed = false; /* re-probe before next use */
- }
-
- command_print(CMD_CTX, "FlexNVM banks will be re-probed to set new data flash size.");
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(kinetis_fcf_source_handler)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 1) {
- if (strcmp(CMD_ARGV[0], "write") == 0)
- allow_fcf_writes = true;
- else if (strcmp(CMD_ARGV[0], "protection") == 0)
- allow_fcf_writes = false;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (allow_fcf_writes) {
- command_print(CMD_CTX, "Arbitrary Flash Configuration Field writes enabled.");
- command_print(CMD_CTX, "Protection info writes to FCF disabled.");
- LOG_WARNING("BEWARE: incorrect flash configuration may permanently lock the device.");
- } else {
- command_print(CMD_CTX, "Protection info writes to Flash Configuration Field enabled.");
- command_print(CMD_CTX, "Arbitrary FCF writes disabled. Mode safe from unwanted locking of the device.");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(kinetis_fopt_handler)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 1)
- fcf_fopt = (uint8_t)strtoul(CMD_ARGV[0], NULL, 0);
- else
- command_print(CMD_CTX, "FCF_FOPT 0x%02" PRIx8, fcf_fopt);
-
- return ERROR_OK;
-}
-
-
-static const struct command_registration kinetis_security_command_handlers[] = {
- {
- .name = "check_security",
- .mode = COMMAND_EXEC,
- .help = "Check status of device security lock",
- .usage = "",
- .handler = kinetis_check_flash_security_status,
- },
- {
- .name = "halt",
- .mode = COMMAND_EXEC,
- .help = "Issue a halt via the MDM-AP",
- .usage = "",
- .handler = kinetis_mdm_halt,
- },
- {
- .name = "mass_erase",
- .mode = COMMAND_EXEC,
- .help = "Issue a complete flash erase via the MDM-AP",
- .usage = "",
- .handler = kinetis_mdm_mass_erase,
- },
- { .name = "reset",
- .mode = COMMAND_EXEC,
- .help = "Issue a reset via the MDM-AP",
- .usage = "",
- .handler = kinetis_mdm_reset,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration kinetis_exec_command_handlers[] = {
- {
- .name = "mdm",
- .mode = COMMAND_ANY,
- .help = "MDM-AP command group",
- .usage = "",
- .chain = kinetis_security_command_handlers,
- },
- {
- .name = "disable_wdog",
- .mode = COMMAND_EXEC,
- .help = "Disable the watchdog timer",
- .usage = "",
- .handler = kinetis_disable_wdog_handler,
- },
- {
- .name = "nvm_partition",
- .mode = COMMAND_EXEC,
- .help = "Show/set data flash or EEPROM backup size in kilobytes,"
- " set two EEPROM sizes in bytes and FlexRAM loading during reset",
- .usage = "('info'|'dataflash' size|'eebkp' size) [eesize1 eesize2] ['on'|'off']",
- .handler = kinetis_nvm_partition,
- },
- {
- .name = "fcf_source",
- .mode = COMMAND_EXEC,
- .help = "Use protection as a source for Flash Configuration Field or allow writing arbitrary values to the FCF"
- " Mode 'protection' is safe from unwanted locking of the device.",
- .usage = "['protection'|'write']",
- .handler = kinetis_fcf_source_handler,
- },
- {
- .name = "fopt",
- .mode = COMMAND_EXEC,
- .help = "FCF_FOPT value source in 'kinetis fcf_source protection' mode",
- .usage = "[num]",
- .handler = kinetis_fopt_handler,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration kinetis_command_handler[] = {
- {
- .name = "kinetis",
- .mode = COMMAND_ANY,
- .help = "Kinetis flash controller commands",
- .usage = "",
- .chain = kinetis_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-
-
-struct flash_driver kinetis_flash = {
- .name = "kinetis",
- .commands = kinetis_command_handler,
- .flash_bank_command = kinetis_flash_bank_command,
- .erase = kinetis_erase,
- .protect = kinetis_protect,
- .write = kinetis_write,
- .read = default_flash_read,
- .probe = kinetis_probe,
- .auto_probe = kinetis_auto_probe,
- .erase_check = kinetis_blank_check,
- .protect_check = kinetis_protect_check,
- .info = kinetis_info,
-};
diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c
deleted file mode 100644
index 636fcc2..0000000
--- a/src/flash/nor/kinetis_ke.c
+++ /dev/null
@@ -1,1314 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Ivan Meleca *
- * ivan@artekit.eu *
- * *
- * Modified from kinetis.c *
- * *
- * Copyright (C) 2011 by Mathias Kuester *
- * kesmtp@freenet.de *
- * *
- * Copyright (C) 2011 sleep(5) ltd *
- * tomas@sleepfive.com *
- * *
- * Copyright (C) 2012 by Christopher D. Kilgour *
- * techie at whiterocker.com *
- * *
- * Copyright (C) 2013 Nemui Trinomius *
- * nemuisan_kawausogasuki@live.jp *
- * *
- * Copyright (C) 2015 Tomas Vanek *
- * vanekt@fbl.cz *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-#include <target/cortex_m.h>
-
-/* Addresses */
-#define SIM_SRSID 0x40048000
-#define ICS_C1 0x40064000
-#define ICS_C2 0x40064001
-#define ICS_C3 0x40064002
-#define ICS_C4 0x40064003
-#define ICS_S 0x40064004
-#define SIM_BUSDIV 0x40048018
-#define SIM_CLKDIV_KE06 0x40048024
-#define SIM_CLKDIV_KE04_44_64_80 0x40048024
-#define SIM_CLKDIV_KE04_16_20_24 0x4004801C
-#define WDOG_CS1 0x40052000
-
-#define ICS_C2_BDIV_MASK 0xE0
-#define ICS_C2_BDIV_SHIFT 5
-#define ICS_C2_BDIV(x) (((uint8_t)(((uint8_t)(x))<<ICS_C2_BDIV_SHIFT))&ICS_C2_BDIV_MASK)
-#define ICS_S_LOCK_MASK 0x40
-#define ICS_C4_SCFTRIM_MASK 0x1
-#define SIM_CLKDIV_OUTDIV2_MASK 0x1000000
-#define FTMRX_FCLKDIV_FDIV_MASK 0x3F
-#define FTMRX_FCLKDIV_FDIV_SHIFT 0
-#define FTMRX_FCLKDIV_FDIV(x) (((uint8_t)(((uint8_t)(x))<<FTMRX_FCLKDIV_FDIV_SHIFT))&FTMRX_FCLKDIV_FDIV_MASK)
-#define FTMRX_FCLKDIV_FDIVLCK_MASK 0x40
-#define FTMRX_FCLKDIV_FDIVLCK_SHIFT 6
-#define FTMRX_FCLKDIV_FDIVLD_MASK 0x80
-#define FTMRX_FCLKDIV_FDIVLD_SHIFT 7
-#define FTMRX_FSTAT_CCIF_MASK 0x80
-#define FTMRX_FSTAT_MGSTAT0_MASK 0x01
-#define FTMRX_FSTAT_MGSTAT1_MASK 0x02
-
-/* Commands */
-#define FTMRX_CMD_ALLERASED 0x01
-#define FTMRX_CMD_BLOCKERASED 0x02
-#define FTMRX_CMD_SECTIONERASED 0x03
-#define FTMRX_CMD_READONCE 0x04
-#define FTMRX_CMD_PROGFLASH 0x06
-#define FTMRX_CMD_PROGONCE 0x07
-#define FTMRX_CMD_ERASEALL 0x08
-#define FTMRX_CMD_ERASEBLOCK 0x09
-#define FTMRX_CMD_ERASESECTOR 0x0A
-#define FTMRX_CMD_UNSECURE 0x0B
-#define FTMRX_CMD_VERIFYACCESS 0x0C
-#define FTMRX_CMD_SETMARGINLVL 0x0D
-#define FTMRX_CMD_SETFACTORYLVL 0x0E
-#define FTMRX_CMD_CONFIGNVM 0x0F
-
-/* Error codes */
-#define FTMRX_ERROR_ACCERR 0x20
-#define FTMRX_ERROR_FPVIOL 0x10
-
-#define KINETIS_KE_SRSID_FAMID(x) ((x >> 28) & 0x0F)
-#define KINETIS_KE_SRSID_SUBFAMID(x) ((x >> 24) & 0x0F)
-#define KINETIS_KE_SRSID_PINCOUNT(x) ((x >> 16) & 0x0F)
-
-#define KINETIS_KE_SRSID_KEX2 0x02
-#define KINETIS_KE_SRSID_KEX4 0x04
-#define KINETIS_KE_SRSID_KEX6 0x06
-
-struct kinetis_ke_flash_bank {
- uint32_t sector_size;
- uint32_t protection_size;
-
- uint32_t sim_srsid;
- uint32_t ftmrx_fclkdiv_addr;
- uint32_t ftmrx_fccobix_addr;
- uint32_t ftmrx_fstat_addr;
- uint32_t ftmrx_fprot_addr;
- uint32_t ftmrx_fccobhi_addr;
- uint32_t ftmrx_fccoblo_addr;
-};
-
-#define MDM_REG_STAT 0x00
-#define MDM_REG_CTRL 0x04
-#define MDM_REG_ID 0xfc
-
-#define MDM_STAT_FMEACK (1<<0)
-#define MDM_STAT_FREADY (1<<1)
-#define MDM_STAT_SYSSEC (1<<2)
-#define MDM_STAT_SYSRES (1<<3)
-#define MDM_STAT_FMEEN (1<<5)
-#define MDM_STAT_BACKDOOREN (1<<6)
-#define MDM_STAT_LPEN (1<<7)
-#define MDM_STAT_VLPEN (1<<8)
-#define MDM_STAT_LLSMODEXIT (1<<9)
-#define MDM_STAT_VLLSXMODEXIT (1<<10)
-#define MDM_STAT_CORE_HALTED (1<<16)
-#define MDM_STAT_CORE_SLEEPDEEP (1<<17)
-#define MDM_STAT_CORESLEEPING (1<<18)
-
-#define MEM_CTRL_FMEIP (1<<0)
-#define MEM_CTRL_DBG_DIS (1<<1)
-#define MEM_CTRL_DBG_REQ (1<<2)
-#define MEM_CTRL_SYS_RES_REQ (1<<3)
-#define MEM_CTRL_CORE_HOLD_RES (1<<4)
-#define MEM_CTRL_VLLSX_DBG_REQ (1<<5)
-#define MEM_CTRL_VLLSX_DBG_ACK (1<<6)
-#define MEM_CTRL_VLLSX_STAT_ACK (1<<7)
-
-#define MDM_ACCESS_TIMEOUT 3000 /* iterations */
-
-static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
-{
- int retval;
- LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value);
-
- retval = dap_queue_ap_write(dap_ap(dap, 1), reg, value);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: failed to queue a write request");
- return retval;
- }
-
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: dap_run failed");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
-{
- int retval;
- retval = dap_queue_ap_read(dap_ap(dap, 1), reg, result);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: failed to queue a read request");
- return retval;
- }
-
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_DEBUG("MDM: dap_run failed");
- return retval;
- }
-
- LOG_DEBUG("MDM_REG[0x%02x]: %08" PRIX32, reg, *result);
- return ERROR_OK;
-}
-
-static int kinetis_ke_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value)
-{
- uint32_t val;
- int retval;
- int timeout = MDM_ACCESS_TIMEOUT;
-
- do {
- retval = kinetis_ke_mdm_read_register(dap, reg, &val);
- if (retval != ERROR_OK || (val & mask) == value)
- return retval;
-
- alive_sleep(1);
- } while (timeout--);
-
- LOG_DEBUG("MDM: polling timed out");
- return ERROR_FAIL;
-}
-
-static int kinetis_ke_prepare_flash(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
- uint8_t c2, c3, c4, s = 0;
- uint16_t trim_value = 0;
- uint16_t timeout = 0;
- uint32_t bus_clock = 0;
- uint32_t bus_reg_val = 0;
- uint32_t bus_reg_addr = 0;
- uint32_t flash_clk_div;
- uint8_t fclkdiv;
- int result;
-
- /*
- * The RM states that the flash clock has to be set to 1MHz for writing and
- * erasing operations (otherwise it can damage the flash).
- * This function configures the entire clock tree to make sure we
- * run at the specified clock. We'll set FEI mode running from the ~32KHz
- * internal clock. So we need to:
- * - Trim internal clock.
- * - Configure the divider for ICSOUTCLK (ICS module).
- * - Configure the divider to get a bus clock (SIM module).
- * - Configure the flash clock that depends on the bus clock.
- *
- * For MKE02_40 and MKE02_20 we set ICSOUTCLK = 20MHz and bus clock = 20MHz.
- * For MKE04 and MKE06 we run at ICSOUTCLK = 48MHz and bus clock = 24MHz.
- */
-
- /*
- * Trim internal clock
- */
- switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
-
- case KINETIS_KE_SRSID_KEX2:
- /* Both KE02_20 and KE02_40 should get the same trim value */
- trim_value = 0x4C;
- break;
-
- case KINETIS_KE_SRSID_KEX4:
- trim_value = 0x54;
- break;
-
- case KINETIS_KE_SRSID_KEX6:
- trim_value = 0x58;
- break;
- }
-
- result = target_read_u8(target, ICS_C4, &c4);
- if (result != ERROR_OK)
- return result;
-
- c3 = trim_value;
- c4 = (c4 & ~(ICS_C4_SCFTRIM_MASK)) | ((trim_value >> 8) & 0x01);
-
- result = target_write_u8(target, ICS_C3, c3);
- if (result != ERROR_OK)
- return result;
-
- result = target_write_u8(target, ICS_C4, c4);
- if (result != ERROR_OK)
- return result;
-
- result = target_read_u8(target, ICS_S, &s);
- if (result != ERROR_OK)
- return result;
-
- /* Wait */
- while (!(s & ICS_S_LOCK_MASK)) {
-
- if (timeout <= 1000) {
- timeout++;
- alive_sleep(1);
- } else {
- return ERROR_FAIL;
- }
-
- result = target_read_u8(target, ICS_S, &s);
- if (result != ERROR_OK)
- return result;
- }
-
- /* ... trim done ... */
-
- /*
- * Configure SIM (bus clock)
- */
- switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
-
- /* KE02 sub-family operates on SIM_BUSDIV */
- case KINETIS_KE_SRSID_KEX2:
- bus_reg_val = 0;
- bus_reg_addr = SIM_BUSDIV;
- bus_clock = 20000000;
- break;
-
- /* KE04 and KE06 sub-family operates on SIM_CLKDIV
- * Clocks are divided by:
- * DIV1 = core clock = 48MHz
- * DIV2 = bus clock = 24Mhz
- * DIV3 = timer clocks
- * So we need to configure SIM_CLKDIV, DIV1 and DIV2 value
- */
- case KINETIS_KE_SRSID_KEX4:
- /* KE04 devices have the SIM_CLKDIV register at a different offset
- * depending on the pin count. */
- switch (KINETIS_KE_SRSID_PINCOUNT(kinfo->sim_srsid)) {
-
- /* 16, 20 and 24 pins */
- case 1:
- case 2:
- case 3:
- bus_reg_addr = SIM_CLKDIV_KE04_16_20_24;
- break;
-
- /* 44, 64 and 80 pins */
- case 5:
- case 7:
- case 8:
- bus_reg_addr = SIM_CLKDIV_KE04_44_64_80;
- break;
-
- default:
- LOG_ERROR("KE04 - Unknown pin count");
- return ERROR_FAIL;
- }
-
- bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
- bus_clock = 24000000;
- break;
-
- case KINETIS_KE_SRSID_KEX6:
- bus_reg_val = SIM_CLKDIV_OUTDIV2_MASK;
- bus_reg_addr = SIM_CLKDIV_KE06;
- bus_clock = 24000000;
- break;
- }
-
- result = target_write_u32(target, bus_reg_addr, bus_reg_val);
- if (result != ERROR_OK)
- return result;
-
- /*
- * Configure ICS to FEI (internal source)
- */
- result = target_read_u8(target, ICS_C2, &c2);
- if (result != ERROR_OK)
- return result;
-
- c2 &= ~ICS_C2_BDIV_MASK;
-
- switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
-
- case KINETIS_KE_SRSID_KEX2:
- /* Note: since there are two KE02 types, the KE02_40 @ 40MHz and the
- * KE02_20 @ 20MHz, we divide here the ~40MHz ICSFLLCLK down to 20MHz,
- * for compatibility.
- */
- c2 |= ICS_C2_BDIV(1);
- break;
-
- case KINETIS_KE_SRSID_KEX4:
- case KINETIS_KE_SRSID_KEX6:
- /* For KE04 and KE06, the ICSFLLCLK can be 48MHz. */
- c2 |= ICS_C2_BDIV(0);
- break;
- }
-
- result = target_write_u8(target, ICS_C2, c2);
- if (result != ERROR_OK)
- return result;
-
- /* Internal clock as reference (IREFS = 1) */
- result = target_write_u8(target, ICS_C1, 4);
- if (result != ERROR_OK)
- return result;
-
- /* Wait for FLL to lock */
- result = target_read_u8(target, ICS_S, &s);
- if (result != ERROR_OK)
- return result;
-
- while (!(s & ICS_S_LOCK_MASK)) {
-
- if (timeout <= 1000) {
- timeout++;
- alive_sleep(1);
- } else {
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- result = target_read_u8(target, ICS_S, &s);
- if (result != ERROR_OK)
- return result;
- }
-
- /*
- * Configure flash clock to 1MHz.
- */
- flash_clk_div = bus_clock / 1000000L - 1;
-
- /* Check if the FCLKDIV register is locked */
- result = target_read_u8(target, kinfo->ftmrx_fclkdiv_addr, &fclkdiv);
- if (result != ERROR_OK)
- return result;
-
- if (!(fclkdiv & FTMRX_FCLKDIV_FDIVLCK_MASK)) {
- /* Unlocked. Check if the register was configured, and if so, if it has the right value */
- if ((fclkdiv & FTMRX_FCLKDIV_FDIVLD_MASK) &&
- ((fclkdiv & FTMRX_FCLKDIV_FDIV_MASK) != FTMRX_FCLKDIV_FDIV(flash_clk_div))) {
- LOG_WARNING("Flash clock was already set and contains an invalid value.");
- LOG_WARNING("Please reset the target.");
- return ERROR_FAIL;
- }
-
- /* Finally, configure the flash clock */
- fclkdiv = (fclkdiv & ~(FTMRX_FCLKDIV_FDIV_MASK)) | FTMRX_FCLKDIV_FDIV(flash_clk_div);
- result = target_write_u8(target, kinfo->ftmrx_fclkdiv_addr, fclkdiv);
- if (result != ERROR_OK)
- return result;
- } else {
- /* Locked. Check if the current value is correct. */
- if ((fclkdiv & FTMRX_FCLKDIV_FDIV_MASK) != FTMRX_FCLKDIV_FDIV(flash_clk_div)) {
- LOG_WARNING("Flash clock register is locked and contains an invalid value.");
- LOG_WARNING("Please reset the target.");
- return ERROR_FAIL;
- }
- }
-
- LOG_INFO("Flash clock ready");
- return ERROR_OK;
-}
-
-int kinetis_ke_stop_watchdog(struct target *target)
-{
- struct working_area *watchdog_algorithm;
- struct armv7m_algorithm armv7m_info;
- int retval;
- uint8_t cs1;
-
- static const uint8_t watchdog_code[] = {
-#include "../../../contrib/loaders/flash/kinetis_ke/kinetis_ke_watchdog.inc"
- };
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Check if the watchdog is enabled */
- retval = target_read_u8(target, WDOG_CS1, &cs1);
- if (retval != ERROR_OK)
- return retval;
-
- if (!(cs1 & 0x80)) {
- /* Already stopped */
- return ERROR_OK;
- }
-
- /* allocate working area with watchdog code */
- if (target_alloc_working_area(target, sizeof(watchdog_code), &watchdog_algorithm) != ERROR_OK) {
- LOG_WARNING("No working area available for watchdog algorithm");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, watchdog_algorithm->address,
- sizeof(watchdog_code), watchdog_code);
- if (retval != ERROR_OK)
- return retval;
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- retval = target_run_algorithm(target, 0, NULL, 0, NULL,
- watchdog_algorithm->address, 0, 100000, &armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing Kinetis KE watchdog algorithm");
- retval = ERROR_FAIL;
- } else {
- LOG_INFO("Watchdog stopped");
- }
-
- target_free_working_area(target, watchdog_algorithm);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(kinetis_ke_disable_wdog_handler)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- if (CMD_ARGC > 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return kinetis_ke_stop_watchdog(target);
-}
-
-COMMAND_HANDLER(kinetis_ke_mdm_mass_erase)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
-
- if (!dap) {
- LOG_ERROR("Cannot perform mass erase with a high-level adapter");
- return ERROR_FAIL;
- }
-
- int retval;
-
- /* According to chapter 18.3.7.2 of the KE02 reference manual */
-
- /* assert SRST */
- if (jtag_get_reset_config() & RESET_HAS_SRST)
- adapter_assert_reset();
-
- /*
- * 1. Reset the device by asserting RESET pin or DAP_CTRL[3]
- */
- retval = kinetis_ke_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_SYS_RES_REQ);
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * ... Read the MDM-AP status register until the Flash Ready bit sets...
- */
- retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_STAT,
- MDM_STAT_FREADY | MDM_STAT_SYSRES,
- MDM_STAT_FREADY);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM : flash ready timeout");
- return retval;
- }
-
- /*
- * 2. Set DAP_CTRL[0] bit to invoke debug mass erase via SWD
- * 3. Release reset by deasserting RESET pin or DAP_CTRL[3] bit via SWD.
- */
- retval = kinetis_ke_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_FMEIP);
- if (retval != ERROR_OK)
- return retval;
-
- /* As a sanity check make sure that device started mass erase procedure */
- retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_STAT,
- MDM_STAT_FMEACK, MDM_STAT_FMEACK);
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * 4. Wait till DAP_CTRL[0] bit is cleared (after mass erase completes,
- * DAP_CTRL[0] bit is cleared automatically).
- */
- retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_CTRL,
- MEM_CTRL_FMEIP,
- 0);
- if (retval != ERROR_OK)
- return retval;
-
- if (jtag_get_reset_config() & RESET_HAS_SRST)
- adapter_deassert_reset();
-
- return ERROR_OK;
-}
-
-static const uint32_t kinetis_ke_known_mdm_ids[] = {
- 0x001C0020, /* Kinetis-L/M/V/E/KE Series */
-};
-
-/*
- * This function implements the procedure to connect to
- * SWD/JTAG on Kinetis K and L series of devices as it is described in
- * AN4835 "Production Flash Programming Best Practices for Kinetis K-
- * and L-series MCUs" Section 4.1.1
- */
-COMMAND_HANDLER(kinetis_ke_check_flash_security_status)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
-
- if (!dap) {
- LOG_WARNING("Cannot check flash security status with a high-level adapter");
- return ERROR_OK;
- }
-
- uint32_t val;
- int retval;
-
- /*
- * ... The MDM-AP ID register can be read to verify that the
- * connection is working correctly...
- */
- retval = kinetis_ke_mdm_read_register(dap, MDM_REG_ID, &val);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to read ID register");
- goto fail;
- }
-
- bool found = false;
- for (size_t i = 0; i < ARRAY_SIZE(kinetis_ke_known_mdm_ids); i++) {
- if (val == kinetis_ke_known_mdm_ids[i]) {
- found = true;
- break;
- }
- }
-
- if (!found)
- LOG_WARNING("MDM: unknown ID %08" PRIX32, val);
-
- /*
- * ... Read the MDM-AP status register until the Flash Ready bit sets...
- */
- retval = kinetis_ke_mdm_poll_register(dap, MDM_REG_STAT,
- MDM_STAT_FREADY,
- MDM_STAT_FREADY);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: flash ready timeout");
- goto fail;
- }
-
- /*
- * ... Read the System Security bit to determine if security is enabled.
- * If System Security = 0, then proceed. If System Security = 1, then
- * communication with the internals of the processor, including the
- * flash, will not be possible without issuing a mass erase command or
- * unsecuring the part through other means (backdoor key unlock)...
- */
- retval = kinetis_ke_mdm_read_register(dap, MDM_REG_STAT, &val);
- if (retval != ERROR_OK) {
- LOG_ERROR("MDM: failed to read MDM_REG_STAT");
- goto fail;
- }
-
- if (val & MDM_STAT_SYSSEC) {
- jtag_poll_set_enabled(false);
-
- LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
- LOG_WARNING("**** ****");
- LOG_WARNING("**** Your Kinetis MCU is in secured state, which means that, ****");
- LOG_WARNING("**** with exception for very basic communication, JTAG/SWD ****");
- LOG_WARNING("**** interface will NOT work. In order to restore its ****");
- LOG_WARNING("**** functionality please issue 'kinetis_ke mdm mass_erase' ****");
- LOG_WARNING("**** command, power cycle the MCU and restart OpenOCD. ****");
- LOG_WARNING("**** ****");
- LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********");
- } else {
- LOG_INFO("MDM: Chip is unsecured. Continuing.");
- jtag_poll_set_enabled(true);
- }
-
- return ERROR_OK;
-
-fail:
- LOG_ERROR("MDM: Failed to check security status of the MCU. Cannot proceed further");
- jtag_poll_set_enabled(false);
- return retval;
-}
-
-FLASH_BANK_COMMAND_HANDLER(kinetis_ke_flash_bank_command)
-{
- struct kinetis_ke_flash_bank *bank_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_INFO("add flash_bank kinetis_ke %s", bank->name);
-
- bank_info = malloc(sizeof(struct kinetis_ke_flash_bank));
-
- memset(bank_info, 0, sizeof(struct kinetis_ke_flash_bank));
-
- bank->driver_priv = bank_info;
-
- return ERROR_OK;
-}
-
-/* Kinetis Program-LongWord Microcodes */
-static uint8_t kinetis_ke_flash_write_code[] = {
-#include "../../../contrib/loaders/flash/kinetis_ke/kinetis_ke_flash.inc"
-};
-
-static int kinetis_ke_write_words(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t words)
-{
- struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t ram_buffer_size = 512 + 16;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[4];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
- uint32_t flash_code_size;
-
- LOG_INFO("Kinetis KE: FLASH Write ...");
-
- /* allocate working area with flash programming code */
- if (target_alloc_working_area(target, sizeof(kinetis_ke_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* Patch the FTMRx registers addresses */
- flash_code_size = sizeof(kinetis_ke_flash_write_code);
- buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-16], 0, 32, kinfo->ftmrx_fstat_addr);
- buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-12], 0, 32, kinfo->ftmrx_fccobix_addr);
- buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-8], 0, 32, kinfo->ftmrx_fccobhi_addr);
- buf_set_u32(&kinetis_ke_flash_write_code[flash_code_size-4], 0, 32, kinfo->ftmrx_fccoblo_addr);
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(kinetis_ke_flash_write_code), kinetis_ke_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- if (target_alloc_working_area(target, ram_buffer_size, &source) != ERROR_OK) {
- /* free working area, write algorithm already allocated */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("No large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_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);
-
- buf_set_u32(reg_params[0].value, 0, 32, address);
- buf_set_u32(reg_params[1].value, 0, 32, words);
- buf_set_u32(reg_params[2].value, 0, 32, source->address);
- buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
-
- retval = target_run_flash_async_algorithm(target, buffer, words, 4,
- 0, NULL,
- 4, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (retval == ERROR_FLASH_OPERATION_FAILED) {
- if (buf_get_u32(reg_params[0].value, 0, 32) & FTMRX_ERROR_ACCERR)
- LOG_ERROR("flash access error");
-
- if (buf_get_u32(reg_params[0].value, 0, 32) & FTMRX_ERROR_FPVIOL)
- LOG_ERROR("flash protection violation");
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- 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 retval;
-}
-
-static int kinetis_ke_protect(struct flash_bank *bank, int set, int first, int last)
-{
- LOG_WARNING("kinetis_ke_protect not supported yet");
- /* FIXME: TODO */
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- return ERROR_FLASH_BANK_INVALID;
-}
-
-static int kinetis_ke_protect_check(struct flash_bank *bank)
-{
- struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int result;
- uint8_t fprot;
- uint8_t fpopen, fpldis, fphdis;
- uint8_t fphs, fpls;
- uint32_t lprot_size = 0, hprot_size = 0;
- uint32_t lprot_to = 0, hprot_from = 0;
-
- /* read protection register */
- result = target_read_u8(bank->target, kinfo->ftmrx_fprot_addr, &fprot);
-
- if (result != ERROR_OK)
- return result;
-
- fpopen = fprot & 0x80;
- fpldis = fprot & 0x04;
- fphdis = fprot & 0x20;
- fphs = (fprot >> 3) & 0x03;
- fpls = fprot & 0x03;
-
- /* Fully unprotected? */
- if (fpopen && fpldis && fphdis) {
- LOG_WARNING("No flash protection found.");
-
- for (uint32_t i = 0; i < (uint32_t) bank->num_sectors; i++)
- bank->sectors[i].is_protected = 0;
-
- kinfo->protection_size = 0;
- } else {
- LOG_WARNING("Flash protected. FPOPEN=%i FPLDIS=%i FPHDIS=%i FPLS=%i FPHS=%i", \
- fpopen ? 1 : 0, fpldis ? 1 : 0, fphdis ? 1 : 0, fpls, fphs);
-
- /* Retrieve which region is protected and how much */
- if (fpopen) {
- if (fpldis == 0)
- lprot_size = (kinfo->sector_size * 4) << fpls;
-
- if (fphdis == 0)
- hprot_size = (kinfo->sector_size * 2) << fphs;
- } else {
- if (fpldis == 1)
- lprot_size = (kinfo->sector_size * 4) << fpls;
-
- if (fphdis == 1)
- hprot_size = (kinfo->sector_size * 2) << fphs;
- }
-
- kinfo->protection_size = lprot_size + hprot_size;
-
- /* lprot_to indicates up to where the lower region is protected */
- lprot_to = lprot_size / kinfo->sector_size;
-
- /* hprot_from indicates from where the upper region is protected */
- hprot_from = (0x8000 - hprot_size) / kinfo->sector_size;
-
- for (uint32_t i = 0; i < (uint32_t) bank->num_sectors; i++) {
-
- /* Check if the sector is in the lower region */
- if (bank->sectors[i].offset < 0x4000) {
- /* Compare the sector start address against lprot_to */
- if (lprot_to && (i < lprot_to))
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
-
- /* Check if the sector is between the lower and upper region
- * OR after the upper region */
- } else if (bank->sectors[i].offset < 0x6000 || bank->sectors[i].offset >= 0x8000) {
- /* If fpopen is 1 then these regions are protected */
- if (fpopen)
- bank->sectors[i].is_protected = 0;
- else
- bank->sectors[i].is_protected = 1;
-
- /* Check if the sector is in the upper region */
- } else if (bank->sectors[i].offset < 0x8000) {
- if (hprot_from && (i > hprot_from))
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-static int kinetis_ke_ftmrx_command(struct flash_bank *bank, uint8_t count,
- uint8_t *FCCOBIX, uint8_t *FCCOBHI, uint8_t *FCCOBLO, uint8_t *fstat)
-{
- uint8_t i;
- int result;
- struct target *target = bank->target;
- struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
- uint32_t timeout = 0;
-
- /* Clear error flags */
- result = target_write_u8(target, kinfo->ftmrx_fstat_addr, 0x30);
- if (result != ERROR_OK)
- return result;
-
- for (i = 0; i < count; i++) {
- /* Write index */
- result = target_write_u8(target, kinfo->ftmrx_fccobix_addr, FCCOBIX[i]);
- if (result != ERROR_OK)
- return result;
-
- /* Write high part */
- result = target_write_u8(target, kinfo->ftmrx_fccobhi_addr, FCCOBHI[i]);
- if (result != ERROR_OK)
- return result;
-
- /* Write low part (that is not always required) */
- if (FCCOBLO) {
- result = target_write_u8(target, kinfo->ftmrx_fccoblo_addr, FCCOBLO[i]);
- if (result != ERROR_OK)
- return result;
- }
- }
-
- /* Launch the command */
- result = target_write_u8(target, kinfo->ftmrx_fstat_addr, 0x80);
- if (result != ERROR_OK)
- return result;
-
- /* Wait for it to finish */
- result = target_read_u8(target, kinfo->ftmrx_fstat_addr, fstat);
- if (result != ERROR_OK)
- return result;
-
- while (!(*fstat & FTMRX_FSTAT_CCIF_MASK)) {
- if (timeout <= 1000) {
- timeout++;
- alive_sleep(1);
- } else {
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- result = target_read_u8(target, kinfo->ftmrx_fstat_addr, fstat);
- if (result != ERROR_OK)
- return result;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(kinetis_ke_securing_test)
-{
- int result;
- struct target *target = get_current_target(CMD_CTX);
- struct flash_bank *bank = NULL;
- uint32_t address;
-
- uint8_t FCCOBIX[2], FCCOBHI[2], FCCOBLO[2], fstat;
-
- result = get_flash_bank_by_addr(target, 0x00000000, true, &bank);
- if (result != ERROR_OK)
- return result;
-
- assert(bank != NULL);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- address = bank->base + 0x00000400;
-
- FCCOBIX[0] = 0;
- FCCOBHI[0] = FTMRX_CMD_ERASESECTOR;
- FCCOBLO[0] = address >> 16;
-
- FCCOBIX[1] = 1;
- FCCOBHI[1] = address >> 8;
- FCCOBLO[1] = address;
-
- return kinetis_ke_ftmrx_command(bank, 2, FCCOBIX, FCCOBHI, FCCOBLO, &fstat);
-}
-
-static int kinetis_ke_erase(struct flash_bank *bank, int first, int last)
-{
- int result, i;
- uint8_t FCCOBIX[2], FCCOBHI[2], FCCOBLO[2], fstat;
- bool fcf_erased = false;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first > bank->num_sectors) || (last > bank->num_sectors))
- return ERROR_FLASH_OPERATION_FAILED;
-
- result = kinetis_ke_prepare_flash(bank);
- if (result != ERROR_OK)
- return result;
-
- for (i = first; i <= last; i++) {
- FCCOBIX[0] = 0;
- FCCOBHI[0] = FTMRX_CMD_ERASESECTOR;
- FCCOBLO[0] = (bank->base + bank->sectors[i].offset) >> 16;
-
- FCCOBIX[1] = 1;
- FCCOBHI[1] = (bank->base + bank->sectors[i].offset) >> 8;
- FCCOBLO[1] = (bank->base + bank->sectors[i].offset);
-
- result = kinetis_ke_ftmrx_command(bank, 2, FCCOBIX, FCCOBHI, FCCOBLO, &fstat);
-
- if (result != ERROR_OK) {
- LOG_WARNING("erase sector %d failed", i);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- bank->sectors[i].is_erased = 1;
-
- if (i == 2)
- fcf_erased = true;
- }
-
- if (fcf_erased) {
- LOG_WARNING
- ("flash configuration field erased, please reset the device");
- }
-
- return ERROR_OK;
-}
-
-static int kinetis_ke_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- int result;
- uint8_t *new_buffer = NULL;
- uint32_t words = count / 4;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset > bank->size)
- return ERROR_FLASH_BANK_INVALID;
-
- if (offset & 0x3) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks the required alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- result = kinetis_ke_stop_watchdog(bank->target);
- if (result != ERROR_OK)
- return result;
-
- result = kinetis_ke_prepare_flash(bank);
- if (result != ERROR_OK)
- return result;
-
- if (count & 0x3) {
- uint32_t old_count = count;
- count = (old_count | 3) + 1;
- new_buffer = malloc(count);
- if (new_buffer == NULL) {
- LOG_ERROR("odd number of bytes to write and no memory "
- "for padding buffer");
- return ERROR_FAIL;
- }
-
- LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " "
- "and padding with 0xff", old_count, count);
-
- memset(new_buffer, 0xff, count);
- buffer = memcpy(new_buffer, buffer, old_count);
- words++;
- }
-
- result = kinetis_ke_write_words(bank, buffer, offset, words);
- free(new_buffer);
-
- return result;
-}
-
-static int kinetis_ke_probe(struct flash_bank *bank)
-{
- int result, i;
- uint32_t offset = 0;
- struct target *target = bank->target;
- struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
-
- result = target_read_u32(target, SIM_SRSID, &kinfo->sim_srsid);
- if (result != ERROR_OK)
- return result;
-
- if (KINETIS_KE_SRSID_FAMID(kinfo->sim_srsid) != 0x00) {
- LOG_ERROR("Unsupported KE family");
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
- case KINETIS_KE_SRSID_KEX2:
- LOG_INFO("KE02 sub-family");
- break;
-
- case KINETIS_KE_SRSID_KEX4:
- LOG_INFO("KE04 sub-family");
- break;
-
- case KINETIS_KE_SRSID_KEX6:
- LOG_INFO("KE06 sub-family");
- break;
-
- default:
- LOG_ERROR("Unsupported KE sub-family");
- return ERROR_FLASH_OPER_UNSUPPORTED;
- }
-
- /* We can only retrieve the ke0x part, but there is no way to know
- * the flash size, so assume the maximum flash size for the entire
- * sub family.
- */
- bank->base = 0x00000000;
- kinfo->sector_size = 512;
-
- switch (KINETIS_KE_SRSID_SUBFAMID(kinfo->sim_srsid)) {
-
- case KINETIS_KE_SRSID_KEX2:
- /* Max. 64KB */
- bank->size = 0x00010000;
- bank->num_sectors = 128;
-
- /* KE02 uses the FTMRH flash controller,
- * and registers have a different offset from the
- * FTMRE flash controller. Sort this out here.
- */
- kinfo->ftmrx_fclkdiv_addr = 0x40020000;
- kinfo->ftmrx_fccobix_addr = 0x40020002;
- kinfo->ftmrx_fstat_addr = 0x40020006;
- kinfo->ftmrx_fprot_addr = 0x40020008;
- kinfo->ftmrx_fccobhi_addr = 0x4002000A;
- kinfo->ftmrx_fccoblo_addr = 0x4002000B;
- break;
-
- case KINETIS_KE_SRSID_KEX6:
- case KINETIS_KE_SRSID_KEX4:
- /* Max. 128KB */
- bank->size = 0x00020000;
- bank->num_sectors = 256;
-
- /* KE04 and KE06 use the FTMRE flash controller,
- * and registers have a different offset from the
- * FTMRH flash controller. Sort this out here.
- */
- kinfo->ftmrx_fclkdiv_addr = 0x40020003;
- kinfo->ftmrx_fccobix_addr = 0x40020001;
- kinfo->ftmrx_fstat_addr = 0x40020005;
- kinfo->ftmrx_fprot_addr = 0x4002000B;
- kinfo->ftmrx_fccobhi_addr = 0x40020009;
- kinfo->ftmrx_fccoblo_addr = 0x40020008;
- break;
- }
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- assert(bank->num_sectors > 0);
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = kinfo->sector_size;
- offset += kinfo->sector_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- return ERROR_OK;
-}
-
-static int kinetis_ke_auto_probe(struct flash_bank *bank)
-{
- struct kinetis_ke_flash_bank *kinfo = bank->driver_priv;
-
- if (kinfo->sim_srsid)
- return ERROR_OK;
-
- return kinetis_ke_probe(bank);
-}
-
-static int kinetis_ke_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- (void) snprintf(buf, buf_size,
- "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
- bank->driver->name, bank->name, bank->base);
-
- return ERROR_OK;
-}
-
-static int kinetis_ke_blank_check(struct flash_bank *bank)
-{
- uint8_t FCCOBIX[3], FCCOBHI[3], FCCOBLO[3], fstat;
- uint16_t longwords = 0;
- int result;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- result = kinetis_ke_prepare_flash(bank);
- if (result != ERROR_OK)
- return result;
-
- /* check if whole bank is blank */
- FCCOBIX[0] = 0;
- FCCOBHI[0] = FTMRX_CMD_ALLERASED;
-
- result = kinetis_ke_ftmrx_command(bank, 1, FCCOBIX, FCCOBHI, NULL, &fstat);
-
- if (result != ERROR_OK)
- return result;
-
- if (fstat & (FTMRX_FSTAT_MGSTAT0_MASK | FTMRX_FSTAT_MGSTAT1_MASK)) {
- /* the whole bank is not erased, check sector-by-sector */
- int i;
-
- for (i = 0; i < bank->num_sectors; i++) {
- FCCOBIX[0] = 0;
- FCCOBHI[0] = FTMRX_CMD_SECTIONERASED;
- FCCOBLO[0] = (bank->base + bank->sectors[i].offset) >> 16;
-
- FCCOBIX[1] = 1;
- FCCOBHI[1] = (bank->base + bank->sectors[i].offset) >> 8;
- FCCOBLO[1] = (bank->base + bank->sectors[i].offset);
-
- longwords = 128;
-
- FCCOBIX[2] = 2;
- FCCOBHI[2] = longwords >> 8;
- FCCOBLO[2] = longwords;
-
- result = kinetis_ke_ftmrx_command(bank, 3, FCCOBIX, FCCOBHI, FCCOBLO, &fstat);
-
- if (result == ERROR_OK) {
- bank->sectors[i].is_erased = !(fstat & (FTMRX_FSTAT_MGSTAT0_MASK | FTMRX_FSTAT_MGSTAT1_MASK));
- } else {
- LOG_DEBUG("Ignoring errored PFlash sector blank-check");
- bank->sectors[i].is_erased = -1;
- }
- }
- } else {
- /* the whole bank is erased, update all sectors */
- int i;
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration kinetis_ke_security_command_handlers[] = {
- {
- .name = "check_security",
- .mode = COMMAND_EXEC,
- .help = "",
- .usage = "",
- .handler = kinetis_ke_check_flash_security_status,
- },
- {
- .name = "mass_erase",
- .mode = COMMAND_EXEC,
- .help = "",
- .usage = "",
- .handler = kinetis_ke_mdm_mass_erase,
- },
- {
- .name = "test_securing",
- .mode = COMMAND_EXEC,
- .help = "",
- .usage = "",
- .handler = kinetis_ke_securing_test,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration kinetis_ke_exec_command_handlers[] = {
- {
- .name = "mdm",
- .mode = COMMAND_ANY,
- .help = "",
- .usage = "",
- .chain = kinetis_ke_security_command_handlers,
- },
- {
- .name = "disable_wdog",
- .mode = COMMAND_EXEC,
- .help = "Disable the watchdog timer",
- .usage = "",
- .handler = kinetis_ke_disable_wdog_handler,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration kinetis_ke_command_handler[] = {
- {
- .name = "kinetis_ke",
- .mode = COMMAND_ANY,
- .help = "Kinetis KE NAND flash controller commands",
- .usage = "",
- .chain = kinetis_ke_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver kinetis_ke_flash = {
- .name = "kinetis_ke",
- .commands = kinetis_ke_command_handler,
- .flash_bank_command = kinetis_ke_flash_bank_command,
- .erase = kinetis_ke_erase,
- .protect = kinetis_ke_protect,
- .write = kinetis_ke_write,
- .read = default_flash_read,
- .probe = kinetis_ke_probe,
- .auto_probe = kinetis_ke_auto_probe,
- .erase_check = kinetis_ke_blank_check,
- .protect_check = kinetis_ke_protect_check,
- .info = kinetis_ke_info,
-};
diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c
deleted file mode 100644
index 76cd86b..0000000
--- a/src/flash/nor/lpc2000.c
+++ /dev/null
@@ -1,1573 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * LPC1700 support Copyright (C) 2009 by Audrius Urmanavicius *
- * didele.deze@gmail.com *
- * *
- * LPC1100 variant and auto-probing support Copyright (C) 2014 *
- * by Cosmin Gorgovan cosmin [at] linux-geek [dot] org *
- * *
- * LPC800/LPC1500/LPC54100 support Copyright (C) 2013/2014 *
- * by Nemui Trinomius *
- * nemuisan_kawausogasuki@live.jp *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/arm_opcodes.h>
-#include <target/armv7m.h>
-
-/**
- * @file
- * flash programming support for NXP LPC8xx,LPC1xxx,LPC4xxx,LP5410x and LPC2xxx devices.
- *
- * @todo Provide a way to update CCLK after declaring the flash bank. The value which is correct after chip reset will
- * rarely still work right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz).
- */
-/*
- * currently supported devices:
- * variant 1 (lpc2000_v1):
- * - 2104 | 5 | 6
- * - 2114 | 9
- * - 2124 | 9
- * - 2194
- * - 2212 | 4
- * - 2292 | 4
- *
- * variant 2 (lpc2000_v2):
- * - 213x
- * - 214x
- * - 2101 | 2 | 3
- * - 2364 | 6 | 8
- * - 2378
- *
- * lpc1700:
- * - 175x
- * - 176x (tested with LPC1768)
- * - 177x
- * - 178x (tested with LPC1788)
- *
- * lpc4000: (lpc1700's alias)
- * - 407x
- * - 408x (tested with LPC4088)
- *
- * lpc4300: (also available as lpc1800 - alias)
- * - 43x2 | 3 | 5 | 7 (tested with LPC4337/LPC4357)
- * - 18x2 | 3 | 5 | 7
- *
- * lpc800:
- * - 810 | 1 | 2 (tested with LPC810/LPC811/LPC812)
- * - 822 | 4 (tested with LPC824)
- *
- * lpc1100:
- * - 11xx
- * - 11Axx
- * - 11Cxx
- * - 11Dxx
- * - 11Exx
- * - 11Uxx (tested with LPC11U34)
- * - 131x
- * - 134x
- *
- * lpc1500:
- * - 15x7 | 8 | 9 (tested with LPC1549)
- *
- * lpc54100:
- * - 54101 | 2 (tested with LPC54102)
- *
- * The auto variant auto-detects parts from the following series:
- * - 11xx
- * - 11Axx
- * - 11Cxx
- * - 11Dxx
- * - 11Exx
- * - 11Uxx
- * - 131x
- * - 134x
- * - 175x
- * - 176x
- * - 177x
- * - 178x
- * - 407x
- * - 408x
- * - 81x
- * - 82x
- */
-
-/* Part IDs for autodetection */
-/* A script which can automatically extract part ids from user manuals is available here:
- * https://github.com/lgeek/lpc_part_ids
- */
-#define LPC1110_1 0x0A07102B
-#define LPC1110_2 0x1A07102B
-#define LPC1111_002_1 0x0A16D02B
-#define LPC1111_002_2 0x1A16D02B
-#define LPC1111_101_1 0x041E502B
-#define LPC1111_101_2 0x2516D02B
-#define LPC1111_103_1 0x00010013
-#define LPC1111_201_1 0x0416502B
-#define LPC1111_201_2 0x2516902B
-#define LPC1111_203_1 0x00010012
-#define LPC1112_101_1 0x042D502B
-#define LPC1112_101_2 0x2524D02B
-#define LPC1112_102_1 0x0A24902B
-#define LPC1112_102_2 0x1A24902B
-#define LPC1112_103_1 0x00020023
-#define LPC1112_201_1 0x0425502B
-#define LPC1112_201_2 0x2524902B
-#define LPC1112_203_1 0x00020022
-#define LPC1113_201_1 0x0434502B
-#define LPC1113_201_2 0x2532902B
-#define LPC1113_203_1 0x00030032
-#define LPC1113_301_1 0x0434102B
-#define LPC1113_301_2 0x2532102B
-#define LPC1113_303_1 0x00030030
-#define LPC1114_102_1 0x0A40902B
-#define LPC1114_102_2 0x1A40902B
-#define LPC1114_201_1 0x0444502B
-#define LPC1114_201_2 0x2540902B
-#define LPC1114_203_1 0x00040042
-#define LPC1114_301_1 0x0444102B
-#define LPC1114_301_2 0x2540102B
-#define LPC1114_303_1 0x00040040
-#define LPC1114_323_1 0x00040060
-#define LPC1114_333_1 0x00040070
-#define LPC1115_303_1 0x00050080
-
-#define LPC11A02_1 0x4D4C802B
-#define LPC11A04_1 0x4D80002B
-#define LPC11A11_001_1 0x455EC02B
-#define LPC11A12_101_1 0x4574802B
-#define LPC11A13_201_1 0x458A402B
-#define LPC11A14_301_1 0x35A0002B
-#define LPC11A14_301_2 0x45A0002B
-
-#define LPC11C12_301_1 0x1421102B
-#define LPC11C14_301_1 0x1440102B
-#define LPC11C22_301_1 0x1431102B
-#define LPC11C24_301_1 0x1430102B
-
-#define LPC11E11_101 0x293E902B
-#define LPC11E12_201 0x2954502B
-#define LPC11E13_301 0x296A102B
-#define LPC11E14_401 0x2980102B
-#define LPC11E36_501 0x00009C41
-#define LPC11E37_401 0x00007C45
-#define LPC11E37_501 0x00007C41
-
-#define LPC11U12_201_1 0x095C802B
-#define LPC11U12_201_2 0x295C802B
-#define LPC11U13_201_1 0x097A802B
-#define LPC11U13_201_2 0x297A802B
-#define LPC11U14_201_1 0x0998802B
-#define LPC11U14_201_2 0x2998802B
-#define LPC11U23_301 0x2972402B
-#define LPC11U24_301 0x2988402B
-#define LPC11U24_401 0x2980002B
-#define LPC11U34_311 0x0003D440
-#define LPC11U34_421 0x0001CC40
-#define LPC11U35_401 0x0001BC40
-#define LPC11U35_501 0x0000BC40
-#define LPC11U36_401 0x00019C40
-#define LPC11U37_401 0x00017C40
-#define LPC11U37H_401 0x00007C44
-#define LPC11U37_501 0x00007C40
-
-#define LPC11E66 0x0000DCC1
-#define LPC11E67 0x0000BC81
-#define LPC11E68 0x00007C01
-
-#define LPC11U66 0x0000DCC8
-#define LPC11U67_1 0x0000BC88
-#define LPC11U67_2 0x0000BC80
-#define LPC11U68_1 0x00007C08
-#define LPC11U68_2 0x00007C00
-
-#define LPC1311 0x2C42502B
-#define LPC1311_1 0x1816902B
-#define LPC1313 0x2C40102B
-#define LPC1313_1 0x1830102B
-#define LPC1315 0x3A010523
-#define LPC1316 0x1A018524
-#define LPC1317 0x1A020525
-#define LPC1342 0x3D01402B
-#define LPC1343 0x3D00002B
-#define LPC1343_1 0x3000002B
-#define LPC1345 0x28010541
-#define LPC1346 0x08018542
-#define LPC1347 0x08020543
-
-#define LPC1751_1 0x25001110
-#define LPC1751_2 0x25001118
-#define LPC1752 0x25001121
-#define LPC1754 0x25011722
-#define LPC1756 0x25011723
-#define LPC1758 0x25013F37
-#define LPC1759 0x25113737
-#define LPC1763 0x26012033
-#define LPC1764 0x26011922
-#define LPC1765 0x26013733
-#define LPC1766 0x26013F33
-#define LPC1767 0x26012837
-#define LPC1768 0x26013F37
-#define LPC1769 0x26113F37
-#define LPC1774 0x27011132
-#define LPC1776 0x27191F43
-#define LPC1777 0x27193747
-#define LPC1778 0x27193F47
-#define LPC1785 0x281D1743
-#define LPC1786 0x281D1F43
-#define LPC1787 0x281D3747
-#define LPC1788 0x281D3F47
-
-#define LPC4072 0x47011121
-#define LPC4074 0x47011132
-#define LPC4076 0x47191F43
-#define LPC4078 0x47193F47
-#define LPC4088 0x481D3F47
-
-#define LPC810_021 0x00008100
-#define LPC811_001 0x00008110
-#define LPC812_101 0x00008120
-#define LPC812_101_1 0x00008121
-#define LPC812_101_2 0x00008122
-#define LPC812_101_3 0x00008123
-
-#define LPC822_101 0x00008221
-#define LPC822_101_1 0x00008222
-#define LPC824_201 0x00008241
-#define LPC824_201_1 0x00008242
-
-#define IAP_CODE_LEN 0x34
-
-typedef enum {
- lpc2000_v1,
- lpc2000_v2,
- lpc1700,
- lpc4300,
- lpc800,
- lpc1100,
- lpc1500,
- lpc54100,
- lpc_auto,
-} lpc2000_variant;
-
-struct lpc2000_flash_bank {
- lpc2000_variant variant;
- uint32_t cclk;
- int cmd51_dst_boundary;
- int calc_checksum;
- uint32_t cmd51_max_buffer;
- int checksum_vector;
- uint32_t iap_max_stack;
- uint32_t lpc4300_bank;
- bool probed;
-};
-
-enum lpc2000_status_codes {
- LPC2000_CMD_SUCCESS = 0,
- LPC2000_INVALID_COMMAND = 1,
- LPC2000_SRC_ADDR_ERROR = 2,
- LPC2000_DST_ADDR_ERROR = 3,
- LPC2000_SRC_ADDR_NOT_MAPPED = 4,
- LPC2000_DST_ADDR_NOT_MAPPED = 5,
- LPC2000_COUNT_ERROR = 6,
- LPC2000_INVALID_SECTOR = 7,
- LPC2000_SECTOR_NOT_BLANK = 8,
- LPC2000_SECTOR_NOT_PREPARED = 9,
- LPC2000_COMPARE_ERROR = 10,
- LPC2000_BUSY = 11,
- LPC2000_PARAM_ERROR = 12,
- LPC2000_ADDR_ERROR = 13,
- LPC2000_ADDR_NOT_MAPPED = 14,
- LPC2000_CMD_NOT_LOCKED = 15,
- LPC2000_INVALID_CODE = 16,
- LPC2000_INVALID_BAUD_RATE = 17,
- LPC2000_INVALID_STOP_BIT = 18,
- LPC2000_CRP_ENABLED = 19,
- LPC2000_INVALID_FLASH_UNIT = 20,
- LPC2000_USER_CODE_CHECKSUM = 21,
- LCP2000_ERROR_SETTING_ACTIVE_PARTITION = 22,
-};
-
-static int lpc2000_build_sector_list(struct flash_bank *bank)
-{
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
- uint32_t offset = 0;
-
- /* default to a 4096 write buffer */
- lpc2000_info->cmd51_max_buffer = 4096;
-
- if (lpc2000_info->variant == lpc2000_v1) {
- lpc2000_info->cmd51_dst_boundary = 512;
- lpc2000_info->checksum_vector = 5;
- lpc2000_info->iap_max_stack = 128;
-
- /* variant 1 has different layout for 128kb and 256kb flashes */
- if (bank->size == 128 * 1024) {
- bank->num_sectors = 16;
- bank->sectors = malloc(sizeof(struct flash_sector) * 16);
- for (int i = 0; i < 16; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 8 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
- } else if (bank->size == 256 * 1024) {
- bank->num_sectors = 18;
- bank->sectors = malloc(sizeof(struct flash_sector) * 18);
-
- for (int i = 0; i < 8; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 8 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
- for (int i = 8; i < 10; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 64 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
- for (int i = 10; i < 18; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 8 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
- } else {
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
- } else if (lpc2000_info->variant == lpc2000_v2) {
- lpc2000_info->cmd51_dst_boundary = 256;
- lpc2000_info->checksum_vector = 5;
- lpc2000_info->iap_max_stack = 128;
-
- /* variant 2 has a uniform layout, only number of sectors differs */
- switch (bank->size) {
- case 4 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024;
- bank->num_sectors = 1;
- break;
- case 8 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024;
- bank->num_sectors = 2;
- break;
- case 16 * 1024:
- bank->num_sectors = 4;
- break;
- case 32 * 1024:
- bank->num_sectors = 8;
- break;
- case 64 * 1024:
- bank->num_sectors = 9;
- break;
- case 128 * 1024:
- bank->num_sectors = 11;
- break;
- case 256 * 1024:
- bank->num_sectors = 15;
- break;
- case 500 * 1024:
- bank->num_sectors = 27;
- break;
- case 512 * 1024:
- case 504 * 1024:
- bank->num_sectors = 28;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- break;
- }
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (int i = 0; i < bank->num_sectors; i++) {
- if (i < 8) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 4 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- } else if (i < 22) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 32 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- } else if (i < 28) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 4 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
- }
- } else if (lpc2000_info->variant == lpc1700) {
- lpc2000_info->cmd51_dst_boundary = 256;
- lpc2000_info->checksum_vector = 7;
- lpc2000_info->iap_max_stack = 128;
-
- switch (bank->size) {
- case 4 * 1024:
- lpc2000_info->cmd51_max_buffer = 256;
- bank->num_sectors = 1;
- break;
- case 8 * 1024:
- lpc2000_info->cmd51_max_buffer = 512;
- bank->num_sectors = 2;
- break;
- case 16 * 1024:
- lpc2000_info->cmd51_max_buffer = 512;
- bank->num_sectors = 4;
- break;
- case 32 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024;
- bank->num_sectors = 8;
- break;
- case 64 * 1024:
- bank->num_sectors = 16;
- break;
- case 128 * 1024:
- bank->num_sectors = 18;
- break;
- case 256 * 1024:
- bank->num_sectors = 22;
- break;
- case 512 * 1024:
- bank->num_sectors = 30;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx/LPC40xx devices */
- bank->sectors[i].size = (i < 16) ? 4 * 1024 : 32 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
- } else if (lpc2000_info->variant == lpc4300) {
- lpc2000_info->cmd51_dst_boundary = 512;
- lpc2000_info->checksum_vector = 7;
- lpc2000_info->iap_max_stack = 208;
-
- switch (bank->size) {
- case 256 * 1024:
- bank->num_sectors = 11;
- break;
- case 384 * 1024:
- bank->num_sectors = 13;
- break;
- case 512 * 1024:
- bank->num_sectors = 15;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- /* sectors 0-7 are 8kB-sized, 8 and above are 64kB-sized for LPC43xx devices */
- bank->sectors[i].size = (i < 8) ? 8 * 1024 : 64 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- } else if (lpc2000_info->variant == lpc800) {
- lpc2000_info->cmd51_dst_boundary = 64;
- lpc2000_info->checksum_vector = 7;
- lpc2000_info->iap_max_stack = 208; /* 148byte for LPC81x,208byte for LPC82x. */
- lpc2000_info->cmd51_max_buffer = 256; /* smallest MCU in the series, LPC810, has 1 kB of SRAM */
-
- switch (bank->size) {
- case 4 * 1024:
- bank->num_sectors = 4;
- break;
- case 8 * 1024:
- bank->num_sectors = 8;
- break;
- case 16 * 1024:
- bank->num_sectors = 16;
- break;
- case 32 * 1024:
- lpc2000_info->cmd51_max_buffer = 1024; /* For LPC824, has 8kB of SRAM */
- bank->num_sectors = 32;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- /* all sectors are 1kB-sized for LPC8xx devices */
- bank->sectors[i].size = 1 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- } else if (lpc2000_info->variant == lpc1100) {
- lpc2000_info->cmd51_dst_boundary = 256;
- lpc2000_info->checksum_vector = 7;
- lpc2000_info->iap_max_stack = 128;
-
- if ((bank->size % (4 * 1024)) != 0) {
- LOG_ERROR("BUG: unknown bank->size encountered,\nLPC1100 flash size must be a multiple of 4096");
- exit(-1);
- }
- lpc2000_info->cmd51_max_buffer = 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */
- bank->num_sectors = bank->size / 4096;
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- /* all sectors are 4kB-sized */
- bank->sectors[i].size = 4 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- } else if (lpc2000_info->variant == lpc1500) {
- lpc2000_info->cmd51_dst_boundary = 256;
- lpc2000_info->checksum_vector = 7;
- lpc2000_info->iap_max_stack = 128;
-
- switch (bank->size) {
- case 64 * 1024:
- bank->num_sectors = 16;
- break;
- case 128 * 1024:
- bank->num_sectors = 32;
- break;
- case 256 * 1024:
- bank->num_sectors = 64;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- /* all sectors are 4kB-sized */
- bank->sectors[i].size = 4 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- } else if (lpc2000_info->variant == lpc54100) {
- lpc2000_info->cmd51_dst_boundary = 256;
- lpc2000_info->checksum_vector = 7;
- lpc2000_info->iap_max_stack = 128;
-
- switch (bank->size) {
- case 256 * 1024:
- bank->num_sectors = 8;
- break;
- case 512 * 1024:
- bank->num_sectors = 16;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- /* all sectors are 32kB-sized */
- bank->sectors[i].size = 32 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- } else {
- LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
- exit(-1);
- }
-
- return ERROR_OK;
-}
-
-/* this function allocates and initializes working area used for IAP algorithm
- * uses 52 + max IAP stack bytes working area
- * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
- * 0x8 to 0x1f: command parameter table (1+5 words)
- * 0x20 to 0x33: command result table (1+4 words)
- * 0x34 to 0xb3|0x104: stack
- * (128b needed for lpc1xxx/2000/5410x, 208b for lpc43xx/lpc82x and 148b for lpc81x)
- */
-
-static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working_area **iap_working_area)
-{
- struct target *target = bank->target;
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
-
- if (target_alloc_working_area(target, IAP_CODE_LEN + lpc2000_info->iap_max_stack, iap_working_area) != ERROR_OK) {
- LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- uint8_t jump_gate[8];
-
- /* write IAP code to working area */
- switch (lpc2000_info->variant) {
- case lpc800:
- case lpc1100:
- case lpc1500:
- case lpc1700:
- case lpc4300:
- case lpc54100:
- case lpc_auto:
- target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
- target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
- break;
- case lpc2000_v1:
- case lpc2000_v2:
- target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
- target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
- break;
- default:
- LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
- exit(-1);
- }
-
- int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate);
- if (retval != ERROR_OK) {
- LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)",
- (*iap_working_area)->address);
- target_free_working_area(target, *iap_working_area);
- }
-
- return retval;
-}
-
-/* call LPC8xx/LPC1xxx/LPC4xxx/LPC5410x/LPC2000 IAP function */
-
-static int lpc2000_iap_call(struct flash_bank *bank, struct working_area *iap_working_area, int code,
- uint32_t param_table[5], uint32_t result_table[4])
-{
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
- struct target *target = bank->target;
-
- struct arm_algorithm arm_algo; /* for LPC2000 */
- struct armv7m_algorithm armv7m_info; /* for LPC8xx/LPC1xxx/LPC4xxx/LPC5410x */
- uint32_t iap_entry_point = 0; /* to make compiler happier */
-
- switch (lpc2000_info->variant) {
- case lpc800:
- case lpc1100:
- case lpc1700:
- case lpc_auto:
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
- iap_entry_point = 0x1fff1ff1;
- break;
- case lpc1500:
- case lpc54100:
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
- iap_entry_point = 0x03000205;
- break;
- case lpc2000_v1:
- case lpc2000_v2:
- arm_algo.common_magic = ARM_COMMON_MAGIC;
- arm_algo.core_mode = ARM_MODE_SVC;
- arm_algo.core_state = ARM_STATE_ARM;
- iap_entry_point = 0x7ffffff1;
- break;
- case lpc4300:
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
- /* read out IAP entry point from ROM driver table at 0x10400100 */
- target_read_u32(target, 0x10400100, &iap_entry_point);
- break;
- default:
- LOG_ERROR("BUG: unknown lpc2000->variant encountered");
- exit(-1);
- }
-
- struct mem_param mem_params[2];
-
- /* command parameter table */
- init_mem_param(&mem_params[0], iap_working_area->address + 8, 6 * 4, PARAM_OUT);
- target_buffer_set_u32(target, mem_params[0].value, code);
- target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
- target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
- target_buffer_set_u32(target, mem_params[0].value + 0x0c, param_table[2]);
- target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]);
- target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]);
-
- struct reg_param reg_params[5];
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
- buf_set_u32(reg_params[0].value, 0, 32, iap_working_area->address + 0x08);
-
- /* command result table */
- init_mem_param(&mem_params[1], iap_working_area->address + 0x20, 5 * 4, PARAM_IN);
-
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
- buf_set_u32(reg_params[1].value, 0, 32, iap_working_area->address + 0x20);
-
- /* IAP entry point */
- init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
- buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
-
- switch (lpc2000_info->variant) {
- case lpc800:
- case lpc1100:
- case lpc1500:
- case lpc1700:
- case lpc4300:
- case lpc54100:
- case lpc_auto:
- /* IAP stack */
- init_reg_param(&reg_params[3], "sp", 32, PARAM_OUT);
- buf_set_u32(reg_params[3].value, 0, 32,
- iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack);
-
- /* return address */
- init_reg_param(&reg_params[4], "lr", 32, PARAM_OUT);
- buf_set_u32(reg_params[4].value, 0, 32, (iap_working_area->address + 0x04) | 1);
- /* bit0 of LR = 1 to return in Thumb mode */
-
- target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address, 0, 10000,
- &armv7m_info);
- break;
- case lpc2000_v1:
- case lpc2000_v2:
- /* IAP stack */
- init_reg_param(&reg_params[3], "sp_svc", 32, PARAM_OUT);
- buf_set_u32(reg_params[3].value, 0, 32,
- iap_working_area->address + IAP_CODE_LEN + lpc2000_info->iap_max_stack);
-
- /* return address */
- init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
- buf_set_u32(reg_params[4].value, 0, 32, iap_working_area->address + 0x04);
-
- target_run_algorithm(target, 2, mem_params, 5, reg_params, iap_working_area->address,
- iap_working_area->address + 0x4, 10000, &arm_algo);
- break;
- default:
- LOG_ERROR("BUG: unknown lpc2000->variant encountered");
- exit(-1);
- }
-
- int status_code = target_buffer_get_u32(target, mem_params[1].value);
- result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04);
- result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08);
- result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
- result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);
-
- LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32
- ") completed with result = %8.8x",
- code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code);
-
- destroy_mem_param(&mem_params[0]);
- destroy_mem_param(&mem_params[1]);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return status_code;
-}
-
-static int lpc2000_iap_blank_check(struct flash_bank *bank, int first, int last)
-{
- if ((first < 0) || (last >= bank->num_sectors))
- return ERROR_FLASH_SECTOR_INVALID;
-
- uint32_t param_table[5] = {0};
- uint32_t result_table[4];
- struct working_area *iap_working_area;
-
- int retval = lpc2000_iap_working_area_init(bank, &iap_working_area);
-
- if (retval != ERROR_OK)
- return retval;
-
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
- if (lpc2000_info->variant == lpc4300)
- param_table[2] = lpc2000_info->lpc4300_bank;
-
- for (int i = first; i <= last && retval == ERROR_OK; i++) {
- /* check single sector */
- param_table[0] = param_table[1] = i;
- int status_code = lpc2000_iap_call(bank, iap_working_area, 53, param_table, result_table);
-
- switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- bank->sectors[i].is_erased = 1;
- break;
- case LPC2000_SECTOR_NOT_BLANK:
- bank->sectors[i].is_erased = 0;
- break;
- case LPC2000_INVALID_SECTOR:
- bank->sectors[i].is_erased = 0;
- break;
- case LPC2000_BUSY:
- retval = ERROR_FLASH_BUSY;
- break;
- default:
- LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code);
- exit(-1);
- }
- }
-
- struct target *target = bank->target;
- target_free_working_area(target, iap_working_area);
-
- return retval;
-}
-
-/*
- * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
- */
-FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
-{
- if (CMD_ARGC < 8)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct lpc2000_flash_bank *lpc2000_info = calloc(1, sizeof(*lpc2000_info));
- lpc2000_info->probed = false;
-
- bank->driver_priv = lpc2000_info;
-
- if (strcmp(CMD_ARGV[6], "lpc2000_v1") == 0) {
- lpc2000_info->variant = lpc2000_v1;
- } else if (strcmp(CMD_ARGV[6], "lpc2000_v2") == 0) {
- lpc2000_info->variant = lpc2000_v2;
- } else if (strcmp(CMD_ARGV[6], "lpc1700") == 0 || strcmp(CMD_ARGV[6], "lpc4000") == 0) {
- lpc2000_info->variant = lpc1700;
- } else if (strcmp(CMD_ARGV[6], "lpc1800") == 0 || strcmp(CMD_ARGV[6], "lpc4300") == 0) {
- lpc2000_info->variant = lpc4300;
- } else if (strcmp(CMD_ARGV[6], "lpc800") == 0) {
- lpc2000_info->variant = lpc800;
- } else if (strcmp(CMD_ARGV[6], "lpc1100") == 0) {
- lpc2000_info->variant = lpc1100;
- } else if (strcmp(CMD_ARGV[6], "lpc1500") == 0) {
- lpc2000_info->variant = lpc1500;
- } else if (strcmp(CMD_ARGV[6], "lpc54100") == 0) {
- lpc2000_info->variant = lpc54100;
- } else if (strcmp(CMD_ARGV[6], "auto") == 0) {
- lpc2000_info->variant = lpc_auto;
- } else {
- LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]);
- free(lpc2000_info);
- return ERROR_FLASH_BANK_INVALID;
- }
-
- /* Maximum size required for the IAP stack.
- This value only gets used when probing, only for auto, lpc1100 and lpc1700.
- We use the maximum size for any part supported by the driver(!) to be safe
- in case the auto variant is mistakenly used on a MCU from one of the series
- for which we don't support auto-probing. */
- lpc2000_info->iap_max_stack = 208;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[7], lpc2000_info->cclk);
- lpc2000_info->calc_checksum = 0;
-
- uint32_t temp_base = 0;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], temp_base);
- if (temp_base >= 0x1B000000)
- lpc2000_info->lpc4300_bank = 1; /* bank B */
- else
- lpc2000_info->lpc4300_bank = 0; /* bank A */
-
- if (CMD_ARGC >= 9) {
- if (strcmp(CMD_ARGV[8], "calc_checksum") == 0)
- lpc2000_info->calc_checksum = 1;
- }
-
- return ERROR_OK;
-}
-
-static int lpc2000_erase(struct flash_bank *bank, int first, int last)
-{
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
- uint32_t param_table[5] = {0};
-
- param_table[0] = first;
- param_table[1] = last;
-
- if (lpc2000_info->variant == lpc4300)
- param_table[2] = lpc2000_info->lpc4300_bank;
- else
- param_table[2] = lpc2000_info->cclk;
-
- uint32_t result_table[4];
- struct working_area *iap_working_area;
-
- int retval = lpc2000_iap_working_area_init(bank, &iap_working_area);
-
- if (retval != ERROR_OK)
- return retval;
-
- if (lpc2000_info->variant == lpc4300)
- /* Init IAP Anyway */
- lpc2000_iap_call(bank, iap_working_area, 49, param_table, result_table);
-
- /* Prepare sectors */
- int status_code = lpc2000_iap_call(bank, iap_working_area, 50, param_table, result_table);
- switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- break;
- case LPC2000_INVALID_SECTOR:
- retval = ERROR_FLASH_SECTOR_INVALID;
- break;
- default:
- LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- if (retval == ERROR_OK) {
- /* Erase sectors */
- param_table[2] = lpc2000_info->cclk;
- if (lpc2000_info->variant == lpc4300)
- param_table[3] = lpc2000_info->lpc4300_bank;
-
- status_code = lpc2000_iap_call(bank, iap_working_area, 52, param_table, result_table);
- switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- break;
- case LPC2000_INVALID_SECTOR:
- retval = ERROR_FLASH_SECTOR_INVALID;
- break;
- default:
- LOG_WARNING("lpc2000 erase sectors returned %i", status_code);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
- }
-
- struct target *target = bank->target;
- target_free_working_area(target, iap_working_area);
-
- return retval;
-}
-
-static int lpc2000_protect(struct flash_bank *bank, int set, int first, int last)
-{
- /* can't protect/unprotect on the lpc2000 */
- return ERROR_OK;
-}
-
-static int lpc2000_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
-
- 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;
-
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
-
- uint32_t dst_min_alignment = lpc2000_info->cmd51_dst_boundary;
-
- if (offset % dst_min_alignment) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, offset, dst_min_alignment);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- int first_sector = 0;
- int last_sector = 0;
-
- for (int i = 0; i < bank->num_sectors; i++) {
- if (offset >= bank->sectors[i].offset)
- first_sector = i;
- if (offset + DIV_ROUND_UP(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset)
- last_sector = i;
- }
-
- LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
-
- /* check if exception vectors should be flashed */
- if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) {
- assert(lpc2000_info->checksum_vector < 8);
- uint32_t checksum = 0;
- for (int i = 0; i < 8; i++) {
- LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
- if (i != lpc2000_info->checksum_vector)
- checksum += buf_get_u32(buffer + (i * 4), 0, 32);
- }
- checksum = 0 - checksum;
- LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);
-
- uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32);
- if (original_value != checksum) {
- LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is "
- "different from calculated vector checksum (0x%8.8" PRIx32 ").", original_value, checksum);
- LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector "
- "checksum.");
- }
-
- /* FIXME: WARNING! This code is broken because it modifies the callers buffer in place. */
- buf_set_u32((uint8_t *)buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
- }
-
- struct working_area *iap_working_area;
-
- int retval = lpc2000_iap_working_area_init(bank, &iap_working_area);
-
- if (retval != ERROR_OK)
- return retval;
-
- struct working_area *download_area;
-
- /* allocate a working area */
- if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, &download_area) != ERROR_OK) {
- LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
- target_free_working_area(target, iap_working_area);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- uint32_t bytes_remaining = count;
- uint32_t bytes_written = 0;
- uint32_t param_table[5] = {0};
- uint32_t result_table[4];
-
- if (lpc2000_info->variant == lpc4300)
- /* Init IAP Anyway */
- lpc2000_iap_call(bank, iap_working_area, 49, param_table, result_table);
-
- while (bytes_remaining > 0) {
- uint32_t thisrun_bytes;
- if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
- thisrun_bytes = lpc2000_info->cmd51_max_buffer;
- else
- thisrun_bytes = lpc2000_info->cmd51_dst_boundary;
-
- /* Prepare sectors */
- param_table[0] = first_sector;
- param_table[1] = last_sector;
-
- if (lpc2000_info->variant == lpc4300)
- param_table[2] = lpc2000_info->lpc4300_bank;
- else
- param_table[2] = lpc2000_info->cclk;
-
- int status_code = lpc2000_iap_call(bank, iap_working_area, 50, param_table, result_table);
- switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- break;
- case LPC2000_INVALID_SECTOR:
- retval = ERROR_FLASH_SECTOR_INVALID;
- break;
- default:
- LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- /* Exit if error occured */
- if (retval != ERROR_OK)
- break;
-
- if (bytes_remaining >= thisrun_bytes) {
- retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written);
- if (retval != ERROR_OK) {
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
- } else {
- uint8_t *last_buffer = malloc(thisrun_bytes);
- memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
- memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining);
- target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer);
- free(last_buffer);
- }
-
- LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32, thisrun_bytes,
- bank->base + offset + bytes_written);
-
- /* Write data */
- param_table[0] = bank->base + offset + bytes_written;
- param_table[1] = download_area->address;
- param_table[2] = thisrun_bytes;
- param_table[3] = lpc2000_info->cclk;
- status_code = lpc2000_iap_call(bank, iap_working_area, 51, param_table, result_table);
- switch (status_code) {
- case ERROR_FLASH_OPERATION_FAILED:
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- case LPC2000_CMD_SUCCESS:
- break;
- case LPC2000_INVALID_SECTOR:
- retval = ERROR_FLASH_SECTOR_INVALID;
- break;
- default:
- LOG_WARNING("lpc2000 returned %i", status_code);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- /* Exit if error occured */
- if (retval != ERROR_OK)
- break;
-
- if (bytes_remaining > thisrun_bytes)
- bytes_remaining -= thisrun_bytes;
- else
- bytes_remaining = 0;
- bytes_written += thisrun_bytes;
- }
-
- target_free_working_area(target, iap_working_area);
- target_free_working_area(target, download_area);
-
- return retval;
-}
-
-static int get_lpc2000_part_id(struct flash_bank *bank, uint32_t *part_id)
-{
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t param_table[5] = {0};
- uint32_t result_table[4];
- struct working_area *iap_working_area;
-
- int retval = lpc2000_iap_working_area_init(bank, &iap_working_area);
-
- if (retval != ERROR_OK)
- return retval;
-
- /* The status seems to be bogus with the part ID command on some IAP
- firmwares, so ignore it. */
- lpc2000_iap_call(bank, iap_working_area, 54, param_table, result_table);
-
- struct target *target = bank->target;
- target_free_working_area(target, iap_working_area);
-
- /* If the result is zero, the command probably didn't work out. */
- if (result_table[0] == 0)
- return LPC2000_INVALID_COMMAND;
-
- *part_id = result_table[0];
- return LPC2000_CMD_SUCCESS;
-}
-
-static int lpc2000_auto_probe_flash(struct flash_bank *bank)
-{
- uint32_t part_id;
- int retval;
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = get_lpc2000_part_id(bank, &part_id);
- if (retval != LPC2000_CMD_SUCCESS) {
- LOG_ERROR("Could not get part ID");
- return retval;
- }
-
- switch (part_id) {
- case LPC1110_1:
- case LPC1110_2:
- lpc2000_info->variant = lpc1100;
- bank->size = 4 * 1024;
- break;
-
- case LPC1111_002_1:
- case LPC1111_002_2:
- case LPC1111_101_1:
- case LPC1111_101_2:
- case LPC1111_103_1:
- case LPC1111_201_1:
- case LPC1111_201_2:
- case LPC1111_203_1:
- case LPC11A11_001_1:
- case LPC11E11_101:
- case LPC1311:
- case LPC1311_1:
- lpc2000_info->variant = lpc1100;
- bank->size = 8 * 1024;
- break;
-
- case LPC1112_101_1:
- case LPC1112_101_2:
- case LPC1112_102_1:
- case LPC1112_102_2:
- case LPC1112_103_1:
- case LPC1112_201_1:
- case LPC1112_201_2:
- case LPC1112_203_1:
- case LPC11A02_1:
- case LPC11C12_301_1:
- case LPC11C22_301_1:
- case LPC11A12_101_1:
- case LPC11E12_201:
- case LPC11U12_201_1:
- case LPC11U12_201_2:
- case LPC1342:
- lpc2000_info->variant = lpc1100;
- bank->size = 16 * 1024;
- break;
-
- case LPC1113_201_1:
- case LPC1113_201_2:
- case LPC1113_203_1:
- case LPC1113_301_1:
- case LPC1113_301_2:
- case LPC1113_303_1:
- case LPC11A13_201_1:
- case LPC11E13_301:
- case LPC11U13_201_1:
- case LPC11U13_201_2:
- case LPC11U23_301:
- lpc2000_info->variant = lpc1100;
- bank->size = 24 * 1024;
- break;
-
- case LPC1114_102_1:
- case LPC1114_102_2:
- case LPC1114_201_1:
- case LPC1114_201_2:
- case LPC1114_203_1:
- case LPC1114_301_1:
- case LPC1114_301_2:
- case LPC1114_303_1:
- case LPC11A04_1:
- case LPC11A14_301_1:
- case LPC11A14_301_2:
- case LPC11C14_301_1:
- case LPC11C24_301_1:
- case LPC11E14_401:
- case LPC11U14_201_1:
- case LPC11U14_201_2:
- case LPC11U24_301:
- case LPC11U24_401:
- case LPC1313:
- case LPC1313_1:
- case LPC1315:
- case LPC1343:
- case LPC1343_1:
- case LPC1345:
- lpc2000_info->variant = lpc1100;
- bank->size = 32 * 1024;
- break;
-
- case LPC1751_1:
- case LPC1751_2:
- lpc2000_info->variant = lpc1700;
- bank->size = 32 * 1024;
- break;
-
- case LPC11U34_311:
- lpc2000_info->variant = lpc1100;
- bank->size = 40 * 1024;
- break;
-
- case LPC1114_323_1:
- case LPC11U34_421:
- case LPC1316:
- case LPC1346:
- lpc2000_info->variant = lpc1100;
- bank->size = 48 * 1024;
- break;
-
- case LPC1114_333_1:
- lpc2000_info->variant = lpc1100;
- bank->size = 56 * 1024;
- break;
-
- case LPC1115_303_1:
- case LPC11U35_401:
- case LPC11U35_501:
- case LPC11E66:
- case LPC11U66:
- case LPC1317:
- case LPC1347:
- lpc2000_info->variant = lpc1100;
- bank->size = 64 * 1024;
- break;
-
- case LPC1752:
- case LPC4072:
- lpc2000_info->variant = lpc1700;
- bank->size = 64 * 1024;
- break;
-
- case LPC11E36_501:
- case LPC11U36_401:
- lpc2000_info->variant = lpc1100;
- bank->size = 96 * 1024;
- break;
-
- case LPC11E37_401:
- case LPC11E37_501:
- case LPC11U37_401:
- case LPC11U37H_401:
- case LPC11U37_501:
- case LPC11E67:
- case LPC11E68:
- case LPC11U67_1:
- case LPC11U67_2:
- lpc2000_info->variant = lpc1100;
- bank->size = 128 * 1024;
- break;
-
- case LPC1754:
- case LPC1764:
- case LPC1774:
- case LPC4074:
- lpc2000_info->variant = lpc1700;
- bank->size = 128 * 1024;
- break;
-
- case LPC11U68_1:
- case LPC11U68_2:
- lpc2000_info->variant = lpc1100;
- bank->size = 256 * 1024;
- break;
-
- case LPC1756:
- case LPC1763:
- case LPC1765:
- case LPC1766:
- case LPC1776:
- case LPC1785:
- case LPC1786:
- case LPC4076:
- lpc2000_info->variant = lpc1700;
- bank->size = 256 * 1024;
- break;
-
- case LPC1758:
- case LPC1759:
- case LPC1767:
- case LPC1768:
- case LPC1769:
- case LPC1777:
- case LPC1778:
- case LPC1787:
- case LPC1788:
- case LPC4078:
- case LPC4088:
- lpc2000_info->variant = lpc1700;
- bank->size = 512 * 1024;
- break;
-
- case LPC810_021:
- lpc2000_info->variant = lpc800;
- bank->size = 4 * 1024;
- break;
-
- case LPC811_001:
- lpc2000_info->variant = lpc800;
- bank->size = 8 * 1024;
- break;
-
- case LPC812_101:
- case LPC812_101_1:
- case LPC812_101_2:
- case LPC812_101_3:
- case LPC822_101:
- case LPC822_101_1:
- lpc2000_info->variant = lpc800;
- bank->size = 16 * 1024;
- break;
-
- case LPC824_201:
- case LPC824_201_1:
- lpc2000_info->variant = lpc800;
- bank->size = 32 * 1024;
- break;
-
- default:
- LOG_ERROR("BUG: unknown Part ID encountered: 0x%" PRIx32, part_id);
- exit(-1);
- }
-
- return ERROR_OK;
-}
-
-static int lpc2000_probe(struct flash_bank *bank)
-{
- int status;
- uint32_t part_id;
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
-
- if (!lpc2000_info->probed) {
- if (lpc2000_info->variant == lpc_auto) {
- status = lpc2000_auto_probe_flash(bank);
- if (status != ERROR_OK)
- return status;
- } else if (lpc2000_info->variant == lpc1100 || lpc2000_info->variant == lpc1700) {
- status = get_lpc2000_part_id(bank, &part_id);
- if (status == LPC2000_CMD_SUCCESS)
- LOG_INFO("If auto-detection fails for this part, please email "
- "openocd-devel@lists.sourceforge.net, citing part id 0x%" PRIx32 ".\n", part_id);
- }
-
- lpc2000_build_sector_list(bank);
- lpc2000_info->probed = true;
- }
-
- return ERROR_OK;
-}
-
-static int lpc2000_erase_check(struct flash_bank *bank)
-{
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- return lpc2000_iap_blank_check(bank, 0, bank->num_sectors - 1);
-}
-
-static int lpc2000_protect_check(struct flash_bank *bank)
-{
- /* sectors are always protected */
- return ERROR_OK;
-}
-
-static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
-
- snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz", lpc2000_info->variant,
- lpc2000_info->cclk);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(lpc2000_handle_part_id_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t part_id;
- int status_code = get_lpc2000_part_id(bank, &part_id);
- if (status_code != 0x0) {
- if (status_code == ERROR_FLASH_OPERATION_FAILED) {
- command_print(CMD_CTX, "no sufficient working area specified, can't access LPC2000 IAP interface");
- } else
- command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code);
- } else
- command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, part_id);
-
- return retval;
-}
-
-static const struct command_registration lpc2000_exec_command_handlers[] = {
- {
- .name = "part_id",
- .handler = lpc2000_handle_part_id_command,
- .mode = COMMAND_EXEC,
- .help = "print part id of lpc2000 flash bank <num>",
- .usage = "<bank>",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration lpc2000_command_handlers[] = {
- {
- .name = "lpc2000",
- .mode = COMMAND_ANY,
- .help = "lpc2000 flash command group",
- .usage = "",
- .chain = lpc2000_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver lpc2000_flash = {
- .name = "lpc2000",
- .commands = lpc2000_command_handlers,
- .flash_bank_command = lpc2000_flash_bank_command,
- .erase = lpc2000_erase,
- .protect = lpc2000_protect,
- .write = lpc2000_write,
- .read = default_flash_read,
- .probe = lpc2000_probe,
- .auto_probe = lpc2000_probe,
- .erase_check = lpc2000_erase_check,
- .protect_check = lpc2000_protect_check,
- .info = get_lpc2000_info,
-};
diff --git a/src/flash/nor/lpc288x.c b/src/flash/nor/lpc288x.c
deleted file mode 100644
index a4d88de..0000000
--- a/src/flash/nor/lpc288x.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by *
- * Karl RobinSod <karl.robinsod@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/***************************************************************************
-* There are some things to notice
-*
-* You need to unprotect flash sectors each time you connect the OpenOCD
-* Dumping 1MB takes about 60 Seconds
-* Full erase (sectors 0-22 inclusive) takes 2-4 seconds
-* Writing 1MB takes 88 seconds
-*
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-
-#define LOAD_TIMER_ERASE 0
-#define LOAD_TIMER_WRITE 1
-
-#define FLASH_PAGE_SIZE 512
-
-/* LPC288X control registers */
-#define DBGU_CIDR 0x8000507C
-/* LPC288X flash registers */
-#define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
-#define F_STAT 0x80102004 /* Flash status register RO 0x45 */
-#define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
-#define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
-#define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0
- **/
-#define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
-#define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
-#define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
-#define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
-#define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
-#define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
-#define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power
- *savings. R/W 1*/
-#define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from
- *Power Down mode. R/W -*/
-
-/* F_CTRL bits */
-#define FC_CS 0x0001
-#define FC_FUNC 0x0002
-#define FC_WEN 0x0004
-#define FC_RD_LATCH 0x0020
-#define FC_PROTECT 0x0080
-#define FC_SET_DATA 0x0400
-#define FC_RSSL 0x0800
-#define FC_PROG_REQ 0x1000
-#define FC_CLR_BUF 0x4000
-#define FC_LOAD_REQ 0x8000
-/* F_STAT bits */
-#define FS_DONE 0x0001
-#define FS_PROGGNT 0x0002
-#define FS_RDY 0x0004
-#define FS_ERR 0x0020
-/* F_PROG_TIME */
-#define FPT_TIME_MASK 0x7FFF
-
-#define FPT_ENABLE 0x8000
-/* F_WAIT */
-#define FW_WAIT_STATES_MASK 0x00FF
-#define FW_SET_MASK 0xC000
-
-/* F_CLK_TIME */
-#define FCT_CLK_DIV_MASK 0x0FFF
-
-struct lpc288x_flash_bank {
- uint32_t working_area;
- uint32_t working_area_size;
-
- /* chip id register */
- uint32_t cidr;
- const char *target_name;
- uint32_t cclk;
-
- uint32_t sector_size_break;
-};
-
-static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout);
-static void lpc288x_load_timer(int erase, struct target *target);
-static void lpc288x_set_flash_clk(struct flash_bank *bank);
-static uint32_t lpc288x_system_ready(struct flash_bank *bank);
-
-static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout)
-{
- uint32_t status;
- struct target *target = bank->target;
- do {
- alive_sleep(1);
- timeout--;
- target_read_u32(target, F_STAT, &status);
- } while (((status & FS_DONE) == 0) && timeout);
-
- if (timeout == 0) {
- LOG_DEBUG("Timedout!");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- return ERROR_OK;
-}
-
-/* Read device id register and fill in driver info structure */
-static int lpc288x_read_part_info(struct flash_bank *bank)
-{
- struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t cidr;
-
- int i = 0;
- uint32_t offset;
-
- if (lpc288x_info->cidr == 0x0102100A)
- return ERROR_OK;/* already probed, multiple probes may cause memory leak, not
- *allowed */
-
- /* Read and parse chip identification register */
- target_read_u32(target, DBGU_CIDR, &cidr);
-
- if (cidr != 0x0102100A) {
- LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- lpc288x_info->cidr = cidr;
- lpc288x_info->sector_size_break = 0x000F0000;
- lpc288x_info->target_name = "LPC288x";
-
- /* setup the sector info... */
- offset = bank->base;
- bank->num_sectors = 23;
- bank->sectors = malloc(sizeof(struct flash_sector) * 23);
-
- for (i = 0; i < 15; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 64 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
- for (i = 15; i < 23; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = 8 * 1024;
- offset += bank->sectors[i].size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- return ERROR_OK;
-}
-
-static int lpc288x_protect_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-/* flash_bank LPC288x 0 0 0 0 <target#> <cclk> */
-FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command)
-{
- struct lpc288x_flash_bank *lpc288x_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank));
- bank->driver_priv = lpc288x_info;
-
- /* part wasn't probed for info yet */
- lpc288x_info->cidr = 0;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], lpc288x_info->cclk);
-
- return ERROR_OK;
-}
-
-/* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
- * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
- * AHB = 12 MHz ?
- * 12000000/66000 = 182
- * CLK_DIV = 60 ? */
-static void lpc288x_set_flash_clk(struct flash_bank *bank)
-{
- uint32_t clk_time;
- struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
- clk_time = (lpc288x_info->cclk / 66000) / 3;
- target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN);
- target_write_u32(bank->target, F_CLK_TIME, clk_time);
-}
-
-/* AHB tcyc (in ns) 83 ns
- * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
- * = 9412 (9500) (AN10548 9375)
- * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
- * = 23 (75) (AN10548 72 - is this wrong?)
- * TODO: Sort out timing calcs ;) */
-static void lpc288x_load_timer(int erase, struct target *target)
-{
- if (erase == LOAD_TIMER_ERASE)
- target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
- else
- target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
-}
-
-static uint32_t lpc288x_system_ready(struct flash_bank *bank)
-{
- struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
- if (lpc288x_info->cidr == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
- return ERROR_OK;
-}
-
-static int lpc288x_erase_check(struct flash_bank *bank)
-{
- uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
- if (status != ERROR_OK) {
- LOG_INFO("Processor not halted/not probed");
- return status;
- }
-
- return ERROR_OK;
-}
-
-static int lpc288x_erase(struct flash_bank *bank, int first, int last)
-{
- uint32_t status;
- int sector;
- struct target *target = bank->target;
-
- status = lpc288x_system_ready(bank); /* probed? halted? */
- if (status != ERROR_OK)
- return status;
-
- if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
- LOG_INFO("Bad sector range");
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- /* Configure the flash controller timing */
- lpc288x_set_flash_clk(bank);
-
- for (sector = first; sector <= last; sector++) {
- if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
-
- lpc288x_load_timer(LOAD_TIMER_ERASE, target);
-
- target_write_u32(target, bank->sectors[sector].offset, 0x00);
-
- target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
- }
- if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
- return ERROR_OK;
-}
-
-static int lpc288x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- uint8_t page_buffer[FLASH_PAGE_SIZE];
- uint32_t status, source_offset, dest_offset;
- struct target *target = bank->target;
- uint32_t bytes_remaining = count;
- uint32_t first_sector, last_sector, sector, page;
- int i;
-
- /* probed? halted? */
- status = lpc288x_system_ready(bank);
- if (status != ERROR_OK)
- return status;
-
- /* Initialise search indices */
- first_sector = last_sector = 0xffffffff;
-
- /* validate the write range... */
- for (i = 0; i < bank->num_sectors; i++) {
- if ((offset >= bank->sectors[i].offset) &&
- (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
- (first_sector == 0xffffffff)) {
- first_sector = i;
- /* all writes must start on a sector boundary... */
- if (offset % bank->sectors[i].size) {
- LOG_INFO(
- "offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
- offset,
- bank->sectors[i].size);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
- }
- if (((offset + count) > bank->sectors[i].offset) &&
- ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
- (last_sector == 0xffffffff))
- last_sector = i;
- }
-
- /* Range check... */
- if (first_sector == 0xffffffff || last_sector == 0xffffffff) {
- LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
- return ERROR_FLASH_DST_OUT_OF_BANK;
- }
-
- /* Configure the flash controller timing */
- lpc288x_set_flash_clk(bank);
-
- /* initialise the offsets */
- source_offset = 0;
- dest_offset = 0;
-
- for (sector = first_sector; sector <= last_sector; sector++) {
- for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) {
- if (bytes_remaining == 0) {
- count = 0;
- memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
- } else if (bytes_remaining < FLASH_PAGE_SIZE) {
- count = bytes_remaining;
- memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
- memcpy(page_buffer, &buffer[source_offset], count);
- } else {
- count = FLASH_PAGE_SIZE;
- memcpy(page_buffer, &buffer[source_offset], count);
- }
-
- /* Wait for flash to become ready */
- if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* fill flash data latches with 1's */
- target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
-
- target_write_u32(target, F_CTRL, FC_CS | FC_WEN | FC_FUNC);
-
- if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE,
- page_buffer) != ERROR_OK) {
- LOG_INFO("Write to flash buffer failed");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- dest_offset += FLASH_PAGE_SIZE;
- source_offset += count;
- bytes_remaining -= count;
-
- lpc288x_load_timer(LOAD_TIMER_WRITE, target);
-
- target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC |
- FC_CS);
- }
- }
-
- return ERROR_OK;
-}
-
-static int lpc288x_probe(struct flash_bank *bank)
-{
- /* we only deal with LPC2888 so flash config is fixed */
- struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
- int retval;
-
- if (lpc288x_info->cidr != 0)
- return ERROR_OK;/* already probed */
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = lpc288x_read_part_info(bank);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_OK;
-}
-
-static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int lockregion, status;
- uint32_t value;
- struct target *target = bank->target;
-
- /* probed? halted? */
- status = lpc288x_system_ready(bank);
- if (status != ERROR_OK)
- return status;
-
- if ((first < 0) || (last < first) || (last >= bank->num_sectors))
- return ERROR_FLASH_SECTOR_INVALID;
-
- /* Configure the flash controller timing */
- lpc288x_set_flash_clk(bank);
-
- for (lockregion = first; lockregion <= last; lockregion++) {
- if (set) {
- /* write an odd value to base addy to protect... */
- value = 0x01;
- } else {
- /* write an even value to base addy to unprotect... */
- value = 0x00;
- }
- target_write_u32(target, bank->sectors[lockregion].offset, value);
- target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC |
- FC_CS);
- }
-
- return ERROR_OK;
-}
-
-struct flash_driver lpc288x_flash = {
- .name = "lpc288x",
- .flash_bank_command = lpc288x_flash_bank_command,
- .erase = lpc288x_erase,
- .protect = lpc288x_protect,
- .write = lpc288x_write,
- .read = default_flash_read,
- .probe = lpc288x_probe,
- .auto_probe = lpc288x_probe,
- .erase_check = lpc288x_erase_check,
- .protect_check = lpc288x_protect_check,
-};
diff --git a/src/flash/nor/lpc2900.c b/src/flash/nor/lpc2900.c
deleted file mode 100644
index 515a3f7..0000000
--- a/src/flash/nor/lpc2900.c
+++ /dev/null
@@ -1,1601 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by *
- * Rolf Meeser <rolfm_9dq@yahoo.de> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/arm.h>
-#include <target/image.h>
-
-/* 1024 bytes */
-#define KiB 1024
-
-/* Some flash constants */
-#define FLASH_PAGE_SIZE 512 /* bytes */
-#define FLASH_ERASE_TIME 100000 /* microseconds */
-#define FLASH_PROGRAM_TIME 1000 /* microseconds */
-
-/* Chip ID / Feature Registers */
-#define CHIPID 0xE0000000 /* Chip ID */
-#define FEAT0 0xE0000100 /* Chip feature 0 */
-#define FEAT1 0xE0000104 /* Chip feature 1 */
-#define FEAT2 0xE0000108 /* Chip feature 2 (contains flash size indicator) */
-#define FEAT3 0xE000010C /* Chip feature 3 */
-
-#define EXPECTED_CHIPID 0x209CE02B /* Chip ID of all LPC2900 devices */
-
-/* Flash/EEPROM Control Registers */
-#define FCTR 0x20200000 /* Flash control */
-#define FPTR 0x20200008 /* Flash program-time */
-#define FTCTR 0x2020000C /* Flash test control */
-#define FBWST 0x20200010 /* Flash bridge wait-state */
-#define FCRA 0x2020001C /* Flash clock divider */
-#define FMSSTART 0x20200020 /* Flash Built-In Selft Test start address */
-#define FMSSTOP 0x20200024 /* Flash Built-In Selft Test stop address */
-#define FMS16 0x20200028 /* Flash 16-bit signature */
-#define FMSW0 0x2020002C /* Flash 128-bit signature Word 0 */
-#define FMSW1 0x20200030 /* Flash 128-bit signature Word 1 */
-#define FMSW2 0x20200034 /* Flash 128-bit signature Word 2 */
-#define FMSW3 0x20200038 /* Flash 128-bit signature Word 3 */
-
-#define EECMD 0x20200080 /* EEPROM command */
-#define EEADDR 0x20200084 /* EEPROM address */
-#define EEWDATA 0x20200088 /* EEPROM write data */
-#define EERDATA 0x2020008C /* EEPROM read data */
-#define EEWSTATE 0x20200090 /* EEPROM wait state */
-#define EECLKDIV 0x20200094 /* EEPROM clock divider */
-#define EEPWRDWN 0x20200098 /* EEPROM power-down/start */
-#define EEMSSTART 0x2020009C /* EEPROM BIST start address */
-#define EEMSSTOP 0x202000A0 /* EEPROM BIST stop address */
-#define EEMSSIG 0x202000A4 /* EEPROM 24-bit BIST signature */
-
-#define INT_CLR_ENABLE 0x20200FD8 /* Flash/EEPROM interrupt clear enable */
-#define INT_SET_ENABLE 0x20200FDC /* Flash/EEPROM interrupt set enable */
-#define INT_STATUS 0x20200FE0 /* Flash/EEPROM interrupt status */
-#define INT_ENABLE 0x20200FE4 /* Flash/EEPROM interrupt enable */
-#define INT_CLR_STATUS 0x20200FE8 /* Flash/EEPROM interrupt clear status */
-#define INT_SET_STATUS 0x20200FEC /* Flash/EEPROM interrupt set status */
-
-/* Interrupt sources */
-#define INTSRC_END_OF_PROG (1 << 28)
-#define INTSRC_END_OF_BIST (1 << 27)
-#define INTSRC_END_OF_RDWR (1 << 26)
-#define INTSRC_END_OF_MISR (1 << 2)
-#define INTSRC_END_OF_BURN (1 << 1)
-#define INTSRC_END_OF_ERASE (1 << 0)
-
-/* FCTR bits */
-#define FCTR_FS_LOADREQ (1 << 15)
-#define FCTR_FS_CACHECLR (1 << 14)
-#define FCTR_FS_CACHEBYP (1 << 13)
-#define FCTR_FS_PROGREQ (1 << 12)
-#define FCTR_FS_RLS (1 << 11)
-#define FCTR_FS_PDL (1 << 10)
-#define FCTR_FS_PD (1 << 9)
-#define FCTR_FS_WPB (1 << 7)
-#define FCTR_FS_ISS (1 << 6)
-#define FCTR_FS_RLD (1 << 5)
-#define FCTR_FS_DCR (1 << 4)
-#define FCTR_FS_WEB (1 << 2)
-#define FCTR_FS_WRE (1 << 1)
-#define FCTR_FS_CS (1 << 0)
-/* FPTR bits */
-#define FPTR_EN_T (1 << 15)
-/* FTCTR bits */
-#define FTCTR_FS_BYPASS_R (1 << 29)
-#define FTCTR_FS_BYPASS_W (1 << 28)
-/* FMSSTOP bits */
-#define FMSSTOP_MISR_START (1 << 17)
-/* EEMSSTOP bits */
-#define EEMSSTOP_STRTBIST (1 << 31)
-
-/* Index sector */
-#define ISS_CUSTOMER_START1 (0x830)
-#define ISS_CUSTOMER_END1 (0xA00)
-#define ISS_CUSTOMER_SIZE1 (ISS_CUSTOMER_END1 - ISS_CUSTOMER_START1)
-#define ISS_CUSTOMER_NWORDS1 (ISS_CUSTOMER_SIZE1 / 4)
-#define ISS_CUSTOMER_START2 (0xA40)
-#define ISS_CUSTOMER_END2 (0xC00)
-#define ISS_CUSTOMER_SIZE2 (ISS_CUSTOMER_END2 - ISS_CUSTOMER_START2)
-#define ISS_CUSTOMER_NWORDS2 (ISS_CUSTOMER_SIZE2 / 4)
-#define ISS_CUSTOMER_SIZE (ISS_CUSTOMER_SIZE1 + ISS_CUSTOMER_SIZE2)
-
-/**
- * Private data for \c lpc2900 flash driver.
- */
-struct lpc2900_flash_bank {
- /**
- * This flag is set when the device has been successfully probed.
- */
- bool is_probed;
-
- /**
- * Holds the value read from CHIPID register.
- * The driver will not load if the chipid doesn't match the expected
- * value of 0x209CE02B of the LPC2900 family. A probe will only be done
- * if the chipid does not yet contain the expected value.
- */
- uint32_t chipid;
-
- /**
- * String holding device name.
- * This string is set by the probe function to the type number of the
- * device. It takes the form "LPC29xx".
- */
- char *target_name;
-
- /**
- * System clock frequency.
- * Holds the clock frequency in Hz, as passed by the configuration file
- * to the <tt>flash bank</tt> command.
- */
- uint32_t clk_sys_fmc;
-
- /**
- * Flag to indicate that dangerous operations are possible.
- * This flag can be set by passing the correct password to the
- * <tt>lpc2900 password</tt> command. If set, other dangerous commands,
- * which operate on the index sector, can be executed.
- */
- uint32_t risky;
-
- /**
- * Maximum contiguous block of internal SRAM (bytes).
- * Autodetected by the driver. Not the total amount of SRAM, only the
- * the largest \em contiguous block!
- */
- uint32_t max_ram_block;
-
-};
-
-static uint32_t lpc2900_wait_status(struct flash_bank *bank, uint32_t mask, int timeout);
-static void lpc2900_setup(struct flash_bank *bank);
-static uint32_t lpc2900_is_ready(struct flash_bank *bank);
-static uint32_t lpc2900_read_security_status(struct flash_bank *bank);
-static uint32_t lpc2900_run_bist128(struct flash_bank *bank,
- uint32_t addr_from, uint32_t addr_to,
- uint32_t signature[4]);
-static uint32_t lpc2900_address2sector(struct flash_bank *bank, uint32_t offset);
-static uint32_t lpc2900_calc_tr(uint32_t clock_var, uint32_t time_var);
-
-/*********************** Helper functions **************************/
-
-/**
- * Wait for an event in mask to occur in INT_STATUS.
- *
- * Return when an event occurs, or after a timeout.
- *
- * @param[in] bank Pointer to the flash bank descriptor
- * @param[in] mask Mask to be used for INT_STATUS
- * @param[in] timeout Timeout in ms
- */
-static uint32_t lpc2900_wait_status(struct flash_bank *bank,
- uint32_t mask,
- int timeout)
-{
- uint32_t int_status;
- struct target *target = bank->target;
-
- do {
- alive_sleep(1);
- timeout--;
- target_read_u32(target, INT_STATUS, &int_status);
- } while (((int_status & mask) == 0) && (timeout != 0));
-
- if (timeout == 0) {
- LOG_DEBUG("Timeout!");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Set up the flash for erase/program operations.
- *
- * Enable the flash, and set the correct CRA clock of 66 kHz.
- *
- * @param bank Pointer to the flash bank descriptor
- */
-static void lpc2900_setup(struct flash_bank *bank)
-{
- uint32_t fcra;
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
- /* Power up the flash block */
- target_write_u32(bank->target, FCTR, FCTR_FS_WEB | FCTR_FS_CS);
-
- fcra = (lpc2900_info->clk_sys_fmc / (3 * 66000)) - 1;
- target_write_u32(bank->target, FCRA, fcra);
-}
-
-/**
- * Check if device is ready.
- *
- * Check if device is ready for flash operation:
- * Must have been successfully probed.
- * Must be halted.
- */
-static uint32_t lpc2900_is_ready(struct flash_bank *bank)
-{
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
- if (!lpc2900_info->is_probed)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Read the status of sector security from the index sector.
- *
- * @param bank Pointer to the flash bank descriptor
- */
-static uint32_t lpc2900_read_security_status(struct flash_bank *bank)
-{
- uint32_t status = lpc2900_is_ready(bank);
- if (status != ERROR_OK)
- return status;
-
- struct target *target = bank->target;
-
- /* Enable ISS access */
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB | FCTR_FS_ISS);
-
- /* Read the relevant block of memory from the ISS sector */
- uint32_t iss_secured_field[0x230/16][4];
- target_read_memory(target, bank->base + 0xC00, 4, 0x230/4,
- (uint8_t *)iss_secured_field);
-
- /* Disable ISS access */
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- /* Check status of each sector. Note that the sector numbering in the LPC2900
- * is different from the logical sector numbers used in OpenOCD!
- * Refer to the user manual for details.
- *
- * All zeros (16x 0x00) are treated as a secured sector (is_protected = 1)
- * All ones (16x 0xFF) are treated as a non-secured sector (is_protected = 0)
- * Anything else is undefined (is_protected = -1). This is treated as
- * a protected sector!
- */
- int sector;
- int index_t;
- for (sector = 0; sector < bank->num_sectors; sector++) {
- /* Convert logical sector number to physical sector number */
- if (sector <= 4)
- index_t = sector + 11;
- else if (sector <= 7)
- index_t = sector + 27;
- else
- index_t = sector - 8;
-
- bank->sectors[sector].is_protected = -1;
-
- if ((iss_secured_field[index_t][0] == 0x00000000) &&
- (iss_secured_field[index_t][1] == 0x00000000) &&
- (iss_secured_field[index_t][2] == 0x00000000) &&
- (iss_secured_field[index_t][3] == 0x00000000))
- bank->sectors[sector].is_protected = 1;
-
- if ((iss_secured_field[index_t][0] == 0xFFFFFFFF) &&
- (iss_secured_field[index_t][1] == 0xFFFFFFFF) &&
- (iss_secured_field[index_t][2] == 0xFFFFFFFF) &&
- (iss_secured_field[index_t][3] == 0xFFFFFFFF))
- bank->sectors[sector].is_protected = 0;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Use BIST to calculate a 128-bit hash value over a range of flash.
- *
- * @param bank Pointer to the flash bank descriptor
- * @param addr_from
- * @param addr_to
- * @param signature
- */
-static uint32_t lpc2900_run_bist128(struct flash_bank *bank,
- uint32_t addr_from,
- uint32_t addr_to,
- uint32_t signature[4])
-{
- struct target *target = bank->target;
-
- /* Clear END_OF_MISR interrupt status */
- target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_MISR);
-
- /* Start address */
- target_write_u32(target, FMSSTART, addr_from >> 4);
- /* End address, and issue start command */
- target_write_u32(target, FMSSTOP, (addr_to >> 4) | FMSSTOP_MISR_START);
-
- /* Poll for end of operation. Calculate a reasonable timeout. */
- if (lpc2900_wait_status(bank, INTSRC_END_OF_MISR, 1000) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* Return the signature */
- uint8_t sig_buf[4 * 4];
- target_read_memory(target, FMSW0, 4, 4, sig_buf);
- target_buffer_get_u32_array(target, sig_buf, 4, signature);
-
- return ERROR_OK;
-}
-
-/**
- * Return sector number for given address.
- *
- * Return the (logical) sector number for a given relative address.
- * No sanity check is done. It assumed that the address is valid.
- *
- * @param bank Pointer to the flash bank descriptor
- * @param offset Offset address relative to bank start
- */
-static uint32_t lpc2900_address2sector(struct flash_bank *bank,
- uint32_t offset)
-{
- uint32_t address = bank->base + offset;
-
- /* Run through all sectors of this bank */
- int sector;
- for (sector = 0; sector < bank->num_sectors; sector++) {
- /* Return immediately if address is within the current sector */
- if (address < (bank->sectors[sector].offset + bank->sectors[sector].size))
- return sector;
- }
-
- /* We should never come here. If we do, return an arbitrary sector number. */
- return 0;
-}
-
-/**
- * Write one page to the index sector.
- *
- * @param bank Pointer to the flash bank descriptor
- * @param pagenum Page number (0...7)
- * @param page Page array (FLASH_PAGE_SIZE bytes)
- */
-static int lpc2900_write_index_page(struct flash_bank *bank,
- int pagenum,
- uint8_t page[FLASH_PAGE_SIZE])
-{
- /* Only pages 4...7 are user writable */
- if ((pagenum < 4) || (pagenum > 7)) {
- LOG_ERROR("Refuse to burn index sector page %d", pagenum);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- /* Get target, and check if it's halted */
- struct target *target = bank->target;
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Private info */
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
- /* Enable flash block and set the correct CRA clock of 66 kHz */
- lpc2900_setup(bank);
-
- /* Un-protect the index sector */
- target_write_u32(target, bank->base, 0);
- target_write_u32(target, FCTR,
- FCTR_FS_LOADREQ | FCTR_FS_WPB | FCTR_FS_ISS |
- FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS);
-
- /* Set latch load mode */
- target_write_u32(target, FCTR,
- FCTR_FS_ISS | FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS);
-
- /* Write whole page to flash data latches */
- if (target_write_memory(target,
- bank->base + pagenum * FLASH_PAGE_SIZE,
- 4, FLASH_PAGE_SIZE / 4, page) != ERROR_OK) {
- LOG_ERROR("Index sector write failed @ page %d", pagenum);
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* Clear END_OF_BURN interrupt status */
- target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_BURN);
-
- /* Set the program/erase time to FLASH_PROGRAM_TIME */
- target_write_u32(target, FPTR,
- FPTR_EN_T | lpc2900_calc_tr(lpc2900_info->clk_sys_fmc,
- FLASH_PROGRAM_TIME));
-
- /* Trigger flash write */
- target_write_u32(target, FCTR,
- FCTR_FS_PROGREQ | FCTR_FS_ISS |
- FCTR_FS_WPB | FCTR_FS_WRE | FCTR_FS_CS);
-
- /* Wait for the end of the write operation. If it's not over after one
- * second, something went dreadfully wrong... :-(
- */
- if (lpc2900_wait_status(bank, INTSRC_END_OF_BURN, 1000) != ERROR_OK) {
- LOG_ERROR("Index sector write failed @ page %d", pagenum);
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- return ERROR_OK;
-}
-
-/**
- * Calculate FPTR.TR register value for desired program/erase time.
- *
- * @param clock System clock in Hz
- * @param time Program/erase time in µs
- */
-static uint32_t lpc2900_calc_tr(uint32_t clock_var, uint32_t time_var)
-{
- /* ((time[µs]/1e6) * f[Hz]) + 511
- * FPTR.TR = -------------------------------
- * 512
- */
-
- uint32_t tr_val = (uint32_t)((((time_var / 1e6) * clock_var) + 511.0) / 512.0);
-
- return tr_val;
-}
-
-/*********************** Private flash commands **************************/
-
-
-/**
- * Command to determine the signature of the whole flash.
- *
- * Uses the Built-In-Self-Test (BIST) to generate a 128-bit hash value
- * of the flash content.
- */
-COMMAND_HANDLER(lpc2900_handle_signature_command)
-{
- uint32_t status;
- uint32_t signature[4];
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Run BIST over whole flash range */
- status = lpc2900_run_bist128(bank, bank->base, bank->base + (bank->size - 1), signature);
- if (status != ERROR_OK)
- return status;
-
- command_print(CMD_CTX, "signature: 0x%8.8" PRIx32
- ":0x%8.8" PRIx32
- ":0x%8.8" PRIx32
- ":0x%8.8" PRIx32,
- signature[3], signature[2], signature[1], signature[0]);
-
- return ERROR_OK;
-}
-
-/**
- * Store customer info in file.
- *
- * Read customer info from index sector, and store that block of data into
- * a disk file. The format is binary.
- */
-COMMAND_HANDLER(lpc2900_handle_read_custom_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
- lpc2900_info->risky = 0;
-
- /* Get target, and check if it's halted */
- struct target *target = bank->target;
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Storage for customer info. Read in two parts */
- uint8_t customer[4 * (ISS_CUSTOMER_NWORDS1 + ISS_CUSTOMER_NWORDS2)];
-
- /* Enable access to index sector */
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB | FCTR_FS_ISS);
-
- /* Read two parts */
- target_read_memory(target, bank->base+ISS_CUSTOMER_START1, 4,
- ISS_CUSTOMER_NWORDS1,
- &customer[0]);
- target_read_memory(target, bank->base+ISS_CUSTOMER_START2, 4,
- ISS_CUSTOMER_NWORDS2,
- &customer[4 * ISS_CUSTOMER_NWORDS1]);
-
- /* Deactivate access to index sector */
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- /* Try and open the file */
- struct fileio *fileio;
- const char *filename = CMD_ARGV[1];
- int ret = fileio_open(&fileio, filename, FILEIO_WRITE, FILEIO_BINARY);
- if (ret != ERROR_OK) {
- LOG_WARNING("Could not open file %s", filename);
- return ret;
- }
-
- size_t nwritten;
- ret = fileio_write(fileio, sizeof(customer), customer, &nwritten);
- if (ret != ERROR_OK) {
- LOG_ERROR("Write operation to file %s failed", filename);
- fileio_close(fileio);
- return ret;
- }
-
- fileio_close(fileio);
-
- return ERROR_OK;
-}
-
-/**
- * Enter password to enable potentially dangerous options.
- */
-COMMAND_HANDLER(lpc2900_handle_password_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
-#define ISS_PASSWORD "I_know_what_I_am_doing"
-
- lpc2900_info->risky = !strcmp(CMD_ARGV[1], ISS_PASSWORD);
-
- if (!lpc2900_info->risky) {
- command_print(CMD_CTX, "Wrong password (use '%s')", ISS_PASSWORD);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- command_print(CMD_CTX,
- "Potentially dangerous operation allowed in next command!");
-
- return ERROR_OK;
-}
-
-/**
- * Write customer info from file to the index sector.
- */
-COMMAND_HANDLER(lpc2900_handle_write_custom_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
- /* Check if command execution is allowed. */
- if (!lpc2900_info->risky) {
- command_print(CMD_CTX, "Command execution not allowed!");
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- lpc2900_info->risky = 0;
-
- /* Get target, and check if it's halted */
- struct target *target = bank->target;
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* The image will always start at offset 0 */
- struct image image;
- image.base_address_set = 1;
- image.base_address = 0;
- image.start_address_set = 0;
-
- const char *filename = CMD_ARGV[1];
- const char *type = (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL;
- retval = image_open(&image, filename, type);
- if (retval != ERROR_OK)
- return retval;
-
- /* Do a sanity check: The image must be exactly the size of the customer
- programmable area. Any other size is rejected. */
- if (image.num_sections != 1) {
- LOG_ERROR("Only one section allowed in image file.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- if ((image.sections[0].base_address != 0) ||
- (image.sections[0].size != ISS_CUSTOMER_SIZE)) {
- LOG_ERROR("Incorrect image file size. Expected %d, "
- "got %" PRIu32,
- ISS_CUSTOMER_SIZE, image.sections[0].size);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* Well boys, I reckon this is it... */
-
- /* Customer info is split into two blocks in pages 4 and 5. */
- uint8_t page[FLASH_PAGE_SIZE];
-
- /* Page 4 */
- uint32_t offset = ISS_CUSTOMER_START1 % FLASH_PAGE_SIZE;
- memset(page, 0xff, FLASH_PAGE_SIZE);
- size_t size_read;
- retval = image_read_section(&image, 0, 0,
- ISS_CUSTOMER_SIZE1, &page[offset], &size_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read from file '%s'", filename);
- image_close(&image);
- return retval;
- }
- retval = lpc2900_write_index_page(bank, 4, page);
- if (retval != ERROR_OK) {
- image_close(&image);
- return retval;
- }
-
- /* Page 5 */
- offset = ISS_CUSTOMER_START2 % FLASH_PAGE_SIZE;
- memset(page, 0xff, FLASH_PAGE_SIZE);
- retval = image_read_section(&image, 0, ISS_CUSTOMER_SIZE1,
- ISS_CUSTOMER_SIZE2, &page[offset], &size_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read from file '%s'", filename);
- image_close(&image);
- return retval;
- }
- retval = lpc2900_write_index_page(bank, 5, page);
- if (retval != ERROR_OK) {
- image_close(&image);
- return retval;
- }
-
- image_close(&image);
-
- return ERROR_OK;
-}
-
-/**
- * Activate 'sector security' for a range of sectors.
- */
-COMMAND_HANDLER(lpc2900_handle_secure_sector_command)
-{
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* Get the bank descriptor */
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
- /* Check if command execution is allowed. */
- if (!lpc2900_info->risky) {
- command_print(CMD_CTX, "Command execution not allowed! "
- "(use 'password' command first)");
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- lpc2900_info->risky = 0;
-
- /* Read sector range, and do a sanity check. */
- int first, last;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
- if ((first >= bank->num_sectors) ||
- (last >= bank->num_sectors) ||
- (first > last)) {
- command_print(CMD_CTX, "Illegal sector range");
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- uint8_t page[FLASH_PAGE_SIZE];
- int sector;
-
- /* Sectors in page 6 */
- if ((first <= 4) || (last >= 8)) {
- memset(&page, 0xff, FLASH_PAGE_SIZE);
- for (sector = first; sector <= last; sector++) {
- if (sector <= 4)
- memset(&page[0xB0 + 16*sector], 0, 16);
- else if (sector >= 8)
- memset(&page[0x00 + 16*(sector - 8)], 0, 16);
- }
-
- retval = lpc2900_write_index_page(bank, 6, page);
- if (retval != ERROR_OK) {
- LOG_ERROR("failed to update index sector page 6");
- return retval;
- }
- }
-
- /* Sectors in page 7 */
- if ((first <= 7) && (last >= 5)) {
- memset(&page, 0xff, FLASH_PAGE_SIZE);
- for (sector = first; sector <= last; sector++) {
- if ((sector >= 5) && (sector <= 7))
- memset(&page[0x00 + 16*(sector - 5)], 0, 16);
- }
-
- retval = lpc2900_write_index_page(bank, 7, page);
- if (retval != ERROR_OK) {
- LOG_ERROR("failed to update index sector page 7");
- return retval;
- }
- }
-
- command_print(CMD_CTX,
- "Sectors security will become effective after next power cycle");
-
- /* Update the sector security status */
- if (lpc2900_read_security_status(bank) != ERROR_OK) {
- LOG_ERROR("Cannot determine sector security status");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Activate JTAG protection.
- */
-COMMAND_HANDLER(lpc2900_handle_secure_jtag_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* Get the bank descriptor */
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
- /* Check if command execution is allowed. */
- if (!lpc2900_info->risky) {
- command_print(CMD_CTX, "Command execution not allowed! "
- "(use 'password' command first)");
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- lpc2900_info->risky = 0;
-
- /* Prepare page */
- uint8_t page[FLASH_PAGE_SIZE];
- memset(&page, 0xff, FLASH_PAGE_SIZE);
-
-
- /* Insert "soft" protection word */
- page[0x30 + 15] = 0x7F;
- page[0x30 + 11] = 0x7F;
- page[0x30 + 7] = 0x7F;
- page[0x30 + 3] = 0x7F;
-
- /* Write to page 5 */
- retval = lpc2900_write_index_page(bank, 5, page);
- if (retval != ERROR_OK) {
- LOG_ERROR("failed to update index sector page 5");
- return retval;
- }
-
- LOG_INFO("JTAG security set. Good bye!");
-
- return ERROR_OK;
-}
-
-/*********************** Flash interface functions **************************/
-
-static const struct command_registration lpc2900_exec_command_handlers[] = {
- {
- .name = "signature",
- .usage = "<bank>",
- .handler = lpc2900_handle_signature_command,
- .mode = COMMAND_EXEC,
- .help = "Calculate and display signature of flash bank.",
- },
- {
- .name = "read_custom",
- .handler = lpc2900_handle_read_custom_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename",
- .help = "Copies 912 bytes of customer information "
- "from index sector into file.",
- },
- {
- .name = "password",
- .handler = lpc2900_handle_password_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id password",
- .help = "Enter fixed password to enable 'dangerous' options.",
- },
- {
- .name = "write_custom",
- .handler = lpc2900_handle_write_custom_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename ('bin'|'ihex'|'elf'|'s19')",
- .help = "Copies 912 bytes of customer info from file "
- "to index sector.",
- },
- {
- .name = "secure_sector",
- .handler = lpc2900_handle_secure_sector_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id first_sector last_sector",
- .help = "Activate sector security for a range of sectors. "
- "It will be effective after a power cycle.",
- },
- {
- .name = "secure_jtag",
- .handler = lpc2900_handle_secure_jtag_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Disable the JTAG port. "
- "It will be effective after a power cycle.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration lpc2900_command_handlers[] = {
- {
- .name = "lpc2900",
- .mode = COMMAND_ANY,
- .help = "LPC2900 flash command group",
- .usage = "",
- .chain = lpc2900_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Evaluate flash bank command. */
-FLASH_BANK_COMMAND_HANDLER(lpc2900_flash_bank_command)
-{
- struct lpc2900_flash_bank *lpc2900_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- lpc2900_info = malloc(sizeof(struct lpc2900_flash_bank));
- bank->driver_priv = lpc2900_info;
-
- /* Get flash clock.
- * Reject it if we can't meet the requirements for program time
- * (if clock too slow), or for erase time (clock too fast).
- */
- uint32_t clk_sys_fmc;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], clk_sys_fmc);
- lpc2900_info->clk_sys_fmc = clk_sys_fmc * 1000;
-
- uint32_t clock_limit;
- /* Check program time limit */
- clock_limit = 512000000l / FLASH_PROGRAM_TIME;
- if (lpc2900_info->clk_sys_fmc < clock_limit) {
- LOG_WARNING("flash clock must be at least %" PRIu32 " kHz",
- (clock_limit / 1000));
- return ERROR_FLASH_BANK_INVALID;
- }
-
- /* Check erase time limit */
- clock_limit = (uint32_t)((32767.0 * 512.0 * 1e6) / FLASH_ERASE_TIME);
- if (lpc2900_info->clk_sys_fmc > clock_limit) {
- LOG_WARNING("flash clock must be a maximum of %" PRIu32 " kHz",
- (clock_limit / 1000));
- return ERROR_FLASH_BANK_INVALID;
- }
-
- /* Chip ID will be obtained by probing the device later */
- lpc2900_info->chipid = 0;
- lpc2900_info->is_probed = false;
-
- return ERROR_OK;
-}
-
-/**
- * Erase sector(s).
- *
- * @param bank Pointer to the flash bank descriptor
- * @param first First sector to be erased
- * @param last Last sector (including) to be erased
- */
-static int lpc2900_erase(struct flash_bank *bank, int first, int last)
-{
- uint32_t status;
- int sector;
- int last_unsecured_sector;
- struct target *target = bank->target;
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
-
-
- status = lpc2900_is_ready(bank);
- if (status != ERROR_OK)
- return status;
-
- /* Sanity check on sector range */
- if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
- LOG_INFO("Bad sector range");
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- /* Update the info about secured sectors */
- lpc2900_read_security_status(bank);
-
- /* The selected sector range might include secured sectors. An attempt
- * to erase such a sector will cause the erase to fail also for unsecured
- * sectors. It is necessary to determine the last unsecured sector now,
- * because we have to treat the last relevant sector in the list in
- * a special way.
- */
- last_unsecured_sector = -1;
- for (sector = first; sector <= last; sector++) {
- if (!bank->sectors[sector].is_protected)
- last_unsecured_sector = sector;
- }
-
- /* Exit now, in case of the rare constellation where all sectors in range
- * are secured. This is regarded a success, since erasing/programming of
- * secured sectors shall be handled transparently.
- */
- if (last_unsecured_sector == -1)
- return ERROR_OK;
-
- /* Enable flash block and set the correct CRA clock of 66 kHz */
- lpc2900_setup(bank);
-
- /* Clear END_OF_ERASE interrupt status */
- target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_ERASE);
-
- /* Set the program/erase timer to FLASH_ERASE_TIME */
- target_write_u32(target, FPTR,
- FPTR_EN_T | lpc2900_calc_tr(lpc2900_info->clk_sys_fmc,
- FLASH_ERASE_TIME));
-
- /* Sectors are marked for erasure, then erased all together */
- for (sector = first; sector <= last_unsecured_sector; sector++) {
- /* Only mark sectors that aren't secured. Any attempt to erase a group
- * of sectors will fail if any single one of them is secured!
- */
- if (!bank->sectors[sector].is_protected) {
- /* Unprotect the sector */
- target_write_u32(target, bank->sectors[sector].offset, 0);
- target_write_u32(target, FCTR,
- FCTR_FS_LOADREQ | FCTR_FS_WPB |
- FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS);
-
- /* Mark the sector for erasure. The last sector in the list
- triggers the erasure. */
- target_write_u32(target, bank->sectors[sector].offset, 0);
- if (sector == last_unsecured_sector) {
- target_write_u32(target, FCTR,
- FCTR_FS_PROGREQ | FCTR_FS_WPB | FCTR_FS_CS);
- } else {
- target_write_u32(target, FCTR,
- FCTR_FS_LOADREQ | FCTR_FS_WPB |
- FCTR_FS_WEB | FCTR_FS_CS);
- }
- }
- }
-
- /* Wait for the end of the erase operation. If it's not over after two seconds,
- * something went dreadfully wrong... :-(
- */
- if (lpc2900_wait_status(bank, INTSRC_END_OF_ERASE, 2000) != ERROR_OK)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* Normal flash operating mode */
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- return ERROR_OK;
-}
-
-static int lpc2900_protect(struct flash_bank *bank, int set, int first, int last)
-{
- /* This command is not supported.
- * "Protection" in LPC2900 terms is handled transparently. Sectors will
- * automatically be unprotected as needed.
- * Instead we use the concept of sector security. A secured sector is shown
- * as "protected" in OpenOCD. Sector security is a permanent feature, and
- * cannot be disabled once activated.
- */
-
- return ERROR_OK;
-}
-
-/**
- * Write data to flash.
- *
- * @param bank Pointer to the flash bank descriptor
- * @param buffer Buffer with data
- * @param offset Start address (relative to bank start)
- * @param count Number of bytes to be programmed
- */
-static int lpc2900_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- uint8_t page[FLASH_PAGE_SIZE];
- uint32_t status;
- uint32_t num_bytes;
- struct target *target = bank->target;
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
- int sector;
- int retval;
-
- static const uint32_t write_target_code[] = {
- /* Set auto latch mode: FCTR=CS|WRE|WEB */
- 0xe3a0a007, /* loop mov r10, #0x007 */
- 0xe583a000, /* str r10,[r3,#0] */
-
- /* Load complete page into latches */
- 0xe3a06020, /* mov r6,#(512/16) */
- 0xe8b00f00, /* next ldmia r0!,{r8-r11} */
- 0xe8a10f00, /* stmia r1!,{r8-r11} */
- 0xe2566001, /* subs r6,#1 */
- 0x1afffffb, /* bne next */
-
- /* Clear END_OF_BURN interrupt status */
- 0xe3a0a002, /* mov r10,#(1 << 1) */
- 0xe583afe8, /* str r10,[r3,#0xfe8] */
-
- /* Set the erase time to FLASH_PROGRAM_TIME */
- 0xe5834008, /* str r4,[r3,#8] */
-
- /* Trigger flash write
- * FCTR = CS | WRE | WPB | PROGREQ */
- 0xe3a0a083, /* mov r10,#0x83 */
- 0xe38aaa01, /* orr r10,#0x1000 */
- 0xe583a000, /* str r10,[r3,#0] */
-
- /* Wait for end of burn */
- 0xe593afe0, /* wait ldr r10,[r3,#0xfe0] */
- 0xe21aa002, /* ands r10,#(1 << 1) */
- 0x0afffffc, /* beq wait */
-
- /* End? */
- 0xe2522001, /* subs r2,#1 */
- 0x1affffed, /* bne loop */
-
- 0xeafffffe /* done b done */
- };
-
-
- status = lpc2900_is_ready(bank);
- if (status != ERROR_OK)
- return status;
-
- /* Enable flash block and set the correct CRA clock of 66 kHz */
- lpc2900_setup(bank);
-
- /* Update the info about secured sectors */
- lpc2900_read_security_status(bank);
-
- /* Unprotect all involved sectors */
- for (sector = 0; sector < bank->num_sectors; sector++) {
- /* Start address in or before this sector?
- * End address in or behind this sector? */
- if (((bank->base + offset) <
- (bank->sectors[sector].offset + bank->sectors[sector].size)) &&
- ((bank->base + (offset + count - 1)) >= bank->sectors[sector].offset)) {
- /* This sector is involved and needs to be unprotected.
- * Don't do it for secured sectors.
- */
- if (!bank->sectors[sector].is_protected) {
- target_write_u32(target, bank->sectors[sector].offset, 0);
- target_write_u32(target, FCTR,
- FCTR_FS_LOADREQ | FCTR_FS_WPB |
- FCTR_FS_WEB | FCTR_FS_WRE | FCTR_FS_CS);
- }
- }
- }
-
- /* Set the program/erase time to FLASH_PROGRAM_TIME */
- uint32_t prog_time = FPTR_EN_T | lpc2900_calc_tr(lpc2900_info->clk_sys_fmc, FLASH_PROGRAM_TIME);
-
- /* If there is a working area of reasonable size, use it to program via
- * a target algorithm. If not, fall back to host programming. */
-
- /* We need some room for target code. */
- const uint32_t target_code_size = sizeof(write_target_code);
-
- /* Try working area allocation. Start with a large buffer, and try with
- * reduced size if that fails. */
- struct working_area *warea;
- uint32_t buffer_size = lpc2900_info->max_ram_block - 1 * KiB;
- while ((retval = target_alloc_working_area_try(target,
- buffer_size + target_code_size,
- &warea)) != ERROR_OK) {
- /* Try a smaller buffer now, and stop if it's too small. */
- buffer_size -= 1 * KiB;
- if (buffer_size < 2 * KiB) {
- LOG_INFO("no (large enough) working area, falling back to host mode");
- warea = NULL;
- break;
- }
- }
-
- if (warea) {
- struct reg_param reg_params[5];
- struct arm_algorithm arm_algo;
-
- /* We can use target mode. Download the algorithm. */
- uint8_t code[sizeof(write_target_code)];
- target_buffer_set_u32_array(target, code, ARRAY_SIZE(write_target_code),
- write_target_code);
- retval = target_write_buffer(target, (warea->address) + buffer_size, sizeof(code), code);
- if (retval != ERROR_OK) {
- LOG_ERROR("Unable to write block write code to target");
- target_free_all_working_areas(target);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- 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);
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
-
- /* Write to flash in large blocks */
- while (count != 0) {
- uint32_t this_npages;
- const uint8_t *this_buffer;
- int start_sector = lpc2900_address2sector(bank, offset);
-
- /* First page / last page / rest */
- if (offset % FLASH_PAGE_SIZE) {
- /* Block doesn't start on page boundary.
- * Burn first partial page separately. */
- memset(&page, 0xff, sizeof(page));
- memcpy(&page[offset % FLASH_PAGE_SIZE],
- buffer,
- FLASH_PAGE_SIZE - (offset % FLASH_PAGE_SIZE));
- this_npages = 1;
- this_buffer = &page[0];
- count = count + (offset % FLASH_PAGE_SIZE);
- offset = offset - (offset % FLASH_PAGE_SIZE);
- } else if (count < FLASH_PAGE_SIZE) {
- /* Download last incomplete page separately. */
- memset(&page, 0xff, sizeof(page));
- memcpy(&page, buffer, count);
- this_npages = 1;
- this_buffer = &page[0];
- count = FLASH_PAGE_SIZE;
- } else {
- /* Download as many full pages as possible */
- this_npages = (count < buffer_size) ?
- count / FLASH_PAGE_SIZE :
- buffer_size / FLASH_PAGE_SIZE;
- this_buffer = buffer;
-
- /* Make sure we stop at the next secured sector */
- sector = start_sector + 1;
- while (sector < bank->num_sectors) {
- /* Secured? */
- if (bank->sectors[sector].is_protected) {
- /* Is that next sector within the current block? */
- if ((bank->sectors[sector].offset - bank->base) <
- (offset + (this_npages * FLASH_PAGE_SIZE))) {
- /* Yes! Split the block */
- this_npages =
- (bank->sectors[sector].offset -
- bank->base - offset)
- / FLASH_PAGE_SIZE;
- break;
- }
- }
-
- sector++;
- }
- }
-
- /* Skip the current sector if it is secured */
- if (bank->sectors[start_sector].is_protected) {
- LOG_DEBUG("Skip secured sector %d",
- start_sector);
-
- /* Stop if this is the last sector */
- if (start_sector == bank->num_sectors - 1)
- break;
-
- /* Skip */
- uint32_t nskip = bank->sectors[start_sector].size -
- (offset % bank->sectors[start_sector].size);
- offset += nskip;
- buffer += nskip;
- count = (count >= nskip) ? (count - nskip) : 0;
- continue;
- }
-
- /* Execute buffer download */
- retval = target_write_buffer(target, warea->address,
- this_npages * FLASH_PAGE_SIZE, this_buffer);
- if (retval != ERROR_OK) {
- LOG_ERROR("Unable to write data to target");
- target_free_all_working_areas(target);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* Prepare registers */
- buf_set_u32(reg_params[0].value, 0, 32, warea->address);
- buf_set_u32(reg_params[1].value, 0, 32, offset);
- buf_set_u32(reg_params[2].value, 0, 32, this_npages);
- buf_set_u32(reg_params[3].value, 0, 32, FCTR);
- buf_set_u32(reg_params[4].value, 0, 32, FPTR_EN_T | prog_time);
-
- /* Execute algorithm, assume breakpoint for last instruction */
- arm_algo.common_magic = ARM_COMMON_MAGIC;
- arm_algo.core_mode = ARM_MODE_SVC;
- arm_algo.core_state = ARM_STATE_ARM;
-
- retval = target_run_algorithm(target, 0, NULL, 5, reg_params,
- (warea->address) + buffer_size,
- (warea->address) + buffer_size + target_code_size - 4,
- 10000, /* 10s should be enough for max. 16 KiB of data */
- &arm_algo);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Execution of flash algorithm failed.");
- target_free_all_working_areas(target);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- count -= this_npages * FLASH_PAGE_SIZE;
- buffer += this_npages * FLASH_PAGE_SIZE;
- offset += this_npages * FLASH_PAGE_SIZE;
- }
-
- /* Free all resources */
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
- target_free_all_working_areas(target);
- } else {
- /* Write to flash memory page-wise */
- while (count != 0) {
- /* How many bytes do we copy this time? */
- num_bytes = (count >= FLASH_PAGE_SIZE) ?
- FLASH_PAGE_SIZE - (offset % FLASH_PAGE_SIZE) :
- count;
-
- /* Don't do anything with it if the page is in a secured sector. */
- if (!bank->sectors[lpc2900_address2sector(bank, offset)].is_protected) {
- /* Set latch load mode */
- target_write_u32(target, FCTR,
- FCTR_FS_CS | FCTR_FS_WRE | FCTR_FS_WEB);
-
- /* Always clear the buffer (a little overhead, but who cares) */
- memset(page, 0xFF, FLASH_PAGE_SIZE);
-
- /* Copy them to the buffer */
- memcpy(&page[offset % FLASH_PAGE_SIZE],
- &buffer[offset % FLASH_PAGE_SIZE],
- num_bytes);
-
- /* Write whole page to flash data latches */
- if (target_write_memory(target,
- bank->base + (offset - (offset % FLASH_PAGE_SIZE)),
- 4, FLASH_PAGE_SIZE / 4, page) != ERROR_OK) {
- LOG_ERROR("Write failed @ 0x%8.8" PRIx32, offset);
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* Clear END_OF_BURN interrupt status */
- target_write_u32(target, INT_CLR_STATUS, INTSRC_END_OF_BURN);
-
- /* Set the programming time */
- target_write_u32(target, FPTR, FPTR_EN_T | prog_time);
-
- /* Trigger flash write */
- target_write_u32(target, FCTR,
- FCTR_FS_CS | FCTR_FS_WRE | FCTR_FS_WPB | FCTR_FS_PROGREQ);
-
- /* Wait for the end of the write operation. If it's not over
- * after one second, something went dreadfully wrong... :-(
- */
- if (lpc2900_wait_status(bank, INTSRC_END_OF_BURN, 1000) != ERROR_OK) {
- LOG_ERROR("Write failed @ 0x%8.8" PRIx32, offset);
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
-
- /* Update pointers and counters */
- offset += num_bytes;
- buffer += num_bytes;
- count -= num_bytes;
- }
-
- retval = ERROR_OK;
- }
-
- /* Normal flash operating mode */
- target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB);
-
- return retval;
-}
-
-/**
- * Try and identify the device.
- *
- * Determine type number and its memory layout.
- *
- * @param bank Pointer to the flash bank descriptor
- */
-static int lpc2900_probe(struct flash_bank *bank)
-{
- struct lpc2900_flash_bank *lpc2900_info = bank->driver_priv;
- struct target *target = bank->target;
- int i = 0;
- uint32_t offset;
-
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* We want to do this only once. */
- if (lpc2900_info->is_probed)
- return ERROR_OK;
-
- /* Probing starts with reading the CHIPID register. We will continue only
- * if this identifies as an LPC2900 device.
- */
- target_read_u32(target, CHIPID, &lpc2900_info->chipid);
-
- if (lpc2900_info->chipid != EXPECTED_CHIPID) {
- LOG_WARNING("Device is not an LPC29xx");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* It's an LPC29xx device. Now read the feature register FEAT0...FEAT3. */
- uint32_t feat0, feat1, feat2, feat3;
- target_read_u32(target, FEAT0, &feat0);
- target_read_u32(target, FEAT1, &feat1);
- target_read_u32(target, FEAT2, &feat2);
- target_read_u32(target, FEAT3, &feat3);
-
- /* Base address */
- bank->base = 0x20000000;
-
- /* Determine flash layout from FEAT2 register */
- uint32_t num_64k_sectors = (feat2 >> 16) & 0xFF;
- uint32_t num_8k_sectors = (feat2 >> 0) & 0xFF;
- bank->num_sectors = num_64k_sectors + num_8k_sectors;
- bank->size = KiB * (64 * num_64k_sectors + 8 * num_8k_sectors);
-
- /* Determine maximum contiguous RAM block */
- lpc2900_info->max_ram_block = 16 * KiB;
- if ((feat1 & 0x30) == 0x30) {
- lpc2900_info->max_ram_block = 32 * KiB;
- if ((feat1 & 0x0C) == 0x0C)
- lpc2900_info->max_ram_block = 48 * KiB;
- }
-
- /* Determine package code and ITCM size */
- uint32_t package_code = feat0 & 0x0F;
- uint32_t itcm_code = (feat1 >> 16) & 0x1F;
-
- /* Determine the exact type number. */
- uint32_t found = 1;
- if ((package_code == 4) && (itcm_code == 5)) {
- /* Old LPC2917 or LPC2919 (non-/01 devices) */
- lpc2900_info->target_name = (bank->size == 768*KiB) ? "LPC2919" : "LPC2917";
- } else {
- if (package_code == 2) {
- /* 100-pin package */
- if (bank->size == 128*KiB)
- lpc2900_info->target_name = "LPC2921";
- else if (bank->size == 256*KiB)
- lpc2900_info->target_name = "LPC2923";
- else if (bank->size == 512*KiB)
- lpc2900_info->target_name = "LPC2925";
- else
- found = 0;
- } else if (package_code == 4) {
- /* 144-pin package */
- if ((bank->size == 256*KiB) && (feat3 == 0xFFFFFFE9))
- lpc2900_info->target_name = "LPC2926";
- else if ((bank->size == 512*KiB) && (feat3 == 0xFFFFFCF0))
- lpc2900_info->target_name = "LPC2917/01";
- else if ((bank->size == 512*KiB) && (feat3 == 0xFFFFFFF1))
- lpc2900_info->target_name = "LPC2927";
- else if ((bank->size == 768*KiB) && (feat3 == 0xFFFFFCF8))
- lpc2900_info->target_name = "LPC2919/01";
- else if ((bank->size == 768*KiB) && (feat3 == 0xFFFFFFF9))
- lpc2900_info->target_name = "LPC2929";
- else
- found = 0;
- } else if (package_code == 5) {
- /* 208-pin package */
- lpc2900_info->target_name = (bank->size == 0) ? "LPC2930" : "LPC2939";
- } else
- found = 0;
- }
-
- if (!found) {
- LOG_WARNING("Unknown LPC29xx derivative (FEATx="
- "%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 ")",
- feat0, feat1, feat2, feat3);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* Show detected device */
- LOG_INFO("Flash bank %d: Device %s, %" PRIu32
- " KiB in %d sectors",
- bank->bank_number,
- lpc2900_info->target_name, bank->size / KiB,
- bank->num_sectors);
-
- /* Flashless devices cannot be handled */
- if (bank->num_sectors == 0) {
- LOG_WARNING("Flashless device cannot be handled");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* Sector layout.
- * These are logical sector numbers. When doing real flash operations,
- * the logical flash number are translated into the physical flash numbers
- * of the device.
- */
- bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
-
- offset = 0;
- for (i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
-
- if (i <= 7)
- bank->sectors[i].size = 8 * KiB;
- else if (i <= 18)
- bank->sectors[i].size = 64 * KiB;
- else {
- /* We shouldn't come here. But there might be a new part out there
- * that has more than 19 sectors. Politely ask for a fix then.
- */
- bank->sectors[i].size = 0;
- LOG_ERROR("Never heard about sector %d", i);
- }
-
- offset += bank->sectors[i].size;
- }
-
- lpc2900_info->is_probed = true;
-
- /* Read sector security status */
- if (lpc2900_read_security_status(bank) != ERROR_OK) {
- LOG_ERROR("Cannot determine sector security status");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Run a blank check for each sector.
- *
- * For speed reasons, the device isn't read word by word.
- * A hash value is calculated by the hardware ("BIST") for each sector.
- * This value is then compared against the known hash of an empty sector.
- *
- * @param bank Pointer to the flash bank descriptor
- */
-static int lpc2900_erase_check(struct flash_bank *bank)
-{
- uint32_t status = lpc2900_is_ready(bank);
- if (status != ERROR_OK) {
- LOG_INFO("Processor not halted/not probed");
- return status;
- }
-
- /* Use the BIST (Built-In Selft Test) to generate a signature of each flash
- * sector. Compare against the expected signature of an empty sector.
- */
- int sector;
- for (sector = 0; sector < bank->num_sectors; sector++) {
- uint32_t signature[4];
- status = lpc2900_run_bist128(bank, bank->sectors[sector].offset,
- bank->sectors[sector].offset + (bank->sectors[sector].size - 1), signature);
- if (status != ERROR_OK)
- return status;
-
- /* The expected signatures for an empty sector are different
- * for 8 KiB and 64 KiB sectors.
- */
- if (bank->sectors[sector].size == 8*KiB) {
- bank->sectors[sector].is_erased =
- (signature[3] == 0x01ABAAAA) &&
- (signature[2] == 0xAAAAAAAA) &&
- (signature[1] == 0xAAAAAAAA) &&
- (signature[0] == 0xAAA00AAA);
- }
- if (bank->sectors[sector].size == 64*KiB) {
- bank->sectors[sector].is_erased =
- (signature[3] == 0x11801222) &&
- (signature[2] == 0xB88844FF) &&
- (signature[1] == 0x11A22008) &&
- (signature[0] == 0x2B1BFE44);
- }
- }
-
- return ERROR_OK;
-}
-
-/**
- * Get protection (sector security) status.
- *
- * Determine the status of "sector security" for each sector.
- * A secured sector is one that can never be erased/programmed again.
- *
- * @param bank Pointer to the flash bank descriptor
- */
-static int lpc2900_protect_check(struct flash_bank *bank)
-{
- return lpc2900_read_security_status(bank);
-}
-
-struct flash_driver lpc2900_flash = {
- .name = "lpc2900",
- .commands = lpc2900_command_handlers,
- .flash_bank_command = lpc2900_flash_bank_command,
- .erase = lpc2900_erase,
- .protect = lpc2900_protect,
- .write = lpc2900_write,
- .read = default_flash_read,
- .probe = lpc2900_probe,
- .auto_probe = lpc2900_probe,
- .erase_check = lpc2900_erase_check,
- .protect_check = lpc2900_protect_check,
-};
diff --git a/src/flash/nor/lpcspifi.c b/src/flash/nor/lpcspifi.c
deleted file mode 100644
index 4eb6cc3..0000000
--- a/src/flash/nor/lpcspifi.c
+++ /dev/null
@@ -1,945 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by George Harris *
- * george@luminairecoffee.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "spi.h"
-#include <jtag/jtag.h>
-#include <helper/time_support.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-/* Offsets from ssp_base into config & data registers */
-#define SSP_CR0 (0x00) /* Control register 0 */
-#define SSP_CR1 (0x04) /* Control register 1 */
-#define SSP_DATA (0x08) /* Data register (TX and RX) */
-#define SSP_SR (0x0C) /* Status register */
-#define SSP_CPSR (0x10) /* Clock prescale register */
-
-/* Status register fields */
-#define SSP_BSY (0x00000010)
-
-/* Timeout in ms */
-#define SSP_CMD_TIMEOUT (100)
-#define SSP_PROBE_TIMEOUT (100)
-#define SSP_MAX_TIMEOUT (3000)
-
-/* Size of the stack to alloc in the working area for the execution of
- * the ROM spifi_init() function */
-#define SPIFI_INIT_STACK_SIZE 512
-
-struct lpcspifi_flash_bank {
- int probed;
- uint32_t ssp_base;
- uint32_t io_base;
- uint32_t ioconfig_base;
- uint32_t bank_num;
- uint32_t max_spi_clock_mhz;
- const struct flash_device *dev;
-};
-
-/* flash_bank lpcspifi <base> <size> <chip_width> <bus_width> <target>
- */
-FLASH_BANK_COMMAND_HANDLER(lpcspifi_flash_bank_command)
-{
- struct lpcspifi_flash_bank *lpcspifi_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- lpcspifi_info = malloc(sizeof(struct lpcspifi_flash_bank));
- if (lpcspifi_info == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- bank->driver_priv = lpcspifi_info;
- lpcspifi_info->probed = 0;
-
- return ERROR_OK;
-}
-
-static inline int ioconfig_write_reg(struct target *target, uint32_t ioconfig_base, uint32_t offset, uint32_t value)
-{
- return target_write_u32(target, ioconfig_base + offset, value);
-}
-
-static inline int ssp_write_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t value)
-{
- return target_write_u32(target, ssp_base + offset, value);
-}
-
-static inline int io_write_reg(struct target *target, uint32_t io_base, uint32_t offset, uint32_t value)
-{
- return target_write_u32(target, io_base + offset, value);
-}
-
-static inline int ssp_read_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t *value)
-{
- return target_read_u32(target, ssp_base + offset, value);
-}
-
-static int ssp_setcs(struct target *target, uint32_t io_base, unsigned int value)
-{
- return io_write_reg(target, io_base, 0x12ac, value ? 0xffffffff : 0x00000000);
-}
-
-/* Poll the SSP busy flag. When this comes back as 0, the transfer is complete
- * and the controller is idle. */
-static int poll_ssp_busy(struct target *target, uint32_t ssp_base, int timeout)
-{
- int64_t endtime;
- uint32_t value;
- int retval;
-
- retval = ssp_read_reg(target, ssp_base, SSP_SR, &value);
- if ((retval == ERROR_OK) && (value & SSP_BSY) == 0)
- return ERROR_OK;
- else if (retval != ERROR_OK)
- return retval;
-
- endtime = timeval_ms() + timeout;
- do {
- alive_sleep(1);
- retval = ssp_read_reg(target, ssp_base, SSP_SR, &value);
- if ((retval == ERROR_OK) && (value & SSP_BSY) == 0)
- return ERROR_OK;
- else if (retval != ERROR_OK)
- return retval;
- } while (timeval_ms() < endtime);
-
- LOG_ERROR("Timeout while polling BSY");
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-/* Un-initialize the ssp module and initialize the SPIFI module */
-static int lpcspifi_set_hw_mode(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- uint32_t ssp_base = lpcspifi_info->ssp_base;
- struct armv7m_algorithm armv7m_info;
- struct working_area *spifi_init_algorithm;
- struct reg_param reg_params[2];
- int retval = ERROR_OK;
-
- LOG_DEBUG("Uninitializing LPC43xx SSP");
- /* Turn off the SSP module */
- retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000);
- if (retval != ERROR_OK)
- return retval;
-
- /* see contrib/loaders/flash/lpcspifi_init.S for src */
- static const uint8_t spifi_init_code[] = {
- 0x4f, 0xea, 0x00, 0x08, 0xa1, 0xb0, 0x00, 0xaf,
- 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
- 0x4f, 0xf0, 0xf3, 0x02, 0xc3, 0xf8, 0x8c, 0x21,
- 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
- 0x4f, 0xf4, 0xc0, 0x42, 0xc4, 0xf2, 0x08, 0x02,
- 0x4f, 0xf4, 0xc0, 0x41, 0xc4, 0xf2, 0x08, 0x01,
- 0x4f, 0xf4, 0xc0, 0x40, 0xc4, 0xf2, 0x08, 0x00,
- 0x4f, 0xf0, 0xd3, 0x04, 0xc0, 0xf8, 0x9c, 0x41,
- 0x20, 0x46, 0xc1, 0xf8, 0x98, 0x01, 0x01, 0x46,
- 0xc2, 0xf8, 0x94, 0x11, 0xc3, 0xf8, 0x90, 0x11,
- 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
- 0x4f, 0xf0, 0x13, 0x02, 0xc3, 0xf8, 0xa0, 0x21,
- 0x40, 0xf2, 0x18, 0x13, 0xc1, 0xf2, 0x40, 0x03,
- 0x1b, 0x68, 0x1c, 0x68, 0x40, 0xf2, 0xb4, 0x30,
- 0xc1, 0xf2, 0x00, 0x00, 0x4f, 0xf0, 0x03, 0x01,
- 0x4f, 0xf0, 0xc0, 0x02, 0x4f, 0xea, 0x08, 0x03,
- 0xa0, 0x47, 0x00, 0xf0, 0x00, 0xb8, 0x00, 0xbe
- };
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
-
- LOG_DEBUG("Allocating working area for SPIFI init algorithm");
- /* Get memory for spifi initialization algorithm */
- retval = target_alloc_working_area(target, sizeof(spifi_init_code)
- + SPIFI_INIT_STACK_SIZE, &spifi_init_algorithm);
- if (retval != ERROR_OK) {
- LOG_ERROR("Insufficient working area to initialize SPIFI "\
- "module. You must allocate at least %zdB of working "\
- "area in order to use this driver.",
- sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE
- );
-
- return retval;
- }
-
- LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32,
- spifi_init_algorithm->address);
- /* Write algorithm to working area */
- retval = target_write_buffer(target,
- spifi_init_algorithm->address,
- sizeof(spifi_init_code),
- spifi_init_code
- );
-
- if (retval != ERROR_OK) {
- target_free_working_area(target, spifi_init_algorithm);
- return retval;
- }
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* spifi clk speed */
- /* the spifi_init() rom API makes use of the stack */
- init_reg_param(&reg_params[1], "sp", 32, PARAM_OUT);
-
- /* For now, the algorithm will set up the SPIFI module
- * @ the IRC clock speed. In the future, it could be made
- * a bit smarter to use other clock sources if the user has
- * already configured them in order to speed up memory-
- * mapped reads. */
- buf_set_u32(reg_params[0].value, 0, 32, 12);
- /* valid stack pointer */
- buf_set_u32(reg_params[1].value, 0, 32, (spifi_init_algorithm->address +
- sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE) & ~7UL);
-
- /* Run the algorithm */
- LOG_DEBUG("Running SPIFI init algorithm");
- retval = target_run_algorithm(target, 0 , NULL, 2, reg_params,
- spifi_init_algorithm->address,
- spifi_init_algorithm->address + sizeof(spifi_init_code) - 2,
- 1000, &armv7m_info);
-
- if (retval != ERROR_OK)
- LOG_ERROR("Error executing SPIFI init algorithm");
-
- target_free_working_area(target, spifi_init_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
-
- return retval;
-}
-
-/* Initialize the ssp module */
-static int lpcspifi_set_sw_mode(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- uint32_t ssp_base = lpcspifi_info->ssp_base;
- uint32_t io_base = lpcspifi_info->io_base;
- uint32_t ioconfig_base = lpcspifi_info->ioconfig_base;
- int retval = ERROR_OK;
-
- /* Re-initialize SPIFI. There are a couple of errata on this, so this makes
- sure that nothing's in an unhappy state. */
- retval = lpcspifi_set_hw_mode(bank);
-
- /* If we couldn't initialize hardware mode, don't even bother continuing */
- if (retval != ERROR_OK)
- return retval;
-
- /* Initialize the pins */
- retval = ioconfig_write_reg(target, ioconfig_base, 0x194, 0x00000040);
- if (retval == ERROR_OK)
- retval = ioconfig_write_reg(target, ioconfig_base, 0x1a0, 0x00000044);
- if (retval == ERROR_OK)
- retval = ioconfig_write_reg(target, ioconfig_base, 0x190, 0x00000040);
- if (retval == ERROR_OK)
- retval = ioconfig_write_reg(target, ioconfig_base, 0x19c, 0x000000ed);
- if (retval == ERROR_OK)
- retval = ioconfig_write_reg(target, ioconfig_base, 0x198, 0x000000ed);
- if (retval == ERROR_OK)
- retval = ioconfig_write_reg(target, ioconfig_base, 0x18c, 0x000000ea);
-
- /* Set CS high & as an output */
- if (retval == ERROR_OK)
- retval = io_write_reg(target, io_base, 0x12ac, 0xffffffff);
- if (retval == ERROR_OK)
- retval = io_write_reg(target, io_base, 0x2014, 0x00000800);
-
- /* Initialize the module */
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_CR0, 0x00000007);
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000);
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_CPSR, 0x00000008);
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000002);
-
- /* If something didn't work out, attempt to return SPIFI to HW mode */
- if (retval != ERROR_OK)
- lpcspifi_set_hw_mode(bank);
-
- return retval;
-}
-
-/* Read the status register of the external SPI flash chip. */
-static int read_status_reg(struct flash_bank *bank, uint32_t *status)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- uint32_t ssp_base = lpcspifi_info->ssp_base;
- uint32_t io_base = lpcspifi_info->io_base;
- uint32_t value;
- int retval = ERROR_OK;
-
- retval = ssp_setcs(target, io_base, 0);
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_STATUS);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
- /* Dummy write to clock in the register */
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_setcs(target, io_base, 1);
-
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
- if (retval == ERROR_OK)
- *status = value;
-
- return retval;
-}
-
-/* check for BSY bit in flash status register */
-/* timeout in ms */
-static int wait_till_ready(struct flash_bank *bank, int timeout)
-{
- uint32_t status;
- int retval;
- int64_t endtime;
-
- endtime = timeval_ms() + timeout;
- do {
- /* read flash status register */
- retval = read_status_reg(bank, &status);
- if (retval != ERROR_OK)
- return retval;
-
- if ((status & SPIFLASH_BSY_BIT) == 0)
- return ERROR_OK;
- alive_sleep(1);
- } while (timeval_ms() < endtime);
-
- LOG_ERROR("timeout waiting for flash to finish write/erase operation");
- return ERROR_FAIL;
-}
-
-/* Send "write enable" command to SPI flash chip. */
-static int lpcspifi_write_enable(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- uint32_t ssp_base = lpcspifi_info->ssp_base;
- uint32_t io_base = lpcspifi_info->io_base;
- uint32_t status, value;
- int retval = ERROR_OK;
-
- retval = ssp_setcs(target, io_base, 0);
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_WRITE_ENABLE);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
- if (retval == ERROR_OK)
- retval = ssp_setcs(target, io_base, 1);
-
- /* read flash status register */
- if (retval == ERROR_OK)
- retval = read_status_reg(bank, &status);
- if (retval != ERROR_OK)
- return retval;
-
- /* Check write enabled */
- if ((status & SPIFLASH_WE_BIT) == 0) {
- LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
- return ERROR_FAIL;
- }
-
- return retval;
-}
-
-static int lpcspifi_bulk_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- uint32_t ssp_base = lpcspifi_info->ssp_base;
- uint32_t io_base = lpcspifi_info->io_base;
- uint32_t value;
- int retval = ERROR_OK;
-
- retval = lpcspifi_set_sw_mode(bank);
-
- if (retval == ERROR_OK)
- retval = lpcspifi_write_enable(bank);
-
- /* send SPI command "bulk erase" */
- if (retval == ERROR_OK)
- ssp_setcs(target, io_base, 0);
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, lpcspifi_info->dev->chip_erase_cmd);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
- if (retval == ERROR_OK)
- retval = ssp_setcs(target, io_base, 1);
-
- /* poll flash BSY for self-timed bulk erase */
- if (retval == ERROR_OK)
- retval = wait_till_ready(bank, bank->num_sectors*SSP_MAX_TIMEOUT);
-
- return retval;
-}
-
-static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- struct reg_param reg_params[4];
- struct armv7m_algorithm armv7m_info;
- struct working_area *erase_algorithm;
- int retval = ERROR_OK;
- int sector;
-
- LOG_DEBUG("erase from sector %d to sector %d", 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 (!(lpcspifi_info->probed)) {
- LOG_ERROR("Flash bank not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- for (sector = first; sector <= last; sector++) {
- if (bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- /* If we're erasing the entire chip and the flash supports
- * it, use a bulk erase instead of going sector-by-sector. */
- if (first == 0 && last == (bank->num_sectors - 1)
- && lpcspifi_info->dev->chip_erase_cmd != lpcspifi_info->dev->erase_cmd) {
- LOG_DEBUG("Chip supports the bulk erase command."\
- " Will use bulk erase instead of sector-by-sector erase.");
- retval = lpcspifi_bulk_erase(bank);
-
- if (retval == ERROR_OK) {
- retval = lpcspifi_set_hw_mode(bank);
- return retval;
- } else
- LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase.");
- }
-
- retval = lpcspifi_set_hw_mode(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* see contrib/loaders/flash/lpcspifi_erase.S for src */
- static const uint8_t lpcspifi_flash_erase_code[] = {
- 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
- 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
- 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
- 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
- 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
- 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
- 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
- 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
- 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
- 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
- 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
- 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
- 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
- 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
- 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
- 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
- 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
- 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
- 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
- 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09,
- 0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8,
- 0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
- 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
- 0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8,
- 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80,
- 0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09,
- 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49,
- 0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29,
- 0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09,
- 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8,
- 0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
- 0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
- 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8,
- 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf,
- 0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7,
- 0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2,
- 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8,
- 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4,
- 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47,
- 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8,
- 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a,
- 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80,
- 0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff
- };
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
-
- /* Get memory for spifi initialization algorithm */
- retval = target_alloc_working_area(target, sizeof(lpcspifi_flash_erase_code),
- &erase_algorithm);
- if (retval != ERROR_OK) {
- LOG_ERROR("Insufficient working area. You must configure a working"\
- " area of at least %zdB in order to erase SPIFI flash.",
- sizeof(lpcspifi_flash_erase_code));
- return retval;
- }
-
- /* Write algorithm to working area */
- retval = target_write_buffer(target, erase_algorithm->address,
- sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code);
- if (retval != ERROR_OK) {
- target_free_working_area(target, erase_algorithm);
- return retval;
- }
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* Start address */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* Sector count */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* Erase command */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Sector size */
-
- buf_set_u32(reg_params[0].value, 0, 32, bank->sectors[first].offset);
- buf_set_u32(reg_params[1].value, 0, 32, last - first + 1);
- buf_set_u32(reg_params[2].value, 0, 32, lpcspifi_info->dev->erase_cmd);
- buf_set_u32(reg_params[3].value, 0, 32, bank->sectors[first].size);
-
- /* Run the algorithm */
- retval = target_run_algorithm(target, 0 , NULL, 4, reg_params,
- erase_algorithm->address,
- erase_algorithm->address + sizeof(lpcspifi_flash_erase_code) - 4,
- 3000*(last - first + 1), &armv7m_info);
-
- if (retval != ERROR_OK)
- LOG_ERROR("Error executing flash erase algorithm");
-
- target_free_working_area(target, erase_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
-
- retval = lpcspifi_set_hw_mode(bank);
-
- return retval;
-}
-
-static int lpcspifi_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 lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- uint32_t page_size, fifo_size;
- struct working_area *fifo;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- struct working_area *write_algorithm;
- int sector;
- int retval = ERROR_OK;
-
- LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32,
- offset, count);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset + count > lpcspifi_info->dev->size_in_bytes) {
- LOG_WARNING("Writes past end of flash. Extra data discarded.");
- count = lpcspifi_info->dev->size_in_bytes - offset;
- }
-
- /* 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? */
- if ((offset <
- (bank->sectors[sector].offset + bank->sectors[sector].size))
- && ((offset + count - 1) >= bank->sectors[sector].offset)
- && bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- page_size = lpcspifi_info->dev->pagesize;
-
- retval = lpcspifi_set_hw_mode(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* see contrib/loaders/flash/lpcspifi_write.S for src */
- static const uint8_t lpcspifi_flash_write_code[] = {
- 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
- 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
- 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
- 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
- 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
- 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
- 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
- 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
- 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
- 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
- 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
- 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
- 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
- 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
- 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
- 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
- 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
- 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
- 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
- 0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45,
- 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8,
- 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8,
- 0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8,
- 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8,
- 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8,
- 0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f,
- 0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8,
- 0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8,
- 0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8,
- 0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8,
- 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8,
- 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f,
- 0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45,
- 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b,
- 0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf,
- 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b,
- 0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45,
- 0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8,
- 0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0,
- 0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0,
- 0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0,
- 0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4,
- 0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4,
- 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8,
- 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0,
- 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8,
- 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08,
- 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08,
- 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
- 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20,
- 0x50, 0x60, 0xff, 0xf7, 0xef, 0xff, 0x30, 0x46,
- 0x00, 0xbe, 0xff, 0xff
- };
-
- if (target_alloc_working_area(target, sizeof(lpcspifi_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_ERROR("Insufficient working area. You must configure"\
- " a working area > %zdB in order to write to SPIFI flash.",
- sizeof(lpcspifi_flash_write_code));
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(lpcspifi_flash_write_code),
- lpcspifi_flash_write_code);
- if (retval != ERROR_OK) {
- target_free_working_area(target, write_algorithm);
- return retval;
- }
-
- /* FIFO allocation */
- fifo_size = target_get_working_area_avail(target);
-
- if (fifo_size == 0) {
- /* if we already allocated the writing code but failed to get fifo
- * space, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_ERROR("Insufficient working area. Please allocate at least"\
- " %zdB of working area to enable flash writes.",
- sizeof(lpcspifi_flash_write_code) + 1
- );
-
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- } else if (fifo_size < page_size)
- LOG_WARNING("Working area size is limited; flash writes may be"\
- " slow. Increase working area size to at least %zdB"\
- " to reduce write times.",
- (size_t)(sizeof(lpcspifi_flash_write_code) + page_size)
- );
- else if (fifo_size > 0x2000) /* Beyond this point, we start to get diminishing returns */
- fifo_size = 0x2000;
-
- if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) {
- target_free_working_area(target, write_algorithm);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */
- 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 (halfword-16bit) */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* page size */
-
- buf_set_u32(reg_params[0].value, 0, 32, fifo->address);
- buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size);
- buf_set_u32(reg_params[2].value, 0, 32, offset);
- buf_set_u32(reg_params[3].value, 0, 32, count);
- buf_set_u32(reg_params[4].value, 0, 32, page_size);
-
- retval = target_run_flash_async_algorithm(target, buffer, count, 1,
- 0, NULL,
- 5, reg_params,
- fifo->address, fifo->size,
- write_algorithm->address, 0,
- &armv7m_info
- );
-
- if (retval != ERROR_OK)
- LOG_ERROR("Error executing flash write algorithm");
-
- target_free_working_area(target, fifo);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- /* Switch to HW mode before return to prompt */
- retval = lpcspifi_set_hw_mode(bank);
- return retval;
-}
-
-/* Return ID of flash device */
-/* On exit, SW mode is kept */
-static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id)
-{
- struct target *target = bank->target;
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- uint32_t ssp_base = lpcspifi_info->ssp_base;
- uint32_t io_base = lpcspifi_info->io_base;
- uint32_t value;
- uint8_t id_buf[3] = {0, 0, 0};
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("Getting ID");
- retval = lpcspifi_set_sw_mode(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* poll WIP */
- if (retval == ERROR_OK)
- retval = wait_till_ready(bank, SSP_PROBE_TIMEOUT);
-
- /* Send SPI command "read ID" */
- if (retval == ERROR_OK)
- retval = ssp_setcs(target, io_base, 0);
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_ID);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
-
- /* Dummy write to clock in data */
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
- if (retval == ERROR_OK)
- id_buf[0] = value;
-
- /* Dummy write to clock in data */
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
- if (retval == ERROR_OK)
- id_buf[1] = value;
-
- /* Dummy write to clock in data */
- if (retval == ERROR_OK)
- retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
- if (retval == ERROR_OK)
- retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
- if (retval == ERROR_OK)
- retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
- if (retval == ERROR_OK)
- id_buf[2] = value;
-
- if (retval == ERROR_OK)
- retval = ssp_setcs(target, io_base, 1);
- if (retval == ERROR_OK)
- *id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];
-
- return retval;
-}
-
-static int lpcspifi_probe(struct flash_bank *bank)
-{
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- struct flash_sector *sectors;
- uint32_t id = 0; /* silence uninitialized warning */
- int retval;
-
- /* If we've already probed, we should be fine to skip this time. */
- if (lpcspifi_info->probed)
- return ERROR_OK;
- lpcspifi_info->probed = 0;
-
- lpcspifi_info->ssp_base = 0x40083000;
- lpcspifi_info->io_base = 0x400F4000;
- lpcspifi_info->ioconfig_base = 0x40086000;
- lpcspifi_info->bank_num = bank->bank_number;
-
- /* read and decode flash ID; returns in SW mode */
- retval = lpcspifi_read_flash_id(bank, &id);
- if (retval != ERROR_OK)
- return retval;
-
- retval = lpcspifi_set_hw_mode(bank);
- if (retval != ERROR_OK)
- return retval;
-
- lpcspifi_info->dev = NULL;
- for (const struct flash_device *p = flash_devices; p->name ; p++)
- if (p->device_id == id) {
- lpcspifi_info->dev = p;
- break;
- }
-
- if (!lpcspifi_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 ")",
- lpcspifi_info->dev->name, lpcspifi_info->dev->device_id);
-
- /* Set correct size value */
- bank->size = lpcspifi_info->dev->size_in_bytes;
-
- /* create and fill sectors array */
- bank->num_sectors =
- lpcspifi_info->dev->size_in_bytes / lpcspifi_info->dev->sectorsize;
- sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- if (sectors == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- for (int sector = 0; sector < bank->num_sectors; sector++) {
- sectors[sector].offset = sector * lpcspifi_info->dev->sectorsize;
- sectors[sector].size = lpcspifi_info->dev->sectorsize;
- sectors[sector].is_erased = -1;
- sectors[sector].is_protected = 0;
- }
-
- bank->sectors = sectors;
-
- lpcspifi_info->probed = 1;
- return ERROR_OK;
-}
-
-static int lpcspifi_auto_probe(struct flash_bank *bank)
-{
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
- if (lpcspifi_info->probed)
- return ERROR_OK;
- return lpcspifi_probe(bank);
-}
-
-static int lpcspifi_protect_check(struct flash_bank *bank)
-{
- /* Nothing to do. Protection is only handled in SW. */
- return ERROR_OK;
-}
-
-static int get_lpcspifi_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
-
- if (!(lpcspifi_info->probed)) {
- snprintf(buf, buf_size,
- "\nSPIFI flash bank not probed yet\n");
- return ERROR_OK;
- }
-
- snprintf(buf, buf_size, "\nSPIFI flash information:\n"
- " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
- lpcspifi_info->dev->name, lpcspifi_info->dev->device_id);
-
- return ERROR_OK;
-}
-
-struct flash_driver lpcspifi_flash = {
- .name = "lpcspifi",
- .flash_bank_command = lpcspifi_flash_bank_command,
- .erase = lpcspifi_erase,
- .protect = lpcspifi_protect,
- .write = lpcspifi_write,
- .read = default_flash_read,
- .probe = lpcspifi_probe,
- .auto_probe = lpcspifi_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = lpcspifi_protect_check,
- .info = get_lpcspifi_info,
-};
diff --git a/src/flash/nor/mdr.c b/src/flash/nor/mdr.c
deleted file mode 100644
index 374cb6f..0000000
--- a/src/flash/nor/mdr.c
+++ /dev/null
@@ -1,635 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * Copyright (C) 2013 by Paul Fertser *
- * fercerpav@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-#define MD_RST_CLK 0x40020000
-#define MD_PER_CLOCK (MD_RST_CLK + 0x1C)
-#define MD_PER_CLOCK_EEPROM (1 << 3)
-#define MD_PER_CLOCK_RST_CLK (1 << 4)
-
-#define FLASH_REG_BASE 0x40018000
-#define FLASH_CMD (FLASH_REG_BASE + 0x00)
-#define FLASH_ADR (FLASH_REG_BASE + 0x04)
-#define FLASH_DI (FLASH_REG_BASE + 0x08)
-#define FLASH_DO (FLASH_REG_BASE + 0x0C)
-#define FLASH_KEY (FLASH_REG_BASE + 0x10)
-
-#define FLASH_NVSTR (1 << 13)
-#define FLASH_PROG (1 << 12)
-#define FLASH_MAS1 (1 << 11)
-#define FLASH_ERASE (1 << 10)
-#define FLASH_IFREN (1 << 9)
-#define FLASH_SE (1 << 8)
-#define FLASH_YE (1 << 7)
-#define FLASH_XE (1 << 6)
-#define FLASH_RD (1 << 2)
-#define FLASH_WR (1 << 1)
-#define FLASH_CON (1 << 0)
-#define FLASH_DELAY_MASK (7 << 3)
-
-#define KEY 0x8AAA5551
-
-struct mdr_flash_bank {
- int probed;
- unsigned int mem_type;
- unsigned int page_count;
- unsigned int sec_count;
-};
-
-/* flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count> */
-FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command)
-{
- struct mdr_flash_bank *mdr_info;
-
- if (CMD_ARGC < 9)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- mdr_info = malloc(sizeof(struct mdr_flash_bank));
-
- bank->driver_priv = mdr_info;
- mdr_info->probed = 0;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], mdr_info->mem_type);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], mdr_info->page_count);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], mdr_info->sec_count);
- return ERROR_OK;
-}
-
-static int mdr_protect_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-static int mdr_mass_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct mdr_flash_bank *mdr_info = bank->driver_priv;
- uint32_t flash_cmd;
- int retval;
- unsigned int i;
-
- retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < mdr_info->sec_count; i++) {
- retval = target_write_u32(target, FLASH_ADR, i << 2);
- if (retval != ERROR_OK)
- return retval;
-
- flash_cmd |= FLASH_XE | FLASH_MAS1 | FLASH_ERASE;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- return retval;
- flash_cmd |= FLASH_NVSTR;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- return retval;
- flash_cmd &= ~FLASH_ERASE;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- return retval;
- flash_cmd &= ~(FLASH_XE | FLASH_MAS1 | FLASH_NVSTR);
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int mdr_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct mdr_flash_bank *mdr_info = bank->driver_priv;
- int i, retval, retval2;
- unsigned int j;
- uint32_t flash_cmd, cur_per_clock;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
- if (retval != ERROR_OK)
- return retval;
-
- if (!(cur_per_clock & 0x10)) {
- LOG_ERROR("Target needs reset before flash operations");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, FLASH_KEY, KEY);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- /* Switch on register access */
- flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
- if (mdr_info->mem_type)
- flash_cmd |= FLASH_IFREN;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- if ((first == 0) && (last == (bank->num_sectors - 1))) {
- retval = mdr_mass_erase(bank);
- goto reset_pg_and_lock;
- }
-
- unsigned int page_size = bank->size / mdr_info->page_count;
- for (i = first; i <= last; i++) {
- for (j = 0; j < mdr_info->sec_count; j++) {
- retval = target_write_u32(target, FLASH_ADR, (i * page_size) | (j << 2));
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- flash_cmd |= FLASH_XE | FLASH_ERASE;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- flash_cmd |= FLASH_NVSTR;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- flash_cmd &= ~FLASH_ERASE;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- flash_cmd &= ~(FLASH_XE | FLASH_NVSTR);
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- }
- bank->sectors[i].is_erased = 1;
- }
-
-reset_pg_and_lock:
- flash_cmd &= FLASH_DELAY_MASK;
- retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval == ERROR_OK)
- retval = retval2;
-
- retval2 = target_write_u32(target, FLASH_KEY, 0);
- if (retval == ERROR_OK)
- retval = retval2;
-
- return retval;
-}
-
-static int mdr_protect(struct flash_bank *bank, int set, int first, int last)
-{
- return ERROR_OK;
-}
-
-static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* see contrib/loaders/flash/mdr32fx.S for src */
- static const uint8_t mdr32fx_flash_write_code[] = {
- 0x07, 0x68, 0x16, 0x68, 0x00, 0x2e, 0x2e, 0xd0, 0x55, 0x68, 0xb5, 0x42,
- 0xf9, 0xd0, 0x2e, 0x68, 0x44, 0x60, 0x86, 0x60, 0x17, 0x4e, 0x37, 0x43,
- 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0, 0x25, 0xf8, 0x15, 0x4e, 0x37, 0x43,
- 0x07, 0x60, 0x0d, 0x26, 0x00, 0xf0, 0x1f, 0xf8, 0x80, 0x26, 0x37, 0x43,
- 0x07, 0x60, 0x3d, 0x26, 0x00, 0xf0, 0x19, 0xf8, 0x80, 0x26, 0xb7, 0x43,
- 0x07, 0x60, 0x0f, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0,
- 0x10, 0xf8, 0x0d, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x04, 0x35, 0x04, 0x34,
- 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46, 0x08, 0x35, 0x55, 0x60, 0x01, 0x39,
- 0x00, 0x29, 0x00, 0xd0, 0xcd, 0xe7, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x3e,
- 0x00, 0x2e, 0xfc, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(mdr32fx_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (32bit) */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
-
- buf_set_u32(reg_params[0].value, 0, 32, FLASH_REG_BASE);
- buf_set_u32(reg_params[1].value, 0, 32, count);
- buf_set_u32(reg_params[2].value, 0, 32, source->address);
- buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
- buf_set_u32(reg_params[4].value, 0, 32, address);
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- retval = target_run_flash_async_algorithm(target, buffer, count, 4,
- 0, NULL,
- 5, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (retval == ERROR_FLASH_OPERATION_FAILED)
- LOG_ERROR("flash write failed at address 0x%"PRIx32,
- buf_get_u32(reg_params[4].value, 0, 32));
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-static int mdr_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct mdr_flash_bank *mdr_info = bank->driver_priv;
- uint8_t *new_buffer = NULL;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x3) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* If there's an odd number of bytes, the data has to be padded. Duplicate
- * the buffer and use the normal code path with a single block write since
- * it's probably cheaper than to special case the last odd write using
- * discrete accesses. */
- int rem = count % 4;
- if (rem) {
- new_buffer = malloc(count + rem);
- if (new_buffer == NULL) {
- LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
- return ERROR_FAIL;
- }
- LOG_INFO("odd number of bytes to write, padding with 0xff");
- buffer = memcpy(new_buffer, buffer, count);
- while (rem--)
- new_buffer[count++] = 0xff;
- }
-
- uint32_t flash_cmd, cur_per_clock;
- int retval, retval2;
-
- retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
- if (retval != ERROR_OK)
- goto free_buffer;
-
- if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
- /* Something's very wrong if the RST_CLK module is not clocked */
- LOG_ERROR("Target needs reset before flash operations");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto free_buffer;
- }
-
- retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
- if (retval != ERROR_OK)
- goto free_buffer;
-
- retval = target_write_u32(target, FLASH_KEY, KEY);
- if (retval != ERROR_OK)
- goto free_buffer;
-
- retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- /* Switch on register access */
- flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
- if (mdr_info->mem_type)
- flash_cmd |= FLASH_IFREN;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- /* try using block write */
- retval = mdr_write_block(bank, buffer, offset, count/4);
-
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single halfword accesses */
- LOG_WARNING("Can't use block writes, falling back to single memory accesses");
-
- unsigned int page_size = bank->size / mdr_info->page_count;
- unsigned int page_mask = page_size - 1;
- while (count > 0) {
- unsigned int i, j;
- unsigned int cur_page = offset & ~page_mask;
- unsigned int bytes_to_write = cur_page + page_size - offset;
- if (count < bytes_to_write)
- bytes_to_write = count;
-
- /*LOG_INFO("Selecting next page: %08x", cur_page);*/
-
- for (i = 0; i < mdr_info->sec_count; i++) {
- retval = target_write_u32(target, FLASH_ADR, offset + i*4);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- /*LOG_INFO("Selecting page/sector: %08x", offset + i*4);*/
-
- flash_cmd |= FLASH_XE | FLASH_PROG;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- flash_cmd |= FLASH_NVSTR;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- for (j = 0;
- (((offset + j + i*4) & ~page_mask) == cur_page) &&
- (j + i*4 < count);
- j += mdr_info->sec_count*4) {
- uint32_t value;
- memcpy(&value, buffer + j + i*4, sizeof(uint32_t));
- retval = target_write_u32(target, FLASH_DI, value);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- /*LOG_INFO("Writing to addr %08x", offset + j + i*4);*/
- retval = target_write_u32(target, FLASH_ADR, offset + j + i*4);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- flash_cmd |= FLASH_YE;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- flash_cmd &= ~FLASH_YE;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- }
- flash_cmd &= ~FLASH_NVSTR;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- flash_cmd &= ~(FLASH_XE | FLASH_PROG);
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- }
-
- buffer += bytes_to_write;
- offset += bytes_to_write;
- count -= bytes_to_write;
- }
- }
-
-reset_pg_and_lock:
- flash_cmd &= FLASH_DELAY_MASK;
- retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval == ERROR_OK)
- retval = retval2;
-
- retval2 = target_write_u32(target, FLASH_KEY, 0);
- if (retval == ERROR_OK)
- retval = retval2;
-
-free_buffer:
- if (new_buffer)
- free(new_buffer);
-
- /* read some bytes bytes to flush buffer in flash accelerator.
- * See errata for 1986VE1T and 1986VE3. Error 0007 */
- if ((retval == ERROR_OK) && (!mdr_info->mem_type)) {
- uint32_t tmp;
- target_checksum_memory(bank->target, bank->base, 64, &tmp);
- }
-
- return retval;
-}
-
-static int mdr_read(struct flash_bank *bank, uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct mdr_flash_bank *mdr_info = bank->driver_priv;
- int retval, retval2;
-
- if (!mdr_info->mem_type)
- return default_flash_read(bank, buffer, offset, count);
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x3) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- if (count & 0x3) {
- LOG_ERROR("count 0x%" PRIx32 " breaks required 4-byte alignment", count);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- uint32_t flash_cmd, cur_per_clock;
-
- retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
- if (retval != ERROR_OK)
- goto err;
-
- if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
- /* Something's very wrong if the RST_CLK module is not clocked */
- LOG_ERROR("Target needs reset before flash operations");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err;
- }
-
- retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
- if (retval != ERROR_OK)
- goto err;
-
- retval = target_write_u32(target, FLASH_KEY, KEY);
- if (retval != ERROR_OK)
- goto err;
-
- retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
- if (retval != ERROR_OK)
- goto err_lock;
-
- /* Switch on register access */
- flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON | FLASH_IFREN;
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- for (uint32_t i = 0; i < count; i += 4) {
- retval = target_write_u32(target, FLASH_ADR, offset + i);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- retval = target_write_u32(target, FLASH_CMD, flash_cmd |
- FLASH_XE | FLASH_YE | FLASH_SE);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- uint32_t buf;
- retval = target_read_u32(target, FLASH_DO, &buf);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- buf_set_u32(buffer, i * 8, 32, buf);
-
- retval = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- }
-
-reset_pg_and_lock:
- flash_cmd &= FLASH_DELAY_MASK;
- retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
- if (retval == ERROR_OK)
- retval = retval2;
-
-err_lock:
- retval2 = target_write_u32(target, FLASH_KEY, 0);
- if (retval == ERROR_OK)
- retval = retval2;
-
-err:
- return retval;
-}
-
-static int mdr_probe(struct flash_bank *bank)
-{
- struct mdr_flash_bank *mdr_info = bank->driver_priv;
- unsigned int page_count, page_size, i;
-
- page_count = mdr_info->page_count;
- page_size = bank->size / page_count;
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->num_sectors = page_count;
- bank->sectors = malloc(sizeof(struct flash_sector) * page_count);
-
- for (i = 0; i < page_count; i++) {
- bank->sectors[i].offset = i * page_size;
- bank->sectors[i].size = page_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 0;
- }
-
- mdr_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int mdr_auto_probe(struct flash_bank *bank)
-{
- struct mdr_flash_bank *mdr_info = bank->driver_priv;
- if (mdr_info->probed)
- return ERROR_OK;
- return mdr_probe(bank);
-}
-
-static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct mdr_flash_bank *mdr_info = bank->driver_priv;
- snprintf(buf, buf_size, "MDR32Fx - %s",
- mdr_info->mem_type ? "info memory" : "main memory");
-
- return ERROR_OK;
-}
-
-struct flash_driver mdr_flash = {
- .name = "mdr",
- .usage = "flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count>\n"
- "<type>: 0 for main memory, 1 for info memory",
- .flash_bank_command = mdr_flash_bank_command,
- .erase = mdr_erase,
- .protect = mdr_protect,
- .write = mdr_write,
- .read = mdr_read,
- .probe = mdr_probe,
- .auto_probe = mdr_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = mdr_protect_check,
- .info = get_mdr_info,
-};
diff --git a/src/flash/nor/mrvlqspi.c b/src/flash/nor/mrvlqspi.c
deleted file mode 100644
index d799170..0000000
--- a/src/flash/nor/mrvlqspi.c
+++ /dev/null
@@ -1,958 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2014 by Mahavir Jain <mjain@marvell.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
- /*
- * This is QSPI flash controller driver for Marvell's Wireless
- * Microcontroller platform.
- *
- * For more information please refer,
- * https://origin-www.marvell.com/microcontrollers/wi-fi-microcontroller-platform/
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "spi.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-#define QSPI_R_EN (0x0)
-#define QSPI_W_EN (0x1)
-#define QSPI_SS_DISABLE (0x0)
-#define QSPI_SS_ENABLE (0x1)
-#define WRITE_DISBALE (0x0)
-#define WRITE_ENABLE (0x1)
-
-#define QSPI_TIMEOUT (1000)
-#define FIFO_FLUSH_TIMEOUT (1000)
-#define BLOCK_ERASE_TIMEOUT (1000)
-#define CHIP_ERASE_TIMEOUT (10000)
-
-#define SS_EN (1 << 0)
-#define XFER_RDY (1 << 1)
-#define RFIFO_EMPTY (1 << 4)
-#define WFIFO_EMPTY (1 << 6)
-#define WFIFO_FULL (1 << 7)
-#define FIFO_FLUSH (1 << 9)
-#define RW_EN (1 << 13)
-#define XFER_STOP (1 << 14)
-#define XFER_START (1 << 15)
-#define CONF_MASK (0x7)
-#define CONF_OFFSET (10)
-
-#define INS_WRITE_ENABLE 0x06
-#define INS_WRITE_DISABLE 0x04
-#define INS_READ_STATUS 0x05
-#define INS_PAGE_PROGRAM 0x02
-
-#define CNTL 0x0 /* QSPI_BASE + 0x0 */
-#define CONF 0x4
-#define DOUT 0x8
-#define DIN 0xc
-#define INSTR 0x10
-#define ADDR 0x14
-#define RDMODE 0x18
-#define HDRCNT 0x1c
-#define DINCNT 0x20
-
-struct mrvlqspi_flash_bank {
- int probed;
- uint32_t reg_base;
- uint32_t bank_num;
- const struct flash_device *dev;
-};
-
-static inline uint32_t mrvlqspi_get_reg(struct flash_bank *bank, uint32_t reg)
-{
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
- return reg + mrvlqspi_info->reg_base;
-}
-
-static inline int mrvlqspi_set_din_cnt(struct flash_bank *bank, uint32_t count)
-{
- struct target *target = bank->target;
-
- return target_write_u32(target, mrvlqspi_get_reg(bank, DINCNT), count);
-}
-
-static inline int mrvlqspi_set_addr(struct flash_bank *bank, uint32_t addr)
-{
- struct target *target = bank->target;
-
- return target_write_u32(target, mrvlqspi_get_reg(bank, ADDR), addr);
-}
-
-static inline int mrvlqspi_set_instr(struct flash_bank *bank, uint32_t instr)
-{
- struct target *target = bank->target;
-
- return target_write_u32(target, mrvlqspi_get_reg(bank, INSTR), instr);
-}
-
-static inline int mrvlqspi_set_hdr_cnt(struct flash_bank *bank, uint32_t hdr_cnt)
-{
- struct target *target = bank->target;
-
- return target_write_u32(target, mrvlqspi_get_reg(bank, HDRCNT), hdr_cnt);
-}
-
-static int mrvlqspi_set_conf(struct flash_bank *bank, uint32_t conf_val)
-{
- int retval;
- uint32_t regval;
- struct target *target = bank->target;
-
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CONF), &regval);
- if (retval != ERROR_OK)
- return retval;
-
- regval &= ~(CONF_MASK << CONF_OFFSET);
- regval |= (conf_val << CONF_OFFSET);
-
- return target_write_u32(target,
- mrvlqspi_get_reg(bank, CONF), regval);
-}
-
-static int mrvlqspi_set_ss_state(struct flash_bank *bank, bool state, int timeout)
-{
- int retval;
- uint32_t regval;
- struct target *target = bank->target;
-
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CNTL), &regval);
- if (retval != ERROR_OK)
- return retval;
-
- if (state)
- regval |= SS_EN;
- else
- regval &= ~(SS_EN);
-
- retval = target_write_u32(target,
- mrvlqspi_get_reg(bank, CNTL), regval);
- if (retval != ERROR_OK)
- return retval;
-
- /* wait for xfer_ready to set */
- for (;;) {
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CNTL), &regval);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%08" PRIx32, regval);
- if ((regval & XFER_RDY) == XFER_RDY)
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
- return ERROR_OK;
-}
-
-static int mrvlqspi_start_transfer(struct flash_bank *bank, bool rw_mode)
-{
- int retval;
- uint32_t regval;
- struct target *target = bank->target;
-
- retval = mrvlqspi_set_ss_state(bank, QSPI_SS_ENABLE, QSPI_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CONF), &regval);
- if (retval != ERROR_OK)
- return retval;
-
- if (rw_mode)
- regval |= RW_EN;
- else
- regval &= ~(RW_EN);
-
- regval |= XFER_START;
-
- retval = target_write_u32(target,
- mrvlqspi_get_reg(bank, CONF), regval);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int mrvlqspi_stop_transfer(struct flash_bank *bank)
-{
- int retval;
- uint32_t regval;
- struct target *target = bank->target;
- int timeout = QSPI_TIMEOUT;
-
- /* wait for xfer_ready and wfifo_empty to set */
- for (;;) {
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CNTL), &regval);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%08" PRIx32, regval);
- if ((regval & (XFER_RDY | WFIFO_EMPTY)) ==
- (XFER_RDY | WFIFO_EMPTY))
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CONF), &regval);
- if (retval != ERROR_OK)
- return retval;
-
- regval |= XFER_STOP;
-
- retval = target_write_u32(target,
- mrvlqspi_get_reg(bank, CONF), regval);
- if (retval != ERROR_OK)
- return retval;
-
- /* wait for xfer_start to reset */
- for (;;) {
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CONF), &regval);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%08" PRIx32, regval);
- if ((regval & XFER_START) == 0)
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
- retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int mrvlqspi_fifo_flush(struct flash_bank *bank, int timeout)
-{
- int retval;
- uint32_t val;
- struct target *target = bank->target;
-
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CONF), &val);
- if (retval != ERROR_OK)
- return retval;
-
- val |= FIFO_FLUSH;
-
- retval = target_write_u32(target,
- mrvlqspi_get_reg(bank, CONF), val);
- if (retval != ERROR_OK)
- return retval;
-
- /* wait for fifo_flush to clear */
- for (;;) {
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CONF), &val);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%08" PRIX32, val);
- if ((val & FIFO_FLUSH) == 0)
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
- return ERROR_OK;
-}
-
-static int mrvlqspi_read_byte(struct flash_bank *bank, uint8_t *data)
-{
- int retval;
- uint32_t val;
- struct target *target = bank->target;
-
- /* wait for rfifo_empty to reset */
- for (;;) {
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, CNTL), &val);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%08" PRIx32, val);
- if ((val & RFIFO_EMPTY) == 0)
- break;
- usleep(10);
- }
-
- retval = target_read_u32(target,
- mrvlqspi_get_reg(bank, DIN), &val);
- if (retval != ERROR_OK)
- return retval;
-
- *data = val & 0xFF;
-
- return ERROR_OK;
-}
-
-static int mrvlqspi_flash_busy_status(struct flash_bank *bank, int timeout)
-{
- uint8_t val;
- int retval;
-
- /* Flush read/write fifo's */
- retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction/addr count value */
- retval = mrvlqspi_set_hdr_cnt(bank, 0x1);
- if (retval != ERROR_OK)
- return retval;
-
- /* Read flash status register in continuous manner */
- retval = mrvlqspi_set_din_cnt(bank, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction */
- retval = mrvlqspi_set_instr(bank, INS_READ_STATUS);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set data and addr pin length */
- retval = mrvlqspi_set_conf(bank, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- /* Enable read mode transfer */
- retval = mrvlqspi_start_transfer(bank, QSPI_R_EN);
- if (retval != ERROR_OK)
- return retval;
-
- for (;;) {
- retval = mrvlqspi_read_byte(bank, &val);
- if (retval != ERROR_OK)
- return retval;
- if (!(val & 0x1))
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
- return mrvlqspi_stop_transfer(bank);
-}
-
-static int mrvlqspi_set_write_status(struct flash_bank *bank, bool mode)
-{
- int retval;
- uint32_t instr;
-
- /* Flush read/write fifo's */
- retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction/addr count value */
- retval = mrvlqspi_set_hdr_cnt(bank, 0x1);
- if (retval != ERROR_OK)
- return retval;
-
- if (mode)
- instr = INS_WRITE_ENABLE;
- else
- instr = INS_WRITE_DISABLE;
-
- /* Set instruction */
- retval = mrvlqspi_set_instr(bank, instr);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_start_transfer(bank, QSPI_W_EN);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_stop_transfer(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-static int mrvlqspi_read_id(struct flash_bank *bank, uint32_t *id)
-{
- uint8_t id_buf[3] = {0, 0, 0};
- int retval, i;
-
- LOG_DEBUG("Getting ID");
-
- /* Flush read/write fifo's */
- retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction/addr count value */
- retval = mrvlqspi_set_hdr_cnt(bank, 0x1);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set count for number of bytes to read */
- retval = mrvlqspi_set_din_cnt(bank, 0x3);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction */
- retval = mrvlqspi_set_instr(bank, SPIFLASH_READ_ID);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set data and addr pin length */
- retval = mrvlqspi_set_conf(bank, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_start_transfer(bank, QSPI_R_EN);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < 3; i++) {
- retval = mrvlqspi_read_byte(bank, &id_buf[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- LOG_DEBUG("ID is 0x%02" PRIx8 " 0x%02" PRIx8 " 0x%02" PRIx8,
- id_buf[0], id_buf[1], id_buf[2]);
- retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- *id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];
- return ERROR_OK;
-}
-
-static int mrvlqspi_block_erase(struct flash_bank *bank, uint32_t offset)
-{
- int retval;
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
-
- /* Set flash write enable */
- retval = mrvlqspi_set_write_status(bank, WRITE_ENABLE);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction/addr count value */
- retval = mrvlqspi_set_hdr_cnt(bank, (0x1 | (0x3 << 4)));
- if (retval != ERROR_OK)
- return retval;
-
- /* Set read offset address */
- retval = mrvlqspi_set_addr(bank, offset);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction */
- retval = mrvlqspi_set_instr(bank, mrvlqspi_info->dev->erase_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_start_transfer(bank, QSPI_W_EN);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_stop_transfer(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return mrvlqspi_flash_busy_status(bank, BLOCK_ERASE_TIMEOUT);
-}
-
-static int mrvlqspi_bulk_erase(struct flash_bank *bank)
-{
- int retval;
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
-
- /* Set flash write enable */
- retval = mrvlqspi_set_write_status(bank, WRITE_ENABLE);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction */
- retval = mrvlqspi_set_instr(bank, mrvlqspi_info->dev->chip_erase_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_start_transfer(bank, QSPI_W_EN);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_stop_transfer(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return mrvlqspi_flash_busy_status(bank, CHIP_ERASE_TIMEOUT);
-}
-
-static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
- int retval = ERROR_OK;
- int sector;
-
- LOG_DEBUG("erase from sector %d to sector %d", 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 (!(mrvlqspi_info->probed)) {
- LOG_ERROR("Flash bank not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- for (sector = first; sector <= last; sector++) {
- if (bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- /* If we're erasing the entire chip and the flash supports
- * it, use a bulk erase instead of going sector-by-sector. */
- if (first == 0 && last == (bank->num_sectors - 1)
- && mrvlqspi_info->dev->chip_erase_cmd !=
- mrvlqspi_info->dev->erase_cmd) {
- LOG_DEBUG("Chip supports the bulk erase command."\
- " Will use bulk erase instead of sector-by-sector erase.");
- retval = mrvlqspi_bulk_erase(bank);
- if (retval == ERROR_OK) {
- return retval;
- } else
- LOG_WARNING("Bulk flash erase failed."
- " Falling back to sector-by-sector erase.");
- }
-
- for (sector = first; sector <= last; sector++) {
- retval = mrvlqspi_block_erase(bank,
- sector * mrvlqspi_info->dev->sectorsize);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
- int retval = ERROR_OK;
- uint32_t page_size, fifo_size;
- struct working_area *fifo;
- struct reg_param reg_params[6];
- struct armv7m_algorithm armv7m_info;
- struct working_area *write_algorithm;
- int sector;
-
- LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32,
- offset, count);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset + count > mrvlqspi_info->dev->size_in_bytes) {
- LOG_WARNING("Writes past end of flash. Extra data discarded.");
- count = mrvlqspi_info->dev->size_in_bytes - offset;
- }
-
- /* 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? */
- if ((offset <
- (bank->sectors[sector].offset + bank->sectors[sector].size))
- && ((offset + count - 1) >= bank->sectors[sector].offset)
- && bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- page_size = mrvlqspi_info->dev->pagesize;
-
- /* See contrib/loaders/flash/mrvlqspi.S for src */
- static const uint8_t mrvlqspi_flash_write_code[] = {
- 0x4f, 0xf0, 0x00, 0x0a, 0xa2, 0x44, 0x92, 0x45,
- 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6b, 0xf8,
- 0x5f, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x1c, 0x80,
- 0x5f, 0xf0, 0x06, 0x08, 0xc5, 0xf8, 0x10, 0x80,
- 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0, 0x6b, 0xf8,
- 0x00, 0xf0, 0x7d, 0xf8, 0x5f, 0xf0, 0x31, 0x08,
- 0xc5, 0xf8, 0x1c, 0x80, 0x90, 0x46, 0xc5, 0xf8,
- 0x14, 0x80, 0x5f, 0xf0, 0x02, 0x08, 0xc5, 0xf8,
- 0x10, 0x80, 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0,
- 0x5a, 0xf8, 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1,
- 0x00, 0x0f, 0x00, 0xf0, 0x8b, 0x80, 0x47, 0x68,
- 0x47, 0x45, 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8,
- 0x01, 0x9b, 0x00, 0xf0, 0x30, 0xf8, 0x8f, 0x42,
- 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60,
- 0x01, 0x3b, 0x00, 0x2b, 0x00, 0xf0, 0x05, 0x80,
- 0x02, 0xf1, 0x01, 0x02, 0x92, 0x45, 0x7f, 0xf4,
- 0xe4, 0xaf, 0x00, 0xf0, 0x50, 0xf8, 0xa2, 0x44,
- 0x00, 0xf0, 0x2d, 0xf8, 0x5f, 0xf0, 0x01, 0x08,
- 0xc5, 0xf8, 0x1c, 0x80, 0x5f, 0xf0, 0x00, 0x08,
- 0xc5, 0xf8, 0x20, 0x80, 0x5f, 0xf0, 0x05, 0x08,
- 0xc5, 0xf8, 0x10, 0x80, 0x5f, 0xf0, 0x00, 0x09,
- 0x00, 0xf0, 0x29, 0xf8, 0x00, 0xf0, 0x13, 0xf8,
- 0x09, 0xf0, 0x01, 0x09, 0xb9, 0xf1, 0x00, 0x0f,
- 0xf8, 0xd1, 0x00, 0xf0, 0x34, 0xf8, 0x00, 0x2b,
- 0xa4, 0xd1, 0x00, 0xf0, 0x53, 0xb8, 0xd5, 0xf8,
- 0x00, 0x80, 0x5f, 0xea, 0x08, 0x68, 0xfa, 0xd4,
- 0xc5, 0xf8, 0x08, 0x90, 0x70, 0x47, 0xd5, 0xf8,
- 0x00, 0x80, 0x5f, 0xea, 0xc8, 0x68, 0xfa, 0xd4,
- 0xd5, 0xf8, 0x0c, 0x90, 0x70, 0x47, 0xd5, 0xf8,
- 0x04, 0x80, 0x48, 0xf4, 0x00, 0x78, 0xc5, 0xf8,
- 0x04, 0x80, 0xd5, 0xf8, 0x04, 0x80, 0x5f, 0xea,
- 0x88, 0x58, 0xfa, 0xd4, 0x70, 0x47, 0xd5, 0xf8,
- 0x00, 0x80, 0x48, 0xf0, 0x01, 0x08, 0xc5, 0xf8,
- 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea,
- 0x88, 0x78, 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80,
- 0x69, 0xf3, 0x4d, 0x38, 0x48, 0xf4, 0x00, 0x48,
- 0xc5, 0xf8, 0x04, 0x80, 0x70, 0x47, 0xd5, 0xf8,
- 0x00, 0x80, 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5,
- 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x48, 0x68,
- 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80, 0x48, 0xf4,
- 0x80, 0x48, 0xc5, 0xf8, 0x04, 0x80, 0xd5, 0xf8,
- 0x04, 0x80, 0x5f, 0xea, 0x08, 0x48, 0xfa, 0xd4,
- 0xd5, 0xf8, 0x00, 0x80, 0x28, 0xf0, 0x01, 0x08,
- 0xc5, 0xf8, 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80,
- 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5, 0x70, 0x47,
- 0x00, 0x20, 0x50, 0x60, 0x30, 0x46, 0x00, 0xbe
- };
-
- if (target_alloc_working_area(target, sizeof(mrvlqspi_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_ERROR("Insufficient working area. You must configure"\
- " a working area > %zdB in order to write to SPIFI flash.",
- sizeof(mrvlqspi_flash_write_code));
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(mrvlqspi_flash_write_code),
- mrvlqspi_flash_write_code);
- if (retval != ERROR_OK) {
- target_free_working_area(target, write_algorithm);
- return retval;
- }
-
- /* FIFO allocation */
- fifo_size = target_get_working_area_avail(target);
-
- if (fifo_size == 0) {
- /* if we already allocated the writing code but failed to get fifo
- * space, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_ERROR("Insufficient working area. Please allocate at least"\
- " %zdB of working area to enable flash writes.",
- sizeof(mrvlqspi_flash_write_code) + 1
- );
-
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- } else if (fifo_size < page_size)
- LOG_WARNING("Working area size is limited; flash writes may be"\
- " slow. Increase working area size to at least %zdB"\
- " to reduce write times.",
- (size_t)(sizeof(mrvlqspi_flash_write_code) + page_size)
- );
-
- if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) {
- target_free_working_area(target, write_algorithm);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */
- 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 (halfword-16bit) */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* page size */
- init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT); /* qspi base address */
-
- buf_set_u32(reg_params[0].value, 0, 32, fifo->address);
- buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size);
- buf_set_u32(reg_params[2].value, 0, 32, offset);
- buf_set_u32(reg_params[3].value, 0, 32, count);
- buf_set_u32(reg_params[4].value, 0, 32, page_size);
- buf_set_u32(reg_params[5].value, 0, 32, (uint32_t) mrvlqspi_info->reg_base);
-
- retval = target_run_flash_async_algorithm(target, buffer, count, 1,
- 0, NULL,
- 6, reg_params,
- fifo->address, fifo->size,
- write_algorithm->address, 0,
- &armv7m_info
- );
-
- if (retval != ERROR_OK)
- LOG_ERROR("Error executing flash write algorithm");
-
- target_free_working_area(target, fifo);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
- destroy_reg_param(&reg_params[5]);
-
- return retval;
-}
-
-int mrvlqspi_flash_read(struct flash_bank *bank, uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
- int retval;
- uint32_t i;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!(mrvlqspi_info->probed)) {
- LOG_ERROR("Flash bank not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- /* Flush read/write fifo's */
- retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction/addr count value */
- retval = mrvlqspi_set_hdr_cnt(bank, (0x1 | (0x3 << 4)));
- if (retval != ERROR_OK)
- return retval;
-
- /* Set count for number of bytes to read */
- retval = mrvlqspi_set_din_cnt(bank, count);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set read address */
- retval = mrvlqspi_set_addr(bank, offset);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set instruction */
- retval = mrvlqspi_set_instr(bank, SPIFLASH_READ);
- if (retval != ERROR_OK)
- return retval;
-
- /* Set data and addr pin length */
- retval = mrvlqspi_set_conf(bank, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mrvlqspi_start_transfer(bank, QSPI_R_EN);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < count; i++) {
- retval = mrvlqspi_read_byte(bank, &buffer[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int mrvlqspi_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
- uint32_t id = 0;
- int retval;
- struct flash_sector *sectors;
-
- /* If we've already probed, we should be fine to skip this time. */
- if (mrvlqspi_info->probed)
- return ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- mrvlqspi_info->probed = 0;
- mrvlqspi_info->bank_num = bank->bank_number;
-
- /* Read flash JEDEC ID */
- retval = mrvlqspi_read_id(bank, &id);
- if (retval != ERROR_OK)
- return retval;
-
- mrvlqspi_info->dev = NULL;
- for (const struct flash_device *p = flash_devices; p->name ; p++)
- if (p->device_id == id) {
- mrvlqspi_info->dev = p;
- break;
- }
-
- if (!mrvlqspi_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,
- mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id);
-
- /* Set correct size value */
- bank->size = mrvlqspi_info->dev->size_in_bytes;
-
- /* create and fill sectors array */
- bank->num_sectors = mrvlqspi_info->dev->size_in_bytes /
- mrvlqspi_info->dev->sectorsize;
- sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- if (sectors == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- for (int sector = 0; sector < bank->num_sectors; sector++) {
- sectors[sector].offset =
- sector * mrvlqspi_info->dev->sectorsize;
- sectors[sector].size = mrvlqspi_info->dev->sectorsize;
- sectors[sector].is_erased = -1;
- sectors[sector].is_protected = 0;
- }
-
- bank->sectors = sectors;
- mrvlqspi_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int mrvlqspi_auto_probe(struct flash_bank *bank)
-{
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
- if (mrvlqspi_info->probed)
- return ERROR_OK;
- return mrvlqspi_probe(bank);
-}
-
-static int mrvlqspi_flash_erase_check(struct flash_bank *bank)
-{
- /* Not implemented yet */
- return ERROR_OK;
-}
-
-static int mrvlqspi_protect_check(struct flash_bank *bank)
-{
- /* Not implemented yet */
- return ERROR_OK;
-}
-
-int mrvlqspi_get_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
-
- if (!(mrvlqspi_info->probed)) {
- snprintf(buf, buf_size,
- "\nQSPI flash bank not probed yet\n");
- return ERROR_OK;
- }
-
- snprintf(buf, buf_size, "\nQSPI flash information:\n"
- " Device \'%s\' ID 0x%08" PRIx32 "\n",
- mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id);
-
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(mrvlqspi_flash_bank_command)
-{
- struct mrvlqspi_flash_bank *mrvlqspi_info;
-
- if (CMD_ARGC < 7)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- mrvlqspi_info = malloc(sizeof(struct mrvlqspi_flash_bank));
- if (mrvlqspi_info == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- /* Get QSPI controller register map base address */
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], mrvlqspi_info->reg_base);
- bank->driver_priv = mrvlqspi_info;
- mrvlqspi_info->probed = 0;
-
- return ERROR_OK;
-}
-
-struct flash_driver mrvlqspi_flash = {
- .name = "mrvlqspi",
- .flash_bank_command = mrvlqspi_flash_bank_command,
- .erase = mrvlqspi_flash_erase,
- .protect = NULL,
- .write = mrvlqspi_flash_write,
- .read = mrvlqspi_flash_read,
- .probe = mrvlqspi_probe,
- .auto_probe = mrvlqspi_auto_probe,
- .erase_check = mrvlqspi_flash_erase_check,
- .protect_check = mrvlqspi_protect_check,
- .info = mrvlqspi_get_info,
-};
diff --git a/src/flash/nor/niietcm4.c b/src/flash/nor/niietcm4.c
deleted file mode 100644
index 4a849fd..0000000
--- a/src/flash/nor/niietcm4.c
+++ /dev/null
@@ -1,1744 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Bogdan Kolbov *
- * kolbov@niiet.ru *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-#define FLASH_DRIVER_VER 0x00010000
-#define CHIPID_ADDR 0xF0000000
-#define K1921VK01T_ID 0x00000000
-
-/*==============================================================================
- * FLASH CONTROL REGS
- *==============================================================================
- */
-
-#define MAIN_MEM_TYPE 0
-#define INFO_MEM_TYPE 1
-#define SERVICE_MODE_ERASE_ADDR 0x80030164
-#define MAGIC_KEY 0xA442
-
-/*-- BOOTFLASH ---------------------------------------------------------------*/
-#define BOOTFLASH_BASE 0xA001C000
-#define FMA (BOOTFLASH_BASE + 0x00)
-#define FMD1 (BOOTFLASH_BASE + 0x04)
-#define FMC (BOOTFLASH_BASE + 0x08)
-#define FCIS (BOOTFLASH_BASE + 0x0C)
-#define FCIM (BOOTFLASH_BASE + 0x10)
-#define FCIC (BOOTFLASH_BASE + 0x14)
-#define FMD2 (BOOTFLASH_BASE + 0x50)
-#define FMD3 (BOOTFLASH_BASE + 0x54)
-#define FMD4 (BOOTFLASH_BASE + 0x58)
-
-
-/*---- FMC: Command register */
-#define FMC_WRITE (1<<0) /* Writing in main region */
-#define FMC_PAGE_ERASE (1<<1) /* Page erase the main region */
-#define FMC_FULL_ERASE (1<<2) /* Erase full flash */
-#define FMC_WRITE_IFB (1<<4) /* Writing in info region */
-#define FMC_PAGEERASE_IFB (1<<5) /* Erase page of info region */
-#define FMC_MAGIC_KEY (MAGIC_KEY<<16) /* Operation run command */
-
-/*---- FCIS: Status register */
-#define FCIS_OP_CMLT (1<<0) /* Completion flag operation */
-#define FCIS_OP_ERROR (1<<1) /* Flag operation error */
-
-/*---- FCIC: CLear status register */
-#define FCIC_CLR_OPCMLT (1<<0) /* Cleare completion flag in register FCIS */
-#define FCIC_CLR_OPERROR (1<<1) /* Cleare error flag in register FCIS */
-
-/*-- USERFLASH ---------------------------------------------------------------*/
-#define USERFLASH_PAGE_SIZE 256
-#define USERFLASH_PAGE_TOTALNUM 256
-
-#define USERFLASH_BASE 0xA0022000
-#define UFMA (USERFLASH_BASE + 0x00)
-#define UFMD (USERFLASH_BASE + 0x04)
-#define UFMC (USERFLASH_BASE + 0x08)
-#define UFCIS (USERFLASH_BASE + 0x0C)
-#define UFCIM (USERFLASH_BASE + 0x10)
-#define UFCIC (USERFLASH_BASE + 0x14)
-
-/*---- UFMC: Command register */
-#define UFMC_WRITE (1<<0) /* Writing in main region */
-#define UFMC_PAGE_ERASE (1<<1) /* Paged erase the main region */
-#define UFMC_FULL_ERASE (1<<2) /* Erase full flash */
-#define UFMC_READ (1<<3) /* Reading from main region */
-#define UFMC_WRITE_IFB (1<<4) /* Writing in info region */
-#define UFMC_PAGEERASE_IFB (1<<5) /* Erase page of info region */
-#define UFMC_READ_IFB (1<<6) /* Reading from info region */
-#define UFMC_MAGIC_KEY (MAGIC_KEY<<16) /* Operation run command */
-
-/*---- UFCIS: Status register */
-#define UFCIS_OP_CMLT (1<<0) /* Completion flag operation */
-#define UFCIS_OP_ERROR (1<<1) /* Flag operation error */
-
-/*---- UFCIC: CLear status register */
-#define UFCIC_CLR_OPCMLT (1<<0) /* Cleared completion flag in register FCIS */
-#define UFCIC_CLR_OPERROR (1<<1) /* Cleared error flag in register FCIS */
-
-/*---- In info userflash address space */
-#define INFOWORD0_ADDR 0x00
-#define INFOWORD0_BOOTFROM_IFB (1<<0) /* Boot from bootflash or bootflash_ifb */
-#define INFOWORD0_EN_GPIO (1<<1) /* Remap to 0x00000000 extmem or bootflash */
-#define INFOWORD0_BOOTFROM_IFB_POS 0
-#define INFOWORD0_EN_GPIO_POS 1
-#define INFOWORD0_EXTMEM_SEL_POS 3 /* Choose altfunc of gpio to work with extmem */
-
-#define INFOWORD1_ADDR 0x01
-#define INFOWORD1_PINNUM_POS 0 /* Choose gpio pin number to control extmem boot */
-#define INFOWORD1_PORTNUM_POS 4 /* Choose gpio port to control extmem boot */
-
-#define INFOWORD2_ADDR 0x02
-#define INFOWORD2_LOCK_IFB_BF (1<<0) /* Protect info part of bootflash */
-
-#define INFOWORD3_ADDR 0x03
-#define INFOWORD3_LOCK_IFB_UF (1<<0) /* Protect info part of userflash */
-
-#define BF_LOCK_ADDR 0x40
-#define UF_LOCK_ADDR 0x80
-
-/**
- * Private data for flash driver.
- */
-struct niietcm4_flash_bank {
- /* target params */
- bool probed;
- uint32_t chipid;
- char *chip_name;
- char chip_brief[4096];
- /* not mapped userflash params */
- uint32_t uflash_width;
- uint32_t uflash_size;
- uint32_t uflash_pagetotal;
- uint32_t uflash_info_size;
- uint32_t uflash_info_pagetotal;
- /* boot params */
- bool bflash_info_remap;
- char *extmem_boot_port;
- uint32_t extmem_boot_pin;
- uint32_t extmem_boot_altfunc;
- bool extmem_boot;
-};
-
-/*==============================================================================
- * HELPER FUNCTIONS
- *==============================================================================
- */
-
-/**
- * Wait while operation with bootflash being performed and check result status
- */
-static int niietcm4_opstatus_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int retval;
- int timeout = 5000;
-
- uint32_t flash_status;
- retval = target_read_u32(target, FCIS, &flash_status);
- if (retval != ERROR_OK)
- return retval;
-
- while (flash_status == 0x00) {
- retval = target_read_u32(target, FCIS, &flash_status);
- if (retval != ERROR_OK)
- return retval;
- if (timeout-- <= 0) {
- LOG_ERROR("Bootflash operation timeout");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- busy_sleep(1); /* can use busy sleep for short times. */
- }
- if (flash_status == FCIS_OP_ERROR) {
- LOG_ERROR("Bootflash operation error");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- /* clear status */
- uint32_t flash_cmd = FCIC_CLR_OPCMLT | FCIC_CLR_OPERROR;
- retval = target_write_u32(target, FCIC, flash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-/**
- * Wait while operation with userflash being performed and check result status
- */
-static int niietcm4_uopstatus_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int retval;
- int timeout = 5000;
-
- uint32_t uflash_status;
- retval = target_read_u32(target, UFCIS, &uflash_status);
- if (retval != ERROR_OK)
- return retval;
-
- while (uflash_status == 0x00) {
- retval = target_read_u32(target, UFCIS, &uflash_status);
- if (retval != ERROR_OK)
- return retval;
- if (timeout-- <= 0) {
- LOG_ERROR("Userflash operation timeout");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- busy_sleep(1); /* can use busy sleep for short times. */
- }
- if (uflash_status == UFCIS_OP_ERROR) {
- LOG_ERROR("Userflash operation error");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- /* clear status */
- uint32_t uflash_cmd = UFCIC_CLR_OPCMLT | UFCIC_CLR_OPERROR;
- retval = target_write_u32(target, UFCIC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-/**
- * Dump page of userflash region.
- * If we want to change some settings, we have to dump it full, because userflash is flash(not EEPROM).
- * And correct write to flash can be performed only after erase.
- * So without dump, changing one registers will clear others.
- */
-static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
-{
- struct target *target = bank->target;
- int i;
- int retval = ERROR_OK;
-
- uint32_t uflash_cmd;
- if (mem_type == INFO_MEM_TYPE)
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
- else
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ;
-
- int first = page_num*USERFLASH_PAGE_SIZE;
- int last = first + USERFLASH_PAGE_SIZE;
-
- for (i = first; i < last; i++) {
- retval = target_write_u32(target, UFMA, i);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, UFMD, &dump[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-/**
- * Load modified page dump to userflash region page.
- */
-static int niietcm4_load_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
-{
- struct target *target = bank->target;
- int i;
- int retval = ERROR_OK;
-
- uint32_t uflash_cmd;
- if (mem_type == INFO_MEM_TYPE)
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_WRITE_IFB;
- else
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_WRITE;
-
- int first = page_num*USERFLASH_PAGE_SIZE;
- int last = first + USERFLASH_PAGE_SIZE;
-
- for (i = first; i < last; i++) {
- retval = target_write_u32(target, UFMA, i);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMD, dump[i]);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-/**
- * Erase one page of userflash info or main region
- */
-static int niietcm4_uflash_page_erase(struct flash_bank *bank, int page_num, int mem_type)
-{
- struct target *target = bank->target;
- int retval;
-
- uint32_t uflash_cmd;
- if (mem_type == INFO_MEM_TYPE)
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_PAGEERASE_IFB;
- else
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_PAGE_ERASE;
-
- retval = target_write_u32(target, UFMA, page_num*USERFLASH_PAGE_SIZE);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMD, 0xFF);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-/**
- * Enable or disable protection of userflash pages
- */
-static int niietcm4_uflash_protect(struct flash_bank *bank, int mem_type, int set, int first, int last)
-{
- int retval;
- if (mem_type == INFO_MEM_TYPE) {
- /* read dump */
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* modify dump */
- if (set)
- uflash_dump[INFOWORD2_ADDR] &= ~INFOWORD3_LOCK_IFB_UF;
- else
- uflash_dump[INFOWORD2_ADDR] |= INFOWORD3_LOCK_IFB_UF;
- /* erase page 0 userflash */
- retval = niietcm4_uflash_page_erase(bank, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* write dump to userflash */
- retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- } else {
- /* read dump */
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* modify dump */
- for (int i = first; i <= last; i++) {
- uint32_t reg_num = i/8;
- uint32_t bit_num = i%8;
- if (set)
- uflash_dump[UF_LOCK_ADDR+reg_num] &= ~(1<<bit_num);
- else
- uflash_dump[UF_LOCK_ADDR+reg_num] |= (1<<bit_num);
- }
- /* erase page 0 info userflash */
- retval = niietcm4_uflash_page_erase(bank, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* write dump to userflash */
- retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-/*==============================================================================
- * FLASH COMMANDS
- *==============================================================================
- */
-COMMAND_HANDLER(niietcm4_handle_uflash_read_byte_command)
-{
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- uint32_t uflash_addr;
- uint32_t uflash_cmd;
- uint32_t uflash_data;
-
- if (strcmp("info", CMD_ARGV[0]) == 0)
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
- else if (strcmp("main", CMD_ARGV[0]) == 0)
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], uflash_addr);
-
- retval = target_write_u32(target, UFMA, uflash_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, UFMD, &uflash_data);
- if (retval != ERROR_OK)
- return retval;
- command_print(CMD_CTX, "Read userflash %s region:\n"
- "address = 0x%04x,\n"
- "value = 0x%02x.", CMD_ARGV[0], uflash_addr, uflash_data);
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_uflash_write_byte_command)
-{
- if (CMD_ARGC < 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- uint32_t uflash_addr;
- uint32_t uflash_data;
- int mem_type;
-
- if (strcmp("info", CMD_ARGV[0]) == 0)
- mem_type = 1;
- else if (strcmp("main", CMD_ARGV[0]) == 0)
- mem_type = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], uflash_addr);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], uflash_data);
-
- int page_num = uflash_addr/USERFLASH_PAGE_SIZE;
-
- command_print(CMD_CTX, "Write userflash %s region:\n"
- "address = 0x%04x,\n"
- "value = 0x%02x.\n"
- "Please wait ... ", CMD_ARGV[0], uflash_addr, uflash_data);
- /* dump */
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- niietcm4_dump_uflash_page(bank, uflash_dump, page_num, mem_type);
-
- /* modify dump */
- uflash_dump[uflash_addr%USERFLASH_PAGE_SIZE] = uflash_data;
-
- /* erase page userflash */
- niietcm4_uflash_page_erase(bank, page_num, mem_type);
-
- /* write dump to userflash */
- niietcm4_load_uflash_page(bank, uflash_dump, page_num, mem_type);
- command_print(CMD_CTX, "done!");
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_uflash_full_erase_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t uflash_addr = 0;
- uint32_t uflash_data = 0xFF;
- uint32_t uflash_cmd = UFMC_MAGIC_KEY | UFMC_FULL_ERASE;
-
- retval = target_write_u32(target, UFMA, uflash_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMD, uflash_data);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- command_print(CMD_CTX, "Userflash full erase done!");
-
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_uflash_erase_command)
-{
- if (CMD_ARGC < 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- unsigned int first, last;
- int mem_type;
-
- if (strcmp("info", CMD_ARGV[0]) == 0)
- mem_type = 1;
- else if (strcmp("main", CMD_ARGV[0]) == 0)
- mem_type = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], first);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], last);
- for (unsigned int i = first; i <= last; i++) {
- retval = niietcm4_uflash_page_erase(bank, i, mem_type);
- if (retval != ERROR_OK)
- return retval;
- }
-
- command_print(CMD_CTX, "Erase %s userflash pages %d through %d done!", CMD_ARGV[0], first, last);
-
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_uflash_protect_check_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
-
- struct target *target = bank->target;
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- int mem_type;
- if (strcmp("info", CMD_ARGV[0]) == 0)
- mem_type = 1;
- else if (strcmp("main", CMD_ARGV[0]) == 0)
- mem_type = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int i, j;
- uint32_t uflash_addr;
- uint32_t uflash_cmd;
- uint32_t uflash_data;
-
- /* chose between main userflash and info userflash */
- if (mem_type == INFO_MEM_TYPE) {
- uflash_addr = INFOWORD3_ADDR;
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
- retval = target_write_u32(target, UFMA, uflash_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, UFMD, &uflash_data);
- if (retval != ERROR_OK)
- return retval;
-
- if (uflash_data & INFOWORD3_LOCK_IFB_UF)
- command_print(CMD_CTX, "All sectors of info userflash are not protected!");
- else
- command_print(CMD_CTX, "All sectors of info userflash are protected!");
- } else {
- uflash_addr = UF_LOCK_ADDR;
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
- for (i = 0; i < USERFLASH_PAGE_TOTALNUM/8; i++) {
- retval = target_write_u32(target, UFMA, uflash_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, UFMD, &uflash_data);
- if (retval != ERROR_OK)
- return retval;
-
- for (j = 0; j < 8; j++) {
- if (uflash_data & 0x1)
- command_print(CMD_CTX, "Userflash sector #%03d: 0x%04x (0x100) is not protected!",
- i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
- else
- command_print(CMD_CTX, "Userflash sector #%03d: 0x%04x (0x100) is protected!",
- i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
- uflash_data = uflash_data >> 1;
- }
- uflash_addr++;
- }
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_uflash_protect_command)
-{
- if (CMD_ARGC < 5)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- int mem_type;
- if (strcmp("info", CMD_ARGV[0]) == 0)
- mem_type = 1;
- else if (strcmp("main", CMD_ARGV[0]) == 0)
- mem_type = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned int first, last;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], first);
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], last);
-
- int set;
- if (strcmp("on", CMD_ARGV[3]) == 0) {
- command_print(CMD_CTX, "Try to enable %s userflash sectors %d through %d protection. Please wait ... ",
- CMD_ARGV[0], first, last);
- set = 1;
- } else if (strcmp("off", CMD_ARGV[3]) == 0) {
- command_print(CMD_CTX, "Try to disable %s userflash sectors %d through %d protection. Please wait ... ",
- CMD_ARGV[0], first, last);
- set = 0;
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- retval = niietcm4_uflash_protect(bank, mem_type, set, first, last);
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "done!");
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_bflash_info_remap_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- int set;
- if (strcmp("on", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to enable bootflash info region remap. Please wait ...");
- set = 1;
- } else if (strcmp("off", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to disable bootflash info region remap. Please wait ...");
- set = 0;
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* dump */
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
-
- /* modify dump */
- if (set)
- uflash_dump[INFOWORD0_ADDR] &= ~INFOWORD0_BOOTFROM_IFB;
- else
- uflash_dump[INFOWORD0_ADDR] |= INFOWORD0_BOOTFROM_IFB;
-
- /* erase page userflash */
- niietcm4_uflash_page_erase(bank, 0, 1);
-
- /* write dump to userflash */
- niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- command_print(CMD_CTX, "done!");
-
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_extmem_cfg_command)
-{
- if (CMD_ARGC < 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- uint32_t port;
- if (strcmp("gpioa", CMD_ARGV[0]) == 0)
- port = 8;
- else if (strcmp("gpiob", CMD_ARGV[0]) == 0)
- port = 9;
- else if (strcmp("gpioc", CMD_ARGV[0]) == 0)
- port = 10;
- else if (strcmp("gpiod", CMD_ARGV[0]) == 0)
- port = 11;
- else if (strcmp("gpioe", CMD_ARGV[0]) == 0)
- port = 12;
- else if (strcmp("gpiof", CMD_ARGV[0]) == 0)
- port = 13;
- else if (strcmp("gpiog", CMD_ARGV[0]) == 0)
- port = 14;
- else if (strcmp("gpioh", CMD_ARGV[0]) == 0)
- port = 15;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t pin;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], pin);
- if (pin > 15)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t func;
- if (strcmp("func1", CMD_ARGV[2]) == 0)
- func = 0;
- else if (strcmp("func3", CMD_ARGV[2]) == 0)
- func = 3;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- command_print(CMD_CTX, "Try to configure external memory boot interface:\n"
- "port = %s\n"
- "pin = %s\n"
- "func = %s\n"
- "Please wait ...", CMD_ARGV[0], CMD_ARGV[1], CMD_ARGV[2]);
- /* dump */
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
-
- /* modify dump */
- uflash_dump[INFOWORD0_ADDR] &= ~(3<<INFOWORD0_EXTMEM_SEL_POS);
- uflash_dump[INFOWORD0_ADDR] |= func<<INFOWORD0_EXTMEM_SEL_POS;
- uflash_dump[INFOWORD1_ADDR] = (port<<INFOWORD1_PORTNUM_POS) | (pin<<INFOWORD1_PINNUM_POS);
-
- /* erase page userflash */
- niietcm4_uflash_page_erase(bank, 0, 1);
-
- /* write dump to userflash */
- niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- command_print(CMD_CTX, "done!");
-
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_extmem_boot_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- int set;
-
- if (strcmp("on", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to enable boot from external memory. Please wait ...");
- set = 1;
- } else if (strcmp("off", CMD_ARGV[0]) == 0) {
- command_print(CMD_CTX, "Try to disable boot from external memory. Please wait ...");
- set = 0;
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* dump */
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
-
- /* modify dump */
- if (set)
- uflash_dump[INFOWORD0_ADDR] &= ~INFOWORD0_EN_GPIO;
- else
- uflash_dump[INFOWORD0_ADDR] |= INFOWORD0_EN_GPIO;
-
- /* erase page userflash */
- niietcm4_uflash_page_erase(bank, 0, 1);
-
- /* write dump to userflash */
- niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- command_print(CMD_CTX, "done!");
-
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_service_mode_erase_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
- struct target *target = bank->target;
-
- command_print(CMD_CTX, "Try to perform service mode erase. Please wait ...");
-
- retval = target_write_u32(target, SERVICE_MODE_ERASE_ADDR, 1);
- if (retval != ERROR_OK)
- return retval;
-
- int timeout = 500;
- uint32_t status;
-
- retval = target_read_u32(target, SERVICE_MODE_ERASE_ADDR, &status);
- if (retval != ERROR_OK)
- return retval;
-
- while (status != 0x03) {
- retval = target_read_u32(target, SERVICE_MODE_ERASE_ADDR, &status);
- if (retval != ERROR_OK)
- return retval;
- if (timeout-- <= 0) {
- LOG_ERROR("Service mode erase timeout");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- busy_sleep(1); /* can use busy sleep for short times. */
- }
- command_print(CMD_CTX, "done! All data erased.");
-
- return retval;
-}
-
-COMMAND_HANDLER(niietcm4_handle_driver_info_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "niietcm4 flash driver\n"
- "version: %d.%d\n"
- "author: Bogdan Kolbov\n"
- "mail: kolbov@niiet.ru",
- FLASH_DRIVER_VER>>16,
- FLASH_DRIVER_VER&0xFFFF);
-
- return retval;
-}
-
-static const struct command_registration niietcm4_exec_command_handlers[] = {
- {
- .name = "uflash_read_byte",
- .handler = niietcm4_handle_uflash_read_byte_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('main'|'info') address",
- .help = "Read byte from main or info userflash region",
- },
- {
- .name = "uflash_write_byte",
- .handler = niietcm4_handle_uflash_write_byte_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('main'|'info') address value",
- .help = "Write byte to main or info userflash region",
- },
- {
- .name = "uflash_full_erase",
- .handler = niietcm4_handle_uflash_full_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Erase all userflash including info region",
- },
- {
- .name = "uflash_erase",
- .handler = niietcm4_handle_uflash_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('main'|'info') first_sector_num last_sector_num",
- .help = "Erase sectors of main or info userflash region, starting at sector first up to and including last.",
- },
- {
- .name = "uflash_protect_check",
- .handler = niietcm4_handle_uflash_protect_check_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('main'|'info')",
- .help = "Check sectors protect.",
- },
- {
- .name = "uflash_protect",
- .handler = niietcm4_handle_uflash_protect_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('main'|'info') first_sector_num last_sector_num ('on'|'off')",
- .help = "Protect sectors of main or info userflash region, starting at sector first up to and including last.",
- },
- {
- .name = "bflash_info_remap",
- .handler = niietcm4_handle_bflash_info_remap_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('on'|'off')",
- .help = "Enable remapping bootflash info region to 0x00000000 (or 0x40000000 if external memory boot used).",
- },
- {
- .name = "extmem_cfg",
- .handler = niietcm4_handle_extmem_cfg_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('gpioa'|'gpiob'|'gpioc'|'gpiod'|'gpioe'|'gpiof'|'gpiog'|'gpioh') pin_num ('func1'|'func3')",
- .help = "Configure external memory interface for boot.",
- },
- {
- .name = "extmem_boot",
- .handler = niietcm4_handle_extmem_boot_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('on'|'off')",
- .help = "Enable boot from external memory.",
- },
- {
- .name = "service_mode_erase",
- .handler = niietcm4_handle_service_mode_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Perform emergency erase of all flash (bootflash and userflash).",
- },
- {
- .name = "driver_info",
- .handler = niietcm4_handle_driver_info_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Show information about flash driver.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration niietcm4_command_handlers[] = {
- {
- .name = "niietcm4",
- .mode = COMMAND_ANY,
- .help = "niietcm4 flash command group",
- .usage = "",
- .chain = niietcm4_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/*==============================================================================
- * FLASH INTERFACE
- *==============================================================================
- */
-
-FLASH_BANK_COMMAND_HANDLER(niietcm4_flash_bank_command)
-{
- struct niietcm4_flash_bank *niietcm4_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- niietcm4_info = malloc(sizeof(struct niietcm4_flash_bank));
-
- bank->driver_priv = niietcm4_info;
-
- /* information will be updated by probing */
- niietcm4_info->probed = false;
- niietcm4_info->chipid = 0;
- niietcm4_info->chip_name = NULL;
- niietcm4_info->uflash_width = 0;
- niietcm4_info->uflash_size = 0;
- niietcm4_info->uflash_pagetotal = 0;
- niietcm4_info->uflash_info_size = 0;
- niietcm4_info->uflash_info_pagetotal = 0;
- niietcm4_info->bflash_info_remap = false;
- niietcm4_info->extmem_boot_port = NULL;
- niietcm4_info->extmem_boot_pin = 0;
- niietcm4_info->extmem_boot_altfunc = 0;
- niietcm4_info->extmem_boot = false;
-
- return ERROR_OK;
-}
-
-static int niietcm4_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
-
- int retval = ERROR_FLASH_OPERATION_FAILED;
- int set;
- uint32_t uflash_addr;
- uint32_t uflash_cmd;
- uint32_t uflash_data;
- /* chose between main bootflash and info bootflash */
- if (niietcm4_info->bflash_info_remap) {
- uflash_addr = INFOWORD2_ADDR;
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
- retval = target_write_u32(target, UFMA, uflash_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, UFMD, &uflash_data);
- if (retval != ERROR_OK)
- return retval;
-
- if (uflash_data & INFOWORD2_LOCK_IFB_BF)
- set = 0;
- else
- set = 1;
- bank->sectors[0].is_protected = set;
- } else {
- uflash_addr = BF_LOCK_ADDR;
- uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
- for (int i = 0; i < bank->num_sectors/8; i++) {
- retval = target_write_u32(target, UFMA, uflash_addr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, UFMD, &uflash_data);
- if (retval != ERROR_OK)
- return retval;
-
- for (int j = 0; j < 8; j++) {
- if (uflash_data & 0x1)
- set = 0;
- else
- set = 1;
- bank->sectors[i*8+j].is_protected = set;
- uflash_data = uflash_data >> 1;
- }
- uflash_addr++;
- }
- }
-
- return retval;
-}
-
-static int niietcm4_mass_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
-
- int retval;
- uint32_t flash_cmd;
-
- /* start mass erase */
- flash_cmd = FMC_MAGIC_KEY | FMC_FULL_ERASE;
- retval = target_write_u32(target, FMC, flash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- /* status check */
- retval = niietcm4_opstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-static int niietcm4_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- int retval = ERROR_FLASH_OPERATION_FAILED;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first == 0) && (last == (bank->num_sectors - 1))) {
- retval = niietcm4_mass_erase(bank);
- return retval;
- }
-
- /* chose between main bootflash and info bootflash */
- uint32_t flash_cmd, flash_addr;
- if (niietcm4_info->bflash_info_remap)
- flash_cmd = FMC_MAGIC_KEY | FMC_PAGEERASE_IFB;
- else
- flash_cmd = FMC_MAGIC_KEY | FMC_PAGE_ERASE;
-
- /* erasing pages */
- unsigned int page_size = bank->size / bank->num_sectors;
- for (int i = first; i <= last; i++) {
- /* current page addr */
- flash_addr = i*page_size;
- retval = target_write_u32(target, FMA, flash_addr);
- if (retval != ERROR_OK)
- return retval;
-
- /* start erase */
- retval = target_write_u32(target, FMC, flash_cmd);
- if (retval != ERROR_OK)
- return retval;
-
- /* status check */
- retval = niietcm4_opstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
-
- bank->sectors[i].is_erased = 1;
- }
-
- return retval;
-}
-
-static int niietcm4_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct target *target = bank->target;
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
-
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_INFO("Plese wait ..."); /* it`s quite a long process */
- /* chose between main bootflash and info bootflash */
- if (niietcm4_info->bflash_info_remap) {
- /* dump */
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* modify dump */
- if (set)
- uflash_dump[INFOWORD2_ADDR] &= ~INFOWORD2_LOCK_IFB_BF;
- else
- uflash_dump[INFOWORD2_ADDR] |= INFOWORD2_LOCK_IFB_BF;
- /* erase page 0 userflash */
- retval = niietcm4_uflash_page_erase(bank, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* write dump to userflash */
- retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- } else {
- /* read dump*/
- uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
- retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* modify dump */
- for (int i = first; i <= last; i++) {
- uint32_t reg_num = i/8;
- uint32_t bit_num = i%8;
- if (set)
- uflash_dump[BF_LOCK_ADDR+reg_num] &= ~(1<<bit_num);
- else
- uflash_dump[BF_LOCK_ADDR+reg_num] |= (1<<bit_num);
- }
- /* erase page 0 info userflash */
- retval = niietcm4_uflash_page_erase(bank, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- /* write dump to userflash */
- retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int niietcm4_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- uint32_t buffer_size = 32768 + 8; /* 8 bytes for rp and wp */
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* see contrib/loaders/flash/k1921vk01t.S for src */
- static const uint8_t niietcm4_flash_write_code[] = {
- 0x14, 0x4f, 0x16, 0x68, 0x00, 0x2e, 0x23, 0xd0, 0x55, 0x68, 0xb5, 0x42, 0xf9, 0xd0, 0x2e, 0x68,
- 0x7e, 0x60, 0x04, 0x35, 0x2e, 0x68, 0x3e, 0x65, 0x04, 0x35, 0x2e, 0x68, 0x7e, 0x65, 0x04, 0x35,
- 0x2e, 0x68, 0xbe, 0x65, 0x04, 0x35, 0x3c, 0x60, 0x10, 0x34, 0xb8, 0x60, 0xfe, 0x68, 0x00, 0x2e,
- 0xfc, 0xd0, 0x02, 0x2e, 0x0a, 0xd0, 0x01, 0x26, 0x7e, 0x61, 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46,
- 0x08, 0x35, 0x55, 0x60, 0x01, 0x39, 0x00, 0x29, 0x02, 0xd0, 0xda, 0xe7, 0x00, 0x20, 0x50, 0x60,
- 0x30, 0x46, 0x00, 0xbe, 0x00, 0xc0, 0x01, 0xa0
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(niietcm4_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(niietcm4_flash_write_code), niietcm4_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- buffer_size &= ~15UL; /* Make sure it's 16 byte aligned */
- buffer_size += 8; /* And 8 bytes for WP and RP */
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* write_cmd base (in), status (out) */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (128bit) */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
-
- uint32_t flash_cmd;
- if (niietcm4_info->bflash_info_remap)
- flash_cmd = FMC_MAGIC_KEY | FMC_WRITE_IFB;
- else
- flash_cmd = FMC_MAGIC_KEY | FMC_WRITE;
-
- buf_set_u32(reg_params[0].value, 0, 32, flash_cmd);
- buf_set_u32(reg_params[1].value, 0, 32, count);
- buf_set_u32(reg_params[2].value, 0, 32, source->address);
- buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
- buf_set_u32(reg_params[4].value, 0, 32, address);
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- retval = target_run_flash_async_algorithm(target, buffer, count, 16,
- 0, NULL,
- 5, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (retval == ERROR_FLASH_OPERATION_FAILED)
- LOG_ERROR("flash write failed at address 0x%"PRIx32,
- buf_get_u32(reg_params[4].value, 0, 32));
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-static int niietcm4_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- uint8_t *new_buffer = NULL;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0xF) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-word alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* If there's an odd number of words, the data has to be padded. Duplicate
- * the buffer and use the normal code path with a single block write since
- * it's probably cheaper than to special case the last odd write using
- * discrete accesses. */
-
- int rem = count % 16;
- if (rem) {
- new_buffer = malloc(count + 16 - rem);
- if (new_buffer == NULL) {
- LOG_ERROR("Odd number of words to write and no memory for padding buffer");
- return ERROR_FAIL;
- }
- LOG_INFO("Odd number of words to write, padding with 0xFFFFFFFF");
- buffer = memcpy(new_buffer, buffer, count);
- while (rem < 16) {
- new_buffer[count++] = 0xff;
- rem++;
- }
- }
-
- int retval;
-
- /* try using block write */
- retval = niietcm4_write_block(bank, buffer, offset, count/16);
- uint32_t flash_addr, flash_cmd, flash_data;
-
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single halfword accesses */
- LOG_WARNING("Can't use block writes, falling back to single memory accesses");
- LOG_INFO("Plese wait ..."); /* it`s quite a long process */
-
- /* chose between main bootflash and info bootflash */
- if (niietcm4_info->bflash_info_remap)
- flash_cmd = FMC_MAGIC_KEY | FMC_WRITE_IFB;
- else
- flash_cmd = FMC_MAGIC_KEY | FMC_WRITE;
-
- /* write 16 bytes per try */
- for (unsigned int i = 0; i < count; i += 16) {
- /* current addr */
- LOG_INFO("%d byte of %d", i, count);
- flash_addr = offset + i;
- retval = target_write_u32(target, FMA, flash_addr);
- if (retval != ERROR_OK)
- goto free_buffer;
-
- /* Prepare data (4 words) */
- uint32_t value[4];
- memcpy(&value, buffer + i*16, 4*sizeof(uint32_t));
-
- /* place in reg 16 bytes of data */
- flash_data = value[0];
- retval = target_write_u32(target, FMD1, flash_data);
- if (retval != ERROR_OK)
- goto free_buffer;
- flash_data = value[1];
- retval = target_write_u32(target, FMD2, flash_data);
- if (retval != ERROR_OK)
- goto free_buffer;
- flash_data = value[2];
- retval = target_write_u32(target, FMD3, flash_data);
- if (retval != ERROR_OK)
- goto free_buffer;
- flash_data = value[3];
- retval = target_write_u32(target, FMD4, flash_data);
- if (retval != ERROR_OK)
- goto free_buffer;
-
- /* write start */
- retval = target_write_u32(target, FMC, flash_cmd);
- if (retval != ERROR_OK)
- goto free_buffer;
-
- /* status check */
- retval = niietcm4_opstatus_check(bank);
- if (retval != ERROR_OK)
- goto free_buffer;
- }
-
- }
-
-free_buffer:
- if (new_buffer)
- free(new_buffer);
-
- return retval;
-}
-
-static int niietcm4_probe_k1921vk01t(struct flash_bank *bank)
-{
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- struct target *target = bank->target;
- int retval;
-
- niietcm4_info->chip_name = "K1921VK01T";
-
- /* check if we in service mode */
- uint32_t service_mode;
- retval = target_read_u32(target, 0x80017000, &service_mode);
- if (retval != ERROR_OK)
- return retval;
- service_mode = (service_mode>>2) & 0x1;
-
- if (!service_mode) {
- niietcm4_info->uflash_width = 8;
- niietcm4_info->uflash_size = 0x10000;
- niietcm4_info->uflash_pagetotal = 256;
- niietcm4_info->uflash_info_size = 0x200;
- niietcm4_info->uflash_info_pagetotal = 2;
-
- uint32_t uflash_data[2];
- uint32_t uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
- for (int i = 0; i < 2; i++) {
- retval = target_write_u32(target, UFMA, i);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, UFMC, uflash_cmd);
- if (retval != ERROR_OK)
- return retval;
- /* status check */
- retval = niietcm4_uopstatus_check(bank);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, UFMD, &uflash_data[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- int boot_from_ifb = (uflash_data[0]>>INFOWORD0_BOOTFROM_IFB_POS) & 0x1;
- int en_gpio = (uflash_data[0]>>INFOWORD0_EN_GPIO_POS) & 0x1;
- int extmem_sel = (uflash_data[0]>>INFOWORD0_EXTMEM_SEL_POS) & 0x3;
- int pinnum = (uflash_data[1]>>INFOWORD1_PINNUM_POS) & 0xF;
- int portnum = (uflash_data[1]>>INFOWORD1_PORTNUM_POS) & 0x7;
-
- if (boot_from_ifb)
- niietcm4_info->bflash_info_remap = false;
- else
- niietcm4_info->bflash_info_remap = true;
- if (extmem_sel == 0x2)
- niietcm4_info->extmem_boot_altfunc = 3;
- else
- niietcm4_info->extmem_boot_altfunc = 1;
- if (portnum == 0x0)
- niietcm4_info->extmem_boot_port = "GPIOA";
- else if (portnum == 0x1)
- niietcm4_info->extmem_boot_port = "GPIOB";
- else if (portnum == 0x2)
- niietcm4_info->extmem_boot_port = "GPIOC";
- else if (portnum == 0x3)
- niietcm4_info->extmem_boot_port = "GPIOD";
- else if (portnum == 0x4)
- niietcm4_info->extmem_boot_port = "GPIOE";
- else if (portnum == 0x5)
- niietcm4_info->extmem_boot_port = "GPIOF";
- else if (portnum == 0x6)
- niietcm4_info->extmem_boot_port = "GPIOG";
- else if (portnum == 0x7)
- niietcm4_info->extmem_boot_port = "GPIOH";
- else
- niietcm4_info->extmem_boot_port = "not defined";
- if (en_gpio)
- niietcm4_info->extmem_boot = false;
- else
- niietcm4_info->extmem_boot = true;
- niietcm4_info->extmem_boot_pin = pinnum;
-
- /* check state of extmem boot en pin, if "high", extmem remapped to 0x00000000 */
- uint32_t extmem_boot_port_data;
- retval = target_read_u32(target, 0x80010000 + 0x1000*portnum, &extmem_boot_port_data);
- if (retval != ERROR_OK)
- return retval;
- int extmem_boot_pin_data = (extmem_boot_port_data>>pinnum) & 0x1;
-
- uint32_t extmem_base;
- uint32_t bflash_base;
- if (extmem_boot_pin_data && niietcm4_info->extmem_boot) {
- extmem_base = 0x00000000;
- bflash_base = 0x40000000;
- } else {
- extmem_base = 0x40000000;
- bflash_base = 0x00000000;
- }
-
- uint32_t bflash_size = 0x100000;
- uint32_t bflash_pages = 128;
- uint32_t bflash_info_size = 0x2000;
- uint32_t bflash_info_pages = 1;
- if (niietcm4_info->bflash_info_remap) {
- bflash_base += 0x2000;
- bflash_size -= 0x2000;
- bflash_pages--;
- bank->size = bflash_info_size;
- bank->num_sectors = bflash_info_pages;
- } else {
- bank->size = bflash_size;
- bank->num_sectors = bflash_pages;
- }
-
- char info_bootflash_addr_str[64];
- if (niietcm4_info->bflash_info_remap)
- snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "0x%08x base adress", bank->base);
- else
- snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "not maped to global adress space");
-
- snprintf(niietcm4_info->chip_brief,
- sizeof(niietcm4_info->chip_brief),
- "\n"
- "MEMORY CONFIGURATION\n"
- "Bootflash :\n"
- " %d kB total\n"
- " %d pages %d kB each\n"
- " 0x%08x base adress\n"
- "%s"
- "Info bootflash :\n"
- " %d kB total\n"
- " %d pages %d kB each\n"
- " %s\n"
- "%s"
- "Userflash :\n"
- " %d kB total\n"
- " %d pages %d B each\n"
- " %d bit cells\n"
- " not maped to global adress space\n"
- "Info userflash :\n"
- " %d B total\n"
- " %d pages of %d B each\n"
- " %d bit cells\n"
- " not maped to global adress space\n"
- "RAM :\n"
- " 192 kB total\n"
- " 0x20000000 base adress\n"
- "External memory :\n"
- " 8/16 bit address space\n"
- " 0x%08x base adress\n"
- "\n"
- "INFOWORD STATUS\n"
- "Bootflash info region remap :\n"
- " %s\n"
- "External memory boot port :\n"
- " %s\n"
- "External memory boot pin :\n"
- " %d\n"
- "External memory interface alternative function :\n"
- " %d\n"
- "Option boot from external memory :\n"
- " %s\n",
- bflash_size/1024,
- bflash_pages,
- (bflash_size/bflash_pages)/1024,
- bflash_base,
- niietcm4_info->bflash_info_remap ? "" : " this flash will be used for debugging, writing and etc\n",
- bflash_info_size/1024,
- bflash_info_pages,
- (bflash_info_size/bflash_info_pages)/1024,
- info_bootflash_addr_str,
- niietcm4_info->bflash_info_remap ? " this flash will be used for debugging, writing and etc\n" : "",
- niietcm4_info->uflash_size/1024,
- niietcm4_info->uflash_pagetotal,
- niietcm4_info->uflash_size/niietcm4_info->uflash_pagetotal,
- niietcm4_info->uflash_width,
- niietcm4_info->uflash_info_size,
- niietcm4_info->uflash_info_pagetotal,
- niietcm4_info->uflash_info_size/niietcm4_info->uflash_info_pagetotal,
- niietcm4_info->uflash_width,
- extmem_base,
- niietcm4_info->bflash_info_remap ? "enable" : "disable",
- niietcm4_info->extmem_boot_port,
- niietcm4_info->extmem_boot_pin,
- niietcm4_info->extmem_boot_altfunc,
- niietcm4_info->extmem_boot ? "enable" : "disable");
- } else{
- bank->size = 0x100000;
- bank->num_sectors = 128;
-
- sprintf(niietcm4_info->chip_brief,
- "\n"
- "H[2] was HIGH while startup. Device entered service mode.\n"
- "All flashes were locked.\n"
- "If you want to perform emergency erase (erase all flashes),\n"
- "please use \"service_mode_erase\" command and reset device.\n"
- "Do not forget to pull H[2] down while reset for returning to normal operation mode.\n"
- );
- }
-
- return retval;
-}
-
-static int niietcm4_probe(struct flash_bank *bank)
-{
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- struct target *target = bank->target;
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
- uint32_t retval;
- uint32_t chipid;
-
- retval = target_read_u32(target, CHIPID_ADDR, &chipid);
- if (retval != ERROR_OK) {
- chipid = K1921VK01T_ID;
- LOG_INFO("unknown chipid, assuming K1921VK01T");
- }
-
- if (chipid == K1921VK01T_ID)
- niietcm4_probe_k1921vk01t(bank);
-
- int page_total = bank->num_sectors;
- int page_size = bank->size / page_total;
-
- bank->sectors = malloc(sizeof(struct flash_sector) * page_total);
-
- for (int i = 0; i < page_total; i++) {
- bank->sectors[i].offset = i * page_size;
- bank->sectors[i].size = page_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- niietcm4_info->probed = true;
-
- return ERROR_OK;
-}
-
-static int niietcm4_auto_probe(struct flash_bank *bank)
-{
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- if (niietcm4_info->probed)
- return ERROR_OK;
- return niietcm4_probe(bank);
-}
-
-static int get_niietcm4_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
- LOG_INFO("\nNIIET Cortex-M4F %s\n%s", niietcm4_info->chip_name, niietcm4_info->chip_brief);
- snprintf(buf, buf_size, " ");
-
- return ERROR_OK;
-}
-
-
-struct flash_driver niietcm4_flash = {
- .name = "niietcm4",
- .usage = "flash bank <name> niietcm4 <base> <size> 0 0 <target#>",
- .commands = niietcm4_command_handlers,
- .flash_bank_command = niietcm4_flash_bank_command,
- .erase = niietcm4_erase,
- .protect = niietcm4_protect,
- .write = niietcm4_write,
- .read = default_flash_read,
- .probe = niietcm4_probe,
- .auto_probe = niietcm4_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = niietcm4_protect_check,
- .info = get_niietcm4_info,
-};
diff --git a/src/flash/nor/non_cfi.c b/src/flash/nor/non_cfi.c
deleted file mode 100644
index 851c0ae..0000000
--- a/src/flash/nor/non_cfi.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * Copyright (C) 2009 Michael Schwingen *
- * michael@schwingen.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "cfi.h"
-#include "non_cfi.h"
-
-#define KB 1024
-#define MB (1024*1024)
-#define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
-
-/* non-CFI compatible flashes */
-static const struct non_cfi non_cfi_flashes[] = {
- {
- .mfr = CFI_MFR_SST,
- .id = 0xd4,
- .pri_id = 0x02,
- .dev_size = 64*KB,
- .interface_desc = 0x0, /* x8 only device */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(16, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0xd5,
- .pri_id = 0x02,
- .dev_size = 128*KB,
- .interface_desc = 0x0, /* x8 only device */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(32, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0xd6,
- .pri_id = 0x02,
- .dev_size = 256*KB,
- .interface_desc = 0x0, /* x8 only device */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(64, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0xd7,
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x0, /* x8 only device */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(128, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_AMD, /* Spansion AM29LV040B */
- .id = 0x4f,
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x0, /* x8 only device */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(8, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x2780,
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x2, /* x8 or x16 device */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(128, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_ST,
- .id = 0xd6, /* ST29F400BB */
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(7, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_ST,
- .id = 0xd5, /* ST29F400BT */
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(7, 64*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 16*KB)
- }
- },
-
- /* SST 39VF* do not support DQ5 status polling - this currently is
- only supported by the host algorithm, not by the target code using
- the work area.
- Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
- without DQ5 status polling are supported by the target code.
- */
- {
- .mfr = CFI_MFR_SST,
- .id = 0x2782, /* SST39xF160 */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(512, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x2783, /* SST39VF320 */
- .pri_id = 0x02,
- .dev_size = 4*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(1024, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x234b, /* SST39VF1601 */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(512, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x274b, /* SST39WF1601 */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(512, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x234a, /* SST39VF1602 */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(512, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x235b, /* SST39VF3201 */
- .pri_id = 0x02,
- .dev_size = 4*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(1024, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x235a, /* SST39VF3202 */
- .pri_id = 0x02,
- .dev_size = 4*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(1024, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_SST,
- .id = 0x236d, /* SST39VF6401B */
- .pri_id = 0x02,
- .dev_size = 8*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
- .num_erase_regions = 1,
- .erase_region_info = {
- ERASE_REGION(2048, 4*KB)
- }
- },
- {
- .mfr = CFI_MFR_AMD,
- .id = 0x22ab, /* AM29F400BB */
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(7, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_AMD,
- .id = 0x2223, /* AM29F400BT */
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(7, 64*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 16*KB)
- }
- },
- {
- .mfr = CFI_MFR_FUJITSU,
- .id = 0x226b, /* AM29SL800DB */
- .pri_id = 0x02,
- .dev_size = 1*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(15, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_FUJITSU,
- .id = 0x22ea, /* MBM29SL800TE */
- .pri_id = 0x02,
- .dev_size = 1*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(15, 64*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 16*KB)
- }
- },
- {
- .mfr = CFI_MFR_FUJITSU,
- .id = 0xba, /* 29LV400BC */
- .pri_id = 0x02,
- .dev_size = 512*KB,
- .interface_desc = 0x1, /* x8 or x16 device w/ nBYTE */
- .max_buf_write_size = 0x00,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(7, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_AMIC,
- .id = 0xb31a, /* A29L800A */
- .pri_id = 0x02,
- .dev_size = 1*MB,
- .interface_desc = 0x2,
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(15, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_MX,
- .id = 0x225b, /* MX29LV800B */
- .pri_id = 0x02,
- .dev_size = 1*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(15, 64*KB)
- }
- },
-
- {
- .mfr = CFI_MFR_MX,
- .id = 0x2249, /* MX29LV160AB: 2MB */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(31, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_MX,
- .id = 0x22C4, /* MX29LV160AT: 2MB */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(31, 64*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 16*KB)
- }
- },
- {
- .mfr = CFI_MFR_EON,
- .id = 0x225b, /* EN29LV800BB */
- .pri_id = 0x02,
- .dev_size = 1*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(15, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_ATMEL,
- .id = 0x00c0, /* Atmel 49BV1614 */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 3,
- .erase_region_info = {
- ERASE_REGION(8, 8*KB),
- ERASE_REGION(2, 32*KB),
- ERASE_REGION(30, 64*KB)
- }
- },
- {
- .mfr = CFI_MFR_ATMEL,
- .id = 0xC2, /* Atmel 49BV1614T */
- .pri_id = 0x02,
- .dev_size = 2*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 3,
- .erase_region_info = {
- ERASE_REGION(30, 64*KB),
- ERASE_REGION(2, 32*KB),
- ERASE_REGION(8, 8*KB)
- }
- },
- {
- .mfr = CFI_MFR_AMD,
- .id = 0x225b, /* S29AL008D */
- .pri_id = 0x02,
- .dev_size = 1*MB,
- .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
- .max_buf_write_size = 0x0,
- .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
- .num_erase_regions = 4,
- .erase_region_info = {
- ERASE_REGION(1, 16*KB),
- ERASE_REGION(2, 8*KB),
- ERASE_REGION(1, 32*KB),
- ERASE_REGION(15, 64*KB)
- }
- },
- {
- .mfr = 0,
- .id = 0,
- }
-};
-
-void cfi_fixup_non_cfi(struct flash_bank *bank)
-{
- unsigned int mask;
- struct cfi_flash_bank *cfi_info = bank->driver_priv;
- const struct non_cfi *non_cfi = non_cfi_flashes;
-
- if (cfi_info->x16_as_x8)
- mask = 0xFF;
- else
- mask = 0xFFFF;
-
- for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++) {
- if ((cfi_info->manufacturer == non_cfi->mfr)
- && (cfi_info->device_id == (non_cfi->id & mask)))
- break;
- }
-
- /* only fixup jedec flashs found in table */
- if (!non_cfi->mfr)
- return;
-
- cfi_info->not_cfi = 1;
-
- /* fill in defaults for non-critical data */
- cfi_info->vcc_min = 0x0;
- cfi_info->vcc_max = 0x0;
- cfi_info->vpp_min = 0x0;
- cfi_info->vpp_max = 0x0;
- /* these are used for timeouts - use vales that should be long enough
- for normal operation. */
- cfi_info->word_write_timeout_typ = 0x0a;
- cfi_info->buf_write_timeout_typ = 0x0d;
- cfi_info->block_erase_timeout_typ = 0x0d;
- cfi_info->chip_erase_timeout_typ = 0x10;
- cfi_info->word_write_timeout_max = 0x0;
- cfi_info->buf_write_timeout_max = 0x0;
- cfi_info->block_erase_timeout_max = 0x0;
- cfi_info->chip_erase_timeout_max = 0x0;
-
- cfi_info->qry[0] = 'Q';
- cfi_info->qry[1] = 'R';
- cfi_info->qry[2] = 'Y';
-
- cfi_info->pri_id = non_cfi->pri_id;
- cfi_info->pri_addr = 0x0;
- cfi_info->alt_id = 0x0;
- cfi_info->alt_addr = 0x0;
- cfi_info->alt_ext = NULL;
-
- cfi_info->interface_desc = non_cfi->interface_desc;
- cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
- cfi_info->status_poll_mask = non_cfi->status_poll_mask;
- cfi_info->num_erase_regions = non_cfi->num_erase_regions;
- size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) *
- cfi_info->num_erase_regions;
- cfi_info->erase_region_info = malloc(erase_region_info_size);
- memcpy(cfi_info->erase_region_info,
- non_cfi->erase_region_info, erase_region_info_size);
- cfi_info->dev_size = non_cfi->dev_size;
-
- if (cfi_info->pri_id == 0x2) {
- struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
-
- pri_ext->pri[0] = 'P';
- pri_ext->pri[1] = 'R';
- pri_ext->pri[2] = 'I';
-
- pri_ext->major_version = '1';
- pri_ext->minor_version = '0';
-
- pri_ext->SiliconRevision = 0x0;
- pri_ext->EraseSuspend = 0x0;
- pri_ext->BlkProt = 0x0;
- pri_ext->TmpBlkUnprotect = 0x0;
- pri_ext->BlkProtUnprot = 0x0;
- pri_ext->SimultaneousOps = 0x0;
- pri_ext->BurstMode = 0x0;
- pri_ext->PageMode = 0x0;
- pri_ext->VppMin = 0x0;
- pri_ext->VppMax = 0x0;
- pri_ext->TopBottom = 0x0;
-
- pri_ext->_unlock1 = 0x5555;
- pri_ext->_unlock2 = 0x2AAA;
- pri_ext->_reversed_geometry = 0;
-
- cfi_info->pri_ext = pri_ext;
- } else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3)) {
- LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
- exit(-1);
- }
-}
diff --git a/src/flash/nor/non_cfi.h b/src/flash/nor/non_cfi.h
deleted file mode 100644
index c411cb8..0000000
--- a/src/flash/nor/non_cfi.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NOR_NON_CFI_H
-#define OPENOCD_FLASH_NOR_NON_CFI_H
-
-struct non_cfi {
- uint16_t mfr;
- uint16_t id;
- uint16_t pri_id;
- uint32_t dev_size;
- uint16_t interface_desc;
- uint16_t max_buf_write_size;
- uint8_t num_erase_regions;
- uint32_t erase_region_info[6];
- uint8_t status_poll_mask;
-};
-
-void cfi_fixup_non_cfi(struct flash_bank *bank);
-
-#endif /* OPENOCD_FLASH_NOR_NON_CFI_H */
diff --git a/src/flash/nor/nrf51.c b/src/flash/nor/nrf51.c
deleted file mode 100644
index 69bf666..0000000
--- a/src/flash/nor/nrf51.c
+++ /dev/null
@@ -1,1334 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Synapse Product Development *
- * Andrey Smirnov <andrew.smironv@gmail.com> *
- * Angus Gratton <gus@projectgus.com> *
- * Erdem U. Altunyurt <spamjunkeater@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-#include <helper/types.h>
-
-enum {
- NRF51_FLASH_BASE = 0x00000000,
-};
-
-enum nrf51_ficr_registers {
- NRF51_FICR_BASE = 0x10000000, /* Factory Information Configuration Registers */
-
-#define NRF51_FICR_REG(offset) (NRF51_FICR_BASE + offset)
-
- NRF51_FICR_CODEPAGESIZE = NRF51_FICR_REG(0x010),
- NRF51_FICR_CODESIZE = NRF51_FICR_REG(0x014),
- NRF51_FICR_CLENR0 = NRF51_FICR_REG(0x028),
- NRF51_FICR_PPFC = NRF51_FICR_REG(0x02C),
- NRF51_FICR_NUMRAMBLOCK = NRF51_FICR_REG(0x034),
- NRF51_FICR_SIZERAMBLOCK0 = NRF51_FICR_REG(0x038),
- NRF51_FICR_SIZERAMBLOCK1 = NRF51_FICR_REG(0x03C),
- NRF51_FICR_SIZERAMBLOCK2 = NRF51_FICR_REG(0x040),
- NRF51_FICR_SIZERAMBLOCK3 = NRF51_FICR_REG(0x044),
- NRF51_FICR_CONFIGID = NRF51_FICR_REG(0x05C),
- NRF51_FICR_DEVICEID0 = NRF51_FICR_REG(0x060),
- NRF51_FICR_DEVICEID1 = NRF51_FICR_REG(0x064),
- NRF51_FICR_ER0 = NRF51_FICR_REG(0x080),
- NRF51_FICR_ER1 = NRF51_FICR_REG(0x084),
- NRF51_FICR_ER2 = NRF51_FICR_REG(0x088),
- NRF51_FICR_ER3 = NRF51_FICR_REG(0x08C),
- NRF51_FICR_IR0 = NRF51_FICR_REG(0x090),
- NRF51_FICR_IR1 = NRF51_FICR_REG(0x094),
- NRF51_FICR_IR2 = NRF51_FICR_REG(0x098),
- NRF51_FICR_IR3 = NRF51_FICR_REG(0x09C),
- NRF51_FICR_DEVICEADDRTYPE = NRF51_FICR_REG(0x0A0),
- NRF51_FICR_DEVICEADDR0 = NRF51_FICR_REG(0x0A4),
- NRF51_FICR_DEVICEADDR1 = NRF51_FICR_REG(0x0A8),
- NRF51_FICR_OVERRIDEN = NRF51_FICR_REG(0x0AC),
- NRF51_FICR_NRF_1MBIT0 = NRF51_FICR_REG(0x0B0),
- NRF51_FICR_NRF_1MBIT1 = NRF51_FICR_REG(0x0B4),
- NRF51_FICR_NRF_1MBIT2 = NRF51_FICR_REG(0x0B8),
- NRF51_FICR_NRF_1MBIT3 = NRF51_FICR_REG(0x0BC),
- NRF51_FICR_NRF_1MBIT4 = NRF51_FICR_REG(0x0C0),
- NRF51_FICR_BLE_1MBIT0 = NRF51_FICR_REG(0x0EC),
- NRF51_FICR_BLE_1MBIT1 = NRF51_FICR_REG(0x0F0),
- NRF51_FICR_BLE_1MBIT2 = NRF51_FICR_REG(0x0F4),
- NRF51_FICR_BLE_1MBIT3 = NRF51_FICR_REG(0x0F8),
- NRF51_FICR_BLE_1MBIT4 = NRF51_FICR_REG(0x0FC),
-};
-
-enum nrf51_uicr_registers {
- NRF51_UICR_BASE = 0x10001000, /* User Information
- * Configuration Regsters */
-
- NRF51_UICR_SIZE = 0x100,
-
-#define NRF51_UICR_REG(offset) (NRF51_UICR_BASE + offset)
-
- NRF51_UICR_CLENR0 = NRF51_UICR_REG(0x000),
- NRF51_UICR_RBPCONF = NRF51_UICR_REG(0x004),
- NRF51_UICR_XTALFREQ = NRF51_UICR_REG(0x008),
- NRF51_UICR_FWID = NRF51_UICR_REG(0x010),
-};
-
-enum nrf51_nvmc_registers {
- NRF51_NVMC_BASE = 0x4001E000, /* Non-Volatile Memory
- * Controller Regsters */
-
-#define NRF51_NVMC_REG(offset) (NRF51_NVMC_BASE + offset)
-
- NRF51_NVMC_READY = NRF51_NVMC_REG(0x400),
- NRF51_NVMC_CONFIG = NRF51_NVMC_REG(0x504),
- NRF51_NVMC_ERASEPAGE = NRF51_NVMC_REG(0x508),
- NRF51_NVMC_ERASEALL = NRF51_NVMC_REG(0x50C),
- NRF51_NVMC_ERASEUICR = NRF51_NVMC_REG(0x514),
-};
-
-enum nrf51_nvmc_config_bits {
- NRF51_NVMC_CONFIG_REN = 0x00,
- NRF51_NVMC_CONFIG_WEN = 0x01,
- NRF51_NVMC_CONFIG_EEN = 0x02,
-
-};
-
-struct nrf51_info {
- uint32_t code_page_size;
- uint32_t code_memory_size;
-
- struct {
- bool probed;
- int (*write) (struct flash_bank *bank,
- struct nrf51_info *chip,
- const uint8_t *buffer, uint32_t offset, uint32_t count);
- } bank[2];
- struct target *target;
-};
-
-struct nrf51_device_spec {
- uint16_t hwid;
- const char *variant;
- const char *build_code;
- unsigned int flash_size_kb;
-};
-
-/* The known devices table below is derived from the "nRF51 Series
- * Compatibility Matrix" document, which can be found by searching for
- * ATTN-51 on the Nordic Semi website:
- *
- * http://www.nordicsemi.com/eng/content/search?SearchText=ATTN-51
- *
- * Up to date with Matrix v2.0, plus some additional HWIDs.
- *
- * The additional HWIDs apply where the build code in the matrix is
- * shown as Gx0, Bx0, etc. In these cases the HWID in the matrix is
- * for x==0, x!=0 means different (unspecified) HWIDs.
- */
-static const struct nrf51_device_spec nrf51_known_devices_table[] = {
- /* nRF51822 Devices (IC rev 1). */
- {
- .hwid = 0x001D,
- .variant = "QFAA",
- .build_code = "CA/C0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0026,
- .variant = "QFAB",
- .build_code = "AA",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x0027,
- .variant = "QFAB",
- .build_code = "A0",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x0020,
- .variant = "CEAA",
- .build_code = "BA",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x002F,
- .variant = "CEAA",
- .build_code = "B0",
- .flash_size_kb = 256,
- },
-
- /* nRF51822 Devices (IC rev 2). */
- {
- .hwid = 0x002A,
- .variant = "QFAA",
- .build_code = "FA0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0044,
- .variant = "QFAA",
- .build_code = "GC0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x003C,
- .variant = "QFAA",
- .build_code = "G0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0057,
- .variant = "QFAA",
- .build_code = "G2",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0058,
- .variant = "QFAA",
- .build_code = "G3",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x004C,
- .variant = "QFAB",
- .build_code = "B0",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x0040,
- .variant = "CEAA",
- .build_code = "CA0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0047,
- .variant = "CEAA",
- .build_code = "DA0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x004D,
- .variant = "CEAA",
- .build_code = "D00",
- .flash_size_kb = 256,
- },
-
- /* nRF51822 Devices (IC rev 3). */
- {
- .hwid = 0x0072,
- .variant = "QFAA",
- .build_code = "H0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x007B,
- .variant = "QFAB",
- .build_code = "C0",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x0083,
- .variant = "QFAC",
- .build_code = "A0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0084,
- .variant = "QFAC",
- .build_code = "A1",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x007D,
- .variant = "CDAB",
- .build_code = "A0",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x0079,
- .variant = "CEAA",
- .build_code = "E0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0087,
- .variant = "CFAC",
- .build_code = "A0",
- .flash_size_kb = 256,
- },
-
- /* nRF51422 Devices (IC rev 1). */
- {
- .hwid = 0x001E,
- .variant = "QFAA",
- .build_code = "CA",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0024,
- .variant = "QFAA",
- .build_code = "C0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0031,
- .variant = "CEAA",
- .build_code = "A0A",
- .flash_size_kb = 256,
- },
-
- /* nRF51422 Devices (IC rev 2). */
- {
- .hwid = 0x002D,
- .variant = "QFAA",
- .build_code = "DAA",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x002E,
- .variant = "QFAA",
- .build_code = "E0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0061,
- .variant = "QFAB",
- .build_code = "A00",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x0050,
- .variant = "CEAA",
- .build_code = "B0",
- .flash_size_kb = 256,
- },
-
- /* nRF51422 Devices (IC rev 3). */
- {
- .hwid = 0x0073,
- .variant = "QFAA",
- .build_code = "F0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x007C,
- .variant = "QFAB",
- .build_code = "B0",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x0085,
- .variant = "QFAC",
- .build_code = "A0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0086,
- .variant = "QFAC",
- .build_code = "A1",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x007E,
- .variant = "CDAB",
- .build_code = "A0",
- .flash_size_kb = 128,
- },
- {
- .hwid = 0x007A,
- .variant = "CEAA",
- .build_code = "C0",
- .flash_size_kb = 256,
- },
- {
- .hwid = 0x0088,
- .variant = "CFAC",
- .build_code = "A0",
- .flash_size_kb = 256,
- },
-
- /* Some early nRF51-DK (PCA10028) & nRF51-Dongle (PCA10031) boards
- with built-in jlink seem to use engineering samples not listed
- in the nRF51 Series Compatibility Matrix V1.0. */
- {
- .hwid = 0x0071,
- .variant = "QFAC",
- .build_code = "AB",
- .flash_size_kb = 256,
- },
-};
-
-static int nrf51_bank_is_probed(struct flash_bank *bank)
-{
- struct nrf51_info *chip = bank->driver_priv;
-
- assert(chip != NULL);
-
- return chip->bank[bank->bank_number].probed;
-}
-static int nrf51_probe(struct flash_bank *bank);
-
-static int nrf51_get_probed_chip_if_halted(struct flash_bank *bank, struct nrf51_info **chip)
-{
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- *chip = bank->driver_priv;
-
- int probed = nrf51_bank_is_probed(bank);
- if (probed < 0)
- return probed;
- else if (!probed)
- return nrf51_probe(bank);
- else
- return ERROR_OK;
-}
-
-static int nrf51_wait_for_nvmc(struct nrf51_info *chip)
-{
- uint32_t ready;
- int res;
- int timeout = 100;
-
- do {
- res = target_read_u32(chip->target, NRF51_NVMC_READY, &ready);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read NVMC_READY register");
- return res;
- }
-
- if (ready == 0x00000001)
- return ERROR_OK;
-
- alive_sleep(1);
- } while (timeout--);
-
- LOG_DEBUG("Timed out waiting for NVMC_READY");
- return ERROR_FLASH_BUSY;
-}
-
-static int nrf51_nvmc_erase_enable(struct nrf51_info *chip)
-{
- int res;
- res = target_write_u32(chip->target,
- NRF51_NVMC_CONFIG,
- NRF51_NVMC_CONFIG_EEN);
-
- if (res != ERROR_OK) {
- LOG_ERROR("Failed to enable erase operation");
- return res;
- }
-
- /*
- According to NVMC examples in Nordic SDK busy status must be
- checked after writing to NVMC_CONFIG
- */
- res = nrf51_wait_for_nvmc(chip);
- if (res != ERROR_OK)
- LOG_ERROR("Erase enable did not complete");
-
- return res;
-}
-
-static int nrf51_nvmc_write_enable(struct nrf51_info *chip)
-{
- int res;
- res = target_write_u32(chip->target,
- NRF51_NVMC_CONFIG,
- NRF51_NVMC_CONFIG_WEN);
-
- if (res != ERROR_OK) {
- LOG_ERROR("Failed to enable write operation");
- return res;
- }
-
- /*
- According to NVMC examples in Nordic SDK busy status must be
- checked after writing to NVMC_CONFIG
- */
- res = nrf51_wait_for_nvmc(chip);
- if (res != ERROR_OK)
- LOG_ERROR("Write enable did not complete");
-
- return res;
-}
-
-static int nrf51_nvmc_read_only(struct nrf51_info *chip)
-{
- int res;
- res = target_write_u32(chip->target,
- NRF51_NVMC_CONFIG,
- NRF51_NVMC_CONFIG_REN);
-
- if (res != ERROR_OK) {
- LOG_ERROR("Failed to enable read-only operation");
- return res;
- }
- /*
- According to NVMC examples in Nordic SDK busy status must be
- checked after writing to NVMC_CONFIG
- */
- res = nrf51_wait_for_nvmc(chip);
- if (res != ERROR_OK)
- LOG_ERROR("Read only enable did not complete");
-
- return res;
-}
-
-static int nrf51_nvmc_generic_erase(struct nrf51_info *chip,
- uint32_t erase_register, uint32_t erase_value)
-{
- int res;
-
- res = nrf51_nvmc_erase_enable(chip);
- if (res != ERROR_OK)
- goto error;
-
- res = target_write_u32(chip->target,
- erase_register,
- erase_value);
- if (res != ERROR_OK)
- goto set_read_only;
-
- res = nrf51_wait_for_nvmc(chip);
- if (res != ERROR_OK)
- goto set_read_only;
-
- return nrf51_nvmc_read_only(chip);
-
-set_read_only:
- nrf51_nvmc_read_only(chip);
-error:
- LOG_ERROR("Failed to erase reg: 0x%08"PRIx32" val: 0x%08"PRIx32,
- erase_register, erase_value);
- return ERROR_FAIL;
-}
-
-static int nrf51_protect_check(struct flash_bank *bank)
-{
- int res;
- uint32_t clenr0;
-
- /* UICR cannot be write protected so just return early */
- if (bank->base == NRF51_UICR_BASE)
- return ERROR_OK;
-
- struct nrf51_info *chip = bank->driver_priv;
-
- assert(chip != NULL);
-
- res = target_read_u32(chip->target, NRF51_FICR_CLENR0,
- &clenr0);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read code region 0 size[FICR]");
- return res;
- }
-
- if (clenr0 == 0xFFFFFFFF) {
- res = target_read_u32(chip->target, NRF51_UICR_CLENR0,
- &clenr0);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read code region 0 size[UICR]");
- return res;
- }
- }
-
- for (int i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_protected =
- clenr0 != 0xFFFFFFFF && bank->sectors[i].offset < clenr0;
-
- return ERROR_OK;
-}
-
-static int nrf51_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int res;
- uint32_t clenr0, ppfc;
- struct nrf51_info *chip;
-
- /* UICR cannot be write protected so just bail out early */
- if (bank->base == NRF51_UICR_BASE)
- return ERROR_FAIL;
-
- res = nrf51_get_probed_chip_if_halted(bank, &chip);
- if (res != ERROR_OK)
- return res;
-
- if (first != 0) {
- LOG_ERROR("Code region 0 must start at the begining of the bank");
- return ERROR_FAIL;
- }
-
- res = target_read_u32(chip->target, NRF51_FICR_PPFC,
- &ppfc);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read PPFC register");
- return res;
- }
-
- if ((ppfc & 0xFF) == 0x00) {
- LOG_ERROR("Code region 0 size was pre-programmed at the factory, can't change flash protection settings");
- return ERROR_FAIL;
- }
-
- res = target_read_u32(chip->target, NRF51_UICR_CLENR0,
- &clenr0);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read code region 0 size[UICR]");
- return res;
- }
-
- if (clenr0 == 0xFFFFFFFF) {
- res = target_write_u32(chip->target, NRF51_UICR_CLENR0,
- clenr0);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't write code region 0 size[UICR]");
- return res;
- }
-
- } else {
- LOG_ERROR("You need to perform chip erase before changing the protection settings");
- }
-
- nrf51_protect_check(bank);
-
- return ERROR_OK;
-}
-
-static int nrf51_probe(struct flash_bank *bank)
-{
- uint32_t hwid;
- int res;
- struct nrf51_info *chip = bank->driver_priv;
-
- res = target_read_u32(chip->target, NRF51_FICR_CONFIGID, &hwid);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read CONFIGID register");
- return res;
- }
-
- hwid &= 0xFFFF; /* HWID is stored in the lower two
- * bytes of the CONFIGID register */
-
- const struct nrf51_device_spec *spec = NULL;
- for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++)
- if (hwid == nrf51_known_devices_table[i].hwid) {
- spec = &nrf51_known_devices_table[i];
- break;
- }
-
- if (!chip->bank[0].probed && !chip->bank[1].probed) {
- if (spec)
- LOG_INFO("nRF51822-%s(build code: %s) %ukB Flash",
- spec->variant, spec->build_code, spec->flash_size_kb);
- else
- LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid);
- }
-
-
- if (bank->base == NRF51_FLASH_BASE) {
- res = target_read_u32(chip->target, NRF51_FICR_CODEPAGESIZE,
- &chip->code_page_size);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read code page size");
- return res;
- }
-
- res = target_read_u32(chip->target, NRF51_FICR_CODESIZE,
- &chip->code_memory_size);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read code memory size");
- return res;
- }
-
- if (spec && chip->code_memory_size != spec->flash_size_kb) {
- LOG_ERROR("Chip's reported Flash capacity does not match expected one");
- return ERROR_FAIL;
- }
-
- bank->size = chip->code_memory_size * 1024;
- bank->num_sectors = bank->size / chip->code_page_size;
- bank->sectors = calloc(bank->num_sectors,
- sizeof((bank->sectors)[0]));
- if (!bank->sectors)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- /* Fill out the sector information: all NRF51 sectors are the same size and
- * there is always a fixed number of them. */
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].size = chip->code_page_size;
- bank->sectors[i].offset = i * chip->code_page_size;
-
- /* mark as unknown */
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- nrf51_protect_check(bank);
-
- chip->bank[0].probed = true;
- } else {
- bank->size = NRF51_UICR_SIZE;
- bank->num_sectors = 1;
- bank->sectors = calloc(bank->num_sectors,
- sizeof((bank->sectors)[0]));
- if (!bank->sectors)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- bank->sectors[0].size = bank->size;
- bank->sectors[0].offset = 0;
-
- /* mark as unknown */
- bank->sectors[0].is_erased = 0;
- bank->sectors[0].is_protected = 0;
-
- chip->bank[1].probed = true;
- }
-
- return ERROR_OK;
-}
-
-static int nrf51_auto_probe(struct flash_bank *bank)
-{
- int probed = nrf51_bank_is_probed(bank);
-
- if (probed < 0)
- return probed;
- else if (probed)
- return ERROR_OK;
- else
- return nrf51_probe(bank);
-}
-
-static struct flash_sector *nrf51_find_sector_by_address(struct flash_bank *bank, uint32_t address)
-{
- struct nrf51_info *chip = bank->driver_priv;
-
- for (int i = 0; i < bank->num_sectors; i++)
- if (bank->sectors[i].offset <= address &&
- address < (bank->sectors[i].offset + chip->code_page_size))
- return &bank->sectors[i];
- return NULL;
-}
-
-static int nrf51_erase_all(struct nrf51_info *chip)
-{
- LOG_DEBUG("Erasing all non-volatile memory");
- return nrf51_nvmc_generic_erase(chip,
- NRF51_NVMC_ERASEALL,
- 0x00000001);
-}
-
-static int nrf51_erase_page(struct flash_bank *bank,
- struct nrf51_info *chip,
- struct flash_sector *sector)
-{
- int res;
-
- LOG_DEBUG("Erasing page at 0x%"PRIx32, sector->offset);
- if (sector->is_protected) {
- LOG_ERROR("Cannot erase protected sector at 0x%" PRIx32, sector->offset);
- return ERROR_FAIL;
- }
-
- if (bank->base == NRF51_UICR_BASE) {
- uint32_t ppfc;
- res = target_read_u32(chip->target, NRF51_FICR_PPFC,
- &ppfc);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read PPFC register");
- return res;
- }
-
- if ((ppfc & 0xFF) == 0xFF) {
- /* We can't erase the UICR. Double-check to
- see if it's already erased before complaining. */
- default_flash_blank_check(bank);
- if (sector->is_erased == 1)
- return ERROR_OK;
-
- LOG_ERROR("The chip was not pre-programmed with SoftDevice stack and UICR cannot be erased separately. Please issue mass erase before trying to write to this region");
- return ERROR_FAIL;
- }
-
- res = nrf51_nvmc_generic_erase(chip,
- NRF51_NVMC_ERASEUICR,
- 0x00000001);
-
-
- } else {
- res = nrf51_nvmc_generic_erase(chip,
- NRF51_NVMC_ERASEPAGE,
- sector->offset);
- }
-
- if (res == ERROR_OK)
- sector->is_erased = 1;
-
- return res;
-}
-
-static const uint8_t nrf51_flash_write_code[] = {
- /* See contrib/loaders/flash/cortex-m0.S */
-/* <wait_fifo>: */
- 0x0d, 0x68, /* ldr r5, [r1, #0] */
- 0x00, 0x2d, /* cmp r5, #0 */
- 0x0b, 0xd0, /* beq.n 1e <exit> */
- 0x4c, 0x68, /* ldr r4, [r1, #4] */
- 0xac, 0x42, /* cmp r4, r5 */
- 0xf9, 0xd0, /* beq.n 0 <wait_fifo> */
- 0x20, 0xcc, /* ldmia r4!, {r5} */
- 0x20, 0xc3, /* stmia r3!, {r5} */
- 0x94, 0x42, /* cmp r4, r2 */
- 0x01, 0xd3, /* bcc.n 18 <no_wrap> */
- 0x0c, 0x46, /* mov r4, r1 */
- 0x08, 0x34, /* adds r4, #8 */
-/* <no_wrap>: */
- 0x4c, 0x60, /* str r4, [r1, #4] */
- 0x04, 0x38, /* subs r0, #4 */
- 0xf0, 0xd1, /* bne.n 0 <wait_fifo> */
-/* <exit>: */
- 0x00, 0xbe /* bkpt 0x0000 */
-};
-
-
-/* Start a low level flash write for the specified region */
-static int nrf51_ll_flash_write(struct nrf51_info *chip, uint32_t offset, const uint8_t *buffer, uint32_t bytes)
-{
- struct target *target = chip->target;
- uint32_t buffer_size = 8192;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = NRF51_FLASH_BASE + offset;
- struct reg_param reg_params[4];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
-
- LOG_DEBUG("Writing buffer to flash offset=0x%"PRIx32" bytes=0x%"PRIx32, offset, bytes);
- assert(bytes % 4 == 0);
-
- /* allocate working area with flash programming code */
- if (target_alloc_working_area(target, sizeof(nrf51_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, falling back to slow memory writes");
-
- for (; bytes > 0; bytes -= 4) {
- retval = target_write_memory(chip->target, offset, 4, 1, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- retval = nrf51_wait_for_nvmc(chip);
- if (retval != ERROR_OK)
- return retval;
-
- offset += 4;
- buffer += 4;
- }
-
- return ERROR_OK;
- }
-
- LOG_WARNING("using fast async flash loader. This is currently supported");
- LOG_WARNING("only with ST-Link and CMSIS-DAP. If you have issues, add");
- LOG_WARNING("\"set WORKAREASIZE 0\" before sourcing nrf51.cfg to disable it");
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(nrf51_flash_write_code),
- nrf51_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
- if (buffer_size <= 256) {
- /* free working area, write algorithm already allocated */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("No large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* byte count */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* buffer start */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer end */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_OUT); /* target address */
-
- buf_set_u32(reg_params[0].value, 0, 32, bytes);
- buf_set_u32(reg_params[1].value, 0, 32, source->address);
- buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size);
- buf_set_u32(reg_params[3].value, 0, 32, address);
-
- retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4,
- 0, NULL,
- 4, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- 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 retval;
-}
-
-/* Check and erase flash sectors in specified range then start a low level page write.
- start/end must be sector aligned.
-*/
-static int nrf51_write_pages(struct flash_bank *bank, uint32_t start, uint32_t end, const uint8_t *buffer)
-{
- int res = ERROR_FAIL;
- struct nrf51_info *chip = bank->driver_priv;
- struct flash_sector *sector;
- uint32_t offset;
-
- assert(start % chip->code_page_size == 0);
- assert(end % chip->code_page_size == 0);
-
- /* Erase all sectors */
- for (offset = start; offset < end; offset += chip->code_page_size) {
- sector = nrf51_find_sector_by_address(bank, offset);
- if (!sector) {
- LOG_ERROR("Invalid sector @ 0x%08"PRIx32, offset);
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- if (sector->is_protected) {
- LOG_ERROR("Can't erase protected sector @ 0x%08"PRIx32, offset);
- goto error;
- }
-
- if (sector->is_erased != 1) { /* 1 = erased, 0= not erased, -1 = unknown */
- res = nrf51_erase_page(bank, chip, sector);
- if (res != ERROR_OK) {
- LOG_ERROR("Failed to erase sector @ 0x%08"PRIx32, sector->offset);
- goto error;
- }
- }
- sector->is_erased = 0;
- }
-
- res = nrf51_nvmc_write_enable(chip);
- if (res != ERROR_OK)
- goto error;
-
- res = nrf51_ll_flash_write(chip, start, buffer, (end - start));
- if (res != ERROR_OK)
- goto set_read_only;
-
- return nrf51_nvmc_read_only(chip);
-
-set_read_only:
- nrf51_nvmc_read_only(chip);
-error:
- LOG_ERROR("Failed to write to nrf51 flash");
- return res;
-}
-
-static int nrf51_erase(struct flash_bank *bank, int first, int last)
-{
- int res;
- struct nrf51_info *chip;
-
- res = nrf51_get_probed_chip_if_halted(bank, &chip);
- if (res != ERROR_OK)
- return res;
-
- /* For each sector to be erased */
- for (int s = first; s <= last && res == ERROR_OK; s++)
- res = nrf51_erase_page(bank, chip, &bank->sectors[s]);
-
- return res;
-}
-
-static int nrf51_code_flash_write(struct flash_bank *bank,
- struct nrf51_info *chip,
- const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
-
- int res;
- /* Need to perform reads to fill any gaps we need to preserve in the first page,
- before the start of buffer, or in the last page, after the end of buffer */
- uint32_t first_page = offset/chip->code_page_size;
- uint32_t last_page = DIV_ROUND_UP(offset+count, chip->code_page_size);
-
- uint32_t first_page_offset = first_page * chip->code_page_size;
- uint32_t last_page_offset = last_page * chip->code_page_size;
-
- LOG_DEBUG("Padding write from 0x%08"PRIx32"-0x%08"PRIx32" as 0x%08"PRIx32"-0x%08"PRIx32,
- offset, offset+count, first_page_offset, last_page_offset);
-
- uint32_t page_cnt = last_page - first_page;
- uint8_t buffer_to_flash[page_cnt*chip->code_page_size];
-
- /* Fill in any space between start of first page and start of buffer */
- uint32_t pre = offset - first_page_offset;
- if (pre > 0) {
- res = target_read_memory(bank->target,
- first_page_offset,
- 1,
- pre,
- buffer_to_flash);
- if (res != ERROR_OK)
- return res;
- }
-
- /* Fill in main contents of buffer */
- memcpy(buffer_to_flash+pre, buffer, count);
-
- /* Fill in any space between end of buffer and end of last page */
- uint32_t post = last_page_offset - (offset+count);
- if (post > 0) {
- /* Retrieve the full row contents from Flash */
- res = target_read_memory(bank->target,
- offset + count,
- 1,
- post,
- buffer_to_flash+pre+count);
- if (res != ERROR_OK)
- return res;
- }
-
- return nrf51_write_pages(bank, first_page_offset, last_page_offset, buffer_to_flash);
-}
-
-static int nrf51_uicr_flash_write(struct flash_bank *bank,
- struct nrf51_info *chip,
- const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- int res;
- uint8_t uicr[NRF51_UICR_SIZE];
- struct flash_sector *sector = &bank->sectors[0];
-
- if ((offset + count) > NRF51_UICR_SIZE)
- return ERROR_FAIL;
-
- res = target_read_memory(bank->target,
- NRF51_UICR_BASE,
- 1,
- NRF51_UICR_SIZE,
- uicr);
-
- if (res != ERROR_OK)
- return res;
-
- if (sector->is_erased != 1) {
- res = nrf51_erase_page(bank, chip, sector);
- if (res != ERROR_OK)
- return res;
- }
-
- res = nrf51_nvmc_write_enable(chip);
- if (res != ERROR_OK)
- return res;
-
- memcpy(&uicr[offset], buffer, count);
-
- res = nrf51_ll_flash_write(chip, NRF51_UICR_BASE, uicr, NRF51_UICR_SIZE);
- if (res != ERROR_OK) {
- nrf51_nvmc_read_only(chip);
- return res;
- }
-
- return nrf51_nvmc_read_only(chip);
-}
-
-
-static int nrf51_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- int res;
- struct nrf51_info *chip;
-
- res = nrf51_get_probed_chip_if_halted(bank, &chip);
- if (res != ERROR_OK)
- return res;
-
- return chip->bank[bank->bank_number].write(bank, chip, buffer, offset, count);
-}
-
-
-FLASH_BANK_COMMAND_HANDLER(nrf51_flash_bank_command)
-{
- static struct nrf51_info *chip;
-
- switch (bank->base) {
- case NRF51_FLASH_BASE:
- bank->bank_number = 0;
- break;
- case NRF51_UICR_BASE:
- bank->bank_number = 1;
- break;
- default:
- LOG_ERROR("Invalid bank address 0x%08" PRIx32, bank->base);
- return ERROR_FAIL;
- }
-
- if (!chip) {
- /* Create a new chip */
- chip = calloc(1, sizeof(*chip));
- if (!chip)
- return ERROR_FAIL;
-
- chip->target = bank->target;
- }
-
- switch (bank->base) {
- case NRF51_FLASH_BASE:
- chip->bank[bank->bank_number].write = nrf51_code_flash_write;
- break;
- case NRF51_UICR_BASE:
- chip->bank[bank->bank_number].write = nrf51_uicr_flash_write;
- break;
- }
-
- chip->bank[bank->bank_number].probed = false;
- bank->driver_priv = chip;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(nrf51_handle_mass_erase_command)
-{
- int res;
- struct flash_bank *bank = NULL;
- struct target *target = get_current_target(CMD_CTX);
-
- res = get_flash_bank_by_addr(target, NRF51_FLASH_BASE, true, &bank);
- if (res != ERROR_OK)
- return res;
-
- assert(bank != NULL);
-
- struct nrf51_info *chip;
-
- res = nrf51_get_probed_chip_if_halted(bank, &chip);
- if (res != ERROR_OK)
- return res;
-
- uint32_t ppfc;
-
- res = target_read_u32(target, NRF51_FICR_PPFC,
- &ppfc);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read PPFC register");
- return res;
- }
-
- if ((ppfc & 0xFF) == 0x00) {
- LOG_ERROR("Code region 0 size was pre-programmed at the factory, "
- "mass erase command won't work.");
- return ERROR_FAIL;
- }
-
- res = nrf51_erase_all(chip);
- if (res != ERROR_OK) {
- LOG_ERROR("Failed to erase the chip");
- nrf51_protect_check(bank);
- return res;
- }
-
- for (int i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- res = nrf51_protect_check(bank);
- if (res != ERROR_OK) {
- LOG_ERROR("Failed to check chip's write protection");
- return res;
- }
-
- res = get_flash_bank_by_addr(target, NRF51_UICR_BASE, true, &bank);
- if (res != ERROR_OK)
- return res;
-
- bank->sectors[0].is_erased = 1;
-
- return ERROR_OK;
-}
-
-static int nrf51_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int res;
-
- struct nrf51_info *chip;
-
- res = nrf51_get_probed_chip_if_halted(bank, &chip);
- if (res != ERROR_OK)
- return res;
-
- static struct {
- const uint32_t address;
- uint32_t value;
- } ficr[] = {
- { .address = NRF51_FICR_CODEPAGESIZE },
- { .address = NRF51_FICR_CODESIZE },
- { .address = NRF51_FICR_CLENR0 },
- { .address = NRF51_FICR_PPFC },
- { .address = NRF51_FICR_NUMRAMBLOCK },
- { .address = NRF51_FICR_SIZERAMBLOCK0 },
- { .address = NRF51_FICR_SIZERAMBLOCK1 },
- { .address = NRF51_FICR_SIZERAMBLOCK2 },
- { .address = NRF51_FICR_SIZERAMBLOCK3 },
- { .address = NRF51_FICR_CONFIGID },
- { .address = NRF51_FICR_DEVICEID0 },
- { .address = NRF51_FICR_DEVICEID1 },
- { .address = NRF51_FICR_ER0 },
- { .address = NRF51_FICR_ER1 },
- { .address = NRF51_FICR_ER2 },
- { .address = NRF51_FICR_ER3 },
- { .address = NRF51_FICR_IR0 },
- { .address = NRF51_FICR_IR1 },
- { .address = NRF51_FICR_IR2 },
- { .address = NRF51_FICR_IR3 },
- { .address = NRF51_FICR_DEVICEADDRTYPE },
- { .address = NRF51_FICR_DEVICEADDR0 },
- { .address = NRF51_FICR_DEVICEADDR1 },
- { .address = NRF51_FICR_OVERRIDEN },
- { .address = NRF51_FICR_NRF_1MBIT0 },
- { .address = NRF51_FICR_NRF_1MBIT1 },
- { .address = NRF51_FICR_NRF_1MBIT2 },
- { .address = NRF51_FICR_NRF_1MBIT3 },
- { .address = NRF51_FICR_NRF_1MBIT4 },
- { .address = NRF51_FICR_BLE_1MBIT0 },
- { .address = NRF51_FICR_BLE_1MBIT1 },
- { .address = NRF51_FICR_BLE_1MBIT2 },
- { .address = NRF51_FICR_BLE_1MBIT3 },
- { .address = NRF51_FICR_BLE_1MBIT4 },
- }, uicr[] = {
- { .address = NRF51_UICR_CLENR0, },
- { .address = NRF51_UICR_RBPCONF },
- { .address = NRF51_UICR_XTALFREQ },
- { .address = NRF51_UICR_FWID },
- };
-
- for (size_t i = 0; i < ARRAY_SIZE(ficr); i++) {
- res = target_read_u32(chip->target, ficr[i].address,
- &ficr[i].value);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read %" PRIx32, ficr[i].address);
- return res;
- }
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(uicr); i++) {
- res = target_read_u32(chip->target, uicr[i].address,
- &uicr[i].value);
- if (res != ERROR_OK) {
- LOG_ERROR("Couldn't read %" PRIx32, uicr[i].address);
- return res;
- }
- }
-
- snprintf(buf, buf_size,
- "\n[factory information control block]\n\n"
- "code page size: %"PRIu32"B\n"
- "code memory size: %"PRIu32"kB\n"
- "code region 0 size: %"PRIu32"kB\n"
- "pre-programmed code: %s\n"
- "number of ram blocks: %"PRIu32"\n"
- "ram block 0 size: %"PRIu32"B\n"
- "ram block 1 size: %"PRIu32"B\n"
- "ram block 2 size: %"PRIu32"B\n"
- "ram block 3 size: %"PRIu32 "B\n"
- "config id: %" PRIx32 "\n"
- "device id: 0x%"PRIx32"%08"PRIx32"\n"
- "encryption root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
- "identity root: 0x%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"\n"
- "device address type: 0x%"PRIx32"\n"
- "device address: 0x%"PRIx32"%08"PRIx32"\n"
- "override enable: %"PRIx32"\n"
- "NRF_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n"
- "BLE_1MBIT values: %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32"\n"
- "\n[user information control block]\n\n"
- "code region 0 size: %"PRIu32"kB\n"
- "read back protection configuration: %"PRIx32"\n"
- "reset value for XTALFREQ: %"PRIx32"\n"
- "firmware id: 0x%04"PRIx32,
- ficr[0].value,
- ficr[1].value,
- (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024,
- ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present",
- ficr[4].value,
- ficr[5].value,
- (ficr[6].value == 0xFFFFFFFF) ? 0 : ficr[6].value,
- (ficr[7].value == 0xFFFFFFFF) ? 0 : ficr[7].value,
- (ficr[8].value == 0xFFFFFFFF) ? 0 : ficr[8].value,
- ficr[9].value,
- ficr[10].value, ficr[11].value,
- ficr[12].value, ficr[13].value, ficr[14].value, ficr[15].value,
- ficr[16].value, ficr[17].value, ficr[18].value, ficr[19].value,
- ficr[20].value,
- ficr[21].value, ficr[22].value,
- ficr[23].value,
- ficr[24].value, ficr[25].value, ficr[26].value, ficr[27].value, ficr[28].value,
- ficr[29].value, ficr[30].value, ficr[31].value, ficr[32].value, ficr[33].value,
- (uicr[0].value == 0xFFFFFFFF) ? 0 : uicr[0].value / 1024,
- uicr[1].value & 0xFFFF,
- uicr[2].value & 0xFF,
- uicr[3].value & 0xFFFF);
-
- return ERROR_OK;
-}
-
-static const struct command_registration nrf51_exec_command_handlers[] = {
- {
- .name = "mass_erase",
- .handler = nrf51_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .help = "Erase all flash contents of the chip.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration nrf51_command_handlers[] = {
- {
- .name = "nrf51",
- .mode = COMMAND_ANY,
- .help = "nrf51 flash command group",
- .usage = "",
- .chain = nrf51_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver nrf51_flash = {
- .name = "nrf51",
- .commands = nrf51_command_handlers,
- .flash_bank_command = nrf51_flash_bank_command,
- .info = nrf51_info,
- .erase = nrf51_erase,
- .protect = nrf51_protect,
- .write = nrf51_write,
- .read = default_flash_read,
- .probe = nrf51_probe,
- .auto_probe = nrf51_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = nrf51_protect_check,
-};
diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c
deleted file mode 100644
index 992baa5..0000000
--- a/src/flash/nor/numicro.c
+++ /dev/null
@@ -1,1883 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by James K. Larson *
- * jlarson@pacifier.com *
- * *
- * Copyright (C) 2013 Cosmin Gorgovan *
- * cosmin [at] linux-geek [dot] org *
- * *
- * Copyright (C) 2014 Pawel Si *
- * stawel+openocd@gmail.com *
- * *
- * Copyright (C) 2015 Nemui Trinomius *
- * nemuisan_kawausogasuki@live.jp *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-#include <target/cortex_m.h>
-
-/* Nuvoton NuMicro register locations */
-#define NUMICRO_SYS_BASE 0x50000000
-#define NUMICRO_SYS_WRPROT 0x50000100
-#define NUMICRO_SYS_IPRSTC1 0x50000008
-
-#define NUMICRO_SYSCLK_BASE 0x50000200
-#define NUMICRO_SYSCLK_PWRCON 0x50000200
-#define NUMICRO_SYSCLK_CLKSEL0 0x50000210
-#define NUMICRO_SYSCLK_CLKDIV 0x50000218
-#define NUMICRO_SYSCLK_AHBCLK 0x50000204
-
-#define NUMICRO_FLASH_BASE 0x5000C000
-#define NUMICRO_FLASH_ISPCON 0x5000C000
-#define NUMICRO_FLASH_ISPADR 0x5000C004
-#define NUMICRO_FLASH_ISPDAT 0x5000C008
-#define NUMICRO_FLASH_ISPCMD 0x5000C00C
-#define NUMICRO_FLASH_ISPTRG 0x5000C010
-#define NUMICRO_FLASH_CHEAT 0x5000C01C /* Undocumented isp register(may be cheat register) */
-
-#define NUMICRO_SCS_BASE 0xE000E000
-#define NUMICRO_SCS_AIRCR 0xE000ED0C
-#define NUMICRO_SCS_DHCSR 0xE000EDF0
-#define NUMICRO_SCS_DEMCR 0xE000EDFC
-
-#define NUMICRO_APROM_BASE 0x00000000
-#define NUMICRO_DATA_BASE 0x0001F000
-#define NUMICRO_LDROM_BASE 0x00100000
-#define NUMICRO_CONFIG_BASE 0x00300000
-
-#define NUMICRO_CONFIG0 0x5000C000
-#define NUMICRO_CONFIG1 0x5000C004
-
-/* Command register bits */
-#define PWRCON_OSC22M (1 << 2)
-#define PWRCON_XTL12M (1 << 0)
-
-#define IPRSTC1_CPU_RST (1 << 1)
-#define IPRSTC1_CHIP_RST (1 << 0)
-
-#define AHBCLK_ISP_EN (1 << 2)
-#define AHBCLK_SRAM_EN (1 << 4)
-#define AHBCLK_TICK_EN (1 << 5)
-
-#define ISPCON_ISPEN (1 << 0)
-#define ISPCON_BS_AP (0 << 1)
-#define ISPCON_BS_LP (1 << 1)
-#define ISPCON_BS_MASK (1 << 1)
-#define ISPCON_APUEN (1 << 3)
-#define ISPCON_CFGUEN (1 << 4)
-#define ISPCON_LDUEN (1 << 5)
-#define ISPCON_ISPFF (1 << 6)
-
-#define CONFIG0_LOCK_MASK (1 << 1)
-
-/* isp commands */
-#define ISPCMD_READ 0x00
-#define ISPCMD_WRITE 0x21
-#define ISPCMD_ERASE 0x22
-#define ISPCMD_CHIPERASE 0x26 /* Undocumented isp "Chip-Erase" command */
-#define ISPCMD_READ_CID 0x0B
-#define ISPCMD_READ_DID 0x0C
-#define ISPCMD_READ_UID 0x04
-#define ISPCMD_VECMAP 0x2E
-#define ISPTRG_ISPGO (1 << 0)
-
-/* access unlock keys */
-#define REG_KEY1 0x59
-#define REG_KEY2 0x16
-#define REG_KEY3 0x88
-#define REG_LOCK 0x00
-
-/* flash pagesizes */
-#define NUMICRO_PAGESIZE 512
-/* flash MAX banks */
-#define NUMICRO_MAX_FLASH_BANKS 4
-
-/* flash bank structs */
-struct numicro_flash_bank_type {
- uint32_t base;
- uint32_t size;
-};
-
-/* part structs */
-struct numicro_cpu_type {
- char *partname;
- uint32_t partid;
- unsigned int n_banks;
- struct numicro_flash_bank_type bank[NUMICRO_MAX_FLASH_BANKS];
-};
-
-/* TODO : Support variable DataFlash region for 128kB Flash model */
-#define NUMICRO_BANKS_NUC100(aprom_size) \
- .n_banks = 4, \
- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
- {NUMICRO_CONFIG_BASE, 1024} }
-
-#define NUMICRO_BANKS_M051(aprom_size) \
- .n_banks = 4, \
- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
- {NUMICRO_CONFIG_BASE, 1024} }
-
-#define NUMICRO_BANKS_MINI51(aprom_size) \
- .n_banks = 3, \
- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_LDROM_BASE, 2*1024}, {NUMICRO_CONFIG_BASE, 512} }
-
-#define NUMICRO_BANKS_NANO(aprom_size) \
- .n_banks = 4, \
- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
- {NUMICRO_CONFIG_BASE, 1024} }
-
-#define NUMICRO_BANKS_NUC400(aprom_size) \
- .n_banks = 4, \
- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 16*1024}, \
- {NUMICRO_CONFIG_BASE, 1024} }
-
-
-static const struct numicro_cpu_type NuMicroParts[] = {
- /*PART NO*/ /*PART ID*/ /*Banks*/
- /* NUC100 Version B */
- {"NUC100LD2BN", 0x10010004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD1BN", 0x10010005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD0BN", 0x10010027, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LC2BN", 0x10010007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LC1BN", 0x10010008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LC0BN", 0x10010028, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LB2BN", 0x10010029, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC100LB1BN", 0x10010030, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC100LB0BN", 0x10010031, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC100LA2BN", 0x10010032, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC100LA1BN", 0x10010033, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC100LA0BN", 0x10010034, NUMICRO_BANKS_NUC100(8*1024)},
-
- {"NUC100RD2BN", 0x10010013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RD1BN", 0x10010014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RD0BN", 0x10010035, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RC2BN", 0x10010016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RC1BN", 0x10010017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RC0BN", 0x10010036, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RB2BN", 0x10010037, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC100RB1BN", 0x10010038, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC100RB0BN", 0x10010039, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC100RA2BN", 0x10010040, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC100RA1BN", 0x10010041, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC100RA0BN", 0x10010042, NUMICRO_BANKS_NUC100(8*1024)},
-
- /* NUC100 Version C */
- {"NUC100LE3CN", 0x20010000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100LE2CN", 0x20010001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100LE1CN", 0x20010002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100LD3CN", 0x20010003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD2CN", 0x20010004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD1CN", 0x20010005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LC3CN", 0x20010006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LC2CN", 0x20010007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LC1CN", 0x20010008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RE3CN", 0x20010009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100RE2CN", 0x20010010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100RE1CN", 0x20010011, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100RD3CN", 0x20010012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RD2CN", 0x20010013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RD1CN", 0x20010014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RC3CN", 0x20010015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RC2CN", 0x20010016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RC1CN", 0x20010017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100VE3CN", 0x20010018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100VE2CN", 0x20010019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100VE1CN", 0x20010020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100VD3CN", 0x20010021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VD2CN", 0x20010022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VD1CN", 0x20010023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VC3CN", 0x20010024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100VC2CN", 0x20010025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100VC1CN", 0x20010026, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC100 Version B */
- {"NUC101YD2BN", 0x10010143, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101YD1BN", 0x10010144, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101YD0BN", 0x10010145, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101YC2BN", 0x10010146, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101YC1BN", 0x10010147, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101YC0BN", 0x10010148, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101YB2BN", 0x10010149, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101YB1BN", 0x10010150, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101YB0BN", 0x10010151, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101YA2BN", 0x10010152, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC101YA1BN", 0x10010153, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC101YA0BN", 0x10010154, NUMICRO_BANKS_NUC100(8*1024)},
-
- {"NUC101LD2BN", 0x10010104, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LD1BN", 0x10010105, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LD0BN", 0x10010127, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LC2BN", 0x10010107, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101LC1BN", 0x10010108, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101LC0BN", 0x10010128, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101LB2BN", 0x10010129, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101LB1BN", 0x10010130, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101LB0BN", 0x10010131, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101LA2BN", 0x10010132, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC101LA1BN", 0x10010133, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC101LA0BN", 0x10010134, NUMICRO_BANKS_NUC100(8*1024)},
-
- {"NUC101RD2BN", 0x10010113, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RD1BN", 0x10010114, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RD0BN", 0x10010135, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RC2BN", 0x10010116, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RC1BN", 0x10010117, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RC0BN", 0x10010136, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RB2BN", 0x10010137, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101RB1BN", 0x10010138, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101RB0BN", 0x10010139, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC101RA2BN", 0x10010140, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC101RA1BN", 0x10010141, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC101RA0BN", 0x10010142, NUMICRO_BANKS_NUC100(8*1024)},
-
- /* NUC101 Version C */
- {"NUC101LE3CN", 0x20010100, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101LE2CN", 0x20010101, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101LE1CN", 0x20010102, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101LD3CN", 0x20010103, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LD2CN", 0x20010104, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LD1CN", 0x20010105, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LC3CN", 0x20010106, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101LC2CN", 0x20010107, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101LC1CN", 0x20010108, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RE3CN", 0x20010109, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101RE2CN", 0x20010110, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101RE1CN", 0x20010111, NUMICRO_BANKS_NUC100(128*1024)},
-
- {"NUC101RD3CN", 0x20010112, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RD2CN", 0x20010113, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RD1CN", 0x20010114, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RC3CN", 0x20010115, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RC2CN", 0x20010116, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RC1CN", 0x20010117, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101VE3CN", 0x20010118, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101VE2CN", 0x20010119, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101VE1CN", 0x20010120, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101VD3CN", 0x20010121, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101VD2CN", 0x20010122, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101VD1CN", 0x20010123, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101VC3CN", 0x20010124, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101VC2CN", 0x20010125, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101VC1CN", 0x20010126, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC102 Version A */
- {"NUC102ZD2AN", 0x00010231, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC102ZC1AN", 0x00010235, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC102LD2AN", 0x00010204, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC102LC1AN", 0x00010208, NUMICRO_BANKS_NUC100(32*1024)},
-
- {"NUC102RB3AN", 0x00010248, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102RB2AN", 0x00010249, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102RB1AN", 0x00010250, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102RA3AN", 0x00010251, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102RA2AN", 0x00010252, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102RA1AN", 0x00010253, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102VB3AN", 0x00010254, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102VB2AN", 0x00010255, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102VB1AN", 0x00010256, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102VA3AN", 0x00010257, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102VA2AN", 0x00010258, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102VA1AN", 0x00010259, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102LA0AN", 0x00010260, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102LB0AN", 0x00010261, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102LC0AN", 0x00010262, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC102LD0AN", 0x00010263, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC102RA0AN", 0x00010264, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102RB0AN", 0x00010265, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102RC0AN", 0x00010266, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC102RD0AN", 0x00010267, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC102VA0AN", 0x00010268, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102VB0AN", 0x00010269, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102VC0AN", 0x00010270, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC102VD0AN", 0x00010271, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC102ZA0AN", 0x00010272, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC102ZB0AN", 0x00010273, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC102ZC0AN", 0x00010274, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC102ZD0AN", 0x00010275, NUMICRO_BANKS_NUC100(64*1024)},
-
- /* NUC102 Version A */
- {"NUC122LD2AN", 0x00012204, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122LD1AN", 0x00012205, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122LC2AN", 0x00012207, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122LC1AN", 0x00012208, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122RD2AN", 0x00012213, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122RD1AN", 0x00012214, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122RC2AN", 0x00012216, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122RC1AN", 0x00012217, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122SD2AN", 0x00012222, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122SD1AN", 0x00012223, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122SC2AN", 0x00012225, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122SC1AN", 0x00012226, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122ZD2AN", 0x00012231, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122ZD1AN", 0x00012232, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122ZC2AN", 0x00012234, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122ZC1AN", 0x00012235, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122ZB2AN", 0x00012237, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122ZB1AN", 0x00012238, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122ZA2AN", 0x00012240, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122ZA1AN", 0x00012241, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122LB2AN", 0x00012243, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122LB1AN", 0x00012244, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122LA2AN", 0x00012246, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122LA1AN", 0x00012247, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122RB2AN", 0x00012249, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122RB1AN", 0x00012250, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122RA2AN", 0x00012252, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122RA1AN", 0x00012253, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122SB2AN", 0x00012255, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122SB1AN", 0x00012256, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122SA2AN", 0x00012258, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122SA1AN", 0x00012259, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122LA0AN", 0x00012260, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122LB0AN", 0x00012261, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122LC0AN", 0x00012262, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122LD0AN", 0x00012263, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122RA0AN", 0x00012264, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122RB0AN", 0x00012265, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122RC0AN", 0x00012266, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122RD0AN", 0x00012267, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122SA0AN", 0x00012268, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122SB0AN", 0x00012269, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122SC0AN", 0x00012270, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122SD0AN", 0x00012271, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122ZA0AN", 0x00012272, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122ZB0AN", 0x00012273, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122ZC0AN", 0x00012274, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122ZD0AN", 0x00012275, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122YD2AN", 0x00012277, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122YD1AN", 0x00012278, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122YD0AN", 0x00012279, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC122YC2AN", 0x00012281, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122YC1AN", 0x00012282, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122YC0AN", 0x00012283, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC122YB2AN", 0x00012285, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122YB1AN", 0x00012286, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122YB0AN", 0x00012287, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC122YA2AN", 0x00012289, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122YA1AN", 0x00012290, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC122YA0AN", 0x00012291, NUMICRO_BANKS_NUC100(8*1024)},
-
- /* NUC120 Version C */
- {"NUC120LD2BN", 0x10012004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD1BN", 0x10012005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD0BN", 0x10012027, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LC2BN", 0x10012007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LC1BN", 0x10012008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LC0BN", 0x10012028, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LB2BN", 0x10012029, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC120LB1BN", 0x10012030, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC120LB0BN", 0x10012031, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC120LA2BN", 0x10012032, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC120LA1BN", 0x10012033, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC120LA0BN", 0x10012034, NUMICRO_BANKS_NUC100(8*1024)},
-
- {"NUC120RD2BN", 0x10012013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RD1BN", 0x10012014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RD0BN", 0x10012035, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RC2BN", 0x10012016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RC1BN", 0x10012017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RC0BN", 0x10012036, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RB2BN", 0x10012037, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC120RB1BN", 0x10012038, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC120RB0BN", 0x10012039, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC120RA2BN", 0x10012040, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC120RA1BN", 0x10012041, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC120RA0BN", 0x10012042, NUMICRO_BANKS_NUC100(8*1024)},
-
- /* NUC120 Version C */
- {"NUC120LE3CN", 0x20012000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120LE2CN", 0x20012001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120LE1CN", 0x20012002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120LD3CN", 0x20012003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD2CN", 0x20012004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD1CN", 0x20012005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LC3CN", 0x20012006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LC2CN", 0x20012007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LC1CN", 0x20012008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RE3CN", 0x20012009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120RE2CN", 0x20012010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120RE1CN", 0x20012011, NUMICRO_BANKS_NUC100(128*1024)},
-
- {"NUC120RD3CN", 0x20012012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RD2CN", 0x20012013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RD1CN", 0x20012014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RC3CN", 0x20012015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RC2CN", 0x20012016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RC1CN", 0x20012017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120VE3CN", 0x20012018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120VE2CN", 0x20012019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120VE1CN", 0x20012020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120VD3CN", 0x20012021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VD2CN", 0x20012022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VD1CN", 0x20012023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VC3CN", 0x20012024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120VC2CN", 0x20012025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120VC1CN", 0x20012026, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC120 Version B */
- {"NUC130LD2BN", 0x10013004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LD1BN", 0x10013005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LD0BN", 0x10013027, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LC2BN", 0x10013007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130LC1BN", 0x10013008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130LC0BN", 0x10013028, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130LB2BN", 0x10013029, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC130LB1BN", 0x10013030, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC130LB0BN", 0x10013031, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC130LA2BN", 0x10013032, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC130LA1BN", 0x10013033, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC130LA0BN", 0x10013034, NUMICRO_BANKS_NUC100(8*1024)},
-
- {"NUC130RD2BN", 0x10013013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RD1BN", 0x10013014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RD0BN", 0x10013035, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RC2BN", 0x10013016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RC1BN", 0x10013017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RC0BN", 0x10013036, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RB2BN", 0x10013037, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC130RB1BN", 0x10013038, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC130RB0BN", 0x10013039, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC130RA2BN", 0x10013040, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC130RA1BN", 0x10013041, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC130RA0BN", 0x10013042, NUMICRO_BANKS_NUC100(8*1024)},
-
- /* NUC130 Version C */
- {"NUC130LE3CN", 0x20013000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130LE2CN", 0x20013001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130LE1CN", 0x20013002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130LD3CN", 0x20013003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LD2CN", 0x20013004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LD1CN", 0x20013005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LC3CN", 0x20013006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130LC2CN", 0x20013007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130LC1CN", 0x20013008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RE3CN", 0x20013009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130RE2CN", 0x20013010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130RE1CN", 0x20013011, NUMICRO_BANKS_NUC100(128*1024)},
-
- {"NUC130RD3CN", 0x20013012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RD2CN", 0x20013013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RD1CN", 0x20013014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RC3CN", 0x20013015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RC2CN", 0x20013016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RC1CN", 0x20013017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130VE3CN", 0x20013018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130VE2CN", 0x20013019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130VE1CN", 0x20013020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130VD3CN", 0x20013021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130VD2CN", 0x20013022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130VD1CN", 0x20013023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130VC3CN", 0x20013024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130VC2CN", 0x20013025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130VC1CN", 0x20013026, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC140 Version B */
- {"NUC140LD2BN", 0x10014004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LD1BN", 0x10014005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LD0BN", 0x10014027, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LC2BN", 0x10014007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140LC1BN", 0x10014008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140LC0BN", 0x10014028, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140LB2BN", 0x10014029, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC140LB1BN", 0x10014030, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC140LB0BN", 0x10014031, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC140LA2BN", 0x10014032, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC140LA1BN", 0x10014033, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC140LA0BN", 0x10014034, NUMICRO_BANKS_NUC100(8*1024)},
-
- {"NUC140RD2BN", 0x10014013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RD1BN", 0x10014014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RD0BN", 0x10014035, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RC2BN", 0x10014016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RC1BN", 0x10014017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RC0BN", 0x10014036, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RB2BN", 0x10014037, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC140RB1BN", 0x10014038, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC140RB0BN", 0x10014039, NUMICRO_BANKS_NUC100(16*1024)},
- {"NUC140RA2BN", 0x10014040, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC140RA1BN", 0x10014041, NUMICRO_BANKS_NUC100(8*1024)},
- {"NUC140RA0BN", 0x10014042, NUMICRO_BANKS_NUC100(8*1024)},
-
- /* NUC140 Version C */
- {"NUC140LE3CN", 0x20014000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140LE2CN", 0x20014001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140LE1CN", 0x20014002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140LD3CN", 0x20014003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LD2CN", 0x20014004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LD1CN", 0x20014005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LC3CN", 0x20014006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140LC2CN", 0x20014007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140LC1CN", 0x20014008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RE3CN", 0x20014009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140RE2CN", 0x20014010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140RE1CN", 0x20014011, NUMICRO_BANKS_NUC100(128*1024)},
-
- {"NUC140RD3CN", 0x20014012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RD2CN", 0x20014013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RD1CN", 0x20014014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RC3CN", 0x20014015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RC2CN", 0x20014016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RC1CN", 0x20014017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140VE3CN", 0x20014018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140VE2CN", 0x20014019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140VE1CN", 0x20014020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140VD3CN", 0x20014021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140VD2CN", 0x20014022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140VD1CN", 0x20014023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140VC3CN", 0x20014024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140VC2CN", 0x20014025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140VC1CN", 0x20014026, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC100 Version A */
- {"NUC100LE3AN", 0x00010000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100LE2AN", 0x00010001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100LE1AN", 0x00010002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100LD3AN", 0x00010003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD2AN", 0x00010004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD1AN", 0x00010005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LC3AN", 0x00010006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LC2AN", 0x00010007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LC1AN", 0x00010008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RE3AN", 0x00010009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100RE2AN", 0x00010010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100RE1AN", 0x00010011, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100RD3AN", 0x00010012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RD2AN", 0x00010013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RD1AN", 0x00010014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RC3AN", 0x00010015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RC2AN", 0x00010016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RC1AN", 0x00010017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100VE3AN", 0x00010018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100VE2AN", 0x00010019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100VE1AN", 0x00010020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100VD3AN", 0x00010021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VD2AN", 0x00010022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VD1AN", 0x00010023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VC3AN", 0x00010024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100VC2AN", 0x00010025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100VC1AN", 0x00010026, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC100 Version A */
- {"NUC101LE3AN", 0x00010100, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101LE2AN", 0x00010101, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101LE1AN", 0x00010102, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101LD3AN", 0x00010103, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LD2AN", 0x00010104, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LD1AN", 0x00010105, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101LC3AN", 0x00010106, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101LC2AN", 0x00010107, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101LC1AN", 0x00010108, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RE3AN", 0x00010109, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101RE2AN", 0x00010110, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101RE1AN", 0x00010111, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101RD3AN", 0x00010112, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RD2AN", 0x00010113, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RD1AN", 0x00010114, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101RC3AN", 0x00010115, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RC2AN", 0x00010116, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101RC1AN", 0x00010117, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101VE3AN", 0x00010118, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101VE2AN", 0x00010119, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101VE1AN", 0x00010120, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC101VD3AN", 0x00010121, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101VD2AN", 0x00010122, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101VD1AN", 0x00010123, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC101VC3AN", 0x00010124, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101VC2AN", 0x00010125, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC101VC1AN", 0x00010126, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC120 Version A */
- {"NUC120LE3AN", 0x00012000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120LE2AN", 0x00012001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120LE1AN", 0x00012002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120LD3AN", 0x00012003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD2AN", 0x00012004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD1AN", 0x00012005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LC3AN", 0x00012006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LC2AN", 0x00012007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LC1AN", 0x00012008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RE3AN", 0x00012009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120RE2AN", 0x00012010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120RE1AN", 0x00012011, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120RD3AN", 0x00012012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RD2AN", 0x00012013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RD1AN", 0x00012014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RC3AN", 0x00012015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RC2AN", 0x00012016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RC1AN", 0x00012017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120VE3AN", 0x00012018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120VE2AN", 0x00012019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120VE1AN", 0x00012020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120VD3AN", 0x00012021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VD2AN", 0x00012022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VD1AN", 0x00012023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VC3AN", 0x00012024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120VC2AN", 0x00012025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120VC1AN", 0x00012026, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC120 Version A */
- {"NUC130LE3AN", 0x00013000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130LE2AN", 0x00013001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130LE1AN", 0x00013002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130LD3AN", 0x00013003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LD2AN", 0x00013004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LD1AN", 0x00013005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130LC3AN", 0x00013006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130LC2AN", 0x00013007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130LC1AN", 0x00013008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RE3AN", 0x00013009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130RE2AN", 0x00013010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130RE1AN", 0x00013011, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130RD3AN", 0x00013012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RD2AN", 0x00013013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RD1AN", 0x00013014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130RC3AN", 0x00013015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RC2AN", 0x00013016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130RC1AN", 0x00013017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130VE3AN", 0x00013018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130VE2AN", 0x00013019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130VE1AN", 0x00013020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130VD3AN", 0x00013021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130VD2AN", 0x00013022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130VD1AN", 0x00013023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC130VC3AN", 0x00013024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130VC2AN", 0x00013025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC130VC1AN", 0x00013026, NUMICRO_BANKS_NUC100(32*1024)},
-
- /* NUC140 Version A */
- {"NUC140LE3AN", 0x00014000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140LE2AN", 0x00014001, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140LE1AN", 0x00014002, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140LD3AN", 0x00014003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LD2AN", 0x00014004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LD1AN", 0x00014005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140LC3AN", 0x00014006, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140LC2AN", 0x00014007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140LC1AN", 0x00014008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RE3AN", 0x00014009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140RE2AN", 0x00014010, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140RE1AN", 0x00014011, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140RD3AN", 0x00014012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RD2AN", 0x00014013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RD1AN", 0x00014014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140RC3AN", 0x00014015, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RC2AN", 0x00014016, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140RC1AN", 0x00014017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140VE3AN", 0x00014018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140VE2AN", 0x00014019, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140VE1AN", 0x00014020, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC140VD3AN", 0x00014021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140VD2AN", 0x00014022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140VD1AN", 0x00014023, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC140VC3AN", 0x00014024, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140VC2AN", 0x00014025, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC140VC1AN", 0x00014026, NUMICRO_BANKS_NUC100(32*1024)},
-
-
- /* M052 */
- {"M052LAN" , 0x00005200, NUMICRO_BANKS_M051(8*1024)},
- {"M052PAN" , 0x00005201, NUMICRO_BANKS_M051(8*1024)},
- {"M052YAN" , 0x00005202, NUMICRO_BANKS_M051(8*1024)},
- {"M052ZAN" , 0x00005203, NUMICRO_BANKS_M051(8*1024)},
-
- /* M054 */
- {"M054LAN" , 0x00005400, NUMICRO_BANKS_M051(16*1024)},
- {"M054PAN" , 0x00005401, NUMICRO_BANKS_M051(16*1024)},
- {"M054YAN" , 0x00005402, NUMICRO_BANKS_M051(16*1024)},
- {"M054ZAN" , 0x00005403, NUMICRO_BANKS_M051(16*1024)},
-
- /* M058 */
- {"M058LAN" , 0x00005800, NUMICRO_BANKS_M051(32*1024)},
- {"M058PAN" , 0x00005801, NUMICRO_BANKS_M051(32*1024)},
- {"M058YAN" , 0x00005802, NUMICRO_BANKS_M051(32*1024)},
- {"M058ZAN" , 0x00005803, NUMICRO_BANKS_M051(32*1024)},
-
- /* M0516 */
- {"M0516LAN" , 0x00005A00, NUMICRO_BANKS_M051(64*1024)},
- {"M0516PAN" , 0x00005A01, NUMICRO_BANKS_M051(64*1024)},
- {"M0516YAN" , 0x00005A02, NUMICRO_BANKS_M051(64*1024)},
- {"M0516ZAN" , 0x00005A03, NUMICRO_BANKS_M051(64*1024)},
- {"M051LBN" , 0x10005100, NUMICRO_BANKS_M051(4*1024)},
- {"M051PBN" , 0x10005101, NUMICRO_BANKS_M051(4*1024)},
- {"M051YBN" , 0x10005102, NUMICRO_BANKS_M051(4*1024)},
- {"M051ZBN" , 0x10005103, NUMICRO_BANKS_M051(4*1024)},
- {"M052LBN" , 0x10005200, NUMICRO_BANKS_M051(8*1024)},
- {"M052PBN" , 0x10005201, NUMICRO_BANKS_M051(8*1024)},
- {"M052YBN" , 0x10005202, NUMICRO_BANKS_M051(8*1024)},
- {"M052ZBN" , 0x10005203, NUMICRO_BANKS_M051(8*1024)},
- {"M054LBN" , 0x10005400, NUMICRO_BANKS_M051(16*1024)},
- {"M054PBN" , 0x10005401, NUMICRO_BANKS_M051(16*1024)},
- {"M054YBN" , 0x10005402, NUMICRO_BANKS_M051(16*1024)},
- {"M054ZBN" , 0x10005403, NUMICRO_BANKS_M051(16*1024)},
- {"M058LBN" , 0x10005800, NUMICRO_BANKS_M051(32*1024)},
- {"M058PBN" , 0x10005801, NUMICRO_BANKS_M051(32*1024)},
- {"M058YBN" , 0x10005802, NUMICRO_BANKS_M051(32*1024)},
- {"M058ZBN" , 0x10005803, NUMICRO_BANKS_M051(32*1024)},
- {"M0516LBN" , 0x10005A00, NUMICRO_BANKS_M051(64*1024)},
- {"M0516PBN" , 0x10005A01, NUMICRO_BANKS_M051(64*1024)},
- {"M0516YBN" , 0x10005A02, NUMICRO_BANKS_M051(64*1024)},
- {"M0516ZBN" , 0x10005A03, NUMICRO_BANKS_M051(64*1024)},
- {"M052LDN" , 0x20005200, NUMICRO_BANKS_M051(8*1024)},
- {"M054LDN" , 0x20005400, NUMICRO_BANKS_M051(16*1024)},
- {"M058LDN" , 0x20005800, NUMICRO_BANKS_M051(32*1024)},
- {"M0516LDN" , 0x20005A00, NUMICRO_BANKS_M051(64*1024)},
- {"M052ZDN" , 0x20005203, NUMICRO_BANKS_M051(8*1024)},
- {"M054ZDN" , 0x20005403, NUMICRO_BANKS_M051(16*1024)},
- {"M058ZDN" , 0x20005803, NUMICRO_BANKS_M051(32*1024)},
- {"M0516ZDN" , 0x20005A03, NUMICRO_BANKS_M051(64*1024)},
- {"M052TDN" , 0x20005204, NUMICRO_BANKS_M051(8*1024)},
- {"M054TDN" , 0x20005404, NUMICRO_BANKS_M051(16*1024)},
- {"M058TDN" , 0x20005804, NUMICRO_BANKS_M051(32*1024)},
- {"M0516TDN" , 0x20005A04, NUMICRO_BANKS_M051(64*1024)},
- {"M052XDN" , 0x20005205, NUMICRO_BANKS_M051(8*1024)},
- {"M054XDN" , 0x20005405, NUMICRO_BANKS_M051(16*1024)},
- {"M058XDN" , 0x20005805, NUMICRO_BANKS_M051(32*1024)},
- {"M0516XDN" , 0x20005A05, NUMICRO_BANKS_M051(64*1024)},
- {"M052LDE" , 0x30005200, NUMICRO_BANKS_M051(8*1024)},
- {"M054LDE" , 0x30005400, NUMICRO_BANKS_M051(16*1024)},
- {"M058LDE" , 0x30005800, NUMICRO_BANKS_M051(32*1024)},
- {"M0516LDE" , 0x30005A00, NUMICRO_BANKS_M051(64*1024)},
- {"M052ZDE" , 0x30005203, NUMICRO_BANKS_M051(8*1024)},
- {"M054ZDE" , 0x30005403, NUMICRO_BANKS_M051(16*1024)},
- {"M058ZDE" , 0x30005803, NUMICRO_BANKS_M051(32*1024)},
- {"M0516ZDE" , 0x30005A03, NUMICRO_BANKS_M051(64*1024)},
- {"M052TDE" , 0x30005204, NUMICRO_BANKS_M051(8*1024)},
- {"M054TDE" , 0x30005404, NUMICRO_BANKS_M051(16*1024)},
- {"M058TDE" , 0x30005804, NUMICRO_BANKS_M051(32*1024)},
- {"M0516TDE" , 0x30005A04, NUMICRO_BANKS_M051(64*1024)},
- {"M052XDE" , 0x30005205, NUMICRO_BANKS_M051(8*1024)},
- {"M054XDE" , 0x30005405, NUMICRO_BANKS_M051(16*1024)},
- {"M058XDE" , 0x30005805, NUMICRO_BANKS_M051(32*1024)},
- {"M0516XDE" , 0x30005A05, NUMICRO_BANKS_M051(64*1024)},
-
- /* Mini51 */
- {"MINI51LAN", 0x00205100, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51QAN", 0x00205101, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51 ", 0x00205102, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51ZAN", 0x00205103, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51TAN", 0x00205104, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI52LAN", 0x00205200, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52QAN", 0x00205201, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52 ", 0x00205202, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52ZAN", 0x00205203, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52TAN", 0x00205204, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI54LAN", 0x00205400, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54QAN", 0x00205401, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54 ", 0x00205402, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54ZAN", 0x00205403, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54TAN", 0x00205404, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI51LBN", 0x10205100, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51QBN", 0x10205101, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51 ", 0x10205102, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51ZBN", 0x10205103, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51TBN", 0x10205104, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI52LBN", 0x10205200, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52QBN", 0x10205201, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52 ", 0x10205202, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52ZBN", 0x10205203, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52TBN", 0x10205204, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI54LBN", 0x10205400, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54QBN", 0x10205401, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54 ", 0x10205402, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54ZBN" , 0x10205403, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54TBN" , 0x10205404, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI51LDE" , 0x20205100, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51QDE" , 0x20205101, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51 " , 0x20205102, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51ZDE" , 0x20205103, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51TDE" , 0x20205104, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI51FDE" , 0x20205105, NUMICRO_BANKS_MINI51(4*1024)},
- {"MINI52LDE" , 0x20205200, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52QDE" , 0x20205201, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52 " , 0x20205202, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52ZDE" , 0x20205203, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52TDE" , 0x20205204, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI52FDE" , 0x20205205, NUMICRO_BANKS_MINI51(8*1024)},
- {"MINI54LDE" , 0x20205400, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54QDE" , 0x20205401, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54 " , 0x20205402, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54ZDE" , 0x20205403, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54TDE" , 0x20205404, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI54FDE" , 0x20205405, NUMICRO_BANKS_MINI51(16*1024)},
- {"MINI55LDE" , 0x20205500, NUMICRO_BANKS_MINI51(16*1024)},
-
- /* NANO100 */
- {"NANO100VF3AN" , 0x00110000, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO100VF2AN" , 0x00110001, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO100RF3AN" , 0x00110002, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO100RF2AN" , 0x00110003, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO100LF3AN" , 0x00110004, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO100LF2AN" , 0x00110005, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO100VE3AN" , 0x00110006, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100VE2AN" , 0x00110007, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100RE3AN" , 0x00110008, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100RE2AN" , 0x00110009, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100LE3AN" , 0x00110010, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100LE2AN" , 0x00110011, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100VD3AN" , 0x00110012, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100VD2AN" , 0x00110013, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100VD1AN" , 0x00110014, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100RD3AN" , 0x00110015, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100RD2AN" , 0x00110016, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100RD1AN" , 0x00110017, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100LD3AN" , 0x00110018, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100LD2AN" , 0x00110019, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100LD1AN" , 0x00110020, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100VC2AN" , 0x00110021, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100VC1AN" , 0x00110022, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100RC2AN" , 0x00110023, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100RC1AN" , 0x00110024, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100LC2AN" , 0x00110025, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100LC1AN" , 0x00110026, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100VB1AN" , 0x00110027, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO100VB0AN" , 0x00110028, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO100RB1AN" , 0x00110029, NUMICRO_BANKS_NANO(16*1024)},
-
- {"NANO110VF3AN" , 0x00111000, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO110VF2AN" , 0x00111001, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO110RF3AN" , 0x00111002, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO110RF2AN" , 0x00111003, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO110VE3AN" , 0x00111006, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110VE2AN" , 0x00111007, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110RE3AN" , 0x00111008, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110RE2AN" , 0x00111009, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110VD3AN" , 0x00111012, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110VD2AN" , 0x00111013, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110VD1AN" , 0x00111014, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110RD3AN" , 0x00111015, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110RD2AN" , 0x00111016, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110RD1AN" , 0x00111017, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110VC2AN" , 0x00111021, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO110VC1AN" , 0x00111022, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO110SC2AN" , 0x00111023, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO110SC1AN" , 0x00111024, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120VF3AN" , 0x00112000, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO120VF2AN" , 0x00112001, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO120RF3AN" , 0x00112002, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO120RF2AN" , 0x00112003, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO120LF3AN" , 0x00112004, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO120LF2AN" , 0x00112005, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO120VE3AN" , 0x00112006, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120VE2AN" , 0x00112007, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120RE3AN" , 0x00112008, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120RE2AN" , 0x00112009, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120LE3AN" , 0x00112010, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120LE2AN" , 0x00112011, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120VD3AN" , 0x00112012, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120VD2AN" , 0x00112013, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120VD1AN" , 0x00112014, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120SD3AN" , 0x00112015, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120SD2AN" , 0x00112016, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120SD1AN" , 0x00112017, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120LD3AN" , 0x00112018, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120LD2AN" , 0x00112019, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120LD1AN" , 0x00112020, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120VC2AN" , 0x00112021, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120VC1AN" , 0x00112022, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120SC2AN" , 0x00112023, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120SC1AN" , 0x00112024, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120LC2AN" , 0x00112025, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120LC1AN" , 0x00112026, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO130VF3AN" , 0x00113000, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO130VF2AN" , 0x00113001, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO130SF3AN" , 0x00113002, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO130SF2AN" , 0x00113003, NUMICRO_BANKS_NANO(256*1024)},
- {"NANO130VE3AN" , 0x00113006, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO130VE2AN" , 0x00113007, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO130SE3AN" , 0x00113008, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO130SE2AN" , 0x00113009, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO130VD3AN" , 0x00113012, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130VD2AN" , 0x00113013, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130VD1AN" , 0x00113014, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130SD3AN" , 0x00113015, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130SD2AN" , 0x00113016, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130SD1AN" , 0x00113017, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130VC2AN" , 0x00113021, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO130VC1AN" , 0x00113022, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO130SC2AN" , 0x00113023, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO130SC1AN" , 0x00113024, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100KE3BN" , 0x00110030, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100KE2BN" , 0x00110031, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100VE3BN" , 0x00110032, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100VE2BN" , 0x00110033, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100SE3BN" , 0x00110034, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100SE2BN" , 0x00110035, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100LE3BN" , 0x00110036, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100LE2BN" , 0x00110037, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO100KD3BN" , 0x00110038, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100KD2BN" , 0x00110039, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100VD3BN" , 0x0011003A, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100VD2BN" , 0x0011003B, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100SD3BN" , 0x0011003C, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100SD2BN" , 0x0011003D, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100LD3BN" , 0x0011003E, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100LD2BN" , 0x0011003F, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO100KC2BN" , 0x00110040, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100VC2BN" , 0x00110041, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100SC2BN" , 0x00110042, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO100LC2BN" , 0x00110043, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO110KE3BN" , 0x00111030, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110KE2BN" , 0x00111031, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110VE3BN" , 0x00111032, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110VE2BN" , 0x00111033, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110SE3BN" , 0x00111034, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110SE2BN" , 0x00111035, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110KD3BN" , 0x00111038, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110KD2BN" , 0x00111039, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110VD3BN" , 0x0011103A, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110VD2BN" , 0x0011103B, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110SD3BN" , 0x0011103C, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110SD2BN" , 0x0011103D, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO110KC2BN" , 0x00111040, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO110VC2BN" , 0x00111041, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO110SC2BN" , 0x00111042, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120KE3BN" , 0x00112030, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120KE2BN" , 0x00112031, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120VE3BN" , 0x00112032, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120VE2BN" , 0x00112033, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120SE3BN" , 0x00112034, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120SE2BN" , 0x00112035, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120LE3BN" , 0x00112036, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120LE2BN" , 0x00112037, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO120KD3BN" , 0x00112038, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120KD2BN" , 0x00112039, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120VD3BN" , 0x0011203A, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120VD2BN" , 0x0011203B, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120SD3BN" , 0x0011203C, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120SD2BN" , 0x0011203D, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120LD3BN" , 0x0011203E, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120LD2BN" , 0x0011203F, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO120KC2BN" , 0x00112040, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120VC2BN" , 0x00112041, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120SC2BN" , 0x00112042, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO120LC2BN" , 0x00112043, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO130KE3BN" , 0x00113030, NUMICRO_BANKS_NANO(123*1024)},
- {"NANO130KE2BN" , 0x00113031, NUMICRO_BANKS_NANO(123*1024)},
- {"NANO130VE3BN" , 0x00113032, NUMICRO_BANKS_NANO(123*1024)},
- {"NANO130VE2BN" , 0x00113033, NUMICRO_BANKS_NANO(123*1024)},
- {"NANO130SE3BN" , 0x00113034, NUMICRO_BANKS_NANO(123*1024)},
- {"NANO130SE2BN" , 0x00113035, NUMICRO_BANKS_NANO(123*1024)},
- {"NANO130KD3BN" , 0x00113038, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130KD2BN" , 0x00113039, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130VD3BN" , 0x0011303A, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130VD2BN" , 0x0011303B, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130SD3BN" , 0x0011303C, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130SD2BN" , 0x0011303D, NUMICRO_BANKS_NANO(64*1024)},
- {"NANO130KC2BN" , 0x00113040, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO130VC2BN" , 0x00113041, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO130SC2BN" , 0x00113042, NUMICRO_BANKS_NANO(32*1024)},
- {"N512DC4" , 0x00100000, NUMICRO_BANKS_NANO(64*1024)},
- {"N512LC4" , 0x00100001, NUMICRO_BANKS_NANO(64*1024)},
- {"N512MC4" , 0x00100003, NUMICRO_BANKS_NANO(64*1024)},
-
- {"N512SC4" , 0x00100005, NUMICRO_BANKS_NANO(64*1024)},
- {"N512VD4" , 0x00100008, NUMICRO_BANKS_NANO(128*1024)},
- {"N512MD4" , 0x00100009, NUMICRO_BANKS_NANO(128*1024)},
- {"N512SD4" , 0x00100010, NUMICRO_BANKS_NANO(128*1024)},
- {"NANO110RC2BN" , 0x00111043, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO110RD3BN" , 0x00111045, NUMICRO_BANKS_NANO(64*1024)},
- {"TX110VE3BN" , 0x00111036, NUMICRO_BANKS_NANO(128*1024)},
-
- /* NANO102/NANO112 */
- {"NANO112LB0AN" , 0x00111201, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112LB1AN" , 0x00111202, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112LC1AN" , 0x00111203, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO112LC2AN" , 0x00111204, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO112SB0AN" , 0x00111205, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112SB1AN" , 0x00111206, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112SC1AN" , 0x00111207, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO112SC2AN" , 0x00111208, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO112RB0AN" , 0x00111209, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112RB1AN" , 0x00111210, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112RC1AN" , 0x00111211, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO112RC2AN" , 0x00111212, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO112VB0AN" , 0x00111213, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112VB1AN" , 0x00111214, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO112VC1AN" , 0x00111215, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO112VC2AN" , 0x00111216, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO102ZB0AN" , 0x00110201, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO102ZB1AN" , 0x00110202, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO102ZC1AN" , 0x00110203, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO102ZC2AN" , 0x00110204, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO102LB0AN" , 0x00110205, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO102LB1AN" , 0x00110206, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO102LC1AN" , 0x00110207, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO102LC2AN" , 0x00110208, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO102SB0AN" , 0x00110209, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO102SB1AN" , 0x00110210, NUMICRO_BANKS_NANO(16*1024)},
- {"NANO102SC1AN" , 0x00110211, NUMICRO_BANKS_NANO(32*1024)},
- {"NANO102SC2AN" , 0x00110212, NUMICRO_BANKS_NANO(32*1024)},
-
- /* NUC103/NUC105/NUC123 */
- {"NUC123SC2AN" , 0x00012305, NUMICRO_BANKS_NUC100(36*1024)},
- {"NUC123SD4AN" , 0x00012315, NUMICRO_BANKS_NUC100(68*1024)},
- {"NUC123LC2AN" , 0x00012325, NUMICRO_BANKS_NUC100(36*1024)},
- {"NUC103LC2AN" , 0x00010325, NUMICRO_BANKS_NUC100(36*1024)},
- {"NUC105LC2AN" , 0x00010525, NUMICRO_BANKS_NUC100(36*1024)},
- {"NUC123LD4AN" , 0x00012335, NUMICRO_BANKS_NUC100(68*1024)},
- {"NUC103LD4AN" , 0x00010335, NUMICRO_BANKS_NUC100(68*1024)},
- {"NUC105LD4AN" , 0x00010535, NUMICRO_BANKS_NUC100(68*1024)},
- {"NUC123ZC2AN" , 0x00012345, NUMICRO_BANKS_NUC100(36*1024)},
- {"NUC103ZC2AN" , 0x00010345, NUMICRO_BANKS_NUC100(36*1024)},
- {"NUC105ZC2AN" , 0x00010545, NUMICRO_BANKS_NUC100(36*1024)},
- {"NUC123ZD4AN" , 0x00012355, NUMICRO_BANKS_NUC100(68*1024)},
- {"NUC103ZD4AN" , 0x00010355, NUMICRO_BANKS_NUC100(68*1024)},
- {"NUC105ZD4AN" , 0x00010555, NUMICRO_BANKS_NUC100(68*1024)},
-
- /* NUC200 */
- {"NUC200LC2AN" , 0x00020007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC200LD2AN" , 0x00020004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC200LE3AN" , 0x00020000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC200SC1AN" , 0x00020035, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC200SD2AN" , 0x00020031, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC200SE3AN" , 0x00020027, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC200VE3AN" , 0x00020018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC220LC2AN" , 0x00022007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC220LD2AN" , 0x00022004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC220LE3AN" , 0x00022000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC220SC1AN" , 0x00022035, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC220SD2AN" , 0x00022031, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC220SE3AN" , 0x00022027, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC220VE3AN" , 0x00022018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC230LC2AN" , 0x00023007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC230LD2AN" , 0x00023004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC230LE3AN" , 0x00023000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC230SC1AN" , 0x00023035, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC230SD2AN" , 0x00023031, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC230SE3AN" , 0x00023027, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC230VE3AN" , 0x00023018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC240LC2AN" , 0x00024007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC240LD2AN" , 0x00024004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC240LE3AN" , 0x00024000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC240SC1AN" , 0x00024035, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC240SD2AN" , 0x00024031, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC240SE3AN" , 0x00024027, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC240VE3AN" , 0x00024018, NUMICRO_BANKS_NUC100(128*1024)},
-
- /* NUC200 NUC2XXAE */
- {"NUC230RC1AE" , 0x40013017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC200LC2AE" , 0x10020007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC200LD2AE" , 0x10020004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC200LE3AE" , 0x10020000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC200SC2AE" , 0x10020034, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC200SD2AE" , 0x10020031, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC200SE3AE" , 0x10020027, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC200VE3AE" , 0x10020018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC230LC2AE" , 0x10023007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC230LD2AE" , 0x10023004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC230LE3AE" , 0x10023000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC230SC2AE" , 0x10023034, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC230SD2AE" , 0x10023031, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC230SE3AE" , 0x10023027, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC230VE3AE" , 0x10023018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC240LC2AE" , 0x10024007, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC240LD2AE" , 0x10024004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC240LE3AE" , 0x10024000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC240SC2AE" , 0x10024034, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC240SD2AE" , 0x10024031, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC240SE3AE" , 0x10024027, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC240VE3AE" , 0x10024018, NUMICRO_BANKS_NUC100(128*1024)},
-
- /* NUC100 Version D */
- {"NUC100LC1DN" , 0x30010008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100LD1DN" , 0x30010005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD2DN" , 0x30010004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RC1DN" , 0x30010017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC100RD1DN" , 0x30010014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RD2DN" , 0x30010013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LD3DN" , 0x30010003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100LE3DN" , 0x30010000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100RD3DN" , 0x30010012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100RE3DN" , 0x30010009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC100VD2DN" , 0x30010022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VD3DN" , 0x30010021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC100VE3DN" , 0x30010018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120LC1DN" , 0x30012008, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120LD1DN" , 0x30012005, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD2DN" , 0x30012004, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RC1DN" , 0x30012017, NUMICRO_BANKS_NUC100(32*1024)},
- {"NUC120RD1DN" , 0x30012014, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RD2DN" , 0x30012013, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LD3DN" , 0x30012003, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120LE3DN" , 0x30012000, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120RD3DN" , 0x30012012, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120RE3DN" , 0x30012009, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC120VD2DN" , 0x30012022, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VD3DN" , 0x30012021, NUMICRO_BANKS_NUC100(64*1024)},
- {"NUC120VE3DN" , 0x30012018, NUMICRO_BANKS_NUC100(128*1024)},
- {"NUC130RC1DN" , 0x30013017, NUMICRO_BANKS_NUC100(32*1024)},
-
- {"UNKNOWN" , 0x00000000, NUMICRO_BANKS_NUC100(128*1024)},
-};
-
-/* Private bank information for NuMicro. */
-struct numicro_flash_bank {
- struct working_area *write_algorithm;
- int probed;
- const struct numicro_cpu_type *cpu;
-};
-
-/* Private methods */
-static int numicro_reg_unlock(struct target *target)
-{
- uint32_t is_protected;
- int retval = ERROR_OK;
-
- /* Check to see if NUC is register unlocked or not */
- retval = target_read_u32(target, NUMICRO_SYS_WRPROT, &is_protected);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("protected = 0x%08" PRIx32 "", is_protected);
- if (is_protected == 0) { /* means protected - so unlock it */
- /* unlock flash registers */
- retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY2);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY3);
- if (retval != ERROR_OK)
- return retval;
- }
- /* Check that unlock worked */
- retval = target_read_u32(target, NUMICRO_SYS_WRPROT, &is_protected);
- if (retval != ERROR_OK)
- return retval;
-
- if (is_protected == 1) { /* means unprotected */
- LOG_DEBUG("protection removed");
- } else {
- LOG_DEBUG("still protected!!");
- }
-
- return ERROR_OK;
-}
-
-static int numicro_init_isp(struct target *target)
-{
- uint32_t reg_stat;
- int retval = ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = numicro_reg_unlock(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* Enable ISP/SRAM/TICK Clock */
- retval = target_read_u32(target, NUMICRO_SYSCLK_AHBCLK, &reg_stat);
- if (retval != ERROR_OK)
- return retval;
-
- reg_stat |= AHBCLK_ISP_EN | AHBCLK_SRAM_EN | AHBCLK_TICK_EN;
- retval = target_write_u32(target, NUMICRO_SYSCLK_AHBCLK, reg_stat);
- if (retval != ERROR_OK)
- return retval;
-
- /* Enable ISP */
- retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &reg_stat);
- if (retval != ERROR_OK)
- return retval;
-
- reg_stat |= ISPCON_ISPFF | ISPCON_LDUEN | ISPCON_APUEN | ISPCON_CFGUEN | ISPCON_ISPEN;
- retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, reg_stat);
- if (retval != ERROR_OK)
- return retval;
-
- /* Write one to undocumented flash control register */
- retval = target_write_u32(target, NUMICRO_FLASH_CHEAT, 1);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-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;
-
- retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, cmd);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, NUMICRO_FLASH_ISPDAT, wdata);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, addr);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO);
- if (retval != ERROR_OK)
- return retval;
-
- /* Wait for busy to clear - check the GO flag */
- timeout = 100;
- for (;;) {
- retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if ((status & (ISPTRG_ISPGO)) == 0)
- break;
- if (timeout-- <= 0) {
- LOG_DEBUG("timed out waiting for flash");
- return ERROR_FAIL;
- }
- busy_sleep(1); /* can use busy sleep for short times. */
- }
-
- retval = target_read_u32(target, NUMICRO_FLASH_ISPDAT, rdata);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-
-/* NuMicro Program-LongWord Microcodes */
-static const uint8_t numicro_flash_write_code[] = {
- /* Params:
- * r0 - workarea buffer / result
- * r1 - target address
- * r2 - wordcount
- * Clobbered:
- * r4 - tmp
- * r5 - tmp
- * r6 - tmp
- * r7 - tmp
- */
-
- /* .L1: */
- /* for(register uint32_t i=0;i<wcount;i++){ */
- 0x04, 0x1C, /* mov r4, r0 */
- 0x00, 0x23, /* mov r3, #0 */
- /* .L2: */
- 0x0D, 0x1A, /* sub r5, r1, r0 */
- 0x67, 0x19, /* add r7, r4, r7 */
- 0x93, 0x42, /* cmp r3, r2 */
- 0x0C, 0xD0, /* beq .L7 */
- /* .L4: */
- /* NUMICRO_FLASH_ISPADR = faddr; */
- 0x08, 0x4E, /* ldr r6, .L8 */
- 0x37, 0x60, /* str r7, [r6] */
- /* NUMICRO_FLASH_ISPDAT = *pLW; */
- 0x80, 0xCC, /* ldmia r4!, {r7} */
- 0x08, 0x4D, /* ldr r5, .L8+4 */
- 0x2F, 0x60, /* str r7, [r5] */
- /* faddr += 4; */
- /* pLW++; */
- /* Trigger write action */
- /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
- 0x08, 0x4D, /* ldr r5, .L8+8 */
- 0x01, 0x26, /* mov r6, #1 */
- 0x2E, 0x60, /* str r6, [r5] */
- /* .L3: */
- /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
- 0x2F, 0x68, /* ldr r7, [r5] */
- 0xFF, 0x07, /* lsl r7, r7, #31 */
- 0xFC, 0xD4, /* bmi .L3 */
-
- 0x01, 0x33, /* add r3, r3, #1 */
- 0xEE, 0xE7, /* b .L2 */
- /* .L7: */
- /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
- 0x05, 0x4B, /* ldr r3, .L8+12 */
- 0x18, 0x68, /* ldr r0, [r3] */
- 0x40, 0x21, /* mov r1, #64 */
- 0x08, 0x40, /* and r0, r1 */
- /* .L9: */
- 0x00, 0xBE, /* bkpt #0 */
- /* .L8: */
- 0x04, 0xC0, 0x00, 0x50,/* .word 1342226436 */
- 0x08, 0xC0, 0x00, 0x50,/* .word 1342226440 */
- 0x10, 0xC0, 0x00, 0x50,/* .word 1342226448 */
- 0x00, 0xC0, 0x00, 0x50 /* .word 1342226432 */
-};
-/* Program LongWord Block Write */
-static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 1024; /* Default minimum value */
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* Params:
- * r0 - workarea buffer / result
- * r1 - target address
- * r2 - wordcount
- * Clobbered:
- * r4 - tmp
- * r5 - tmp
- * r6 - tmp
- * r7 - tmp
- */
-
- /* Increase buffer_size if needed */
- if (buffer_size < (target->working_area_size/2))
- buffer_size = (target->working_area_size/2);
-
- /* check code alignment */
- if (offset & 0x1) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* allocate working area with flash programming code */
- if (target_alloc_working_area(target, sizeof(numicro_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(numicro_flash_write_code), numicro_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 4;
- if (buffer_size <= 256) {
- /* free working area, write algorithm already allocated */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("No large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* *pLW (*buffer) */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* faddr */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of words to program */
-
- struct armv7m_common *armv7m = target_to_armv7m(target);
- if (armv7m == NULL) {
- /* something is very wrong if armv7m is NULL */
- LOG_ERROR("unable to get armv7m target");
- return retval;
- }
-
- /* write code buffer and use Flash programming code within NuMicro */
- /* Set breakpoint to 0 with time-out of 1000 ms */
- while (count > 0) {
- uint32_t thisrun_count = (count > (buffer_size / 4)) ? (buffer_size / 4) : count;
-
- retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
- if (retval != ERROR_OK)
- break;
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
-
- retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- write_algorithm->address, 0, 100000, &armv7m_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing NuMicro Flash programming algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- buffer += thisrun_count * 4;
- address += thisrun_count * 4;
- count -= thisrun_count;
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- return retval;
-}
-
-/* Flash Lock checking - examines the lock bit. */
-static int numicro_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- uint32_t set, config[2];
- int i, retval = ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_INFO("Nuvoton NuMicro: Flash Lock Check...");
-
- retval = numicro_init_isp(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* Read CONFIG0,CONFIG1 */
- numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG0, 0 , &config[0]);
- numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG1, 0 , &config[1]);
-
- LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32 "", config[0], config[1]);
-
- if ((config[0] & (1<<7)) == 0)
- LOG_INFO("CBS=0: Boot From LPROM");
- else
- LOG_INFO("CBS=1: Boot From APROM");
-
- if ((config[0] & CONFIG0_LOCK_MASK) == 0) {
-
- LOG_INFO("Flash is secure locked!");
- LOG_INFO("TO UNLOCK FLASH,EXECUTE chip_erase COMMAND!!");
- set = 1;
- } else {
- LOG_INFO("Flash is not locked!");
- set = 0;
- }
-
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_protected = set;
-
- return ERROR_OK;
-}
-
-
-static int numicro_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- uint32_t timeout, status;
- int i, retval = ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_INFO("Nuvoton NuMicro: Sector Erase ... (%d to %d)", first, last);
-
- retval = numicro_init_isp(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, ISPCMD_ERASE);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = first; i <= last; i++) {
- LOG_DEBUG("erasing sector %d at address 0x%" PRIx32 "", i, bank->base + bank->sectors[i].offset);
- retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + bank->sectors[i].offset);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO); /* This is the only bit available */
- if (retval != ERROR_OK)
- return retval;
-
- /* wait for busy to clear - check the GO flag */
- timeout = 100;
- for (;;) {
- retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if (status == 0)
- break;
- if (timeout-- <= 0) {
- LOG_DEBUG("timed out waiting for flash");
- return ERROR_FAIL;
- }
- busy_sleep(1); /* can use busy sleep for short times. */
- }
-
- /* check for failure */
- retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &status);
- if (retval != ERROR_OK)
- return retval;
- if ((status & ISPCON_ISPFF) != 0) {
- LOG_DEBUG("failure: 0x%" PRIx32 "", status);
- /* if bit is set, then must write to it to clear it. */
- retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, (status | ISPCON_ISPFF));
- if (retval != ERROR_OK)
- return retval;
- } else {
- bank->sectors[i].is_erased = 1;
- }
- }
-
- /* done, */
- LOG_DEBUG("Erase done.");
-
- return ERROR_OK;
-}
-
-/* The write routine stub. */
-static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t timeout, status;
- uint8_t *new_buffer = NULL;
- int retval = ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_INFO("Nuvoton NuMicro: Flash Write ...");
-
- retval = numicro_init_isp(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, ISPCMD_WRITE);
- if (retval != ERROR_OK)
- return retval;
-
- if (count & 0x3) {
- uint32_t old_count = count;
- count = (old_count | 3) + 1;
- new_buffer = malloc(count);
- if (new_buffer == NULL) {
- LOG_ERROR("odd number of bytes to write and no memory "
- "for padding buffer");
- return ERROR_FAIL;
- }
- LOG_INFO("odd number of bytes to write (%d), extending to %d "
- "and padding with 0xff", old_count, count);
- memset(new_buffer, 0xff, count);
- buffer = memcpy(new_buffer, buffer, old_count);
- }
-
- uint32_t words_remaining = count / 4;
-
- /* try using a block write */
- retval = numicro_writeblock(bank, buffer, offset, words_remaining);
-
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single word accesses */
- LOG_WARNING("couldn't use block writes, falling back to single "
- "memory accesses");
-
- /* program command */
- for (uint32_t i = 0; i < count; i += 4) {
-
- LOG_DEBUG("write longword @ %08X", offset + i);
-
- uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
- memcpy(padding, buffer + i, MIN(4, count-i));
-
- retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + offset + i);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_memory(target, NUMICRO_FLASH_ISPDAT, 4, 1, padding);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO);
- if (retval != ERROR_OK)
- return retval;
-
- /* wait for busy to clear - check the GO flag */
- timeout = 100;
- for (;;) {
- retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if (status == 0)
- break;
- if (timeout-- <= 0) {
- LOG_DEBUG("timed out waiting for flash");
- return ERROR_FAIL;
- }
- busy_sleep(1); /* can use busy sleep for short times. */
- }
-
- }
- }
-
- /* check for failure */
- retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &status);
- if (retval != ERROR_OK)
- return retval;
- if ((status & ISPCON_ISPFF) != 0) {
- LOG_DEBUG("failure: 0x%" PRIx32 "", status);
- /* if bit is set, then must write to it to clear it. */
- retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, (status | ISPCON_ISPFF));
- if (retval != ERROR_OK)
- return retval;
- } else {
- LOG_DEBUG("Write OK");
- }
-
- /* done. */
- LOG_DEBUG("Write done.");
-
- return ERROR_OK;
-}
-
-static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type** cpu)
-{
- uint32_t part_id;
- int retval = ERROR_OK;
-
- /* Read NuMicro PartID */
- retval = target_read_u32(target, NUMICRO_SYS_BASE, &part_id);
- if (retval != ERROR_OK) {
- LOG_WARNING("NuMicro flash driver: Failed to Get PartID\n");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- LOG_INFO("Device ID: 0x%08" PRIx32 "", part_id);
- /* search part numbers */
- for (size_t i = 0; i < sizeof(NuMicroParts)/sizeof(NuMicroParts[0]); i++) {
- if (part_id == NuMicroParts[i].partid) {
- *cpu = &NuMicroParts[i];
- LOG_INFO("Device Name: %s", (*cpu)->partname);
- return ERROR_OK;
- }
- }
-
- return ERROR_FAIL;
-}
-
-static int numicro_get_flash_size(struct flash_bank *bank, const struct numicro_cpu_type *cpu, uint32_t *flash_size)
-{
- for (size_t i = 0; i < cpu->n_banks; i++) {
- if (bank->base == cpu->bank[i].base) {
- *flash_size = cpu->bank[i].size;
- LOG_INFO("bank base = 0x%08" PRIx32 ", size = 0x%08" PRIx32 "", bank->base, *flash_size);
- return ERROR_OK;
- }
- }
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-static int numicro_probe(struct flash_bank *bank)
-{
- uint32_t flash_size, offset = 0;
- int num_pages;
- const struct numicro_cpu_type *cpu;
- struct target *target = bank->target;
- int retval = ERROR_OK;
-
- retval = numicro_get_cpu_type(target, &cpu);
- if (retval != ERROR_OK) {
- LOG_WARNING("NuMicro flash driver: Failed to detect a known part\n");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- retval = numicro_get_flash_size(bank, cpu, &flash_size);
- if (retval != ERROR_OK) {
- LOG_WARNING("NuMicro flash driver: Failed to detect flash size\n");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- num_pages = flash_size / NUMICRO_PAGESIZE;
-
- bank->num_sectors = num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
- bank->size = flash_size;
-
- for (int i = 0; i < num_pages; i++) {
- bank->sectors[i].offset = offset;
- bank->sectors[i].size = NUMICRO_PAGESIZE;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 0;
- offset += NUMICRO_PAGESIZE;
- }
-
- struct numicro_flash_bank *numicro_info = bank->driver_priv;
- numicro_info->probed = true;
- numicro_info->cpu = cpu;
- LOG_DEBUG("Nuvoton NuMicro: Probed ...");
-
- return ERROR_OK;
-}
-
-/* Standard approach to autoprobing. */
-static int numicro_auto_probe(struct flash_bank *bank)
-{
- struct numicro_flash_bank *numicro_info = bank->driver_priv;
- if (numicro_info->probed)
- return ERROR_OK;
- return numicro_probe(bank);
-}
-
-
-/* This is the function called in the config file. */
-FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
-{
- struct numicro_flash_bank *bank_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_DEBUG("add flash_bank numicro %s", bank->name);
-
- bank_info = malloc(sizeof(struct numicro_flash_bank));
-
- memset(bank_info, 0, sizeof(struct numicro_flash_bank));
-
- bank->driver_priv = bank_info;
-
- return ERROR_OK;
-
-}
-
-COMMAND_HANDLER(numicro_handle_read_isp_command)
-{
- uint32_t address;
- uint32_t ispdat;
- int retval = ERROR_OK;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
-
- struct target *target = get_current_target(CMD_CTX);
-
- retval = numicro_init_isp(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = numicro_fmc_cmd(target, ISPCMD_READ, address, 0, &ispdat);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(numicro_handle_write_isp_command)
-{
- uint32_t address;
- uint32_t ispdat, rdat;
- int retval = ERROR_OK;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat);
-
- struct target *target = get_current_target(CMD_CTX);
-
- retval = numicro_init_isp(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = numicro_fmc_cmd(target, ISPCMD_WRITE, address, ispdat, &rdat);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(numicro_handle_chip_erase_command)
-{
- int retval = ERROR_OK;
- uint32_t rdat;
-
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct target *target = get_current_target(CMD_CTX);
-
- retval = numicro_init_isp(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = numicro_fmc_cmd(target, ISPCMD_CHIPERASE, 0, 0, &rdat);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX, "numicro chip_erase failed");
- return retval;
- }
-
- command_print(CMD_CTX, "numicro chip_erase complete");
-
- return ERROR_OK;
-}
-
-static const struct command_registration numicro_exec_command_handlers[] = {
- {
- .name = "read_isp",
- .handler = numicro_handle_read_isp_command,
- .usage = "address",
- .mode = COMMAND_EXEC,
- .help = "read flash through ISP.",
- },
- {
- .name = "write_isp",
- .handler = numicro_handle_write_isp_command,
- .usage = "address value",
- .mode = COMMAND_EXEC,
- .help = "write flash through ISP.",
- },
- {
- .name = "chip_erase",
- .handler = numicro_handle_chip_erase_command,
- .mode = COMMAND_EXEC,
- .help = "chip erase through ISP.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration numicro_command_handlers[] = {
- {
- .name = "numicro",
- .mode = COMMAND_ANY,
- .help = "numicro flash command group",
- .usage = "",
- .chain = numicro_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver numicro_flash = {
- .name = "numicro",
- .commands = numicro_command_handlers,
- .flash_bank_command = numicro_flash_bank_command,
- .erase = numicro_erase,
- .write = numicro_write,
- .read = default_flash_read,
- .probe = numicro_probe,
- .auto_probe = numicro_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = numicro_protect_check,
-};
diff --git a/src/flash/nor/ocl.c b/src/flash/nor/ocl.c
deleted file mode 100644
index 4ae5652..0000000
--- a/src/flash/nor/ocl.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Pavel Chromy *
- * chromy@asix.cz *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "ocl.h"
-#include <target/embeddedice.h>
-
-struct ocl_priv {
- struct arm_jtag *jtag_info;
- unsigned int buflen;
- unsigned int bufalign;
-};
-
-static int ocl_erase_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-static int ocl_protect_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-/* flash_bank ocl 0 0 0 0 <target#> */
-FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
-{
- struct arm7_9_common *arm7_9;
- struct ocl_priv *ocl;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- arm7_9 = target_to_arm7_9(bank->target);
- if (!is_arm7_9(arm7_9))
- return ERROR_TARGET_INVALID;
-
- ocl = bank->driver_priv = malloc(sizeof(struct ocl_priv));
- ocl->jtag_info = &arm7_9->jtag_info;
- ocl->buflen = 0;
- ocl->bufalign = 1;
-
- return ERROR_OK;
-}
-
-static int ocl_erase(struct flash_bank *bank, int first, int last)
-{
- struct ocl_priv *ocl = bank->driver_priv;
- int retval;
- uint32_t dcc_buffer[3];
-
- /* check preconditions */
- if (bank->num_sectors == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (bank->target->state != TARGET_RUNNING) {
- LOG_ERROR("target has to be running to communicate with the loader");
- return ERROR_TARGET_NOT_RUNNING;
- }
-
- if ((first == 0) && (last == bank->num_sectors - 1)) {
- dcc_buffer[0] = OCL_ERASE_ALL;
- retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
- } else {
- dcc_buffer[0] = OCL_ERASE_BLOCK;
- dcc_buffer[1] = first;
- dcc_buffer[2] = last;
- retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* wait for response, fixed timeout of 1 s */
- retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
- if (retval != ERROR_OK)
- return retval;
-
- /* receive response */
- retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1);
- if (retval != ERROR_OK)
- return retval;
-
- if (dcc_buffer[1] != OCL_CMD_DONE) {
- if (dcc_buffer[0] == OCL_ERASE_ALL)
- LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
- else
- LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32 "", dcc_buffer[1]);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int ocl_protect(struct flash_bank *bank, int set, int first, int last)
-{
- return ERROR_OK;
-}
-
-static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct ocl_priv *ocl = bank->driver_priv;
- int retval;
- uint32_t *dcc_buffer;
- uint32_t *dcc_bufptr;
- int byteofs;
- int runlen;
- uint32_t chksum;
-
- int i;
-
- /* check preconditions */
- if (ocl->buflen == 0 || ocl->bufalign == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (bank->target->state != TARGET_RUNNING) {
- LOG_ERROR("target has to be running to communicate with the loader");
- return ERROR_TARGET_NOT_RUNNING;
- }
-
- /* allocate buffer for max. ocl buffer + overhead */
- dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
-
- while (count) {
- if (count + (offset % ocl->bufalign) > ocl->buflen)
- runlen = ocl->buflen - (offset % ocl->bufalign);
- else
- runlen = count;
-
- dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
- dcc_buffer[1] = offset;
- dcc_bufptr = &dcc_buffer[2];
-
- *dcc_bufptr = 0xffffffff;
- byteofs = (offset % ocl->bufalign) % 4;
- chksum = OCL_CHKS_INIT;
-
- /* copy data to DCC buffer in proper byte order and properly aligned */
- for (i = 0; i < runlen; i++) {
- switch (byteofs++) {
- case 0:
- *dcc_bufptr &= *(buffer++) | 0xffffff00;
- break;
- case 1:
- *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff;
- break;
- case 2:
- *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff;
- break;
- case 3:
- *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff;
- chksum ^= *(dcc_bufptr++);
- *dcc_bufptr = 0xffffffff;
- byteofs = 0;
- break;
- }
- }
-
- /* add the remaining word to checksum */
- if (byteofs)
- chksum ^= *(dcc_bufptr++);
-
- *(dcc_bufptr++) = chksum;
-
- /* send the data */
- retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer);
- if (retval != ERROR_OK) {
- free(dcc_buffer);
- return retval;
- }
-
- /* wait for response, fixed timeout of 1 s */
- retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
- if (retval != ERROR_OK) {
- free(dcc_buffer);
- return retval;
- }
-
- /* receive response */
- retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK) {
- free(dcc_buffer);
- return retval;
- }
-
- if (dcc_buffer[0] != OCL_CMD_DONE) {
- LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
- free(dcc_buffer);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- count -= runlen;
- offset += runlen;
- }
-
- free(dcc_buffer);
- return ERROR_OK;
-}
-
-static int ocl_probe(struct flash_bank *bank)
-{
- struct ocl_priv *ocl = bank->driver_priv;
- int retval;
- uint32_t dcc_buffer[1];
- int sectsize;
- int i;
-
- /* purge pending data in DCC */
- embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
-
- dcc_buffer[0] = OCL_PROBE;
- retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
-
- /* wait for response, fixed timeout of 1 s */
- retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
- if (retval != ERROR_OK)
- return retval;
-
- /* receive response */
- retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
-
- if (dcc_buffer[0] != OCL_CMD_DONE) {
- LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* receive and fill in parameters, detection of loader is important, receive it one by one */
- retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
- if (retval != ERROR_OK)
- return retval;
- retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
- bank->base = dcc_buffer[0];
-
- retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
- if (retval != ERROR_OK)
- return retval;
- retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
- bank->size = dcc_buffer[0];
-
- retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
- if (retval != ERROR_OK)
- return retval;
- retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
- bank->num_sectors = dcc_buffer[0];
-
- retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
- if (retval != ERROR_OK)
- return retval;
- retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
- ocl->buflen = dcc_buffer[0] & 0xffff;
- ocl->bufalign = dcc_buffer[0] >> 16;
-
- bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
- if (bank->num_sectors == 0) {
- LOG_ERROR("number of sectors shall be non zero value");
- return ERROR_FLASH_BANK_INVALID;
- }
- if (bank->size % bank->num_sectors) {
- LOG_ERROR("bank size not divisible by number of sectors");
- return ERROR_FLASH_BANK_INVALID;
- }
- sectsize = bank->size / bank->num_sectors;
- for (i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = i * sectsize;
- bank->sectors[i].size = sectsize;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- if (ocl->bufalign == 0)
- ocl->bufalign = 1;
-
- if (ocl->buflen == 0) {
- LOG_ERROR("buflen shall be non zero value");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) {
- LOG_ERROR("buflen is not multiple of bufalign");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- if (ocl->buflen % 4) {
- LOG_ERROR("buflen shall be divisible by 4");
- return ERROR_FLASH_BANK_INVALID;
- }
-
- return ERROR_OK;
-}
-
-static int ocl_auto_probe(struct flash_bank *bank)
-{
- struct ocl_priv *ocl = bank->driver_priv;
-
- if (ocl->buflen == 0 || ocl->bufalign == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- return ERROR_OK;
-}
-
-struct flash_driver ocl_flash = {
- .name = "ocl",
- .flash_bank_command = ocl_flash_bank_command,
- .erase = ocl_erase,
- .protect = ocl_protect,
- .write = ocl_write,
- .read = default_flash_read,
- .probe = ocl_probe,
- .erase_check = ocl_erase_check,
- .protect_check = ocl_protect_check,
- .auto_probe = ocl_auto_probe,
-};
diff --git a/src/flash/nor/ocl.h b/src/flash/nor/ocl.h
deleted file mode 100644
index 3e83f76..0000000
--- a/src/flash/nor/ocl.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Pavel Chromy *
- * chromy@asix.cz *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NOR_OCL_H
-#define OPENOCD_FLASH_NOR_OCL_H
-
-/* command/response mask */
-#define OCL_CMD_MASK 0xFFFF0000L
-
-/* commads */
-#define OCL_FLASH_BLOCK 0x0CFB0000L
-#define OCL_ERASE_BLOCK 0x0CEB0000L
-#define OCL_ERASE_ALL 0x0CEA0000L
-#define OCL_PROBE 0x0CBE0000L
-
-/* responses */
-#define OCL_CMD_DONE 0x0ACD0000L
-#define OCL_CMD_ERR 0x0ACE0000L
-#define OCL_CHKS_FAIL 0x0ACF0000L
-#define OCL_BUFF_OVER 0x0AB00000L
-
-#define OCL_CHKS_INIT 0xC100CD0CL
-
-#endif /* OPENOCD_FLASH_NOR_OCL_H */
diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c
deleted file mode 100644
index de212ed..0000000
--- a/src/flash/nor/pic32mx.c
+++ /dev/null
@@ -1,984 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by John McCarthy *
- * jgmcc@magma.ca *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/jtag.h>
-#include "imp.h"
-#include <target/algorithm.h>
-#include <target/mips32.h>
-#include <target/mips_m4k.h>
-
-#define PIC32MX_MANUF_ID 0x029
-
-/* pic32mx memory locations */
-
-#define PIC32MX_PHYS_RAM 0x00000000
-#define PIC32MX_PHYS_PGM_FLASH 0x1D000000
-#define PIC32MX_PHYS_PERIPHERALS 0x1F800000
-#define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000
-
-/*
- * Translate Virtual and Physical addresses.
- * Note: These macros only work for KSEG0/KSEG1 addresses.
- */
-
-#define Virt2Phys(v) ((v) & 0x1FFFFFFF)
-
-/* pic32mx configuration register locations */
-
-#define PIC32MX_DEVCFG0_1xx_2xx 0xBFC00BFC
-#define PIC32MX_DEVCFG0 0xBFC02FFC
-#define PIC32MX_DEVCFG1 0xBFC02FF8
-#define PIC32MX_DEVCFG2 0xBFC02FF4
-#define PIC32MX_DEVCFG3 0xBFC02FF0
-#define PIC32MX_DEVID 0xBF80F220
-
-#define PIC32MX_BMXPFMSZ 0xBF882060
-#define PIC32MX_BMXBOOTSZ 0xBF882070
-#define PIC32MX_BMXDRMSZ 0xBF882040
-
-/* pic32mx flash controller register locations */
-
-#define PIC32MX_NVMCON 0xBF80F400
-#define PIC32MX_NVMCONCLR 0xBF80F404
-#define PIC32MX_NVMCONSET 0xBF80F408
-#define PIC32MX_NVMCONINV 0xBF80F40C
-#define NVMCON_NVMWR (1 << 15)
-#define NVMCON_NVMWREN (1 << 14)
-#define NVMCON_NVMERR (1 << 13)
-#define NVMCON_LVDERR (1 << 12)
-#define NVMCON_LVDSTAT (1 << 11)
-#define NVMCON_OP_PFM_ERASE 0x5
-#define NVMCON_OP_PAGE_ERASE 0x4
-#define NVMCON_OP_ROW_PROG 0x3
-#define NVMCON_OP_WORD_PROG 0x1
-#define NVMCON_OP_NOP 0x0
-
-#define PIC32MX_NVMKEY 0xBF80F410
-#define PIC32MX_NVMADDR 0xBF80F420
-#define PIC32MX_NVMADDRCLR 0xBF80F424
-#define PIC32MX_NVMADDRSET 0xBF80F428
-#define PIC32MX_NVMADDRINV 0xBF80F42C
-#define PIC32MX_NVMDATA 0xBF80F430
-#define PIC32MX_NVMSRCADDR 0xBF80F440
-
-/* flash unlock keys */
-
-#define NVMKEY1 0xAA996655
-#define NVMKEY2 0x556699AA
-
-#define MX_1xx_2xx 1 /* PIC32mx1xx/2xx */
-#define MX_17x_27x 2 /* PIC32mx17x/27x */
-
-struct pic32mx_flash_bank {
- int probed;
- int dev_type; /* Default 0. 1 for Pic32MX1XX/2XX variant */
-};
-
-/*
- * DEVID values as per PIC32MX Flash Programming Specification Rev N
- */
-
-static const struct pic32mx_devs_s {
- uint32_t devid;
- const char *name;
-} pic32mx_devs[] = {
- {0x04A07053, "110F016B"},
- {0x04A09053, "110F016C"},
- {0x04A0B053, "110F016D"},
- {0x04A06053, "120F032B"},
- {0x04A08053, "120F032C"},
- {0x04A0A053, "120F032D"},
- {0x04D07053, "130F064B"},
- {0x04D09053, "130F064C"},
- {0x04D0B053, "130F064D"},
- {0x04D06053, "150F128B"},
- {0x04D08053, "150F128C"},
- {0x04D0A053, "150F128D"},
- {0x06610053, "170F256B"},
- {0x0661A053, "170F256D"},
- {0x04A01053, "210F016B"},
- {0x04A03053, "210F016C"},
- {0x04A05053, "210F016D"},
- {0x04A00053, "220F032B"},
- {0x04A02053, "220F032C"},
- {0x04A04053, "220F032D"},
- {0x04D01053, "230F064B"},
- {0x04D03053, "230F064C"},
- {0x04D05053, "230F064D"},
- {0x04D00053, "250F128B"},
- {0x04D02053, "250F128C"},
- {0x04D04053, "250F128D"},
- {0x06600053, "270F256B"},
- {0x0660A053, "270F256D"},
- {0x05600053, "330F064H"},
- {0x05601053, "330F064L"},
- {0x05602053, "430F064H"},
- {0x05603053, "430F064L"},
- {0x0570C053, "350F128H"},
- {0x0570D053, "350F128L"},
- {0x0570E053, "450F128H"},
- {0x0570F053, "450F128L"},
- {0x05704053, "350F256H"},
- {0x05705053, "350F256L"},
- {0x05706053, "450F256H"},
- {0x05707053, "450F256L"},
- {0x05808053, "370F512H"},
- {0x05809053, "370F512L"},
- {0x0580A053, "470F512H"},
- {0x0580B053, "470F512L"},
- {0x00938053, "360F512L"},
- {0x00934053, "360F256L"},
- {0x0092D053, "340F128L"},
- {0x0092A053, "320F128L"},
- {0x00916053, "340F512H"},
- {0x00912053, "340F256H"},
- {0x0090D053, "340F128H"},
- {0x0090A053, "320F128H"},
- {0x00906053, "320F064H"},
- {0x00902053, "320F032H"},
- {0x00978053, "460F512L"},
- {0x00974053, "460F256L"},
- {0x0096D053, "440F128L"},
- {0x00952053, "440F256H"},
- {0x00956053, "440F512H"},
- {0x0094D053, "440F128H"},
- {0x00942053, "420F032H"},
- {0x04307053, "795F512L"},
- {0x0430E053, "795F512H"},
- {0x04306053, "775F512L"},
- {0x0430D053, "775F512H"},
- {0x04312053, "775F256L"},
- {0x04303053, "775F256H"},
- {0x04417053, "764F128L"},
- {0x0440B053, "764F128H"},
- {0x04341053, "695F512L"},
- {0x04325053, "695F512H"},
- {0x04311053, "675F512L"},
- {0x0430C053, "675F512H"},
- {0x04305053, "675F256L"},
- {0x0430B053, "675F256H"},
- {0x04413053, "664F128L"},
- {0x04407053, "664F128H"},
- {0x04411053, "664F064L"},
- {0x04405053, "664F064H"},
- {0x0430F053, "575F512L"},
- {0x04309053, "575F512H"},
- {0x04333053, "575F256L"},
- {0x04317053, "575F256H"},
- {0x0440F053, "564F128L"},
- {0x04403053, "564F128H"},
- {0x0440D053, "564F064L"},
- {0x04401053, "564F064H"},
- {0x04400053, "534F064H"},
- {0x0440C053, "534F064L"},
- {0x00000000, NULL}
-};
-
-/* flash bank pic32mx <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
-{
- struct pic32mx_flash_bank *pic32mx_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
- bank->driver_priv = pic32mx_info;
-
- pic32mx_info->probed = 0;
- pic32mx_info->dev_type = 0;
-
- return ERROR_OK;
-}
-
-static uint32_t pic32mx_get_flash_status(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- uint32_t status;
-
- target_read_u32(target, PIC32MX_NVMCON, &status);
-
- return status;
-}
-
-static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout)
-{
- uint32_t status;
-
- /* wait for busy to clear */
- while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) {
- LOG_DEBUG("status: 0x%" PRIx32, status);
- alive_sleep(1);
- }
- if (timeout <= 0)
- LOG_DEBUG("timeout: status: 0x%" PRIx32, status);
-
- return status;
-}
-
-static int pic32mx_nvm_exec(struct flash_bank *bank, uint32_t op, uint32_t timeout)
-{
- struct target *target = bank->target;
- uint32_t status;
-
- target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN | op);
-
- /* unlock flash registers */
- target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1);
- target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2);
-
- /* start operation */
- target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR);
-
- status = pic32mx_wait_status_busy(bank, timeout);
-
- /* lock flash registers */
- target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN);
-
- return status;
-}
-
-static int pic32mx_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
-
- uint32_t config0_address;
- uint32_t devcfg0;
- int s;
- int num_pages;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- switch (pic32mx_info->dev_type) {
- case MX_1xx_2xx:
- case MX_17x_27x:
- config0_address = PIC32MX_DEVCFG0_1xx_2xx;
- break;
- default:
- config0_address = PIC32MX_DEVCFG0;
- break;
- }
-
- target_read_u32(target, config0_address, &devcfg0);
-
- if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
- num_pages = 0xffff; /* All pages protected */
- else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
- if (devcfg0 & (1 << 24))
- num_pages = 0; /* All pages unprotected */
- else
- num_pages = 0xffff; /* All pages protected */
- } else {
- /* pgm flash */
- switch (pic32mx_info->dev_type) {
- case MX_1xx_2xx:
- num_pages = (~devcfg0 >> 10) & 0x7f;
- break;
- case MX_17x_27x:
- num_pages = (~devcfg0 >> 10) & 0x1ff;
- break;
- default:
- num_pages = (~devcfg0 >> 12) & 0xff;
- break;
- }
- }
-
- for (s = 0; s < bank->num_sectors && s < num_pages; s++)
- bank->sectors[s].is_protected = 1;
- for (; s < bank->num_sectors; s++)
- bank->sectors[s].is_protected = 0;
-
- return ERROR_OK;
-}
-
-static int pic32mx_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- int i;
- uint32_t status;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first == 0) && (last == (bank->num_sectors - 1))
- && (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) {
- /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
- * we need to use the MTAP to perform a full erase */
- LOG_DEBUG("Erasing entire program flash");
- status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50);
- if (status & NVMCON_NVMERR)
- return ERROR_FLASH_OPERATION_FAILED;
- if (status & NVMCON_LVDERR)
- return ERROR_FLASH_OPERATION_FAILED;
- return ERROR_OK;
- }
-
- for (i = first; i <= last; i++) {
- target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset));
-
- status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
-
- if (status & NVMCON_NVMERR)
- return ERROR_FLASH_OPERATION_FAILED;
- if (status & NVMCON_LVDERR)
- return ERROR_FLASH_OPERATION_FAILED;
- bank->sectors[i].is_erased = 1;
- }
-
- return ERROR_OK;
-}
-
-static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- return ERROR_OK;
-}
-
-/* see contib/loaders/flash/pic32mx.s for src */
-
-static uint32_t pic32mx_flash_write_code[] = {
- /* write: */
- 0x3C08AA99, /* lui $t0, 0xaa99 */
- 0x35086655, /* ori $t0, 0x6655 */
- 0x3C095566, /* lui $t1, 0x5566 */
- 0x352999AA, /* ori $t1, 0x99aa */
- 0x3C0ABF80, /* lui $t2, 0xbf80 */
- 0x354AF400, /* ori $t2, 0xf400 */
- 0x340B4003, /* ori $t3, $zero, 0x4003 */
- 0x340C8000, /* ori $t4, $zero, 0x8000 */
- /* write_row: */
- 0x2CD30080, /* sltiu $s3, $a2, 128 */
- 0x16600008, /* bne $s3, $zero, write_word */
- 0x340D4000, /* ori $t5, $zero, 0x4000 */
- 0xAD450020, /* sw $a1, 32($t2) */
- 0xAD440040, /* sw $a0, 64($t2) */
- 0x04110016, /* bal progflash */
- 0x24840200, /* addiu $a0, $a0, 512 */
- 0x24A50200, /* addiu $a1, $a1, 512 */
- 0x1000FFF7, /* beq $zero, $zero, write_row */
- 0x24C6FF80, /* addiu $a2, $a2, -128 */
- /* write_word: */
- 0x3C15A000, /* lui $s5, 0xa000 */
- 0x36B50000, /* ori $s5, $s5, 0x0 */
- 0x00952025, /* or $a0, $a0, $s5 */
- 0x10000008, /* beq $zero, $zero, next_word */
- 0x340B4001, /* ori $t3, $zero, 0x4001 */
- /* prog_word: */
- 0x8C940000, /* lw $s4, 0($a0) */
- 0xAD540030, /* sw $s4, 48($t2) */
- 0xAD450020, /* sw $a1, 32($t2) */
- 0x04110009, /* bal progflash */
- 0x24840004, /* addiu $a0, $a0, 4 */
- 0x24A50004, /* addiu $a1, $a1, 4 */
- 0x24C6FFFF, /* addiu $a2, $a2, -1 */
- /* next_word: */
- 0x14C0FFF8, /* bne $a2, $zero, prog_word */
- 0x00000000, /* nop */
- /* done: */
- 0x10000002, /* beq $zero, $zero, exit */
- 0x24040000, /* addiu $a0, $zero, 0 */
- /* error: */
- 0x26240000, /* addiu $a0, $s1, 0 */
- /* exit: */
- 0x7000003F, /* sdbbp */
- /* progflash: */
- 0xAD4B0000, /* sw $t3, 0($t2) */
- 0xAD480010, /* sw $t0, 16($t2) */
- 0xAD490010, /* sw $t1, 16($t2) */
- 0xAD4C0008, /* sw $t4, 8($t2) */
- /* waitflash: */
- 0x8D500000, /* lw $s0, 0($t2) */
- 0x020C8024, /* and $s0, $s0, $t4 */
- 0x1600FFFD, /* bne $s0, $zero, waitflash */
- 0x00000000, /* nop */
- 0x00000000, /* nop */
- 0x00000000, /* nop */
- 0x00000000, /* nop */
- 0x00000000, /* nop */
- 0x8D510000, /* lw $s1, 0($t2) */
- 0x30113000, /* andi $s1, $zero, 0x3000 */
- 0x1620FFEF, /* bne $s1, $zero, error */
- 0xAD4D0004, /* sw $t5, 4($t2) */
- 0x03E00008, /* jr $ra */
- 0x00000000 /* nop */
-};
-
-static int pic32mx_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[3];
- uint32_t row_size;
- int retval = ERROR_OK;
-
- struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
- struct mips32_algorithm mips32_info;
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* Change values for counters and row size, depending on variant */
- switch (pic32mx_info->dev_type) {
- case MX_1xx_2xx:
- case MX_17x_27x:
- /* 128 byte row */
- pic32mx_flash_write_code[8] = 0x2CD30020;
- pic32mx_flash_write_code[14] = 0x24840080;
- pic32mx_flash_write_code[15] = 0x24A50080;
- pic32mx_flash_write_code[17] = 0x24C6FFE0;
- row_size = 128;
- break;
- default:
- /* 512 byte row */
- pic32mx_flash_write_code[8] = 0x2CD30080;
- pic32mx_flash_write_code[14] = 0x24840200;
- pic32mx_flash_write_code[15] = 0x24A50200;
- pic32mx_flash_write_code[17] = 0x24C6FF80;
- row_size = 512;
- break;
- }
-
- uint8_t code[sizeof(pic32mx_flash_write_code)];
- target_buffer_set_u32_array(target, code, ARRAY_SIZE(pic32mx_flash_write_code),
- pic32mx_flash_write_code);
- retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- mips32_info.common_magic = MIPS32_COMMON_MAGIC;
- mips32_info.isa_mode = MIPS32_ISA_MIPS32;
-
- init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
- init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
- init_reg_param(&reg_params[2], "r6", 32, PARAM_OUT);
-
- int row_offset = offset % row_size;
- uint8_t *new_buffer = NULL;
- if (row_offset && (count >= (row_size / 4))) {
- new_buffer = malloc(buffer_size);
- if (new_buffer == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- memset(new_buffer, 0xff, row_offset);
- address -= row_offset;
- } else
- row_offset = 0;
-
- while (count > 0) {
- uint32_t status;
- uint32_t thisrun_count;
-
- if (row_offset) {
- thisrun_count = (count > ((buffer_size - row_offset) / 4)) ?
- ((buffer_size - row_offset) / 4) : count;
-
- memcpy(new_buffer + row_offset, buffer, thisrun_count * 4);
-
- retval = target_write_buffer(target, source->address,
- row_offset + thisrun_count * 4, new_buffer);
- if (retval != ERROR_OK)
- break;
- } else {
- thisrun_count = (count > (buffer_size / 4)) ?
- (buffer_size / 4) : count;
-
- retval = target_write_buffer(target, source->address,
- thisrun_count * 4, buffer);
- if (retval != ERROR_OK)
- break;
- }
-
- buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address));
- buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address));
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count + row_offset / 4);
-
- retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- write_algorithm->address,
- 0, 10000, &mips32_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("error executing pic32mx flash write algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- status = buf_get_u32(reg_params[0].value, 0, 32);
-
- if (status & NVMCON_NVMERR) {
- LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- if (status & NVMCON_LVDERR) {
- LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- buffer += thisrun_count * 4;
- address += thisrun_count * 4;
- count -= thisrun_count;
- if (row_offset) {
- address += row_offset;
- row_offset = 0;
- }
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- if (new_buffer != NULL)
- free(new_buffer);
- return retval;
-}
-
-static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_t word)
-{
- struct target *target = bank->target;
-
- target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(address));
- target_write_u32(target, PIC32MX_NVMDATA, word);
-
- return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5);
-}
-
-static int pic32mx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- uint32_t words_remaining = (count / 4);
- uint32_t bytes_remaining = (count & 0x00000003);
- uint32_t address = bank->base + offset;
- uint32_t bytes_written = 0;
- uint32_t status;
- int retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32
- " count: 0x%8.8" PRIx32 "", bank->base, offset, count);
-
- if (offset & 0x3) {
- LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* multiple words (4-byte) to be programmed? */
- if (words_remaining > 0) {
- /* try using a block write */
- retval = pic32mx_write_block(bank, buffer, offset, words_remaining);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single dword accesses */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
- } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("flash writing failed");
- return retval;
- }
- } else {
- buffer += words_remaining * 4;
- address += words_remaining * 4;
- words_remaining = 0;
- }
- }
-
- while (words_remaining > 0) {
- uint32_t value;
- memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
-
- status = pic32mx_write_word(bank, address, value);
-
- if (status & NVMCON_NVMERR) {
- LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (status & NVMCON_LVDERR) {
- LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- bytes_written += 4;
- words_remaining--;
- address += 4;
- }
-
- if (bytes_remaining) {
- uint32_t value = 0xffffffff;
- memcpy(&value, buffer + bytes_written, bytes_remaining);
-
- status = pic32mx_write_word(bank, address, value);
-
- if (status & NVMCON_NVMERR) {
- LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (status & NVMCON_LVDERR) {
- LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- }
-
- return ERROR_OK;
-}
-
-static int pic32mx_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
- struct mips32_common *mips32 = target->arch_info;
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- int i;
- uint32_t num_pages = 0;
- uint32_t device_id;
- int page_size;
-
- pic32mx_info->probed = 0;
-
- device_id = ejtag_info->idcode;
- LOG_INFO("device id = 0x%08" PRIx32 " (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
- device_id,
- (unsigned)((device_id >> 1) & 0x7ff),
- (unsigned)((device_id >> 12) & 0xffff),
- (unsigned)((device_id >> 28) & 0xf));
-
- if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
- LOG_WARNING("Cannot identify target as a PIC32MX family.");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* Check for PIC32mx1xx/2xx */
- for (i = 0; pic32mx_devs[i].name != NULL; i++) {
- if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
- if ((pic32mx_devs[i].name[0] == '1') || (pic32mx_devs[i].name[0] == '2'))
- pic32mx_info->dev_type = (pic32mx_devs[i].name[1] == '7') ? MX_17x_27x : MX_1xx_2xx;
- break;
- }
- }
-
- switch (pic32mx_info->dev_type) {
- case MX_1xx_2xx:
- case MX_17x_27x:
- page_size = 1024;
- break;
- default:
- page_size = 4096;
- break;
- }
-
- if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
- /* 0x1FC00000: Boot flash size */
-#if 0
- /* for some reason this register returns 8k for the boot bank size
- * this does not match the docs, so for now set the boot bank at a
- * fixed 12k */
- if (target_read_u32(target, PIC32MX_BMXBOOTSZ, &num_pages) != ERROR_OK) {
- LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
- num_pages = (12 * 1024);
- }
-#else
- /* fixed 12k boot bank - see comments above */
- switch (pic32mx_info->dev_type) {
- case MX_1xx_2xx:
- case MX_17x_27x:
- num_pages = (3 * 1024);
- break;
- default:
- num_pages = (12 * 1024);
- break;
- }
-#endif
- } else {
- /* read the flash size from the device */
- if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
- switch (pic32mx_info->dev_type) {
- case MX_1xx_2xx:
- case MX_17x_27x:
- LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash");
- num_pages = (32 * 1024);
- break;
- default:
- LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
- num_pages = (512 * 1024);
- break;
- }
- }
- }
-
- LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024);
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- /* calculate numbers of pages */
- num_pages /= page_size;
- bank->size = (num_pages * page_size);
- bank->num_sectors = num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
-
- for (i = 0; i < (int)num_pages; i++) {
- bank->sectors[i].offset = i * page_size;
- bank->sectors[i].size = page_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- pic32mx_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int pic32mx_auto_probe(struct flash_bank *bank)
-{
- struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
- if (pic32mx_info->probed)
- return ERROR_OK;
- return pic32mx_probe(bank);
-}
-
-static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct target *target = bank->target;
- struct mips32_common *mips32 = target->arch_info;
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- uint32_t device_id;
- int printed = 0, i;
-
- device_id = ejtag_info->idcode;
-
- if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
- snprintf(buf, buf_size,
- "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
- (unsigned)((device_id >> 1) & 0x7ff),
- PIC32MX_MANUF_ID);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- for (i = 0; pic32mx_devs[i].name != NULL; i++) {
- if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
- printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
- break;
- }
- }
-
- if (pic32mx_devs[i].name == NULL)
- printed = snprintf(buf, buf_size, "Unknown");
-
- buf += printed;
- buf_size -= printed;
- snprintf(buf, buf_size, " Ver: 0x%02x",
- (unsigned)((device_id >> 28) & 0xf));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
-{
- uint32_t address, value;
- int status, res;
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 2, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (address < bank->base || address >= (bank->base + bank->size)) {
- command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- res = ERROR_OK;
- status = pic32mx_write_word(bank, address, value);
- if (status & NVMCON_NVMERR)
- res = ERROR_FLASH_OPERATION_FAILED;
- if (status & NVMCON_LVDERR)
- res = ERROR_FLASH_OPERATION_FAILED;
-
- if (res == ERROR_OK)
- command_print(CMD_CTX, "pic32mx pgm word complete");
- else
- command_print(CMD_CTX, "pic32mx pgm word failed (status = 0x%x)", status);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(pic32mx_handle_unlock_command)
-{
- uint32_t mchip_cmd;
- struct target *target = NULL;
- struct mips_m4k_common *mips_m4k;
- struct mips_ejtag *ejtag_info;
- int timeout = 10;
-
- if (CMD_ARGC < 1) {
- command_print(CMD_CTX, "pic32mx unlock <bank>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- target = bank->target;
- mips_m4k = target_to_m4k(target);
- ejtag_info = &mips_m4k->mips32.ejtag_info;
-
- /* we have to use the MTAP to perform a full erase */
- mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
- mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
-
- /* first check status of device */
- mchip_cmd = MCHP_STATUS;
- mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
- if (mchip_cmd & (1 << 7)) {
- /* device is not locked */
- command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway");
- }
-
- /* unlock/erase device */
- mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
- jtag_add_sleep(200);
-
- mips_ejtag_drscan_8_out(ejtag_info, MCHP_ERASE);
-
- do {
- mchip_cmd = MCHP_STATUS;
- mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
- if (timeout-- == 0) {
- LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd);
- break;
- }
- alive_sleep(1);
- } while ((mchip_cmd & (1 << 2)) || (!(mchip_cmd & (1 << 3))));
-
- mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
-
- /* select ejtag tap */
- mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
-
- command_print(CMD_CTX, "pic32mx unlocked.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.");
-
- return ERROR_OK;
-}
-
-static const struct command_registration pic32mx_exec_command_handlers[] = {
- {
- .name = "pgm_word",
- .usage = "<addr> <value> <bank>",
- .handler = pic32mx_handle_pgm_word_command,
- .mode = COMMAND_EXEC,
- .help = "program a word",
- },
- {
- .name = "unlock",
- .handler = pic32mx_handle_unlock_command,
- .mode = COMMAND_EXEC,
- .usage = "[bank_id]",
- .help = "Unlock/Erase entire device.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration pic32mx_command_handlers[] = {
- {
- .name = "pic32mx",
- .mode = COMMAND_ANY,
- .help = "pic32mx flash command group",
- .usage = "",
- .chain = pic32mx_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver pic32mx_flash = {
- .name = "pic32mx",
- .commands = pic32mx_command_handlers,
- .flash_bank_command = pic32mx_flash_bank_command,
- .erase = pic32mx_erase,
- .protect = pic32mx_protect,
- .write = pic32mx_write,
- .read = default_flash_read,
- .probe = pic32mx_probe,
- .auto_probe = pic32mx_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = pic32mx_protect_check,
- .info = pic32mx_info,
-};
diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c
deleted file mode 100644
index c7c8573..0000000
--- a/src/flash/nor/psoc4.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * Copyright (C) 2014 by Tomas Vanek (PSoC 4 support derived from STM32) *
- * vanekt@fbl.cz *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <jtag/jtag.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-/* device documets:
-
- PSoC(R) 4: PSoC 4200 Family Datasheet
- Document Number: 001-87197 Rev. *B Revised August 29, 2013
-
- PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM
- Document No. 001-85634 Rev. *C March 25, 2014
-
- PSoC(R) 4 Registers TRM Spec.
- Document No. 001-85847 Rev. *A June 25, 2013
-
- CY8C41xx, CY8C42xx Programming Specifications
- Document No. 001-81799 Rev. *C March 4, 2014
-*/
-
-/* register locations */
-#define PSOC4_CPUSS_SYSREQ 0x40000004
-#define PSOC4_CPUSS_SYSARG 0x40000008
-#define PSOC4_TEST_MODE 0x40030014
-#define PSOC4_SPCIF_GEOMETRY 0x400E0000
-
-#define PSOC4_SFLASH_MACRO 0x0ffff000
-
-/* constants */
-#define PSOC4_SROM_KEY1 0xb6
-#define PSOC4_SROM_KEY2 0xd3
-#define PSOC4_SROM_SYSREQ_BIT (1<<31)
-#define PSOC4_SROM_HMASTER_BIT (1<<30)
-#define PSOC4_SROM_PRIVILEGED_BIT (1<<28)
-#define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000
-#define PSOC4_SROM_STATUS_FAILED 0xf0000000
-
-#define PSOC4_CMD_GET_SILICON_ID 0
-#define PSOC4_CMD_LOAD_LATCH 4
-#define PSOC4_CMD_WRITE_ROW 5
-#define PSOC4_CMD_PROGRAM_ROW 6
-#define PSOC4_CMD_ERASE_ALL 0xa
-#define PSOC4_CMD_CHECKSUM 0xb
-#define PSOC4_CMD_WRITE_PROTECTION 0xd
-
-#define PSOC4_CHIP_PROT_VIRGIN 0x0
-#define PSOC4_CHIP_PROT_OPEN 0x1
-#define PSOC4_CHIP_PROT_PROTECTED 0x2
-#define PSOC4_CHIP_PROT_KILL 0x4
-
-
-struct psoc4_chip_details {
- uint16_t id;
- const char *type;
- const char *package;
- uint32_t flash_size_in_kb;
-};
-
-/* list of PSoC 4 chips
- * flash_size_in_kb is not necessary as it can be decoded from SPCIF_GEOMETRY
- */
-const struct psoc4_chip_details psoc4_devices[] = {
- /* 4200 series */
- { 0x04A6, "CY8C4245PVI-482", "SSOP-28", .flash_size_in_kb = 32 },
- { 0x04B6, "CY8C4245LQI-483", "QFN-40", .flash_size_in_kb = 32 },
- { 0x04C8, "CY8C4245AXI-483", "TQFP-44", .flash_size_in_kb = 32 },
- { 0x04FB, "CY8C4245AXI-473", "TQFP-44", .flash_size_in_kb = 32 },
- { 0x04F0, "CY8C4244PVI-432", "SSOP-28", .flash_size_in_kb = 16 },
- { 0x04F1, "CY8C4244PVI-442", "SSOP-28", .flash_size_in_kb = 16 },
- { 0x04F6, "CY8C4244LQI-443", "QFN-40", .flash_size_in_kb = 16 },
- { 0x04FA, "CY8C4244AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
-
- /* 4100 series */
- { 0x0410, "CY8C4124PVI-432", "SSOP-28", .flash_size_in_kb = 16 },
- { 0x0411, "CY8C4124PVI-442", "SSOP-28", .flash_size_in_kb = 16 },
- { 0x041C, "CY8C4124LQI-443", "QFN-40", .flash_size_in_kb = 16 },
- { 0x041A, "CY8C4124AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
- { 0x041B, "CY8C4125AXI-473", "TQFP-44", .flash_size_in_kb = 32 },
- { 0x0412, "CY8C4125PVI-482", "SSOP-28", .flash_size_in_kb = 32 },
- { 0x0417, "CY8C4125LQI-483", "QFN-40", .flash_size_in_kb = 32 },
- { 0x0416, "CY8C4125AXI-483", "TQFP-44", .flash_size_in_kb = 32 },
-
- /* CCG1 series */
- { 0x0490, "CYPD1103-35FNXI", "CSP-35", .flash_size_in_kb = 32 },
- { 0x0489, "CYPD1121-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
- { 0x048A, "CYPD1122-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
- { 0x0491, "CYPD1131-35FNXI", "CSP-35", .flash_size_in_kb = 32 },
- { 0x0498, "CYPD1132-16SXI", "SOIC-16", .flash_size_in_kb = 32 },
- { 0x0481, "CYPD1134-28PVXI", "SSOP-28", .flash_size_in_kb = 32 },
- { 0x048B, "CYPD1134-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
-};
-
-
-struct psoc4_flash_bank {
- uint32_t row_size;
- uint32_t user_bank_size;
- int probed;
- uint32_t silicon_id;
- uint8_t chip_protection;
- uint8_t cmd_program_row;
-};
-
-
-static const struct psoc4_chip_details *psoc4_details_by_id(uint32_t silicon_id)
-{
- const struct psoc4_chip_details *p = psoc4_devices;
- unsigned int i;
- uint16_t id = silicon_id >> 16; /* ignore die revision */
- for (i = 0; i < sizeof(psoc4_devices)/sizeof(psoc4_devices[0]); i++, p++) {
- if (p->id == id)
- return p;
- }
- LOG_DEBUG("Unknown PSoC 4 device silicon id 0x%08" PRIx32 ".", silicon_id);
- return NULL;
-}
-
-static const char *psoc4_decode_chip_protection(uint8_t protection)
-{
- switch (protection) {
- case PSOC4_CHIP_PROT_VIRGIN:
- return "protection VIRGIN";
- case PSOC4_CHIP_PROT_OPEN:
- return "protection open";
- case PSOC4_CHIP_PROT_PROTECTED:
- return "PROTECTED";
- case PSOC4_CHIP_PROT_KILL:
- return "protection KILL";
- default:
- LOG_WARNING("Unknown protection state 0x%02" PRIx8 "", protection);
- return "";
- }
-}
-
-
-/* flash bank <name> psoc <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
-{
- struct psoc4_flash_bank *psoc4_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank));
-
- bank->driver_priv = psoc4_info;
- psoc4_info->user_bank_size = bank->size;
-
- return ERROR_OK;
-}
-
-
-/* PSoC 4 system ROM request
- * Setting SROM_SYSREQ_BIT in CPUSS_SYSREQ register runs NMI service
- * in sysrem ROM. Algorithm just waits for NMI to finish.
- * When sysreq_params_size == 0 only one parameter is passed in CPUSS_SYSARG register.
- * Otherwise address of memory parameter block is set in CPUSS_SYSARG
- * and the first parameter is written to the first word of parameter block
- */
-static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
- uint32_t *sysreq_params, uint32_t sysreq_params_size)
-{
- struct working_area *sysreq_wait_algorithm;
- struct working_area *sysreq_mem;
-
- struct reg_param reg_params[1];
- struct armv7m_algorithm armv7m_info;
-
- int retval = ERROR_OK;
-
- uint32_t param1 = PSOC4_SROM_KEY1
- | ((PSOC4_SROM_KEY2 + cmd) << 8)
- | (cmd_param << 16);
-
- static uint8_t psoc4_sysreq_wait_code[] = {
- /* system request NMI is served immediately after algo run
- now we are done: break */
- 0x00, 0xbe, /* bkpt 0 */
- };
-
- const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4;
- /* stack must be aligned */
- const int stack_size = 196;
- /* tested stack sizes on PSoC 4:
- ERASE_ALL 144
- PROGRAM_ROW 112
- other sysreq 68
- */
-
- /* allocate area for sysreq wait code and stack */
- if (target_alloc_working_area(target, code_words * 4 + stack_size,
- &sysreq_wait_algorithm) != ERROR_OK) {
- LOG_DEBUG("no working area for sysreq code");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* Write the code */
- retval = target_write_buffer(target,
- sysreq_wait_algorithm->address,
- sizeof(psoc4_sysreq_wait_code),
- psoc4_sysreq_wait_code);
- if (retval != ERROR_OK) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- goto cleanup_algo;
- }
-
- if (sysreq_params_size) {
- /* Allocate memory for sysreq_params */
- retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem);
- if (retval != ERROR_OK) {
- LOG_WARNING("no working area for sysreq parameters");
-
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto cleanup_algo;
- }
-
- /* Write sysreq_params */
- sysreq_params[0] = param1;
- retval = target_write_buffer(target, sysreq_mem->address,
- sysreq_params_size, (uint8_t *)sysreq_params);
- if (retval != ERROR_OK)
- goto cleanup_mem;
-
- /* Set address of sysreq parameters block */
- retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, sysreq_mem->address);
- if (retval != ERROR_OK)
- goto cleanup_mem;
-
- } else {
- /* Sysreq without memory block of parameters */
- /* Set register parameter */
- retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, param1);
- if (retval != ERROR_OK)
- goto cleanup_mem;
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- /* sysreq stack */
- init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
- buf_set_u32(reg_params[0].value, 0, 32,
- sysreq_wait_algorithm->address + sysreq_wait_algorithm->size);
-
- struct armv7m_common *armv7m = target_to_armv7m(target);
- if (armv7m == NULL) {
-
- /* something is very wrong if armv7m is NULL */
- LOG_ERROR("unable to get armv7m target");
- goto cleanup;
- }
-
- /* Set SROM request */
- retval = target_write_u32(target, PSOC4_CPUSS_SYSREQ,
- PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd);
- if (retval != ERROR_OK)
- goto cleanup;
-
- /* Execute wait code */
- retval = target_run_algorithm(target, 0, NULL,
- sizeof(reg_params) / sizeof(*reg_params), reg_params,
- sysreq_wait_algorithm->address, 0, 1000, &armv7m_info);
- if (retval != ERROR_OK)
- LOG_ERROR("sysreq wait code execution failed");
-
-cleanup:
- destroy_reg_param(&reg_params[0]);
-
-cleanup_mem:
- if (sysreq_params_size)
- target_free_working_area(target, sysreq_mem);
-
-cleanup_algo:
- target_free_working_area(target, sysreq_wait_algorithm);
-
- return retval;
-}
-
-
-/* helper routine to get silicon ID from a PSoC 4 chip */
-static int psoc4_get_silicon_id(struct target *target, uint32_t *silicon_id, uint8_t *protection)
-{
- uint32_t params = PSOC4_SROM_KEY1
- | ((PSOC4_SROM_KEY2 + PSOC4_CMD_GET_SILICON_ID) << 8);
- uint32_t part0, part1;
-
- int retval = psoc4_sysreq(target, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, PSOC4_CPUSS_SYSARG, &part0);
- if (retval != ERROR_OK)
- return retval;
-
- if (part0 == params) {
- LOG_ERROR("sysreq silicon id request not served");
- return ERROR_FAIL;
- }
-
- retval = target_read_u32(target, PSOC4_CPUSS_SYSREQ, &part1);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t silicon = ((part0 & 0xffff) << 16)
- | (((part0 >> 16) & 0xff) << 8)
- | (part1 & 0xff);
- uint8_t prot = (part1 >> 12) & 0xff;
-
- if (silicon_id)
- *silicon_id = silicon;
- if (protection)
- *protection = prot;
-
- LOG_DEBUG("silicon id: 0x%08" PRIx32 "", silicon);
- LOG_DEBUG("protection: 0x%02" PRIx8 "", prot);
- return retval;
-}
-
-
-static int psoc4_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
-
- uint32_t prot_addr = PSOC4_SFLASH_MACRO;
- uint32_t protection;
- int i, s;
- int num_bits;
- int retval = ERROR_OK;
-
- num_bits = bank->num_sectors;
-
- for (i = 0; i < num_bits; i += 32) {
- retval = target_read_u32(target, prot_addr, &protection);
- if (retval != ERROR_OK)
- return retval;
-
- prot_addr += 4;
-
- for (s = 0; s < 32; s++) {
- if (i + s >= num_bits)
- break;
- bank->sectors[i + s].is_protected = (protection & (1 << s)) ? 1 : 0;
- }
- }
-
- retval = psoc4_get_silicon_id(target, NULL, &(psoc4_info->chip_protection));
- return retval;
-}
-
-
-static int psoc4_mass_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int i;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Call "Erase All" system ROM API */
- uint32_t param;
- int retval = psoc4_sysreq(target, PSOC4_CMD_ERASE_ALL,
- 0,
- &param, sizeof(param));
-
- if (retval == ERROR_OK)
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- return retval;
-}
-
-
-static int psoc4_erase(struct flash_bank *bank, int first, int last)
-{
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
- if (psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW) {
- LOG_INFO("Autoerase enabled, erase command ignored");
- return ERROR_OK;
- }
-
- if ((first == 0) && (last == (bank->num_sectors - 1)))
- return psoc4_mass_erase(bank);
-
- LOG_ERROR("Only mass erase available");
-
- return ERROR_FAIL;
-}
-
-
-static int psoc4_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct target *target = bank->target;
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
-
- if (psoc4_info->probed == 0)
- return ERROR_FAIL;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t *sysrq_buffer = NULL;
- int retval;
- int num_bits = bank->num_sectors;
- const int param_sz = 8;
- int prot_sz = num_bits / 8;
- int chip_prot = PSOC4_CHIP_PROT_OPEN;
- int flash_macro = 0; /* PSoC 42xx has only macro 0 */
- int i;
-
- sysrq_buffer = calloc(1, param_sz + prot_sz);
- if (sysrq_buffer == NULL) {
- LOG_ERROR("no memory for row buffer");
- return ERROR_FAIL;
- }
-
- for (i = first; i < num_bits && i <= last; i++)
- bank->sectors[i].is_protected = set;
-
- uint32_t *p = sysrq_buffer + 2;
- for (i = 0; i < num_bits; i++) {
- if (bank->sectors[i].is_protected)
- p[i / 32] |= 1 << (i % 32);
- }
-
- /* Call "Load Latch" system ROM API */
- sysrq_buffer[1] = prot_sz - 1;
- retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH,
- 0, /* Byte number in latch from what to write */
- sysrq_buffer, param_sz + psoc4_info->row_size);
- if (retval != ERROR_OK)
- goto cleanup;
-
- /* Call "Write Protection" system ROM API */
- retval = psoc4_sysreq(target, PSOC4_CMD_WRITE_PROTECTION,
- chip_prot | (flash_macro << 8), NULL, 0);
-cleanup:
- if (retval != ERROR_OK)
- psoc4_protect_check(bank);
-
- if (sysrq_buffer)
- free(sysrq_buffer);
-
- return retval;
-}
-
-
-COMMAND_HANDLER(psoc4_handle_flash_autoerase_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
- bool enable = psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW;
-
- if (CMD_ARGC >= 2)
- COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
-
- if (enable) {
- psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
- LOG_INFO("Flash auto-erase enabled, non mass erase commands will be ignored.");
- } else {
- psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
- LOG_INFO("Flash auto-erase disabled. Use psoc mass_erase before flash programming.");
- }
-
- return retval;
-}
-
-
-static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t *sysrq_buffer = NULL;
- int retval = ERROR_OK;
- const int param_sz = 8;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x1) {
- LOG_ERROR("offset 0x%08" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- sysrq_buffer = malloc(param_sz + psoc4_info->row_size);
- if (sysrq_buffer == NULL) {
- LOG_ERROR("no memory for row buffer");
- return ERROR_FAIL;
- }
-
- uint8_t *row_buffer = (uint8_t *)sysrq_buffer + param_sz;
- uint32_t row_num = offset / psoc4_info->row_size;
- uint32_t row_offset = offset - row_num * psoc4_info->row_size;
- if (row_offset)
- memset(row_buffer, 0, row_offset);
-
- bool save_poll = jtag_poll_get_enabled();
- jtag_poll_set_enabled(false);
-
- while (count) {
- uint32_t chunk_size = psoc4_info->row_size - row_offset;
- if (chunk_size > count) {
- chunk_size = count;
- memset(row_buffer + chunk_size, 0, psoc4_info->row_size - chunk_size);
- }
- memcpy(row_buffer + row_offset, buffer, chunk_size);
- LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
- offset, row_offset, chunk_size);
-
- /* Call "Load Latch" system ROM API */
- sysrq_buffer[1] = psoc4_info->row_size - 1;
- retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH,
- 0, /* Byte number in latch from what to write */
- sysrq_buffer, param_sz + psoc4_info->row_size);
- if (retval != ERROR_OK)
- goto cleanup;
-
- /* Call "Program Row" or "Write Row" system ROM API */
- uint32_t sysrq_param;
- retval = psoc4_sysreq(target, psoc4_info->cmd_program_row,
- row_num & 0xffff,
- &sysrq_param, sizeof(sysrq_param));
- if (retval != ERROR_OK)
- goto cleanup;
-
- buffer += chunk_size;
- row_num++;
- row_offset = 0;
- count -= chunk_size;
- }
-
-cleanup:
- jtag_poll_set_enabled(save_poll);
-
- if (sysrq_buffer)
- free(sysrq_buffer);
-
- return retval;
-}
-
-
-static int psoc4_probe(struct flash_bank *bank)
-{
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t flash_size_in_kb = 0;
- uint32_t max_flash_size_in_kb;
- uint32_t cpu_id;
- uint32_t silicon_id;
- uint32_t row_size;
- uint32_t base_address = 0x00000000;
- uint8_t protection;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- psoc4_info->probed = 0;
- psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
-
- /* Get the CPUID from the ARM Core
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */
- int retval = target_read_u32(target, 0xE000ED00, &cpu_id);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("cpu id = 0x%08" PRIx32 "", cpu_id);
-
- /* set page size, protection granularity and max flash size depending on family */
- switch ((cpu_id >> 4) & 0xFFF) {
- case 0xc20: /* M0 -> PSoC4 */
- row_size = 128;
- max_flash_size_in_kb = 32;
- break;
- default:
- LOG_WARNING("Cannot identify target as a PSoC 4 family.");
- return ERROR_FAIL;
- }
-
- uint32_t spcif_geometry;
- retval = target_read_u32(target, PSOC4_SPCIF_GEOMETRY, &spcif_geometry);
- if (retval == ERROR_OK) {
- row_size = 128 * ((spcif_geometry >> 22) & 3);
- flash_size_in_kb = (spcif_geometry & 0xffff) * 256 / 1024;
- LOG_INFO("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.",
- flash_size_in_kb, row_size);
- }
-
- /* Early revisions of ST-Link v2 have some problem reading PSOC4_SPCIF_GEOMETRY
- and an error is reported late. Dummy read gets this error. */
- uint32_t dummy;
- target_read_u32(target, PSOC4_CPUSS_SYSREQ, &dummy);
-
- /* get silicon ID from target. */
- retval = psoc4_get_silicon_id(target, &silicon_id, &protection);
- if (retval != ERROR_OK)
- return retval;
-
- const struct psoc4_chip_details *details = psoc4_details_by_id(silicon_id);
- if (details) {
- LOG_INFO("%s device detected.", details->type);
- if (flash_size_in_kb == 0)
- flash_size_in_kb = details->flash_size_in_kb;
- else if (flash_size_in_kb != details->flash_size_in_kb)
- LOG_ERROR("Flash size mismatch");
- }
-
- psoc4_info->row_size = row_size;
- psoc4_info->silicon_id = silicon_id;
- psoc4_info->chip_protection = protection;
-
- /* failed reading flash size or flash size invalid (early silicon),
- * default to max target family */
- if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
- LOG_WARNING("PSoC 4 flash size failed, probe inaccurate - assuming %" PRIu32 " k flash",
- max_flash_size_in_kb);
- flash_size_in_kb = max_flash_size_in_kb;
- }
-
- /* if the user sets the size manually then ignore the probed value
- * this allows us to work around devices that have a invalid flash size register value */
- if (psoc4_info->user_bank_size) {
- LOG_INFO("ignoring flash probed value, using configured bank size");
- flash_size_in_kb = psoc4_info->user_bank_size / 1024;
- }
-
- LOG_INFO("flash size = %" PRIu32 " kbytes", flash_size_in_kb);
-
- /* did we assign flash size? */
- assert(flash_size_in_kb != 0xffff);
-
- /* calculate numbers of pages */
- uint32_t num_rows = flash_size_in_kb * 1024 / row_size;
-
- /* check that calculation result makes sense */
- assert(num_rows > 0);
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->base = base_address;
- bank->size = num_rows * row_size;
- bank->num_sectors = num_rows;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_rows);
-
- uint32_t i;
- for (i = 0; i < num_rows; i++) {
- bank->sectors[i].offset = i * row_size;
- bank->sectors[i].size = row_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- LOG_INFO("flash bank set %" PRIu32 " rows", num_rows);
- psoc4_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int psoc4_auto_probe(struct flash_bank *bank)
-{
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
- if (psoc4_info->probed)
- return ERROR_OK;
- return psoc4_probe(bank);
-}
-
-
-static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
- int printed = 0;
-
- if (psoc4_info->probed == 0)
- return ERROR_FAIL;
-
- const struct psoc4_chip_details *details = psoc4_details_by_id(psoc4_info->silicon_id);
-
- if (details) {
- uint32_t chip_revision = psoc4_info->silicon_id & 0xffff;
- printed = snprintf(buf, buf_size, "PSoC 4 %s rev 0x%04" PRIx32 " package %s",
- details->type, chip_revision, details->package);
- } else
- printed = snprintf(buf, buf_size, "PSoC 4 silicon id 0x%08" PRIx32 "",
- psoc4_info->silicon_id);
-
- buf += printed;
- buf_size -= printed;
-
- const char *prot_txt = psoc4_decode_chip_protection(psoc4_info->chip_protection);
- uint32_t size_in_kb = bank->size / 1024;
- snprintf(buf, buf_size, " flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
- return ERROR_OK;
-}
-
-
-COMMAND_HANDLER(psoc4_handle_mass_erase_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = psoc4_mass_erase(bank);
- if (retval == ERROR_OK)
- command_print(CMD_CTX, "psoc mass erase complete");
- else
- command_print(CMD_CTX, "psoc mass erase failed");
-
- return retval;
-}
-
-
-static const struct command_registration psoc4_exec_command_handlers[] = {
- {
- .name = "mass_erase",
- .handler = psoc4_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Erase entire flash device.",
- },
- {
- .name = "flash_autoerase",
- .handler = psoc4_handle_flash_autoerase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id on|off",
- .help = "Set autoerase mode for flash bank.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration psoc4_command_handlers[] = {
- {
- .name = "psoc4",
- .mode = COMMAND_ANY,
- .help = "PSoC 4 flash command group",
- .usage = "",
- .chain = psoc4_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver psoc4_flash = {
- .name = "psoc4",
- .commands = psoc4_command_handlers,
- .flash_bank_command = psoc4_flash_bank_command,
- .erase = psoc4_erase,
- .protect = psoc4_protect,
- .write = psoc4_write,
- .read = default_flash_read,
- .probe = psoc4_probe,
- .auto_probe = psoc4_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = psoc4_protect_check,
- .info = get_psoc4_info,
-};
diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c
deleted file mode 100644
index ce9a21e..0000000
--- a/src/flash/nor/sim3x.c
+++ /dev/null
@@ -1,1126 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2014 by Ladislav Bábel *
- * ladababel@seznam.cz *
- * *
- * Copyright (C) 2015 by Andreas Bomholtz *
- * andreas@seluxit.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <helper/time_support.h>
-#include <target/algorithm.h>
-#include <target/cortex_m.h>
-
-/* SI32_DEVICEID0 */
-#define DEVICEID0_DEVICEID0 (0x400490C0)
-#define DEVICEID0_DEVICEID1 (0x400490D0)
-#define DEVICEID0_DEVICEID2 (0x400490E0)
-#define DEVICEID0_DEVICEID3 (0x400490F0)
-
-/* cortex_m CPUID */
-#define CPUID_CHECK_VALUE (0x410FC230)
-#define CPUID_CHECK_VALUE_MASK (0xFF0FFFF0)
-
-/* Flash */
-#define FLASH_BASE_ADDRESS (0x00000000)
-#define LOCK_WORD_ADDRESS (0x0003FFFC)
-
-#define LOCK_WORD_MCU_UNLOCKED (0xFFFFFFFF)
-/* Can't by locked again without erase, because LOCK_WORD is in FLASH */
-#define LOCK_WORD_MCU_UNLOCKED_BY_FIRMWARE (0x00000000)
-
-/* SI32_FLASHCTRL_0 */
-#define FLASHCTRL0_CONFIG_ALL (0x4002E000)
-#define FLASHCTRL0_CONFIG_SET (0x4002E004)
-#define FLASHCTRL0_CONFIG_CLR (0x4002E008)
-#define FLASHCTRL0_CONFIG_ERASEEN_MASK (0x00040000)
-#define FLASHCTRL0_CONFIG_BUSYF_MASK (0x00100000)
-
-#define FLASHCTRL0_WRADDR (0x4002E0A0)
-#define FLASHCTRL0_WRDATA (0x4002E0B0)
-
-#define FLASHCTRL0_KEY (0x4002E0C0)
-#define FLASHCTRL0_KEY_INITIAL_UNLOCK (0x000000A5)
-#define FLASHCTRL0_KEY_SINGLE_UNLOCK (0x000000F1)
-#define FLASHCTRL0_KEY_MULTIPLE_UNLOCK (0x000000F2)
-#define FLASHCTRL0_KEY_MULTIPLE_LOCK (0x0000005A)
-
-#define FLASH_BUSY_TIMEOUT (100)
-
-/* SI32_RSTSRC_0 */
-#define RSTSRC0_RESETEN_ALL (0x4002D060)
-#define RSTSRC0_RESETEN_SET (0x4002D064)
-#define RSTSRC0_RESETEN_CLR (0x4002D068)
-#define RSTSRC0_RESETEN_VMONREN_MASK (0x00000004)
-#define RSTSRC0_RESETEN_SWREN_MASK (0x00000040)
-
-/* SI32_VMON_0 */
-#define VMON0_CONTROL_ALL (0x4002F000)
-#define VMON0_CONTROL_SET (0x4002F004)
-#define VMON0_CONTROL_CLR (0x4002F008)
-#define VMON0_CONTROL_VMONEN_MASK (0x80000000)
-
-/* SI32_CLKCTRL_0 */
-#define CLKCTRL0_APBCLKG0_ALL (0x4002D020)
-#define CLKCTRL0_APBCLKG0_SET (0x4002D024)
-#define CLKCTRL0_APBCLKG0_CLR (0x4002D028)
-#define CLKCTRL0_APBCLKG0_FLCTRLCEN_MASK (0x40000000)
-
-/* SI32_WDTIMER_0 */
-#define WDTIMER0_CONTROL_ALL (0x40030000)
-#define WDTIMER0_CONTROL_SET (0x40030004)
-#define WDTIMER0_CONTROL_CLR (0x40030008)
-#define WDTIMER0_CONTROL_DBGMD_MASK (0x00000002)
-
-#define WDTIMER0_STATUS_ALL (0x40030010)
-#define WDTIMER0_STATUS_SET (0x40030014)
-#define WDTIMER0_STATUS_CLR (0x40030018)
-#define WDTIMER0_STATUS_KEYSTS_MASK (0x00000001)
-#define WDTIMER0_STATUS_PRIVSTS_MASK (0x00000002)
-
-#define WDTIMER0_THRESHOLD (0x40030020)
-
-#define WDTIMER0_WDTKEY (0x40030030)
-#define WDTIMER0_KEY_ATTN (0x000000A5)
-#define WDTIMER0_KEY_WRITE (0x000000F1)
-#define WDTIMER0_KEY_RESET (0x000000CC)
-#define WDTIMER0_KEY_DISABLE (0x000000DD)
-#define WDTIMER0_KEY_START (0x000000EE)
-#define WDTIMER0_KEY_LOCK (0x000000FF)
-
-/* DAP */
-#define SIM3X_AP (0x0A)
-
-#define SIM3X_AP_CTRL1 (0x00)
-#define SIM3X_AP_CTRL2 (0x04)
-#define SIM3X_AP_LOCK (0x08)
-#define SIM3X_AP_CRC (0x0C)
-
-#define SIM3X_AP_INIT_STAT (0x10)
-#define SIM3X_AP_DAP_IN (0x14)
-#define SIM3X_AP_DAP_OUT (0x18)
-
-#define SIM3X_AP_ID (0xFC)
-
-/* DAP register values */
-#define SIM3X_AP_CTRL1_MASS_ERASE_REQ (0x00000001)
-#define SIM3X_AP_CTRL1_RESET_REQ (0x00000008)
-/* this bit is set if MCU is locked */
-#define SIM3X_AP_INIT_STAT_LOCK (0x00000004)
-/* expected value inside SIM3X_AP_ID */
-#define SIM3X_AP_ID_VALUE (0x2430002)
-
-#define SIM3X_FLASH_PAGE_SIZE 1024
-
-struct sim3x_info {
- uint16_t flash_size_kb;
- uint16_t part_number;
- char part_family;
- uint8_t device_revision;
- char device_package[4];
- bool probed;
- bool need_init;
- bool flash_locked;
-};
-
-/* flash bank sim3x 0 0 0 0 <target#> */
-FLASH_BANK_COMMAND_HANDLER(sim3x_flash_bank_command)
-{
- struct sim3x_info *sim3x_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* Init sim3x_info struct */
- sim3x_info = malloc(sizeof(struct sim3x_info));
- sim3x_info->probed = false;
- sim3x_info->need_init = true;
- sim3x_info->device_revision = 0;
- memset(sim3x_info->device_package, 0, 4);
- bank->driver_priv = sim3x_info;
-
- return ERROR_OK;
-}
-
-static int sim3x_init(struct flash_bank *bank)
-{
- int ret;
- struct target *target;
- struct sim3x_info *sim3x_info;
-
- target = bank->target;
-
- /* Disable watchdog timer */
- ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_ATTN);
- if (ret != ERROR_OK)
- return ret;
-
- ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_DISABLE);
- if (ret != ERROR_OK)
- return ret;
-
- /* Enable one write command */
- ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_ATTN);
- if (ret != ERROR_OK)
- return ret;
-
- ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_WRITE);
- if (ret != ERROR_OK)
- return ret;
-
- /* Watchdog Timer Debug Mode */
- ret = target_write_u32(target, WDTIMER0_CONTROL_SET,
- WDTIMER0_CONTROL_DBGMD_MASK);
- if (ret != ERROR_OK)
- return ret;
-
- /* Enable VDD Supply Monitor */
- ret = target_write_u32(target, VMON0_CONTROL_SET,
- VMON0_CONTROL_VMONEN_MASK);
- if (ret != ERROR_OK)
- return ret;
-
- /* Set VDD Supply Monitor as a reset source */
- ret = target_write_u32(target, RSTSRC0_RESETEN_SET,
- RSTSRC0_RESETEN_VMONREN_MASK);
- if (ret != ERROR_OK)
- return ret;
-
- /* Flash Controller Clock Enable */
- ret = target_write_u32(target, CLKCTRL0_APBCLKG0_SET,
- CLKCTRL0_APBCLKG0_FLCTRLCEN_MASK);
- if (ret != ERROR_OK)
- return ret;
-
- /* Disable Flash Erase Mode */
- ret = target_write_u32(target, FLASHCTRL0_CONFIG_CLR,
- FLASHCTRL0_CONFIG_ERASEEN_MASK);
- if (ret != ERROR_OK)
- return ret;
-
- sim3x_info = bank->driver_priv;
- sim3x_info->need_init = 0;
- return ERROR_OK;
-}
-
-static int sim3x_erase_page(struct flash_bank *bank, uint32_t addr)
-{
- int ret, i;
- uint32_t temp;
- struct target *target;
-
- target = bank->target;
-
- for (i = 0; i < FLASH_BUSY_TIMEOUT; i++) {
- ret = target_read_u32(target, FLASHCTRL0_CONFIG_ALL, &temp);
- if (ret != ERROR_OK)
- return ret;
-
- /* If is not busy */
- if ((temp & FLASHCTRL0_CONFIG_BUSYF_MASK) == 0) {
- /* If erase is not enabled */
- if ((temp & FLASHCTRL0_CONFIG_ERASEEN_MASK) == 0) {
- /* Enter Flash Erase Mode */
- ret = target_write_u32(target, FLASHCTRL0_CONFIG_SET,
- FLASHCTRL0_CONFIG_ERASEEN_MASK);
- if (ret != ERROR_OK)
- return ret;
- }
-
- /* Write the address of the Flash page to WRADDR */
- ret = target_write_u32(target, FLASHCTRL0_WRADDR, addr);
- if (ret != ERROR_OK)
- return ret;
-
- /* Write the inital unlock value to KEY */
- ret = target_write_u32(target, FLASHCTRL0_KEY,
- FLASHCTRL0_KEY_INITIAL_UNLOCK);
- if (ret != ERROR_OK)
- return ret;
-
- /* Write the single unlock value to KEY */
- ret = target_write_u32(target, FLASHCTRL0_KEY,
- FLASHCTRL0_KEY_SINGLE_UNLOCK);
- if (ret != ERROR_OK)
- return ret;
-
- /* Write any value to WRDATA to initiate the page erase */
- ret = target_write_u32(target, FLASHCTRL0_WRDATA, 0);
- if (ret != ERROR_OK)
- return ret;
-
- return ERROR_OK;
- }
-
- alive_sleep(1);
- }
-
- LOG_ERROR("timed out waiting for FLASHCTRL0_CONFIG_BUSYF");
- return ERROR_FAIL;
-}
-
-static int sim3x_flash_erase(struct flash_bank *bank, int first, int last)
-{
- int ret, i;
- uint32_t temp;
- struct sim3x_info *sim3x_info;
- struct target *target;
-
- /* Check if target is halted */
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- sim3x_info = bank->driver_priv;
-
- /* Init MCU after reset */
- if (sim3x_info->need_init) {
- ret = sim3x_init(bank);
- if (ret != ERROR_OK) {
- LOG_ERROR("Failed to init MCU");
- return ret;
- }
- }
-
- /* erase pages */
- for (i = first; i <= last; i++) {
- ret = sim3x_erase_page(bank, bank->sectors[i].offset);
- if (ret != ERROR_OK)
- return ret;
- }
-
- target = bank->target;
-
- /* Wait until busy */
- for (i = 0; i < FLASH_BUSY_TIMEOUT; i++) {
- ret = target_read_u32(target, FLASHCTRL0_CONFIG_ALL, &temp);
- if (ret != ERROR_OK)
- return ret;
-
- if ((temp & FLASHCTRL0_CONFIG_BUSYF_MASK) == 0) { /* If is not busy */
- if ((temp & FLASHCTRL0_CONFIG_ERASEEN_MASK) != 0) { /* If erase is enabled */
- /* Disable Flash Erase Mode */
- ret = target_write_u32(target, FLASHCTRL0_CONFIG_CLR,
- FLASHCTRL0_CONFIG_ERASEEN_MASK);
- if (ret != ERROR_OK)
- return ret;
- }
-
- return ERROR_OK;
- }
-
- alive_sleep(1);
- }
-
- LOG_ERROR("timed out waiting for FLASHCTRL0_CONFIG_BUSYF");
- return ERROR_FAIL;
-}
-
-static int sim3x_write_block(struct flash_bank *bank, const uint8_t *buf,
- uint32_t offset, uint32_t count) /* count is count of half words (2 bytes)! */
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- int ret = ERROR_OK;
-
- /* see contrib/loaders/flash/sim3x.s for src */
-
- static const uint8_t sim3x_flash_write_code[] = {
- /* Write the initial unlock value to KEY (0xA5) */
- 0xA5, 0x26, /* movs r6, #INITIAL_UNLOCK */
- 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */
-
- /* Write the multiple unlock value to KEY (0xF2) */
- 0xF2, 0x26, /* movs r6, #MULTIPLE_UNLOCK */
- 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */
-
- /* wait_fifo: */
- 0x16, 0x68, /* ldr r6, [r2, #0] */
- 0x00, 0x2E, /* cmp r6, #0 */
- 0x16, 0xD0, /* beq exit */
- 0x55, 0x68, /* ldr r5, [r2, #4] */
- 0xB5, 0x42, /* cmp r5, r6 */
- 0xF9, 0xD0, /* beq wait_fifo */
-
- /* wait for BUSYF flag */
- /* wait_busy1: */
- 0x06, 0x68, /* ldr r6, [r0, #FLASHCTRL_CONFIG] */
- 0x16, 0xF4, 0x80, 0x1F, /* tst r6, #BUSYF */
- 0xFB, 0xD1, /* bne wait_busy1 */
-
- /* Write the destination address to WRADDR */
- 0xC0, 0xF8, 0xA0, 0x40, /* str r4, [r0, #FLASHCTRL_WRADDR] */
-
- /* Write the data half-word to WRDATA in right-justified format */
- 0x2E, 0x88, /* ldrh r6, [r5] */
- 0xC0, 0xF8, 0xB0, 0x60, /* str r6, [r0, #FLASHCTRL_WRDATA] */
-
- 0x02, 0x35, /* adds r5, #2 */
- 0x02, 0x34, /* adds r4, #2 */
-
- /* wrap rp at end of buffer */
- 0x9D, 0x42, /* cmp r5, r3 */
- 0x01, 0xD3, /* bcc no_wrap */
- 0x15, 0x46, /* mov r5, r2 */
- 0x08, 0x35, /* adds r5, #8 */
-
- /* no_wrap: */
- 0x55, 0x60, /* str r5, [r2, #4] */
- 0x49, 0x1E, /* subs r1, r1, #1 */
- 0x00, 0x29, /* cmp r1, #0 */
- 0x00, 0xD0, /* beq exit */
- 0xE5, 0xE7, /* b wait_fifo */
-
- /* exit: */
- 0x5A, 0x26, /* movs r6, #MULTIPLE_LOCK */
- 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */
-
- /* wait for BUSYF flag */
- /* wait_busy2: */
- 0x06, 0x68, /* ldr r6, [r0, #FLASHCTRL_CONFIG] */
- 0x16, 0xF4, 0x80, 0x1F, /* tst r6, #BUSYF */
- 0xFB, 0xD1, /* bne wait_busy2 */
-
- 0x00, 0xBE /* bkpt #0 */
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(sim3x_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- ret = target_write_buffer(target, write_algorithm->address,
- sizeof(sim3x_flash_write_code), sim3x_flash_write_code);
- if (ret != ERROR_OK)
- return ret;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- buffer_size &= ~1UL; /* Make sure it's 2 byte aligned */
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm
- */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* flash base */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
-
- buf_set_u32(reg_params[0].value, 0, 32, FLASHCTRL0_CONFIG_ALL);
- buf_set_u32(reg_params[1].value, 0, 32, count);
- buf_set_u32(reg_params[2].value, 0, 32, source->address);
- buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
- buf_set_u32(reg_params[4].value, 0, 32, address);
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- ret = target_run_flash_async_algorithm(target, buf, count, 2, 0, NULL, 5,
- reg_params, source->address, source->size, write_algorithm->address,
- 0, &armv7m_info);
-
- if (ret == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("flash write failed at address 0x%"PRIx32,
- buf_get_u32(reg_params[4].value, 0, 32));
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return ret;
-}
-
-static int sim3x_flash_write(struct flash_bank *bank, const uint8_t * buffer, uint32_t offset, uint32_t count)
-{
- int ret;
- struct target *target;
- struct sim3x_info *sim3x_info;
- uint8_t *new_buffer = NULL;
-
- target = bank->target;
-
- /* Check if target is halted */
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- sim3x_info = bank->driver_priv;
-
- if (sim3x_info->flash_locked) {
- LOG_ERROR("Falsh is locked");
- return ERROR_FAIL;
- }
-
- /* Init MCU after reset */
- if (sim3x_info->need_init) {
- ret = sim3x_init(bank);
- if (ret != ERROR_OK)
- return ret;
- }
-
- if (offset & 0x1) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- if (count & 0x1) {
- uint32_t old_count = count;
- count++;
- new_buffer = malloc(count);
-
- if (new_buffer == NULL) {
- LOG_ERROR("odd number of bytes to write and no memory "
- "for padding buffer");
- return ERROR_FAIL;
- }
- LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32
- " and padding with 0xff", old_count, count);
-
- new_buffer[count - 1] = 0xff;
- buffer = memcpy(new_buffer, buffer, old_count);
- }
-
- ret = sim3x_write_block(bank, buffer, offset, count / 2);
- free(new_buffer);
- return ret;
-}
-
-static int sim3x_flash_lock_check(struct flash_bank *bank)
-{
- int ret;
- uint32_t lock_word;
- struct sim3x_info *sim3x_info;
-
- ret = target_read_u32(bank->target, LOCK_WORD_ADDRESS, &lock_word);
- if (ret != ERROR_OK) {
- LOG_ERROR("Can not read Lock Word");
- return ret;
- }
-
- sim3x_info = bank->driver_priv;
- sim3x_info->flash_locked = (lock_word != 0xFFFFFFFF);
-
- return ERROR_OK;
-}
-
-static int sim3x_flash_protect_check(struct flash_bank *bank)
-{
- int ret, i;
- struct sim3x_info *sim3x_info;
-
- /* Check if target is halted */
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- ret = sim3x_flash_lock_check(bank);
- if (ret != ERROR_OK)
- return ret;
-
- sim3x_info = bank->driver_priv;
-
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_protected = sim3x_info->flash_locked;
-
- return ERROR_OK;
-}
-
-static int sim3x_flash_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int ret;
- uint8_t lock_word[4];
- struct sim3x_info *sim3x_info;
- struct target *target;
-
- target = bank->target;
-
- /* Check if target is halted */
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (first != 0 || last != bank->num_sectors - 1) {
- LOG_ERROR("Flash does not support finer granularity");
- return ERROR_FAIL;
- }
-
- sim3x_info = bank->driver_priv;
-
- if (set) {
- if (sim3x_info->flash_locked) {
- LOG_INFO("Flash is already locked");
- return ERROR_OK;
- }
-
- /* Lock Flash */
- target_buffer_set_u32(target, lock_word, 0xFFFFFFFE);
- ret = sim3x_flash_write(bank, lock_word, LOCK_WORD_ADDRESS, 4);
- if (ret != ERROR_OK)
- return ret;
-
- } else {
- /* Flash is unlocked by an erase operation */
- ret = sim3x_flash_erase(bank, 0, 0);
- if (ret != ERROR_OK)
- return ret;
- }
-
- ret = sim3x_flash_protect_check(bank);
- if (ret != ERROR_OK)
- return ret;
-
- if (set) {
- if (sim3x_info->flash_locked) {
- LOG_INFO("Flash locked");
- return ERROR_OK;
- } else {
- LOG_ERROR("Flash lock error");
- return ERROR_FAIL;
- }
- } else {
- if (sim3x_info->flash_locked) {
- LOG_ERROR("Flash unlock error");
- return ERROR_FAIL;
- } else {
- LOG_INFO("Flash unlocked");
- return ERROR_OK;
- }
- }
-}
-
-static int sim3x_read_deviceid(struct flash_bank *bank)
-{
- int ret;
- struct sim3x_info *sim3x_info;
-
- uint32_t device_id;
- int part_number;
- char part_num_string[4];
-
- sim3x_info = bank->driver_priv;
-
- /* MCU check */
- ret = target_read_u32(bank->target, DEVICEID0_DEVICEID2, &device_id);
- if (ret != ERROR_OK)
- return ret;
-
- /* Device ID should be 'M3' */
- if (device_id != 0x00004D33)
- return ERROR_FAIL;
-
- /* Family and Part number */
- ret = target_read_u32(bank->target, DEVICEID0_DEVICEID1, &device_id);
- if (ret != ERROR_OK)
- return ret;
-
- part_num_string[0] = device_id >> 16;
- part_num_string[1] = device_id >> 8;
- part_num_string[2] = device_id;
- part_num_string[3] = 0;
-
- part_number = atoi(part_num_string);
-
- /* Part Number should be between 100 and 999 */
- if (!isalpha(device_id >> 24) || part_number < 100 || part_number > 999)
- return ERROR_FAIL;
-
- sim3x_info->part_family = device_id >> 24;
- sim3x_info->part_number = part_number;
-
- /* Package and Revision */
- ret = target_read_u32(bank->target, DEVICEID0_DEVICEID0, &device_id);
- if (ret != ERROR_OK)
- return ret;
-
- sim3x_info->device_package[0] = device_id >> 24;
- sim3x_info->device_package[1] = device_id >> 16;
- sim3x_info->device_package[2] = device_id >> 8;
- sim3x_info->device_package[3] = 0;
-
- sim3x_info->device_revision = device_id;
-
- return ERROR_OK;
-}
-
-static int sim3x_parse_part_info(struct sim3x_info *sim3x_info)
-{
- switch (sim3x_info->part_number) {
- case 134:
- case 136:
- sim3x_info->flash_size_kb = 32;
- break;
- case 144:
- case 146:
- sim3x_info->flash_size_kb = 64;
- break;
- case 154:
- case 156:
- case 157:
- sim3x_info->flash_size_kb = 128;
- break;
- case 164:
- case 166:
- case 167:
- sim3x_info->flash_size_kb = 256;
- break;
- default:
- LOG_ERROR("Unknown Part number %d", sim3x_info->part_number);
- sim3x_info->part_number = 0;
- return ERROR_FAIL;
- }
-
- switch (sim3x_info->part_family) {
- case 'c':
- case 'C':
- LOG_INFO("SiM3C%d detected", sim3x_info->part_number);
- break;
- case 'u':
- case 'U':
- LOG_INFO("SiM3U%d detected", sim3x_info->part_number);
- break;
- case 'l':
- case 'L':
- LOG_INFO("SiM3L%d detected", sim3x_info->part_number);
- break;
- default:
- LOG_ERROR("Unsupported MCU family %c", sim3x_info->part_family);
- sim3x_info->part_family = 0;
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int sim3x_read_info(struct flash_bank *bank)
-{
- int ret;
- struct sim3x_info *sim3x_info;
- uint32_t cpuid;
-
- sim3x_info = bank->driver_priv;
-
- /* Core check */
- ret = target_read_u32(bank->target, CPUID, &cpuid);
- if (ret != ERROR_OK) {
- LOG_ERROR("Failed to read CPU ID");
- return ret;
- }
-
- if (((cpuid >> 4) & 0xfff) != 0xc23) {
- LOG_ERROR("Target is not Cortex-M3");
- return ERROR_FAIL;
- }
-
- /* Read info from chip */
- ret = sim3x_read_deviceid(bank);
- if (ret == ERROR_OK) {
- ret = sim3x_parse_part_info(sim3x_info);
- if (ret != ERROR_OK) {
- LOG_ERROR("Failed to parse info from MCU");
- return ERROR_FAIL;
- }
- } else {
- LOG_WARNING("Failed to read info from MCU, using info from flash bank parameters");
-
- /* Check if flash size is given in flash bank command */
- if (!bank->size) {
- LOG_ERROR("Flash size not set in the flash bank command");
- return ERROR_FAIL;
- }
-
- /* Convert bank size to kb */
- sim3x_info->flash_size_kb = bank->size / 1024;
- }
-
- LOG_INFO("Flash size = %dKB", sim3x_info->flash_size_kb);
-
- return ERROR_OK;
-}
-
-static int sim3x_probe(struct flash_bank *bank)
-{
- int ret, i;
- struct sim3x_info *sim3x_info;
-
- sim3x_info = bank->driver_priv;
- sim3x_info->probed = false;
- sim3x_info->need_init = true;
-
- /* Read info from chip */
- ret = sim3x_read_info(bank);
- if (ret != ERROR_OK)
- return ret;
-
- ret = sim3x_flash_lock_check(bank);
- if (ret != ERROR_OK)
- return ret;
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->base = FLASH_BASE_ADDRESS;
- bank->size = sim3x_info->flash_size_kb * SIM3X_FLASH_PAGE_SIZE;
- bank->num_sectors = SIM3X_FLASH_PAGE_SIZE;
- bank->sectors = malloc(sizeof(struct flash_sector) * sim3x_info->flash_size_kb);
-
- for (i = 0; i < sim3x_info->flash_size_kb; i++) {
- bank->sectors[i].offset = i * SIM3X_FLASH_PAGE_SIZE;
- bank->sectors[i].size = SIM3X_FLASH_PAGE_SIZE;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = sim3x_info->flash_locked;
- }
-
- sim3x_info->probed = true;
-
- return ERROR_OK;
-}
-
-static int sim3x_auto_probe(struct flash_bank *bank)
-{
- struct sim3x_info *sim3x_info;
-
- sim3x_info = bank->driver_priv;
-
- if (sim3x_info->probed) {
- sim3x_info->need_init = true;
- return ERROR_OK;
- } else {
- return sim3x_probe(bank);
- }
-}
-
-static int sim3x_flash_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int ret;
- int printed = 0;
- struct sim3x_info *sim3x_info;
-
- sim3x_info = bank->driver_priv;
-
- /* Read info about chip */
- ret = sim3x_read_info(bank);
- if (ret != ERROR_OK)
- return ret;
-
- /* Part */
- if (sim3x_info->part_family && sim3x_info->part_number) {
- printed = snprintf(buf, buf_size, "SiM3%c%d", sim3x_info->part_family, sim3x_info->part_number);
- buf += printed;
- buf_size -= printed;
-
- if (buf_size <= 0)
- return ERROR_BUF_TOO_SMALL;
-
- /* Revision */
- if (sim3x_info->device_revision && sim3x_info->device_revision <= 'Z' - 'A') {
- printed = snprintf(buf, buf_size, "-%c", sim3x_info->device_revision + 'A');
- buf += printed;
- buf_size -= printed;
-
- if (buf_size <= 0)
- return ERROR_BUF_TOO_SMALL;
-
- /* Package */
- printed = snprintf(buf, buf_size, "-G%s", sim3x_info->device_package);
- buf += printed;
- buf_size -= printed;
-
- if (buf_size <= 0)
- return ERROR_BUF_TOO_SMALL;
- }
- }
-
- /* Print flash size */
- printed = snprintf(buf, buf_size, " flash_size = %dKB", sim3x_info->flash_size_kb);
- buf_size -= printed;
-
- if (buf_size <= 0)
- return ERROR_BUF_TOO_SMALL;
-
- return ERROR_OK;
-}
-/**
- * reg 31:8 - no effect
- * reg 7:4 - bank
- * reg 3:2 - register
- * reg 1:0 - no effect
- */
-static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
-{
- int retval;
- LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value);
-
- retval = dap_queue_ap_write(dap_ap(dap, SIM3X_AP), reg, value);
- if (retval != ERROR_OK) {
- LOG_DEBUG("DAP: failed to queue a write request");
- return retval;
- }
-
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_DEBUG("DAP: dap_run failed");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
-{
- int retval;
-
- retval = dap_queue_ap_read(dap_ap(dap, SIM3X_AP), reg, result);
- if (retval != ERROR_OK) {
- LOG_DEBUG("DAP: failed to queue a read request");
- return retval;
- }
-
- retval = dap_run(dap);
- if (retval != ERROR_OK) {
- LOG_DEBUG("DAP: dap_run failed");
- return retval;
- }
-
- LOG_DEBUG("DAP_REG[0x%02x]: %08" PRIX32, reg, *result);
- return ERROR_OK;
-}
-
-static int ap_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value, int timeout)
-{
- uint32_t val;
- int retval;
-
- do {
- retval = ap_read_register(dap, reg, &val);
- if (retval != ERROR_OK || (val & mask) == value)
- return retval;
-
- alive_sleep(1);
- } while (timeout--);
-
- LOG_DEBUG("DAP: polling timed out");
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(sim3x_mass_erase)
-{
- uint32_t val;
- int ret;
-
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
-
- if (dap == NULL) {
- /* Used debug interface doesn't support direct DAP access */
- LOG_ERROR("mass_erase can't be used by this debug interface");
- return ERROR_FAIL;
- }
-
- ret = ap_read_register(dap, SIM3X_AP_ID, &val);
- if (ret != ERROR_OK)
- return ret;
-
- if (val != SIM3X_AP_ID_VALUE) {
- LOG_ERROR("Wrong SIM3X_AP_ID");
- return ERROR_FAIL;
- }
-
- /* Mass erase sequence */
- ret = ap_write_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_RESET_REQ);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ap_write_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_RESET_REQ | SIM3X_AP_CTRL1_MASS_ERASE_REQ);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ap_poll_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_MASS_ERASE_REQ, 0x00000000, FLASH_BUSY_TIMEOUT);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ap_write_register(dap, SIM3X_AP_CTRL1, 0x00000000); /* clear SIM3X_AP_CTRL1_RESET_REQ */
- if (ret != ERROR_OK)
- return ret;
-
- LOG_INFO("Mass erase success");
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sim3x_lock)
-{
- uint32_t val;
- int ret;
-
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
-
- if (dap == NULL) {
- /* Used debug interface doesn't support direct DAP access */
- LOG_INFO("Target can't by unlocked by this debug interface");
-
- /* Core check */
- ret = target_read_u32(target, CPUID, &val);
- if (ret != ERROR_OK)
- return ret;
-
- if ((val & CPUID_CHECK_VALUE_MASK) != CPUID_CHECK_VALUE) {
- LOG_ERROR("Target is not ARM Cortex-M3 or is already locked");
- return ERROR_FAIL;
- }
- } else {
- /* check SIM3X_AP_ID */
- ret = ap_read_register(dap, SIM3X_AP_ID, &val);
- if (ret != ERROR_OK)
- return ret;
-
- if (val != SIM3X_AP_ID_VALUE) {
- LOG_ERROR("Wrong SIM3X_AP_ID");
- return ERROR_FAIL;
- }
-
- /* check if locked */
- ret = target_read_u32(target, CPUID, &val);
- /* if correct value is read, then it will continue */
- if (ret != ERROR_OK || (val & CPUID_CHECK_VALUE_MASK) != CPUID_CHECK_VALUE) {
- /* if correct value is'n read, then it will check SIM3X_AP_INIT_STAT register */
- ret = ap_read_register(dap, SIM3X_AP_INIT_STAT, &val);
- if (ret != ERROR_OK)
- return ret;
-
- if (val & SIM3X_AP_INIT_STAT_LOCK) {
- LOG_INFO("Target is already locked");
- return ERROR_OK;
- } else {
- LOG_ERROR("Target doesn't seem to be locked but memory was not read correct");
- return ERROR_FAIL;
- }
- }
- }
-
- ret = target_read_u32(target, LOCK_WORD_ADDRESS, &val);
- if (ret != ERROR_OK)
- return ret;
-
- if (val == LOCK_WORD_MCU_UNLOCKED) {
- /* Lock Flash */
- uint8_t lock_word[4];
- target_buffer_set_u32(target, lock_word, 0xFFFFFFFE);
-
- /* Get Flash Bank */
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (retval != ERROR_OK)
- return retval;
-
- ret = sim3x_flash_write(bank, lock_word, LOCK_WORD_ADDRESS, 4);
- if (ERROR_OK != ret)
- return ret;
-
- LOG_INFO("Target is successfully locked");
- return ERROR_OK;
- } else if (val == LOCK_WORD_MCU_UNLOCKED_BY_FIRMWARE) {
- /* Can't by locked again without erase, because LOCK_WORD is in FLASH */
- LOG_ERROR("Target is unlocked by firmware and can't by locked again without the lock page erase or mass erase");
- return ERROR_FAIL;
- } else {
- LOG_ERROR("Unexpected lock word value");
-
- /* SIM3X_AP_ID_VALUE is not checked */
- if (dap == NULL)
- LOG_INFO("Maybe this isn't a SiM3x MCU");
-
- return ERROR_FAIL;
- }
-}
-
-static const struct command_registration sim3x_exec_command_handlers[] = {
- {
- .name = "mass_erase",
- .mode = COMMAND_EXEC,
- .help = "Erase the complete flash",
- .usage = "",
- .handler = sim3x_mass_erase,
- },
- {
- .name = "lock",
- .mode = COMMAND_EXEC,
- .help = "Locks the flash. Unlock by mass erase",
- .usage = "",
- .handler = sim3x_lock,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration sim3x_command_handlers[] = {
- {
- .name = "sim3x",
- .mode = COMMAND_ANY,
- .help = "sim3x flash command group",
- .usage = "",
- .chain = sim3x_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver sim3x_flash = {
- .name = "sim3x",
- .commands = sim3x_command_handlers,
- .flash_bank_command = sim3x_flash_bank_command,
- .erase = sim3x_flash_erase,
- .protect = sim3x_flash_protect,
- .write = sim3x_flash_write,
- .read = default_flash_read,
- .probe = sim3x_probe,
- .auto_probe = sim3x_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = sim3x_flash_protect_check,
- .info = sim3x_flash_info
-};
diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
deleted file mode 100644
index c8239d2..0000000
--- a/src/flash/nor/spi.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by George Harris *
- * george@luminairecoffee.com *
- * *
- * Copyright (C) 2010 by Antonio Borneo *
- * borneo.antonio@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "spi.h"
-#include <jtag/jtag.h>
-
- /* Shared table of known SPI flash devices for SPI-based flash drivers. Taken
- * from device datasheets and Linux SPI flash drivers. */
-const struct flash_device flash_devices[] = {
- /* name, erase_cmd, chip_erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
- FLASH_ID("st m25p05", 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000),
- FLASH_ID("st m25p10", 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000),
- FLASH_ID("st m25p20", 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
- FLASH_ID("st m25p40", 0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000),
- FLASH_ID("st m25p80", 0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000),
- FLASH_ID("st m25p16", 0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000),
- FLASH_ID("st m25p32", 0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000),
- FLASH_ID("st m25p64", 0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000),
- FLASH_ID("st m25p128", 0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000),
- FLASH_ID("st m45pe10", 0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
- FLASH_ID("st m45pe20", 0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
- FLASH_ID("st m45pe40", 0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
- FLASH_ID("st m45pe80", 0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
- FLASH_ID("sp s25fl004", 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000),
- FLASH_ID("sp s25fl008", 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000),
- FLASH_ID("sp s25fl016", 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000),
- FLASH_ID("sp s25fl116k", 0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000),
- FLASH_ID("sp s25fl032", 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000),
- FLASH_ID("sp s25fl132k", 0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000),
- FLASH_ID("sp s25fl064", 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000),
- FLASH_ID("sp s25fl164k", 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000),
- FLASH_ID("sp s25fl128", 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000),
- FLASH_ID("sp s25fl256", 0xd8, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000),
- FLASH_ID("atmel 25f512", 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000),
- FLASH_ID("atmel 25f1024", 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000),
- FLASH_ID("atmel 25f2048", 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
- FLASH_ID("atmel 25f4096", 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
- FLASH_ID("atmel 25fs040", 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
- FLASH_ID("mac 25l512", 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
- FLASH_ID("mac 25l1005", 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
- FLASH_ID("mac 25l2005", 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
- FLASH_ID("mac 25l4005", 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000),
- FLASH_ID("mac 25l8005", 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000),
- FLASH_ID("mac 25l1605", 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000),
- FLASH_ID("mac 25l3205", 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000),
- FLASH_ID("mac 25l6405", 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000),
- FLASH_ID("micron n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
- FLASH_ID("micron n25q128", 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
- FLASH_ID("issi is25lp128", 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
- FLASH_ID("win w25q80bv", 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000),
- FLASH_ID("win w25q32fv", 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000),
- FLASH_ID("win w25q32dw", 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000),
- FLASH_ID("win w25q64cv", 0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000),
- FLASH_ID("win w25q128fv", 0xd8, 0xc7, 0x001840ef, 0x100, 0x10000, 0x1000000),
- FLASH_ID("gd gd25q20", 0x20, 0xc7, 0x00c84012, 0x100, 0x1000, 0x80000),
- FLASH_ID("gd gd25q16c", 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
- FLASH_ID("gd gd25q32c", 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
- FLASH_ID("gd gd25q128c", 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
- FLASH_ID(NULL, 0, 0, 0, 0, 0, 0)
-};
diff --git a/src/flash/nor/spi.h b/src/flash/nor/spi.h
deleted file mode 100644
index a184998..0000000
--- a/src/flash/nor/spi.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by George Harris *
- * george@luminairecoffee.com *
- * *
- * Copyright (C) 2010 by Antonio Borneo *
- * borneo.antonio@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_FLASH_NOR_SPI_H
-#define OPENOCD_FLASH_NOR_SPI_H
-
-/* data structure to maintain flash ids from different vendors */
-struct flash_device {
- char *name;
- uint8_t erase_cmd;
- uint8_t chip_erase_cmd;
- uint32_t device_id;
- uint32_t pagesize;
- unsigned long sectorsize;
- unsigned long size_in_bytes;
-};
-
-#define FLASH_ID(n, es, ces, id, psize, ssize, size) \
-{ \
- .name = n, \
- .erase_cmd = es, \
- .chip_erase_cmd = ces, \
- .device_id = id, \
- .pagesize = psize, \
- .sectorsize = ssize, \
- .size_in_bytes = size \
-}
-
-extern const struct flash_device flash_devices[];
-
-/* fields in SPI flash status register */
-#define SPIFLASH_BSY_BIT 0x00000001 /* WIP Bit of SPI SR on SMI SR */
-#define SPIFLASH_WE_BIT 0x00000002 /* WEL Bit of SPI SR on SMI SR */
-
-/* SPI Flash Commands */
-#define SPIFLASH_READ_ID 0x9F /* Read Flash Identification */
-#define SPIFLASH_READ_STATUS 0x05 /* Read Status Register */
-#define SPIFLASH_WRITE_ENABLE 0x06 /* Write Enable */
-#define SPIFLASH_PAGE_PROGRAM 0x02 /* Page Program */
-#define SPIFLASH_FAST_READ 0x0B /* Fast Read */
-#define SPIFLASH_READ 0x03 /* Normal Read */
-
-#endif /* OPENOCD_FLASH_NOR_SPI_H */
diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c
deleted file mode 100644
index d28ceee..0000000
--- a/src/flash/nor/stellaris.c
+++ /dev/null
@@ -1,1455 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/***************************************************************************
-* STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
-***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "imp.h"
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-#define DID0_VER(did0) ((did0 >> 28)&0x07)
-
-/* STELLARIS control registers */
-#define SCB_BASE 0x400FE000
-#define DID0 0x000
-#define DID1 0x004
-#define DC0 0x008
-#define DC1 0x010
-#define DC2 0x014
-#define DC3 0x018
-#define DC4 0x01C
-
-#define RIS 0x050
-#define RCC 0x060
-#define PLLCFG 0x064
-#define RCC2 0x070
-#define NVMSTAT 0x1a0
-
-/* "legacy" flash memory protection registers (64KB max) */
-#define FMPRE 0x130
-#define FMPPE 0x134
-
-/* new flash memory protection registers (for more than 64KB) */
-#define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
-#define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
-
-#define USECRL 0x140
-
-#define FLASH_CONTROL_BASE 0x400FD000
-#define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
-#define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
-#define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
-#define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
-#define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
-#define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
-#define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0)
-#define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4)
-
-#define AMISC 1
-#define PMISC 2
-
-#define AMASK 1
-#define PMASK 2
-
-/* Flash Controller Command bits */
-#define FMC_WRKEY (0xA442 << 16)
-#define FMC_COMT (1 << 3)
-#define FMC_MERASE (1 << 2)
-#define FMC_ERASE (1 << 1)
-#define FMC_WRITE (1 << 0)
-
-/* STELLARIS constants */
-
-/* values to write in FMA to commit write-"once" values */
-#define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
-#define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
-
-static void stellaris_read_clock_info(struct flash_bank *bank);
-static int stellaris_mass_erase(struct flash_bank *bank);
-
-struct stellaris_flash_bank {
- /* chip id register */
- uint32_t did0;
- uint32_t did1;
- uint32_t dc0;
- uint32_t dc1;
- uint32_t fsize;
- uint32_t ssize;
-
- const char *target_name;
- uint8_t target_class;
-
- uint32_t sramsiz;
- /* flash geometry */
- uint32_t num_pages;
- uint32_t pagesize;
-
- /* main clock status */
- uint32_t rcc;
- uint32_t rcc2;
- uint8_t mck_valid;
- uint8_t xtal_mask;
- uint32_t iosc_freq;
- uint32_t mck_freq;
- const char *iosc_desc;
- const char *mck_desc;
-};
-
-/* Autogenerated by contrib/gen-stellaris-part-header.pl */
-/* From Stellaris Firmware Development Package revision 9453 */
-static const struct {
- uint8_t class;
- uint8_t partno;
- const char *partname;
-} StellarisParts[] = {
- {0x00, 0x01, "LM3S101"},
- {0x00, 0x02, "LM3S102"},
- {0x01, 0xBF, "LM3S1110"},
- {0x01, 0xC3, "LM3S1133"},
- {0x01, 0xC5, "LM3S1138"},
- {0x01, 0xC1, "LM3S1150"},
- {0x01, 0xC4, "LM3S1162"},
- {0x01, 0xC2, "LM3S1165"},
- {0x01, 0xEC, "LM3S1166"},
- {0x01, 0xC6, "LM3S1332"},
- {0x01, 0xBC, "LM3S1435"},
- {0x01, 0xBA, "LM3S1439"},
- {0x01, 0xBB, "LM3S1512"},
- {0x01, 0xC7, "LM3S1538"},
- {0x01, 0xDB, "LM3S1601"},
- {0x03, 0x06, "LM3S1607"},
- {0x01, 0xDA, "LM3S1608"},
- {0x01, 0xC0, "LM3S1620"},
- {0x04, 0xCD, "LM3S1621"},
- {0x03, 0x03, "LM3S1625"},
- {0x03, 0x04, "LM3S1626"},
- {0x03, 0x05, "LM3S1627"},
- {0x01, 0xB3, "LM3S1635"},
- {0x01, 0xEB, "LM3S1636"},
- {0x01, 0xBD, "LM3S1637"},
- {0x04, 0xB1, "LM3S1651"},
- {0x01, 0xB9, "LM3S1751"},
- {0x03, 0x10, "LM3S1776"},
- {0x04, 0x16, "LM3S1811"},
- {0x04, 0x3D, "LM3S1816"},
- {0x01, 0xB4, "LM3S1850"},
- {0x01, 0xDD, "LM3S1911"},
- {0x01, 0xDC, "LM3S1918"},
- {0x01, 0xB7, "LM3S1937"},
- {0x01, 0xBE, "LM3S1958"},
- {0x01, 0xB5, "LM3S1960"},
- {0x01, 0xB8, "LM3S1968"},
- {0x01, 0xEA, "LM3S1969"},
- {0x04, 0xCE, "LM3S1B21"},
- {0x06, 0xCA, "LM3S1C21"},
- {0x06, 0xCB, "LM3S1C26"},
- {0x06, 0x98, "LM3S1C58"},
- {0x06, 0xB0, "LM3S1D21"},
- {0x06, 0xCC, "LM3S1D26"},
- {0x06, 0x1D, "LM3S1F11"},
- {0x06, 0x1B, "LM3S1F16"},
- {0x06, 0xAF, "LM3S1G21"},
- {0x06, 0x95, "LM3S1G58"},
- {0x06, 0x1E, "LM3S1H11"},
- {0x06, 0x1C, "LM3S1H16"},
- {0x04, 0x0F, "LM3S1J11"},
- {0x04, 0x3C, "LM3S1J16"},
- {0x04, 0x0E, "LM3S1N11"},
- {0x04, 0x3B, "LM3S1N16"},
- {0x04, 0xB2, "LM3S1P51"},
- {0x04, 0x9E, "LM3S1R21"},
- {0x04, 0xC9, "LM3S1R26"},
- {0x04, 0x30, "LM3S1W16"},
- {0x04, 0x2F, "LM3S1Z16"},
- {0x01, 0x51, "LM3S2110"},
- {0x01, 0x84, "LM3S2139"},
- {0x03, 0x39, "LM3S2276"},
- {0x01, 0xA2, "LM3S2410"},
- {0x01, 0x59, "LM3S2412"},
- {0x01, 0x56, "LM3S2432"},
- {0x01, 0x5A, "LM3S2533"},
- {0x01, 0xE1, "LM3S2601"},
- {0x01, 0xE0, "LM3S2608"},
- {0x03, 0x33, "LM3S2616"},
- {0x01, 0x57, "LM3S2620"},
- {0x01, 0x85, "LM3S2637"},
- {0x01, 0x53, "LM3S2651"},
- {0x03, 0x80, "LM3S2671"},
- {0x03, 0x50, "LM3S2678"},
- {0x01, 0xA4, "LM3S2730"},
- {0x01, 0x52, "LM3S2739"},
- {0x03, 0x3A, "LM3S2776"},
- {0x04, 0x6D, "LM3S2793"},
- {0x01, 0xE3, "LM3S2911"},
- {0x01, 0xE2, "LM3S2918"},
- {0x01, 0xED, "LM3S2919"},
- {0x01, 0x54, "LM3S2939"},
- {0x01, 0x8F, "LM3S2948"},
- {0x01, 0x58, "LM3S2950"},
- {0x01, 0x55, "LM3S2965"},
- {0x04, 0x6C, "LM3S2B93"},
- {0x06, 0x94, "LM3S2D93"},
- {0x06, 0x93, "LM3S2U93"},
- {0x00, 0x19, "LM3S300"},
- {0x00, 0x11, "LM3S301"},
- {0x00, 0x1A, "LM3S308"},
- {0x00, 0x12, "LM3S310"},
- {0x00, 0x13, "LM3S315"},
- {0x00, 0x14, "LM3S316"},
- {0x00, 0x17, "LM3S317"},
- {0x00, 0x15, "LM3S328"},
- {0x03, 0x08, "LM3S3634"},
- {0x03, 0x43, "LM3S3651"},
- {0x04, 0xC8, "LM3S3654"},
- {0x03, 0x44, "LM3S3739"},
- {0x03, 0x49, "LM3S3748"},
- {0x03, 0x45, "LM3S3749"},
- {0x04, 0x42, "LM3S3826"},
- {0x04, 0x41, "LM3S3J26"},
- {0x04, 0x40, "LM3S3N26"},
- {0x04, 0x3F, "LM3S3W26"},
- {0x04, 0x3E, "LM3S3Z26"},
- {0x03, 0x81, "LM3S5632"},
- {0x04, 0x0C, "LM3S5651"},
- {0x03, 0x8A, "LM3S5652"},
- {0x04, 0x4D, "LM3S5656"},
- {0x03, 0x91, "LM3S5662"},
- {0x03, 0x96, "LM3S5732"},
- {0x03, 0x97, "LM3S5737"},
- {0x03, 0xA0, "LM3S5739"},
- {0x03, 0x99, "LM3S5747"},
- {0x03, 0xA7, "LM3S5749"},
- {0x03, 0x9A, "LM3S5752"},
- {0x03, 0x9C, "LM3S5762"},
- {0x04, 0x69, "LM3S5791"},
- {0x04, 0x0B, "LM3S5951"},
- {0x04, 0x4E, "LM3S5956"},
- {0x04, 0x68, "LM3S5B91"},
- {0x06, 0x2E, "LM3S5C31"},
- {0x06, 0x2C, "LM3S5C36"},
- {0x06, 0x5E, "LM3S5C51"},
- {0x06, 0x5B, "LM3S5C56"},
- {0x06, 0x5F, "LM3S5D51"},
- {0x06, 0x5C, "LM3S5D56"},
- {0x06, 0x87, "LM3S5D91"},
- {0x06, 0x2D, "LM3S5G31"},
- {0x06, 0x1F, "LM3S5G36"},
- {0x06, 0x5D, "LM3S5G51"},
- {0x06, 0x4F, "LM3S5G56"},
- {0x04, 0x09, "LM3S5K31"},
- {0x04, 0x4A, "LM3S5K36"},
- {0x04, 0x0A, "LM3S5P31"},
- {0x04, 0x48, "LM3S5P36"},
- {0x04, 0xB6, "LM3S5P3B"},
- {0x04, 0x0D, "LM3S5P51"},
- {0x04, 0x4C, "LM3S5P56"},
- {0x04, 0x07, "LM3S5R31"},
- {0x04, 0x4B, "LM3S5R36"},
- {0x04, 0x47, "LM3S5T36"},
- {0x06, 0x7F, "LM3S5U91"},
- {0x04, 0x46, "LM3S5Y36"},
- {0x00, 0x2A, "LM3S600"},
- {0x00, 0x21, "LM3S601"},
- {0x00, 0x2B, "LM3S608"},
- {0x00, 0x22, "LM3S610"},
- {0x01, 0xA1, "LM3S6100"},
- {0x00, 0x23, "LM3S611"},
- {0x01, 0x74, "LM3S6110"},
- {0x00, 0x24, "LM3S612"},
- {0x00, 0x25, "LM3S613"},
- {0x00, 0x26, "LM3S615"},
- {0x00, 0x28, "LM3S617"},
- {0x00, 0x29, "LM3S618"},
- {0x00, 0x27, "LM3S628"},
- {0x01, 0xA5, "LM3S6420"},
- {0x01, 0x82, "LM3S6422"},
- {0x01, 0x75, "LM3S6432"},
- {0x01, 0x76, "LM3S6537"},
- {0x01, 0x71, "LM3S6610"},
- {0x01, 0xE7, "LM3S6611"},
- {0x01, 0xE6, "LM3S6618"},
- {0x01, 0x83, "LM3S6633"},
- {0x01, 0x8B, "LM3S6637"},
- {0x01, 0xA3, "LM3S6730"},
- {0x01, 0x77, "LM3S6753"},
- {0x01, 0xE9, "LM3S6911"},
- {0x01, 0xE8, "LM3S6918"},
- {0x01, 0x89, "LM3S6938"},
- {0x01, 0x72, "LM3S6950"},
- {0x01, 0x78, "LM3S6952"},
- {0x01, 0x73, "LM3S6965"},
- {0x06, 0xAA, "LM3S6C11"},
- {0x06, 0xAC, "LM3S6C65"},
- {0x06, 0x9F, "LM3S6G11"},
- {0x06, 0xAB, "LM3S6G65"},
- {0x00, 0x38, "LM3S800"},
- {0x00, 0x31, "LM3S801"},
- {0x00, 0x39, "LM3S808"},
- {0x00, 0x32, "LM3S811"},
- {0x00, 0x33, "LM3S812"},
- {0x00, 0x34, "LM3S815"},
- {0x00, 0x36, "LM3S817"},
- {0x00, 0x37, "LM3S818"},
- {0x00, 0x35, "LM3S828"},
- {0x01, 0x64, "LM3S8530"},
- {0x01, 0x8E, "LM3S8538"},
- {0x01, 0x61, "LM3S8630"},
- {0x01, 0x63, "LM3S8730"},
- {0x01, 0x8D, "LM3S8733"},
- {0x01, 0x86, "LM3S8738"},
- {0x01, 0x65, "LM3S8930"},
- {0x01, 0x8C, "LM3S8933"},
- {0x01, 0x88, "LM3S8938"},
- {0x01, 0xA6, "LM3S8962"},
- {0x01, 0x62, "LM3S8970"},
- {0x01, 0xD7, "LM3S8971"},
- {0x06, 0xAE, "LM3S8C62"},
- {0x06, 0xAD, "LM3S8G62"},
- {0x04, 0xCF, "LM3S9781"},
- {0x04, 0x67, "LM3S9790"},
- {0x04, 0x6B, "LM3S9792"},
- {0x04, 0x2D, "LM3S9971"},
- {0x04, 0x20, "LM3S9997"},
- {0x04, 0xD0, "LM3S9B81"},
- {0x04, 0x66, "LM3S9B90"},
- {0x04, 0x6A, "LM3S9B92"},
- {0x04, 0x6E, "LM3S9B95"},
- {0x04, 0x6F, "LM3S9B96"},
- {0x04, 0x1D, "LM3S9BN2"},
- {0x04, 0x1E, "LM3S9BN5"},
- {0x04, 0x1F, "LM3S9BN6"},
- {0x06, 0x70, "LM3S9C97"},
- {0x06, 0xA9, "LM3S9D81"},
- {0x06, 0x7E, "LM3S9D90"},
- {0x06, 0x92, "LM3S9D92"},
- {0x06, 0x9D, "LM3S9D96"},
- {0x06, 0x7B, "LM3S9DN5"},
- {0x06, 0x7C, "LM3S9DN6"},
- {0x06, 0x60, "LM3S9G97"},
- {0x06, 0x79, "LM3S9GN5"},
- {0x04, 0x1B, "LM3S9L71"},
- {0x04, 0x18, "LM3S9L97"},
- {0x06, 0xA8, "LM3S9U81"},
- {0x06, 0x7D, "LM3S9U90"},
- {0x06, 0x90, "LM3S9U92"},
- {0x06, 0x9B, "LM3S9U96"},
- {0x05, 0x01, "LM4F120B2QR/TM4C1233C3PM"},
- {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"},
- {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"},
- {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"},
- {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"},
- {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"},
- {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"},
- {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"},
- {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"},
- {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"},
- {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"},
- {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"},
- {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"},
- {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"},
- {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"},
- {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"},
- {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"},
- {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"},
- {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"},
- {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"},
- {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"},
- {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"},
- {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"},
- {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"},
- {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"},
- {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"},
- {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"},
- {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"},
- {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"},
- {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"},
- {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"},
- {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"},
- {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"},
- {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"},
- {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"},
- {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
- {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"},
- {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"},
- {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"},
- {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"},
- {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"},
- {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"},
- {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"},
- {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"},
- {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"},
- {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"},
- {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"},
- {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"},
- {0x05, 0xE1, "LM4FSXLH5BB"},
- {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"},
- {0x05, 0xE4, "LM4FS99H5BB"},
- {0x05, 0xE5, "LM4FS1AH5BB"},
- {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"},
- {0x05, 0xEA, "LM4FS1GH5BB"},
- {0x05, 0xF0, "TM4C123GH6ZXR"},
- {0x0A, 0x19, "TM4C1290NCPDT"},
- {0x0A, 0x1B, "TM4C1290NCZAD"},
- {0x0A, 0x1C, "TM4C1292NCPDT"},
- {0x0A, 0x1E, "TM4C1292NCZAD"},
- {0x0A, 0x1F, "TM4C1294NCPDT"},
- {0x0A, 0x21, "TM4C1294NCZAD"},
- {0x0A, 0x22, "TM4C1297NCZAD"},
- {0x0A, 0x23, "TM4C1299NCZAD"},
- {0x0A, 0x24, "TM4C129CNCPDT"},
- {0x0A, 0x26, "TM4C129CNCZAD"},
- {0x0A, 0x27, "TM4C129DNCPDT"},
- {0x0A, 0x29, "TM4C129DNCZAD"},
- {0x0A, 0x2D, "TM4C129ENCPDT"},
- {0x0A, 0x2F, "TM4C129ENCZAD"},
- {0x0A, 0x30, "TM4C129LNCZAD"},
- {0x0A, 0x32, "TM4C129XNCZAD"},
- {0x0A, 0x34, "TM4C1294KCPDT"},
- {0x0A, 0x35, "TM4C129EKCPDT"},
- {0x0A, 0x36, "TM4C1299KCZAD"},
- {0x0A, 0x37, "TM4C129XKCZAD"},
- {0xFF, 0x00, "Unknown Part"}
-};
-
-static const char * const StellarisClassname[] = {
- "Sandstorm",
- "Fury",
- "Unknown",
- "DustDevil",
- "Tempest",
- "Blizzard/TM4C123x",
- "Firestorm",
- "",
- "",
- "",
- "Snowflake",
-};
-
-/***************************************************************************
-* openocd command interface *
-***************************************************************************/
-
-/* flash_bank stellaris <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
-{
- struct stellaris_flash_bank *stellaris_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
- bank->base = 0x0;
- bank->driver_priv = stellaris_info;
-
- stellaris_info->target_name = "Unknown target";
-
- /* part wasn't probed for info yet */
- stellaris_info->did1 = 0;
-
- /* TODO Specify the main crystal speed in kHz using an optional
- * argument; ditto, the speed of an external oscillator used
- * instead of a crystal. Avoid programming flash using IOSC.
- */
- return ERROR_OK;
-}
-
-static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int printed;
- struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
-
- if (stellaris_info->did1 == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- /* Read main and master clock freqency register */
- stellaris_read_clock_info(bank);
-
- printed = snprintf(buf,
- buf_size,
- "\nTI/LMI Stellaris information: Chip is "
- "class %i (%s) %s rev %c%i\n",
- stellaris_info->target_class,
- StellarisClassname[stellaris_info->target_class],
- stellaris_info->target_name,
- (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
- (int)((stellaris_info->did0) & 0xFF));
- buf += printed;
- buf_size -= printed;
-
- printed = snprintf(buf,
- buf_size,
- "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
- ", eproc: %s, ramsize: %" PRIu32 "k, flashsize: %" PRIu32 "k\n",
- stellaris_info->did1,
- stellaris_info->did1,
- "ARMv7M",
- stellaris_info->sramsiz,
- (uint32_t)(stellaris_info->num_pages * stellaris_info->pagesize / 1024));
- buf += printed;
- buf_size -= printed;
-
- snprintf(buf,
- buf_size,
- "master clock: %ikHz%s, "
- "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 ", "
- "pagesize: %" PRIu32 ", pages: %" PRIu32,
- (int)(stellaris_info->mck_freq / 1000),
- stellaris_info->mck_desc,
- stellaris_info->rcc,
- stellaris_info->rcc2,
- stellaris_info->pagesize,
- stellaris_info->num_pages);
-
- return ERROR_OK;
-}
-
-/***************************************************************************
-* chip identification and status *
-***************************************************************************/
-
-/* Set the flash timimg register to match current clocking */
-static void stellaris_set_flash_timing(struct flash_bank *bank)
-{
- struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
-
- /* only valid for Sandstorm and Fury class devices */
- if (stellaris_info->target_class > 1)
- return;
-
- LOG_DEBUG("usecrl = %i", (int)(usecrl));
- target_write_u32(target, SCB_BASE | USECRL, usecrl);
-}
-
-static const unsigned rcc_xtal[32] = {
- [0x00] = 1000000, /* no pll */
- [0x01] = 1843200, /* no pll */
- [0x02] = 2000000, /* no pll */
- [0x03] = 2457600, /* no pll */
-
- [0x04] = 3579545,
- [0x05] = 3686400,
- [0x06] = 4000000, /* usb */
- [0x07] = 4096000,
-
- [0x08] = 4915200,
- [0x09] = 5000000, /* usb */
- [0x0a] = 5120000,
- [0x0b] = 6000000, /* (reset) usb */
-
- [0x0c] = 6144000,
- [0x0d] = 7372800,
- [0x0e] = 8000000, /* usb */
- [0x0f] = 8192000,
-
- /* parts before DustDevil use just 4 bits for xtal spec */
-
- [0x10] = 10000000, /* usb */
- [0x11] = 12000000, /* usb */
- [0x12] = 12288000,
- [0x13] = 13560000,
-
- [0x14] = 14318180,
- [0x15] = 16000000, /* usb */
- [0x16] = 16384000,
-};
-
-/** Read clock configuration and set stellaris_info->usec_clocks. */
-static void stellaris_read_clock_info(struct flash_bank *bank)
-{
- struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
- unsigned xtal;
- unsigned long mainfreq;
-
- target_read_u32(target, SCB_BASE | RCC, &rcc);
- LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
-
- target_read_u32(target, SCB_BASE | RCC2, &rcc2);
- LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
-
- target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
- LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
-
- stellaris_info->rcc = rcc;
- stellaris_info->rcc2 = rcc2;
-
- sysdiv = (rcc >> 23) & 0xF;
- usesysdiv = (rcc >> 22) & 0x1;
- bypass = (rcc >> 11) & 0x1;
- oscsrc = (rcc >> 4) & 0x3;
- xtal = (rcc >> 6) & stellaris_info->xtal_mask;
-
- /* NOTE: post-Sandstorm parts have RCC2 which may override
- * parts of RCC ... with more sysdiv options, option for
- * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
- * as zero, so the "use RCC2" flag is always clear.
- */
- if (rcc2 & (1 << 31)) {
- sysdiv = (rcc2 >> 23) & 0x3F;
- bypass = (rcc2 >> 11) & 0x1;
- oscsrc = (rcc2 >> 4) & 0x7;
-
- /* FIXME Tempest parts have an additional lsb for
- * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
- */
- }
-
- stellaris_info->mck_desc = "";
-
- switch (oscsrc) {
- case 0: /* MOSC */
- mainfreq = rcc_xtal[xtal];
- break;
- case 1: /* IOSC */
- mainfreq = stellaris_info->iosc_freq;
- stellaris_info->mck_desc = stellaris_info->iosc_desc;
- break;
- case 2: /* IOSC/4 */
- mainfreq = stellaris_info->iosc_freq / 4;
- stellaris_info->mck_desc = stellaris_info->iosc_desc;
- break;
- case 3: /* lowspeed */
- /* Sandstorm doesn't have this 30K +/- 30% osc */
- mainfreq = 30000;
- stellaris_info->mck_desc = " (±30%)";
- break;
- case 8: /* hibernation osc */
- /* not all parts support hibernation */
- mainfreq = 32768;
- break;
-
- default: /* NOTREACHED */
- mainfreq = 0;
- break;
- }
-
- /* PLL is used if it's not bypassed; its output is 200 MHz
- * even when it runs at 400 MHz (adds divide-by-two stage).
- */
- if (!bypass)
- mainfreq = 200000000;
-
- if (usesysdiv)
- stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
- else
- stellaris_info->mck_freq = mainfreq;
-}
-
-/* Read device id register, main clock frequency register and fill in driver info structure */
-static int stellaris_read_part_info(struct flash_bank *bank)
-{
- struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t did0, did1, ver, fam;
- int i;
-
- /* Read and parse chip identification register */
- target_read_u32(target, SCB_BASE | DID0, &did0);
- target_read_u32(target, SCB_BASE | DID1, &did1);
- target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
- target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
- LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
- did0, did1, stellaris_info->dc0, stellaris_info->dc1);
-
- ver = DID0_VER(did0);
- if ((ver != 0) && (ver != 1)) {
- LOG_WARNING("Unknown did0 version, cannot identify target");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (did1 == 0) {
- LOG_WARNING("Cannot identify target as a Stellaris");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- ver = did1 >> 28;
- fam = (did1 >> 24) & 0xF;
- if (((ver != 0) && (ver != 1)) || (fam != 0)) {
- LOG_WARNING("Unknown did1 version/family.");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
- * is 12 MHz, but some older parts have 15 MHz. A few data sheets
- * even give _both_ numbers! We'll use current numbers; IOSC is
- * always approximate.
- *
- * For Tempest: IOSC is calibrated, 16 MHz
- * For Blizzard: IOSC is calibrated, 16 MHz
- * For Firestorm: IOSC is calibrated, 16 MHz
- */
- stellaris_info->iosc_freq = 12000000;
- stellaris_info->iosc_desc = " (±30%)";
- stellaris_info->xtal_mask = 0x0f;
-
- /* get device class */
- if (DID0_VER(did0) > 0) {
- stellaris_info->target_class = (did0 >> 16) & 0xFF;
- } else {
- /* Sandstorm class */
- stellaris_info->target_class = 0;
- }
-
- switch (stellaris_info->target_class) {
- case 0: /* Sandstorm */
- /*
- * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
- * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
- * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
- */
- if (((did0 >> 8) & 0xff) < 2) {
- stellaris_info->iosc_freq = 15000000;
- stellaris_info->iosc_desc = " (±50%)";
- }
- break;
-
- case 1: /* Fury */
- break;
-
- case 4: /* Tempest */
- case 5: /* Blizzard */
- case 6: /* Firestorm */
- case 0xa: /* Snowflake */
- stellaris_info->iosc_freq = 16000000; /* +/- 1% */
- stellaris_info->iosc_desc = " (±1%)";
- /* FALL THROUGH */
-
- case 3: /* DustDevil */
- stellaris_info->xtal_mask = 0x1f;
- break;
-
- default:
- LOG_WARNING("Unknown did0 class");
- }
-
- for (i = 0; StellarisParts[i].partno; i++) {
- if ((StellarisParts[i].partno == ((did1 >> 16) & 0xFF)) &&
- (StellarisParts[i].class == stellaris_info->target_class))
- break;
- }
-
- stellaris_info->target_name = StellarisParts[i].partname;
-
- stellaris_info->did0 = did0;
- stellaris_info->did1 = did1;
-
- if (stellaris_info->target_class == 5) { /* Blizzard */
- target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize);
- target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize);
-
- stellaris_info->num_pages = 2 * (1 + (stellaris_info->fsize & 0xFFFF));
- stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4;
- stellaris_info->pagesize = 1024;
- } else if (stellaris_info->target_class == 0xa) { /* Snowflake */
- target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize);
- target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize);
-
- stellaris_info->pagesize = (1 << ((stellaris_info->fsize >> 16) & 7)) * 1024;
- stellaris_info->num_pages = 2048 * (1 + (stellaris_info->fsize & 0xFFFF)) /
- stellaris_info->pagesize;
- stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4;
- } else {
- stellaris_info->num_pages = 2 * (1 + (stellaris_info->dc0 & 0xFFFF));
- stellaris_info->sramsiz = (1 + ((stellaris_info->dc0 >> 16) & 0xFFFF)) / 4;
- stellaris_info->pagesize = 1024;
- }
-
- /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
- * That exposes a 32-word Flash Write Buffer ... enabling
- * writes of more than one word at a time.
- */
-
- return ERROR_OK;
-}
-
-/***************************************************************************
-* flash operations *
-***************************************************************************/
-
-static int stellaris_protect_check(struct flash_bank *bank)
-{
- struct stellaris_flash_bank *stellaris = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t flash_sizek = stellaris->pagesize / 1024 *
- stellaris->num_pages;
- uint32_t fmppe_addr;
- int status = ERROR_OK;
- unsigned i;
-
- if (stellaris->did1 == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- for (i = 0; i < (unsigned) bank->num_sectors; i++)
- bank->sectors[i].is_protected = -1;
-
- /* Read each Flash Memory Protection Program Enable (FMPPE) register
- * to report any pages that we can't write. Ignore the Read Enable
- * register (FMPRE).
- */
-
- if (stellaris->target_class >= 0x0a || flash_sizek > 64)
- fmppe_addr = SCB_BASE | FMPPE0;
- else
- fmppe_addr = SCB_BASE | FMPPE;
-
- unsigned int page = 0, lockbitnum, lockbitcnt = flash_sizek / 2;
- unsigned int bits_per_page = stellaris->pagesize / 2048;
- /* Every lock bit always corresponds to a 2k region */
- for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) {
- uint32_t fmppe;
-
- target_read_u32(target, fmppe_addr, &fmppe);
- for (i = 0; i < 32 && lockbitnum + i < lockbitcnt; i++) {
- bool protect = !(fmppe & (1 << i));
- if (bits_per_page) {
- bank->sectors[page++].is_protected = protect;
- i += bits_per_page - 1;
- } else { /* 1024k pages, every lockbit covers 2 pages */
- bank->sectors[page++].is_protected = protect;
- bank->sectors[page++].is_protected = protect;
- }
- }
- fmppe_addr += 4;
- }
-
- return status;
-}
-
-static int stellaris_erase(struct flash_bank *bank, int first, int last)
-{
- int banknr;
- uint32_t flash_fmc, flash_cris;
- struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
- struct target *target = bank->target;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (stellaris_info->did1 == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
- return ERROR_FLASH_SECTOR_INVALID;
-
- if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
- return stellaris_mass_erase(bank);
-
- /* Refresh flash controller timing */
- stellaris_read_clock_info(bank);
- stellaris_set_flash_timing(bank);
-
- /* Clear and disable flash programming interrupts */
- target_write_u32(target, FLASH_CIM, 0);
- target_write_u32(target, FLASH_MISC, PMISC | AMISC);
-
- /* REVISIT this clobbers state set by any halted firmware ...
- * it might want to process those IRQs.
- */
-
- for (banknr = first; banknr <= last; banknr++) {
- /* Address is first word in page */
- target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
- /* Write erase command */
- target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
- /* Wait until erase complete */
- do {
- target_read_u32(target, FLASH_FMC, &flash_fmc);
- } while (flash_fmc & FMC_ERASE);
-
- /* Check acess violations */
- target_read_u32(target, FLASH_CRIS, &flash_cris);
- if (flash_cris & (AMASK)) {
- LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "",
- banknr, flash_cris);
- target_write_u32(target, FLASH_CRIS, 0);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- bank->sectors[banknr].is_erased = 1;
- }
-
- return ERROR_OK;
-}
-
-static int stellaris_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct stellaris_flash_bank *stellaris = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t flash_fmc, flash_cris;
- unsigned int bits_per_page = stellaris->pagesize / 2048;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!set) {
- LOG_ERROR("Hardware doesn't support page-level unprotect. "
- "Try the 'recover' command.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (stellaris->did1 == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (stellaris->target_class == 0x03 &&
- !((stellaris->did0 >> 8) & 0xFF) &&
- !((stellaris->did0) & 0xFF)) {
- LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (!bits_per_page && (first % 2 || !(last % 2))) {
- LOG_ERROR("Can't protect unaligned pages");
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- /* Refresh flash controller timing */
- stellaris_read_clock_info(bank);
- stellaris_set_flash_timing(bank);
-
- /* Clear and disable flash programming interrupts */
- target_write_u32(target, FLASH_CIM, 0);
- target_write_u32(target, FLASH_MISC, PMISC | AMISC);
-
- uint32_t flash_sizek = stellaris->pagesize / 1024 *
- stellaris->num_pages;
- uint32_t fmppe_addr;
-
- if (stellaris->target_class >= 0x0a || flash_sizek > 64)
- fmppe_addr = SCB_BASE | FMPPE0;
- else
- fmppe_addr = SCB_BASE | FMPPE;
-
- int page = 0;
- unsigned int lockbitnum, lockbitcnt = flash_sizek / 2;
- /* Every lock bit always corresponds to a 2k region */
- for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) {
- uint32_t fmppe;
-
- target_read_u32(target, fmppe_addr, &fmppe);
- for (unsigned int i = 0;
- i < 32 && lockbitnum + i < lockbitcnt;
- i++) {
- if (page >= first && page <= last)
- fmppe &= ~(1 << i);
-
- if (bits_per_page) {
- if (!((i + 1) % bits_per_page))
- page++;
- } else { /* 1024k pages, every lockbit covers 2 pages */
- page += 2;
- }
- }
- target_write_u32(target, fmppe_addr, fmppe);
-
- /* Commit FMPPE* */
- target_write_u32(target, FLASH_FMA, 1 + lockbitnum / 16);
- /* Write commit command */
- target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT);
-
- /* Wait until commit complete */
- do {
- target_read_u32(target, FLASH_FMC, &flash_fmc);
- } while (flash_fmc & FMC_COMT);
-
- /* Check access violations */
- target_read_u32(target, FLASH_CRIS, &flash_cris);
- if (flash_cris & (AMASK)) {
- LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
- target_write_u32(target, FLASH_CRIS, 0);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- fmppe_addr += 4;
- }
-
- return ERROR_OK;
-}
-
-/* see contib/loaders/flash/stellaris.s for src */
-
-static const uint8_t stellaris_write_code[] = {
- /* write: */
- 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
- 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
- /* wait_fifo: */
- 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
- 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
- 0x17, 0xD0, /* beq exit */
- 0x47, 0x68, /* ldr r7, [r0, #4] */
- 0x47, 0x45, /* cmp r7, r8 */
- 0xF7, 0xD0, /* beq wait_fifo */
- /* mainloop: */
- 0x22, 0x60, /* str r2, [r4, #0] */
- 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
- 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
- 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
- 0xA5, 0x60, /* str r5, [r4, #8] */
- /* busy: */
- 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
- 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
- 0xFA, 0xD1, /* bne busy */
- 0x8F, 0x42, /* cmp r7, r1 */
- 0x28, 0xBF, /* it cs */
- 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
- 0x47, 0x60, /* str r7, [r0, #4] */
- 0x01, 0x3B, /* subs r3, r3, #1 */
- 0x03, 0xB1, /* cbz r3, exit */
- 0xE2, 0xE7, /* b wait_fifo */
- /* exit: */
- 0x00, 0xBE, /* bkpt #0 */
-
- /* pFLASH_CTRL_BASE: */
- 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
- /* FLASHWRITECMD: */
- 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
-};
-static int stellaris_write_block(struct flash_bank *bank,
- const uint8_t *buffer, uint32_t offset, uint32_t wcount)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *source;
- struct working_area *write_algorithm;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[4];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* power of two, and multiple of word size */
- static const unsigned buf_min = 128;
-
- /* for small buffers it's faster not to download an algorithm */
- if (wcount * 4 < buf_min)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
- bank, buffer, offset, wcount);
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(stellaris_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_DEBUG("no working area for block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* plus a buffer big enough for this data */
- if (wcount * 4 < buffer_size)
- buffer_size = wcount * 4;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= buf_min) {
- target_free_working_area(target, write_algorithm);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
- target_name(target), (unsigned) buffer_size);
- }
-
- target_write_buffer(target, write_algorithm->address,
- sizeof(stellaris_write_code),
- stellaris_write_code);
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- 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);
-
- 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, wcount);
-
- retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
- 0, NULL,
- 4, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (retval == ERROR_FLASH_OPERATION_FAILED)
- LOG_ERROR("error %d executing stellaris flash write algorithm", retval);
-
- target_free_working_area(target, write_algorithm);
- target_free_working_area(target, source);
-
- 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 retval;
-}
-
-static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t address = offset;
- uint32_t flash_cris, flash_fmc;
- uint32_t words_remaining = (count / 4);
- uint32_t bytes_remaining = (count & 0x00000003);
- uint32_t bytes_written = 0;
- int retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
- bank, buffer, offset, count);
-
- if (stellaris_info->did1 == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- if (offset & 0x3) {
- LOG_WARNING("offset size must be word aligned");
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- if (offset + count > bank->size)
- return ERROR_FLASH_DST_OUT_OF_BANK;
-
- /* Refresh flash controller timing */
- stellaris_read_clock_info(bank);
- stellaris_set_flash_timing(bank);
-
- /* Clear and disable flash programming interrupts */
- target_write_u32(target, FLASH_CIM, 0);
- target_write_u32(target, FLASH_MISC, PMISC | AMISC);
-
- /* REVISIT this clobbers state set by any halted firmware ...
- * it might want to process those IRQs.
- */
-
- /* multiple words to be programmed? */
- if (words_remaining > 0) {
- /* try using a block write */
- retval = stellaris_write_block(bank, buffer, offset,
- words_remaining);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- LOG_DEBUG("writing flash word-at-a-time");
- } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
- /* if an error occured, we examine the reason, and quit */
- target_read_u32(target, FLASH_CRIS, &flash_cris);
-
- LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- } else {
- buffer += words_remaining * 4;
- address += words_remaining * 4;
- words_remaining = 0;
- }
- }
-
- while (words_remaining > 0) {
- if (!(address & 0xff))
- LOG_DEBUG("0x%" PRIx32 "", address);
-
- /* Program one word */
- target_write_u32(target, FLASH_FMA, address);
- target_write_buffer(target, FLASH_FMD, 4, buffer);
- target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
- /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
- /* Wait until write complete */
- do {
- target_read_u32(target, FLASH_FMC, &flash_fmc);
- } while (flash_fmc & FMC_WRITE);
-
- buffer += 4;
- address += 4;
- words_remaining--;
- }
-
- if (bytes_remaining) {
- uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
-
- /* copy the last remaining bytes into the write buffer */
- memcpy(last_word, buffer+bytes_written, bytes_remaining);
-
- if (!(address & 0xff))
- LOG_DEBUG("0x%" PRIx32 "", address);
-
- /* Program one word */
- target_write_u32(target, FLASH_FMA, address);
- target_write_buffer(target, FLASH_FMD, 4, last_word);
- target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
- /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
- /* Wait until write complete */
- do {
- target_read_u32(target, FLASH_FMC, &flash_fmc);
- } while (flash_fmc & FMC_WRITE);
- }
-
- /* Check access violations */
- target_read_u32(target, FLASH_CRIS, &flash_cris);
- if (flash_cris & (AMASK)) {
- LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- return ERROR_OK;
-}
-
-static int stellaris_probe(struct flash_bank *bank)
-{
- struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
- int retval;
-
- /* If this is a stellaris chip, it has flash; probe() is just
- * to figure out how much is present. Only do it once.
- */
- if (stellaris_info->did1 != 0)
- return ERROR_OK;
-
- /* stellaris_read_part_info() already handled error checking and
- * reporting. Note that it doesn't write, so we don't care about
- * whether the target is halted or not.
- */
- retval = stellaris_read_part_info(bank);
- if (retval != ERROR_OK)
- return retval;
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- /* provide this for the benefit of the NOR flash framework */
- bank->size = stellaris_info->num_pages * stellaris_info->pagesize;
- bank->num_sectors = stellaris_info->num_pages;
- bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].offset = i * stellaris_info->pagesize;
- bank->sectors[i].size = stellaris_info->pagesize;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- return retval;
-}
-
-static int stellaris_mass_erase(struct flash_bank *bank)
-{
- struct target *target = NULL;
- struct stellaris_flash_bank *stellaris_info = NULL;
- uint32_t flash_fmc;
-
- stellaris_info = bank->driver_priv;
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (stellaris_info->did1 == 0)
- return ERROR_FLASH_BANK_NOT_PROBED;
-
- /* Refresh flash controller timing */
- stellaris_read_clock_info(bank);
- stellaris_set_flash_timing(bank);
-
- /* Clear and disable flash programming interrupts */
- target_write_u32(target, FLASH_CIM, 0);
- target_write_u32(target, FLASH_MISC, PMISC | AMISC);
-
- /* REVISIT this clobbers state set by any halted firmware ...
- * it might want to process those IRQs.
- */
-
- target_write_u32(target, FLASH_FMA, 0);
- target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
- /* Wait until erase complete */
- do {
- target_read_u32(target, FLASH_FMC, &flash_fmc);
- } while (flash_fmc & FMC_MERASE);
-
- /* if device has > 128k, then second erase cycle is needed
- * this is only valid for older devices, but will not hurt */
- if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) {
- target_write_u32(target, FLASH_FMA, 0x20000);
- target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
- /* Wait until erase complete */
- do {
- target_read_u32(target, FLASH_FMC, &flash_fmc);
- } while (flash_fmc & FMC_MERASE);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stellaris_handle_mass_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (stellaris_mass_erase(bank) == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "stellaris mass erase complete");
- } else
- command_print(CMD_CTX, "stellaris mass erase failed");
-
- return ERROR_OK;
-}
-
-/**
- * Perform the Stellaris "Recovering a 'Locked' Device procedure.
- * This performs a mass erase and then restores all nonvolatile registers
- * (including USER_* registers and flash lock bits) to their defaults.
- * Accordingly, flash can be reprogrammed, and JTAG can be used.
- *
- * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
- * can affect this operation if flash protection has been enabled.
- */
-COMMAND_HANDLER(stellaris_handle_recover_command)
-{
- struct flash_bank *bank;
- int retval;
-
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- bank = get_flash_bank_by_num_noprobe(0);
- if (!bank)
- return ERROR_FAIL;
-
- /* REVISIT ... it may be worth sanity checking that the AP is
- * inactive before we start. ARM documents that switching a DP's
- * mode while it's active can cause fault modes that need a power
- * cycle to recover.
- */
-
- Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", 0, 0);
- if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) {
- retval = ERROR_OK;
- goto user_action;
- }
-
- /* assert SRST */
- if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
- LOG_ERROR("Can't recover Stellaris flash without SRST");
- return ERROR_FAIL;
- }
- adapter_assert_reset();
-
- for (int i = 0; i < 5; i++) {
- retval = dap_to_swd(bank->target);
- if (retval != ERROR_OK)
- goto done;
-
- retval = dap_to_jtag(bank->target);
- if (retval != ERROR_OK)
- goto done;
- }
-
- /* de-assert SRST */
- adapter_deassert_reset();
- retval = jtag_execute_queue();
-
- /* wait 400+ msec ... OK, "1+ second" is simpler */
- usleep(1000);
-
-user_action:
- /* USER INTERVENTION required for the power cycle
- * Restarting OpenOCD is likely needed because of mode switching.
- */
- LOG_INFO("USER ACTION: "
- "power cycle Stellaris chip, then restart OpenOCD.");
-
-done:
- return retval;
-}
-
-static const struct command_registration stellaris_exec_command_handlers[] = {
- {
- .name = "mass_erase",
- .usage = "<bank>",
- .handler = stellaris_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .help = "erase entire device",
- },
- {
- .name = "recover",
- .handler = stellaris_handle_recover_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "recover (and erase) locked device",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration stellaris_command_handlers[] = {
- {
- .name = "stellaris",
- .mode = COMMAND_EXEC,
- .help = "Stellaris flash command group",
- .usage = "",
- .chain = stellaris_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver stellaris_flash = {
- .name = "stellaris",
- .commands = stellaris_command_handlers,
- .flash_bank_command = stellaris_flash_bank_command,
- .erase = stellaris_erase,
- .protect = stellaris_protect,
- .write = stellaris_write,
- .read = default_flash_read,
- .probe = stellaris_probe,
- .auto_probe = stellaris_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = stellaris_protect_check,
- .info = get_stellaris_info,
-};
diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c
deleted file mode 100644
index d446707..0000000
--- a/src/flash/nor/stm32f1x.c
+++ /dev/null
@@ -1,1650 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-/* stm32x register locations */
-
-#define FLASH_REG_BASE_B0 0x40022000
-#define FLASH_REG_BASE_B1 0x40022040
-
-#define STM32_FLASH_ACR 0x00
-#define STM32_FLASH_KEYR 0x04
-#define STM32_FLASH_OPTKEYR 0x08
-#define STM32_FLASH_SR 0x0C
-#define STM32_FLASH_CR 0x10
-#define STM32_FLASH_AR 0x14
-#define STM32_FLASH_OBR 0x1C
-#define STM32_FLASH_WRPR 0x20
-
-/* TODO: Check if code using these really should be hard coded to bank 0.
- * There are valid cases, on dual flash devices the protection of the
- * second bank is done on the bank0 reg's. */
-#define STM32_FLASH_ACR_B0 0x40022000
-#define STM32_FLASH_KEYR_B0 0x40022004
-#define STM32_FLASH_OPTKEYR_B0 0x40022008
-#define STM32_FLASH_SR_B0 0x4002200C
-#define STM32_FLASH_CR_B0 0x40022010
-#define STM32_FLASH_AR_B0 0x40022014
-#define STM32_FLASH_OBR_B0 0x4002201C
-#define STM32_FLASH_WRPR_B0 0x40022020
-
-/* option byte location */
-
-#define STM32_OB_RDP 0x1FFFF800
-#define STM32_OB_USER 0x1FFFF802
-#define STM32_OB_DATA0 0x1FFFF804
-#define STM32_OB_DATA1 0x1FFFF806
-#define STM32_OB_WRP0 0x1FFFF808
-#define STM32_OB_WRP1 0x1FFFF80A
-#define STM32_OB_WRP2 0x1FFFF80C
-#define STM32_OB_WRP3 0x1FFFF80E
-
-/* FLASH_CR register bits */
-
-#define FLASH_PG (1 << 0)
-#define FLASH_PER (1 << 1)
-#define FLASH_MER (1 << 2)
-#define FLASH_OPTPG (1 << 4)
-#define FLASH_OPTER (1 << 5)
-#define FLASH_STRT (1 << 6)
-#define FLASH_LOCK (1 << 7)
-#define FLASH_OPTWRE (1 << 9)
-
-/* FLASH_SR register bits */
-
-#define FLASH_BSY (1 << 0)
-#define FLASH_PGERR (1 << 2)
-#define FLASH_WRPRTERR (1 << 4)
-#define FLASH_EOP (1 << 5)
-
-/* STM32_FLASH_OBR bit definitions (reading) */
-
-#define OPT_ERROR 0
-#define OPT_READOUT 1
-#define OPT_RDWDGSW 2
-#define OPT_RDRSTSTOP 3
-#define OPT_RDRSTSTDBY 4
-#define OPT_BFB2 5 /* dual flash bank only */
-
-/* register unlock keys */
-
-#define KEY1 0x45670123
-#define KEY2 0xCDEF89AB
-
-/* timeout values */
-
-#define FLASH_WRITE_TIMEOUT 10
-#define FLASH_ERASE_TIMEOUT 100
-
-struct stm32x_options {
- uint16_t RDP;
- uint16_t user_options;
- uint16_t user_data;
- uint16_t protection[4];
-};
-
-struct stm32x_flash_bank {
- struct stm32x_options option_bytes;
- int ppage_size;
- int probed;
-
- bool has_dual_banks;
- /* used to access dual flash bank stm32xl */
- uint32_t register_base;
- uint16_t default_rdp;
- int user_data_offset;
- int option_offset;
- uint32_t user_bank_size;
-};
-
-static int stm32x_mass_erase(struct flash_bank *bank);
-static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id);
-static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count);
-
-/* flash bank stm32x <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
-{
- struct stm32x_flash_bank *stm32x_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
-
- bank->driver_priv = stm32x_info;
- stm32x_info->probed = 0;
- stm32x_info->has_dual_banks = false;
- stm32x_info->register_base = FLASH_REG_BASE_B0;
- stm32x_info->user_bank_size = bank->size;
-
- return ERROR_OK;
-}
-
-static inline int stm32x_get_flash_reg(struct flash_bank *bank, uint32_t reg)
-{
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
- return reg + stm32x_info->register_base;
-}
-
-static inline int stm32x_get_flash_status(struct flash_bank *bank, uint32_t *status)
-{
- struct target *target = bank->target;
- return target_read_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), status);
-}
-
-static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
-{
- struct target *target = bank->target;
- uint32_t status;
- int retval = ERROR_OK;
-
- /* wait for busy to clear */
- for (;;) {
- retval = stm32x_get_flash_status(bank, &status);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if ((status & FLASH_BSY) == 0)
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
- if (status & FLASH_WRPRTERR) {
- LOG_ERROR("stm32x device protected");
- retval = ERROR_FAIL;
- }
-
- if (status & FLASH_PGERR) {
- LOG_ERROR("stm32x device programming failed");
- retval = ERROR_FAIL;
- }
-
- /* Clear but report errors */
- if (status & (FLASH_WRPRTERR | FLASH_PGERR)) {
- /* If this operation fails, we ignore it and report the original
- * retval
- */
- target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR),
- FLASH_WRPRTERR | FLASH_PGERR);
- }
- return retval;
-}
-
-static int stm32x_check_operation_supported(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
-
- /* if we have a dual flash bank device then
- * we need to perform option byte stuff on bank0 only */
- if (stm32x_info->register_base != FLASH_REG_BASE_B0) {
- LOG_ERROR("Option Byte Operation's must use bank0");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int stm32x_read_options(struct flash_bank *bank)
-{
- uint32_t optiondata;
- struct stm32x_flash_bank *stm32x_info = NULL;
- struct target *target = bank->target;
-
- stm32x_info = bank->driver_priv;
-
- /* read current option bytes */
- int retval = target_read_u32(target, STM32_FLASH_OBR_B0, &optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- stm32x_info->option_bytes.user_options = (optiondata >> stm32x_info->option_offset >> 2) & 0xffff;
- stm32x_info->option_bytes.user_data = (optiondata >> stm32x_info->user_data_offset) & 0xffff;
- stm32x_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5;
-
- if (optiondata & (1 << OPT_READOUT))
- LOG_INFO("Device Security Bit Set");
-
- /* each bit refers to a 4bank protection */
- retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- stm32x_info->option_bytes.protection[0] = (uint16_t)optiondata;
- stm32x_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8);
- stm32x_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16);
- stm32x_info->option_bytes.protection[3] = (uint16_t)(optiondata >> 24);
-
- return ERROR_OK;
-}
-
-static int stm32x_erase_options(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = NULL;
- struct target *target = bank->target;
-
- stm32x_info = bank->driver_priv;
-
- /* read current options */
- stm32x_read_options(bank);
-
- /* unlock flash registers */
- int retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* unlock option flash registers */
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* erase option bytes */
- retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_OPTWRE);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- /* clear readout protection and complementary option bytes
- * this will also force a device unlock if set */
- stm32x_info->option_bytes.RDP = stm32x_info->default_rdp;
-
- return ERROR_OK;
-}
-
-static int stm32x_write_options(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = NULL;
- struct target *target = bank->target;
-
- stm32x_info = bank->driver_priv;
-
- /* unlock flash registers */
- int retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* unlock option flash registers */
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* program option bytes */
- retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTPG | FLASH_OPTWRE);
- if (retval != ERROR_OK)
- return retval;
-
- uint8_t opt_bytes[16];
-
- target_buffer_set_u16(target, opt_bytes, stm32x_info->option_bytes.RDP);
- target_buffer_set_u16(target, opt_bytes + 2, stm32x_info->option_bytes.user_options);
- target_buffer_set_u16(target, opt_bytes + 4, stm32x_info->option_bytes.user_data & 0xff);
- target_buffer_set_u16(target, opt_bytes + 6, (stm32x_info->option_bytes.user_data >> 8) & 0xff);
- target_buffer_set_u16(target, opt_bytes + 8, stm32x_info->option_bytes.protection[0]);
- target_buffer_set_u16(target, opt_bytes + 10, stm32x_info->option_bytes.protection[1]);
- target_buffer_set_u16(target, opt_bytes + 12, stm32x_info->option_bytes.protection[2]);
- target_buffer_set_u16(target, opt_bytes + 14, stm32x_info->option_bytes.protection[3]);
-
- uint32_t offset = STM32_OB_RDP - bank->base;
- retval = stm32x_write_block(bank, opt_bytes, offset, sizeof(opt_bytes) / 2);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
- LOG_ERROR("working area required to erase options bytes");
- return retval;
- }
-
- retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32x_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
-
- uint32_t protection;
- int i, s;
- int num_bits;
- int set;
-
- int retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
- return retval;
-
- /* medium density - each bit refers to a 4bank protection
- * high density - each bit refers to a 2bank protection */
- retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &protection);
- if (retval != ERROR_OK)
- return retval;
-
- /* medium density - each protection bit is for 4 * 1K pages
- * high density - each protection bit is for 2 * 2K pages */
- num_bits = (bank->num_sectors / stm32x_info->ppage_size);
-
- if (stm32x_info->ppage_size == 2) {
- /* high density flash/connectivity line protection */
-
- set = 1;
-
- if (protection & (1 << 31))
- set = 0;
-
- /* bit 31 controls sector 62 - 255 protection for high density
- * bit 31 controls sector 62 - 127 protection for connectivity line */
- for (s = 62; s < bank->num_sectors; s++)
- bank->sectors[s].is_protected = set;
-
- if (bank->num_sectors > 61)
- num_bits = 31;
-
- for (i = 0; i < num_bits; i++) {
- set = 1;
-
- if (protection & (1 << i))
- set = 0;
-
- for (s = 0; s < stm32x_info->ppage_size; s++)
- bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
- }
- } else {
- /* low/medium density flash protection */
- for (i = 0; i < num_bits; i++) {
- set = 1;
-
- if (protection & (1 << i))
- set = 0;
-
- for (s = 0; s < stm32x_info->ppage_size; s++)
- bank->sectors[(i * stm32x_info->ppage_size) + s].is_protected = set;
- }
- }
-
- return ERROR_OK;
-}
-
-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");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((first == 0) && (last == (bank->num_sectors - 1)))
- return stm32x_mass_erase(bank);
-
- /* unlock flash registers */
- int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- for (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;
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_AR),
- bank->base + bank->sectors[i].offset);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target,
- stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER | FLASH_STRT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- bank->sectors[i].is_erased = 1;
- }
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct stm32x_flash_bank *stm32x_info = NULL;
- struct target *target = bank->target;
- uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
- int i, reg, bit;
- int status;
- uint32_t protection;
-
- stm32x_info = bank->driver_priv;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
- return retval;
-
- if ((first % stm32x_info->ppage_size) != 0) {
- LOG_WARNING("aligned start protect sector to a %d sector boundary",
- stm32x_info->ppage_size);
- first = first - (first % stm32x_info->ppage_size);
- }
- if (((last + 1) % stm32x_info->ppage_size) != 0) {
- LOG_WARNING("aligned end protect sector to a %d sector boundary",
- stm32x_info->ppage_size);
- last++;
- last = last - (last % stm32x_info->ppage_size);
- last--;
- }
-
- /* medium density - each bit refers to a 4bank protection
- * high density - each bit refers to a 2bank protection */
- retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &protection);
- if (retval != ERROR_OK)
- return retval;
-
- prot_reg[0] = (uint16_t)protection;
- prot_reg[1] = (uint16_t)(protection >> 8);
- prot_reg[2] = (uint16_t)(protection >> 16);
- prot_reg[3] = (uint16_t)(protection >> 24);
-
- if (stm32x_info->ppage_size == 2) {
- /* high density flash */
-
- /* bit 7 controls sector 62 - 255 protection */
- if (last > 61) {
- if (set)
- prot_reg[3] &= ~(1 << 7);
- else
- prot_reg[3] |= (1 << 7);
- }
-
- if (first > 61)
- first = 62;
- if (last > 61)
- last = 61;
-
- for (i = first; i <= last; i++) {
- reg = (i / stm32x_info->ppage_size) / 8;
- bit = (i / stm32x_info->ppage_size) - (reg * 8);
-
- if (set)
- prot_reg[reg] &= ~(1 << bit);
- else
- prot_reg[reg] |= (1 << bit);
- }
- } else {
- /* medium density flash */
- for (i = first; i <= last; i++) {
- reg = (i / stm32x_info->ppage_size) / 8;
- bit = (i / stm32x_info->ppage_size) - (reg * 8);
-
- if (set)
- prot_reg[reg] &= ~(1 << bit);
- else
- prot_reg[reg] |= (1 << bit);
- }
- }
-
- status = stm32x_erase_options(bank);
- if (status != ERROR_OK)
- return status;
-
- stm32x_info->option_bytes.protection[0] = prot_reg[0];
- stm32x_info->option_bytes.protection[1] = prot_reg[1];
- stm32x_info->option_bytes.protection[2] = prot_reg[2];
- stm32x_info->option_bytes.protection[3] = prot_reg[3];
-
- return stm32x_write_options(bank);
-}
-
-static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* see contrib/loaders/flash/stm32f1x.S for src */
-
- static const uint8_t stm32x_flash_write_code[] = {
- /* #define STM32_FLASH_SR_OFFSET 0x0C */
- /* wait_fifo: */
- 0x16, 0x68, /* ldr r6, [r2, #0] */
- 0x00, 0x2e, /* cmp r6, #0 */
- 0x18, 0xd0, /* beq exit */
- 0x55, 0x68, /* ldr r5, [r2, #4] */
- 0xb5, 0x42, /* cmp r5, r6 */
- 0xf9, 0xd0, /* beq wait_fifo */
- 0x2e, 0x88, /* ldrh r6, [r5, #0] */
- 0x26, 0x80, /* strh r6, [r4, #0] */
- 0x02, 0x35, /* adds r5, #2 */
- 0x02, 0x34, /* adds r4, #2 */
- /* busy: */
- 0xc6, 0x68, /* ldr r6, [r0, #STM32_FLASH_SR_OFFSET] */
- 0x01, 0x27, /* movs r7, #1 */
- 0x3e, 0x42, /* tst r6, r7 */
- 0xfb, 0xd1, /* bne busy */
- 0x14, 0x27, /* movs r7, #0x14 */
- 0x3e, 0x42, /* tst r6, r7 */
- 0x08, 0xd1, /* bne error */
- 0x9d, 0x42, /* cmp r5, r3 */
- 0x01, 0xd3, /* bcc no_wrap */
- 0x15, 0x46, /* mov r5, r2 */
- 0x08, 0x35, /* adds r5, #8 */
- /* no_wrap: */
- 0x55, 0x60, /* str r5, [r2, #4] */
- 0x01, 0x39, /* subs r1, r1, #1 */
- 0x00, 0x29, /* cmp r1, #0 */
- 0x02, 0xd0, /* beq exit */
- 0xe5, 0xe7, /* b wait_fifo */
- /* error: */
- 0x00, 0x20, /* movs r0, #0 */
- 0x50, 0x60, /* str r0, [r2, #4] */
- /* exit: */
- 0x30, 0x46, /* mov r0, r6 */
- 0x00, 0xbe, /* bkpt #0 */
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(stm32x_flash_write_code), stm32x_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (halfword-16bit) */
- init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
- init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
-
- buf_set_u32(reg_params[0].value, 0, 32, stm32x_info->register_base);
- buf_set_u32(reg_params[1].value, 0, 32, count);
- buf_set_u32(reg_params[2].value, 0, 32, source->address);
- buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
- buf_set_u32(reg_params[4].value, 0, 32, address);
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- retval = target_run_flash_async_algorithm(target, buffer, count, 2,
- 0, NULL,
- 5, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (retval == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("flash write failed at address 0x%"PRIx32,
- buf_get_u32(reg_params[4].value, 0, 32));
-
- if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) {
- LOG_ERROR("flash memory not erased before writing");
- /* Clear but report errors */
- target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_PGERR);
- }
-
- if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) {
- LOG_ERROR("flash memory write protected");
- /* Clear but report errors */
- target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), FLASH_WRPRTERR);
- }
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint8_t *new_buffer = NULL;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x1) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- /* If there's an odd number of bytes, the data has to be padded. Duplicate
- * the buffer and use the normal code path with a single block write since
- * it's probably cheaper than to special case the last odd write using
- * discrete accesses. */
- if (count & 1) {
- new_buffer = malloc(count + 1);
- if (new_buffer == NULL) {
- LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
- return ERROR_FAIL;
- }
- LOG_INFO("odd number of bytes to write, padding with 0xff");
- buffer = memcpy(new_buffer, buffer, count);
- new_buffer[count++] = 0xff;
- }
-
- uint32_t words_remaining = count / 2;
- int retval, retval2;
-
- /* unlock flash registers */
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
- if (retval != ERROR_OK)
- goto cleanup;
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
- if (retval != ERROR_OK)
- goto cleanup;
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PG);
- if (retval != ERROR_OK)
- goto cleanup;
-
- /* try using a block write */
- retval = stm32x_write_block(bank, buffer, offset, words_remaining);
-
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single halfword accesses */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
-
- while (words_remaining > 0) {
- uint16_t value;
- memcpy(&value, buffer, sizeof(uint16_t));
-
- retval = target_write_u16(target, bank->base + offset, value);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- retval = stm32x_wait_status_busy(bank, 5);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- words_remaining--;
- buffer += 2;
- offset += 2;
- }
- }
-
-reset_pg_and_lock:
- retval2 = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval == ERROR_OK)
- retval = retval2;
-
-cleanup:
- if (new_buffer)
- free(new_buffer);
-
- return retval;
-}
-
-static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
-{
- /* This check the device CPUID core register to detect
- * the M0 from the M3 devices. */
-
- struct target *target = bank->target;
- uint32_t cpuid, device_id_register = 0;
-
- /* Get the CPUID from the ARM Core
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */
- int retval = target_read_u32(target, 0xE000ED00, &cpuid);
- if (retval != ERROR_OK)
- return retval;
-
- if (((cpuid >> 4) & 0xFFF) == 0xC20) {
- /* 0xC20 is M0 devices */
- device_id_register = 0x40015800;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC23) {
- /* 0xC23 is M3 devices */
- device_id_register = 0xE0042000;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC24) {
- /* 0xC24 is M4 devices */
- device_id_register = 0xE0042000;
- } else {
- LOG_ERROR("Cannot identify target as a stm32x");
- return ERROR_FAIL;
- }
-
- /* read stm32 device id register */
- retval = target_read_u32(target, device_id_register, device_id);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb)
-{
- struct target *target = bank->target;
- uint32_t cpuid, flash_size_reg;
-
- int retval = target_read_u32(target, 0xE000ED00, &cpuid);
- if (retval != ERROR_OK)
- return retval;
-
- if (((cpuid >> 4) & 0xFFF) == 0xC20) {
- /* 0xC20 is M0 devices */
- flash_size_reg = 0x1FFFF7CC;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC23) {
- /* 0xC23 is M3 devices */
- flash_size_reg = 0x1FFFF7E0;
- } else if (((cpuid >> 4) & 0xFFF) == 0xC24) {
- /* 0xC24 is M4 devices */
- flash_size_reg = 0x1FFFF7CC;
- } else {
- LOG_ERROR("Cannot identify target as a stm32x");
- return ERROR_FAIL;
- }
-
- retval = target_read_u16(target, flash_size_reg, flash_size_in_kb);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-static int stm32x_probe(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
- int i;
- uint16_t flash_size_in_kb;
- uint16_t max_flash_size_in_kb;
- uint32_t device_id;
- int page_size;
- uint32_t base_address = 0x08000000;
-
- stm32x_info->probed = 0;
- stm32x_info->register_base = FLASH_REG_BASE_B0;
- stm32x_info->user_data_offset = 10;
- stm32x_info->option_offset = 0;
-
- /* default factory protection level */
- stm32x_info->default_rdp = 0x5AA5;
-
- /* read stm32 device id register */
- int retval = stm32x_get_device_id(bank, &device_id);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
-
- /* set page size, protection granularity and max flash size depending on family */
- switch (device_id & 0xfff) {
- case 0x410: /* medium density */
- page_size = 1024;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 128;
- break;
- case 0x412: /* low density */
- page_size = 1024;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 32;
- break;
- case 0x414: /* high density */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 512;
- break;
- case 0x418: /* connectivity line density */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 256;
- break;
- case 0x420: /* value line density */
- page_size = 1024;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 128;
- break;
- case 0x422: /* stm32f302/3xb/c */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 256;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0x55AA;
- break;
- case 0x446: /* stm32f303xD/E */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 512;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0x55AA;
- break;
- case 0x428: /* value line High density */
- page_size = 2048;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 128;
- break;
- case 0x430: /* xl line density (dual flash banks) */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 1024;
- stm32x_info->has_dual_banks = true;
- break;
- case 0x432: /* stm32f37x */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 256;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0x55AA;
- break;
- case 0x438: /* stm32f33x */
- case 0x439: /* stm32f302x6/8 */
- page_size = 2048;
- stm32x_info->ppage_size = 2;
- max_flash_size_in_kb = 64;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0x55AA;
- break;
- case 0x440: /* stm32f05x */
- case 0x444: /* stm32f03x */
- case 0x445: /* stm32f04x */
- page_size = 1024;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 64;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0x55AA;
- break;
- case 0x448: /* stm32f07x */
- case 0x442: /* stm32f09x */
- page_size = 2048;
- stm32x_info->ppage_size = 4;
- max_flash_size_in_kb = 256;
- stm32x_info->user_data_offset = 16;
- stm32x_info->option_offset = 6;
- stm32x_info->default_rdp = 0x55AA;
- break;
- default:
- LOG_WARNING("Cannot identify target as a STM32 family.");
- return ERROR_FAIL;
- }
-
- /* get flash size from target. */
- retval = stm32x_get_flash_size(bank, &flash_size_in_kb);
-
- /* failed reading flash size or flash size invalid (early silicon),
- * default to max target family */
- if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
- LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash",
- max_flash_size_in_kb);
- flash_size_in_kb = max_flash_size_in_kb;
- }
-
- if (stm32x_info->has_dual_banks) {
- /* split reported size into matching bank */
- if (bank->base != 0x08080000) {
- /* bank 0 will be fixed 512k */
- flash_size_in_kb = 512;
- } else {
- flash_size_in_kb -= 512;
- /* bank1 also uses a register offset */
- stm32x_info->register_base = FLASH_REG_BASE_B1;
- base_address = 0x08080000;
- }
- }
-
- /* if the user sets the size manually then ignore the probed value
- * this allows us to work around devices that have a invalid flash size register value */
- if (stm32x_info->user_bank_size) {
- LOG_INFO("ignoring flash probed value, using configured bank size");
- flash_size_in_kb = stm32x_info->user_bank_size / 1024;
- }
-
- LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
-
- /* did we assign flash size? */
- assert(flash_size_in_kb != 0xffff);
-
- /* calculate numbers of pages */
- int num_pages = flash_size_in_kb * 1024 / page_size;
-
- /* check that calculation result makes sense */
- assert(num_pages > 0);
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->base = base_address;
- bank->size = (num_pages * page_size);
- bank->num_sectors = num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
-
- for (i = 0; i < num_pages; i++) {
- bank->sectors[i].offset = i * page_size;
- bank->sectors[i].size = page_size;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- stm32x_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int stm32x_auto_probe(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
- if (stm32x_info->probed)
- return ERROR_OK;
- return stm32x_probe(bank);
-}
-
-#if 0
-COMMAND_HANDLER(stm32x_handle_part_id_command)
-{
- return ERROR_OK;
-}
-#endif
-
-static const char *get_stm32f0_revision(uint16_t rev_id)
-{
- const char *rev_str = NULL;
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "1.0";
- break;
- case 0x2000:
- rev_str = "2.0";
- break;
- }
- return rev_str;
-}
-
-static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- uint32_t dbgmcu_idcode;
-
- /* read stm32 device id register */
- int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
- if (retval != ERROR_OK)
- return retval;
-
- uint16_t device_id = dbgmcu_idcode & 0xfff;
- uint16_t rev_id = dbgmcu_idcode >> 16;
- const char *device_str;
- const char *rev_str = NULL;
-
- switch (device_id) {
- case 0x410:
- device_str = "STM32F10x (Medium Density)";
-
- switch (rev_id) {
- case 0x0000:
- rev_str = "A";
- break;
-
- case 0x2000:
- rev_str = "B";
- break;
-
- case 0x2001:
- rev_str = "Z";
- break;
-
- case 0x2003:
- rev_str = "Y";
- break;
- }
- break;
-
- case 0x412:
- device_str = "STM32F10x (Low Density)";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
- }
- break;
-
- case 0x414:
- device_str = "STM32F10x (High Density)";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
-
- case 0x1003:
- rev_str = "Y";
- break;
- }
- break;
-
- case 0x418:
- device_str = "STM32F10x (Connectivity)";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
- }
- break;
-
- case 0x420:
- device_str = "STM32F100 (Low/Medium Density)";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
- }
- break;
-
- case 0x422:
- device_str = "STM32F302xB/C";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
-
- case 0x1003:
- rev_str = "Y";
- break;
-
- case 0x2000:
- rev_str = "B";
- break;
- }
- break;
-
- case 0x428:
- device_str = "STM32F100 (High Density)";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
- }
- break;
-
- case 0x430:
- device_str = "STM32F10x (XL Density)";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
- }
- break;
-
- case 0x432:
- device_str = "STM32F37x";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x2000:
- rev_str = "B";
- break;
- }
- break;
-
- case 0x438:
- device_str = "STM32F33x";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
- }
- break;
-
- case 0x439:
- device_str = "STM32F302x6/8";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
- }
- break;
-
- case 0x444:
- device_str = "STM32F03x";
- rev_str = get_stm32f0_revision(rev_id);
- break;
-
- case 0x440:
- device_str = "STM32F05x";
- rev_str = get_stm32f0_revision(rev_id);
- break;
-
- case 0x445:
- device_str = "STM32F04x";
- rev_str = get_stm32f0_revision(rev_id);
- break;
-
- case 0x446:
- device_str = "STM32F303xD/E";
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
- }
- break;
-
- case 0x448:
- device_str = "STM32F07x";
- rev_str = get_stm32f0_revision(rev_id);
- break;
-
- case 0x442:
- device_str = "STM32F09x";
- rev_str = get_stm32f0_revision(rev_id);
- break;
-
- default:
- snprintf(buf, buf_size, "Cannot identify target as a STM32F0/1/3\n");
- return ERROR_FAIL;
- }
-
- if (rev_str != NULL)
- snprintf(buf, buf_size, "%s - Rev: %s", device_str, rev_str);
- else
- snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", device_str, rev_id);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_lock_command)
-{
- struct target *target = NULL;
- struct stm32x_flash_bank *stm32x_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32x_info = bank->driver_priv;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (stm32x_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to erase options");
- return ERROR_OK;
- }
-
- /* set readout protection */
- stm32x_info->option_bytes.RDP = 0;
-
- if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to lock device");
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "stm32x locked");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_unlock_command)
-{
- struct target *target = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
- return retval;
-
- if (stm32x_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to unlock device");
- return ERROR_OK;
- }
-
- if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to lock device");
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "stm32x unlocked.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_options_read_command)
-{
- uint32_t optionbyte;
- struct target *target = NULL;
- struct stm32x_flash_bank *stm32x_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32x_info = bank->driver_priv;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = target_read_u32(target, STM32_FLASH_OBR_B0, &optionbyte);
- if (retval != ERROR_OK)
- return retval;
- command_print(CMD_CTX, "Option Byte: 0x%" PRIx32 "", optionbyte);
-
- int user_data = optionbyte;
-
- if (optionbyte >> OPT_ERROR & 1)
- command_print(CMD_CTX, "Option Byte Complement Error");
-
- if (optionbyte >> OPT_READOUT & 1)
- command_print(CMD_CTX, "Readout Protection On");
- else
- command_print(CMD_CTX, "Readout Protection Off");
-
- /* user option bytes are offset depending on variant */
- optionbyte >>= stm32x_info->option_offset;
-
- if (optionbyte >> OPT_RDWDGSW & 1)
- command_print(CMD_CTX, "Software Watchdog");
- else
- command_print(CMD_CTX, "Hardware Watchdog");
-
- if (optionbyte >> OPT_RDRSTSTOP & 1)
- command_print(CMD_CTX, "Stop: No reset generated");
- else
- command_print(CMD_CTX, "Stop: Reset generated");
-
- if (optionbyte >> OPT_RDRSTSTDBY & 1)
- command_print(CMD_CTX, "Standby: No reset generated");
- else
- command_print(CMD_CTX, "Standby: Reset generated");
-
- if (stm32x_info->has_dual_banks) {
- if (optionbyte >> OPT_BFB2 & 1)
- command_print(CMD_CTX, "Boot: Bank 0");
- else
- command_print(CMD_CTX, "Boot: Bank 1");
- }
-
- command_print(CMD_CTX, "User Option0: 0x%02" PRIx8,
- (uint8_t)((user_data >> stm32x_info->user_data_offset) & 0xff));
- command_print(CMD_CTX, "User Option1: 0x%02" PRIx8,
- (uint8_t)((user_data >> (stm32x_info->user_data_offset + 8)) & 0xff));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_options_write_command)
-{
- struct target *target = NULL;
- struct stm32x_flash_bank *stm32x_info = NULL;
- uint16_t optionbyte;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32x_info = bank->driver_priv;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = stm32x_check_operation_supported(bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32x_read_options(bank);
- if (ERROR_OK != retval)
- return retval;
-
- /* start with current options */
- optionbyte = stm32x_info->option_bytes.user_options;
-
- /* skip over flash bank */
- CMD_ARGC--;
- CMD_ARGV++;
-
- while (CMD_ARGC) {
- if (strcmp("SWWDG", CMD_ARGV[0]) == 0)
- optionbyte |= (1 << 0);
- else if (strcmp("HWWDG", CMD_ARGV[0]) == 0)
- optionbyte &= ~(1 << 0);
- else if (strcmp("NORSTSTOP", CMD_ARGV[0]) == 0)
- optionbyte |= (1 << 1);
- else if (strcmp("RSTSTOP", CMD_ARGV[0]) == 0)
- optionbyte &= ~(1 << 1);
- else if (strcmp("NORSTSTNDBY", CMD_ARGV[0]) == 0)
- optionbyte |= (1 << 2);
- else if (strcmp("RSTSTNDBY", CMD_ARGV[0]) == 0)
- optionbyte &= ~(1 << 2);
- else if (stm32x_info->has_dual_banks) {
- if (strcmp("BOOT0", CMD_ARGV[0]) == 0)
- optionbyte |= (1 << 3);
- else if (strcmp("BOOT1", CMD_ARGV[0]) == 0)
- optionbyte &= ~(1 << 3);
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
- CMD_ARGC--;
- CMD_ARGV++;
- }
-
- if (stm32x_erase_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to erase options");
- return ERROR_OK;
- }
-
- stm32x_info->option_bytes.user_options = optionbyte;
-
- if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32x failed to write options");
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "stm32x write options complete.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.");
-
- return ERROR_OK;
-}
-
-static int stm32x_mass_erase(struct flash_bank *bank)
-{
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* unlock option flash registers */
- int retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* mass erase flash memory */
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
- FLASH_MER | FLASH_STRT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_mass_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32x_mass_erase(bank);
- if (retval == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "stm32x mass erase complete");
- } else
- command_print(CMD_CTX, "stm32x mass erase failed");
-
- return retval;
-}
-
-static const struct command_registration stm32x_exec_command_handlers[] = {
- {
- .name = "lock",
- .handler = stm32x_handle_lock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Lock entire flash device.",
- },
- {
- .name = "unlock",
- .handler = stm32x_handle_unlock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Unlock entire protected flash device.",
- },
- {
- .name = "mass_erase",
- .handler = stm32x_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Erase entire flash device.",
- },
- {
- .name = "options_read",
- .handler = stm32x_handle_options_read_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Read and display device option byte.",
- },
- {
- .name = "options_write",
- .handler = stm32x_handle_options_write_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ('SWWDG'|'HWWDG') "
- "('RSTSTNDBY'|'NORSTSTNDBY') "
- "('RSTSTOP'|'NORSTSTOP')",
- .help = "Replace bits in device option byte.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration stm32x_command_handlers[] = {
- {
- .name = "stm32f1x",
- .mode = COMMAND_ANY,
- .help = "stm32f1x flash command group",
- .usage = "",
- .chain = stm32x_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver stm32f1x_flash = {
- .name = "stm32f1x",
- .commands = stm32x_command_handlers,
- .flash_bank_command = stm32x_flash_bank_command,
- .erase = stm32x_erase,
- .protect = stm32x_protect,
- .write = stm32x_write,
- .read = default_flash_read,
- .probe = stm32x_probe,
- .auto_probe = stm32x_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = stm32x_protect_check,
- .info = get_stm32x_info,
-};
diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c
deleted file mode 100644
index 1acab82..0000000
--- a/src/flash/nor/stm32f2x.c
+++ /dev/null
@@ -1,1463 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-/* Regarding performance:
- *
- * Short story - it might be best to leave the performance at
- * current levels.
- *
- * You may see a jump in speed if you change to using
- * 32bit words for the block programming.
- *
- * Its a shame you cannot use the double word as its
- * even faster - but you require external VPP for that mode.
- *
- * Having said all that 16bit writes give us the widest vdd
- * operating range, so may be worth adding a note to that effect.
- *
- */
-
-/* Danger!!!! The STM32F1x and STM32F2x series actually have
- * quite different flash controllers.
- *
- * What's more scary is that the names of the registers and their
- * addresses are the same, but the actual bits and what they do are
- * can be very different.
- *
- * To reduce testing complexity and dangers of regressions,
- * a seperate file is used for stm32fx2x.
- *
- * Sector sizes in kiBytes:
- * 1 MiByte part with 4 x 16, 1 x 64, 7 x 128.
- * 2 MiByte part with 4 x 16, 1 x 64, 7 x 128, 4 x 16, 1 x 64, 7 x 128.
- * 1 MiByte STM32F42x/43x part with DB1M Option set:
- * 4 x 16, 1 x 64, 3 x 128, 4 x 16, 1 x 64, 3 x 128.
- *
- * STM32F7[4|5]
- * 1 MiByte part with 4 x 32, 1 x 128, 3 x 256.
- *
- * STM32F7[6|7]
- * 1 MiByte part in single bank mode with 4 x 32, 1 x 128, 3 x 256.
- * 1 MiByte part in dual-bank mode two banks with 4 x 16, 1 x 64, 3 x 128 each.
- * 2 MiByte part in single-bank mode with 4 x 32, 1 x 128, 7 x 256.
- * 2 MiByte part in dual-bank mode two banks with 4 x 16, 1 x 64, 7 x 128 each.
- *
- * Protection size is sector size.
- *
- * Tested with STM3220F-EVAL board.
- *
- * STM32F4xx series for reference.
- *
- * RM0090
- * http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf
- *
- * PM0059
- * www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/
- * PROGRAMMING_MANUAL/CD00233952.pdf
- *
- * STM32F7xx series for reference.
- *
- * RM0385
- * http://www.st.com/web/en/resource/technical/document/reference_manual/DM00124865.pdf
- *
- * RM0410
- * http://www.st.com/resource/en/reference_manual/dm00224583.pdf
- *
- * STM32F1x series - notice that this code was copy, pasted and knocked
- * into a stm32f2x driver, so in case something has been converted or
- * bugs haven't been fixed, here are the original manuals:
- *
- * RM0008 - Reference manual
- *
- * RM0042, the Flash programming manual for low-, medium- high-density and
- * connectivity line STM32F10x devices
- *
- * PM0068, the Flash programming manual for XL-density STM32F10x devices.
- *
- */
-
-/* Erase time can be as high as 1000ms, 10x this and it's toast... */
-#define FLASH_ERASE_TIMEOUT 10000
-#define FLASH_WRITE_TIMEOUT 5
-
-#define STM32_FLASH_BASE 0x40023c00
-#define STM32_FLASH_ACR 0x40023c00
-#define STM32_FLASH_KEYR 0x40023c04
-#define STM32_FLASH_OPTKEYR 0x40023c08
-#define STM32_FLASH_SR 0x40023c0C
-#define STM32_FLASH_CR 0x40023c10
-#define STM32_FLASH_OPTCR 0x40023c14
-#define STM32_FLASH_OPTCR1 0x40023c18
-
-/* FLASH_CR register bits */
-#define FLASH_PG (1 << 0)
-#define FLASH_SER (1 << 1)
-#define FLASH_MER (1 << 2) /* MER/MER1 for f76x/77x */
-#define FLASH_MER1 (1 << 15) /* MER2 for f76x/77x, confusing ... */
-#define FLASH_STRT (1 << 16)
-#define FLASH_PSIZE_8 (0 << 8)
-#define FLASH_PSIZE_16 (1 << 8)
-#define FLASH_PSIZE_32 (2 << 8)
-#define FLASH_PSIZE_64 (3 << 8)
-/* The sector number encoding is not straight binary for dual bank flash.
- * Warning: evaluates the argument multiple times */
-#define FLASH_SNB(a) ((((a) >= 12) ? 0x10 | ((a) - 12) : (a)) << 3)
-#define FLASH_LOCK (1 << 31)
-
-/* FLASH_SR register bits */
-#define FLASH_BSY (1 << 16)
-#define FLASH_PGSERR (1 << 7) /* Programming sequence error */
-#define FLASH_PGPERR (1 << 6) /* Programming parallelism error */
-#define FLASH_PGAERR (1 << 5) /* Programming alignment error */
-#define FLASH_WRPERR (1 << 4) /* Write protection error */
-#define FLASH_OPERR (1 << 1) /* Operation error */
-
-#define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR)
-
-/* STM32_FLASH_OPTCR register bits */
-#define OPTCR_LOCK (1 << 0)
-#define OPTCR_START (1 << 1)
-#define OPTCR_NDBANK (1 << 29) /* not dual bank mode */
-#define OPTCR_DB1M (1 << 30) /* 1 MiB devices dual flash bank option */
-
-/* register unlock keys */
-#define KEY1 0x45670123
-#define KEY2 0xCDEF89AB
-
-/* option register unlock key */
-#define OPTKEY1 0x08192A3B
-#define OPTKEY2 0x4C5D6E7F
-
-struct stm32x_options {
- uint8_t RDP;
- uint16_t user_options; /* bit 0-7 usual options, bit 8-11 extra options */
- uint32_t protection;
- uint32_t boot_addr;
-};
-
-struct stm32x_flash_bank {
- struct stm32x_options option_bytes;
- int probed;
- bool has_large_mem; /* F42x/43x/469/479/7xx in dual bank mode */
- bool has_boot_addr; /* F7xx */
- bool has_extra_options; /* F42x/43x/469/479/7xx */
- uint32_t user_bank_size;
-};
-
-/* flash bank stm32x <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
-{
- struct stm32x_flash_bank *stm32x_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
- bank->driver_priv = stm32x_info;
-
- stm32x_info->probed = 0;
- stm32x_info->user_bank_size = bank->size;
-
- return ERROR_OK;
-}
-
-static inline int stm32x_get_flash_reg(struct flash_bank *bank, uint32_t reg)
-{
- return reg;
-}
-
-static inline int stm32x_get_flash_status(struct flash_bank *bank, uint32_t *status)
-{
- struct target *target = bank->target;
- return target_read_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR), status);
-}
-
-static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout)
-{
- struct target *target = bank->target;
- uint32_t status;
- int retval = ERROR_OK;
-
- /* wait for busy to clear */
- for (;;) {
- retval = stm32x_get_flash_status(bank, &status);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if ((status & FLASH_BSY) == 0)
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
-
- if (status & FLASH_WRPERR) {
- LOG_ERROR("stm32x device protected");
- retval = ERROR_FAIL;
- }
-
- /* Clear but report errors */
- if (status & FLASH_ERROR) {
- /* If this operation fails, we ignore it and report the original
- * retval
- */
- target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_SR),
- status & FLASH_ERROR);
- }
- return retval;
-}
-
-static int stm32x_unlock_reg(struct target *target)
-{
- uint32_t ctrl;
-
- /* first check if not already unlocked
- * otherwise writing on STM32_FLASH_KEYR will fail
- */
- int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if ((ctrl & FLASH_LOCK) == 0)
- return ERROR_OK;
-
- /* unlock flash registers */
- retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if (ctrl & FLASH_LOCK) {
- LOG_ERROR("flash not unlocked STM32_FLASH_CR: %" PRIx32, ctrl);
- return ERROR_TARGET_FAILURE;
- }
-
- return ERROR_OK;
-}
-
-static int stm32x_unlock_option_reg(struct target *target)
-{
- uint32_t ctrl;
-
- int retval = target_read_u32(target, STM32_FLASH_OPTCR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if ((ctrl & OPTCR_LOCK) == 0)
- return ERROR_OK;
-
- /* unlock option registers */
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY2);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, STM32_FLASH_OPTCR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if (ctrl & OPTCR_LOCK) {
- LOG_ERROR("options not unlocked STM32_FLASH_OPTCR: %" PRIx32, ctrl);
- return ERROR_TARGET_FAILURE;
- }
-
- return ERROR_OK;
-}
-
-static int stm32x_read_options(struct flash_bank *bank)
-{
- uint32_t optiondata;
- struct stm32x_flash_bank *stm32x_info = NULL;
- struct target *target = bank->target;
-
- stm32x_info = bank->driver_priv;
-
- /* read current option bytes */
- int retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- /* caution: F2 implements 5 bits (WDG_SW only)
- * whereas F7 6 bits (IWDG_SW and WWDG_SW) in user_options */
- stm32x_info->option_bytes.user_options = optiondata & 0xfc;
- stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff;
- stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xfff;
-
- if (stm32x_info->has_extra_options) {
- /* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */
- stm32x_info->option_bytes.user_options |= (optiondata >> 20) & 0xf00;
- }
-
- if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) {
- retval = target_read_u32(target, STM32_FLASH_OPTCR1, &optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- /* FLASH_OPTCR1 has quite diffent meanings ... */
- if (stm32x_info->has_boot_addr) {
- /* for F7xx it contains boot0 and boot1 */
- stm32x_info->option_bytes.boot_addr = optiondata;
- } else {
- /* for F42x/43x/469/479 it contains 12 additional protection bits */
- stm32x_info->option_bytes.protection |= (optiondata >> 4) & 0x00fff000;
- }
- }
-
- if (stm32x_info->option_bytes.RDP != 0xAA)
- LOG_INFO("Device Security Bit Set");
-
- return ERROR_OK;
-}
-
-static int stm32x_write_options(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = NULL;
- struct target *target = bank->target;
- uint32_t optiondata, optiondata2;
-
- stm32x_info = bank->driver_priv;
-
- int retval = stm32x_unlock_option_reg(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* rebuild option data */
- optiondata = stm32x_info->option_bytes.user_options & 0xfc;
- optiondata |= stm32x_info->option_bytes.RDP << 8;
- optiondata |= (stm32x_info->option_bytes.protection & 0x0fff) << 16;
-
- if (stm32x_info->has_extra_options) {
- /* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */
- optiondata |= (stm32x_info->option_bytes.user_options & 0xf00) << 20;
- }
-
- if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) {
- if (stm32x_info->has_boot_addr) {
- /* F7xx uses FLASH_OPTCR1 for boot0 and boot1 ... */
- optiondata2 = stm32x_info->option_bytes.boot_addr;
- } else {
- /* F42x/43x/469/479 uses FLASH_OPTCR1 for additional protection bits */
- optiondata2 = (stm32x_info->option_bytes.protection & 0x00fff000) << 4;
- }
-
- retval = target_write_u32(target, STM32_FLASH_OPTCR1, optiondata2);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* program options */
- retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- /* start programming cycle */
- retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPTCR_START);
- if (retval != ERROR_OK)
- return retval;
-
- /* wait for completion */
- retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- /* relock registers */
- retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPTCR_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32x_protect_check(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
-
- /* read write protection settings */
- int retval = stm32x_read_options(bank);
- if (retval != ERROR_OK) {
- LOG_DEBUG("unable to read option bytes");
- return retval;
- }
-
- if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) {
- /* F76x/77x: bit k protects sectors 2*k and 2*k+1 */
- for (int i = 0; i < (bank->num_sectors >> 1); i++) {
- if (stm32x_info->option_bytes.protection & (1 << i)) {
- bank->sectors[i << 1].is_protected = 0;
- bank->sectors[(i << 1) + 1].is_protected = 0;
- } else {
- bank->sectors[i << 1].is_protected = 1;
- bank->sectors[(i << 1) + 1].is_protected = 1;
- }
- }
- } else {
- /* one protection bit per sector */
- for (int i = 0; i < bank->num_sectors; i++) {
- if (stm32x_info->option_bytes.protection & (1 << i))
- bank->sectors[i].is_protected = 0;
- else
- bank->sectors[i].is_protected = 1;
- }
- }
-
- return ERROR_OK;
-}
-
-static int stm32x_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- int i;
-
- assert((0 <= first) && (first <= last) && (last < bank->num_sectors));
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int retval;
- retval = stm32x_unlock_reg(target);
- if (retval != ERROR_OK)
- return retval;
-
- /*
- Sector Erase
- To erase a sector, follow the procedure below:
- 1. Check that no Flash memory operation is ongoing by checking the BSY bit in the
- FLASH_SR register
- 2. Set the SER bit and select the sector
- you wish to erase (SNB) in the FLASH_CR register
- 3. Set the STRT bit in the FLASH_CR register
- 4. Wait for the BSY bit to be cleared
- */
-
- for (i = first; i <= last; i++) {
- retval = target_write_u32(target,
- stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_SER | FLASH_SNB(i) | FLASH_STRT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- bank->sectors[i].is_erased = 1;
- }
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct target *target = bank->target;
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* read protection settings */
- int retval = stm32x_read_options(bank);
- if (retval != ERROR_OK) {
- LOG_DEBUG("unable to read option bytes");
- return retval;
- }
-
- if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) {
- /* F76x/77x: bit k protects sectors 2*k and 2*k+1 */
- if ((first & 1) != 0 || (last & 1) != 1) {
- LOG_ERROR("sector protection must be double sector aligned");
- return ERROR_FAIL;
- } else {
- first >>= 1;
- last >>= 1;
- }
- }
-
- for (int i = first; i <= last; i++) {
- if (set)
- stm32x_info->option_bytes.protection &= ~(1 << i);
- else
- stm32x_info->option_bytes.protection |= (1 << i);
- }
-
- retval = stm32x_write_options(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* see contrib/loaders/flash/stm32f2x.S for src */
-
- static const uint8_t stm32x_flash_write_code[] = {
- /* wait_fifo: */
- 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
- 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
- 0x1A, 0xD0, /* beq exit */
- 0x47, 0x68, /* ldr r7, [r0, #4] */
- 0x47, 0x45, /* cmp r7, r8 */
- 0xF7, 0xD0, /* beq wait_fifo */
-
- 0xDF, 0xF8, 0x34, 0x60, /* ldr r6, STM32_PROG16 */
- 0x26, 0x61, /* str r6, [r4, #STM32_FLASH_CR_OFFSET] */
- 0x37, 0xF8, 0x02, 0x6B, /* ldrh r6, [r7], #0x02 */
- 0x22, 0xF8, 0x02, 0x6B, /* strh r6, [r2], #0x02 */
- 0xBF, 0xF3, 0x4F, 0x8F, /* dsb sy */
- /* busy: */
- 0xE6, 0x68, /* ldr r6, [r4, #STM32_FLASH_SR_OFFSET] */
- 0x16, 0xF4, 0x80, 0x3F, /* tst r6, #0x10000 */
- 0xFB, 0xD1, /* bne busy */
- 0x16, 0xF0, 0xF0, 0x0F, /* tst r6, #0xf0 */
- 0x07, 0xD1, /* bne error */
-
- 0x8F, 0x42, /* cmp r7, r1 */
- 0x28, 0xBF, /* it cs */
- 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
- 0x47, 0x60, /* str r7, [r0, #4] */
- 0x01, 0x3B, /* subs r3, r3, #1 */
- 0x13, 0xB1, /* cbz r3, exit */
- 0xDF, 0xE7, /* b wait_fifo */
- /* error: */
- 0x00, 0x21, /* movs r1, #0 */
- 0x41, 0x60, /* str r1, [r0, #4] */
- /* exit: */
- 0x30, 0x46, /* mov r0, r6 */
- 0x00, 0xBE, /* bkpt #0x00 */
-
- /* <STM32_PROG16>: */
- 0x01, 0x01, 0x00, 0x00, /* .word 0x00000101 */
- };
-
- if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(stm32x_flash_write_code),
- stm32x_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */
- 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 (halfword-16bit) */
- init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* flash 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);
- buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE);
-
- retval = target_run_flash_async_algorithm(target, buffer, count, 2,
- 0, NULL,
- 5, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (retval == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("error executing stm32x flash write algorithm");
-
- uint32_t error = buf_get_u32(reg_params[0].value, 0, 32) & FLASH_ERROR;
-
- if (error & FLASH_WRPERR)
- LOG_ERROR("flash memory write protected");
-
- if (error != 0) {
- LOG_ERROR("flash write failed = %08" PRIx32, error);
- /* Clear but report errors */
- target_write_u32(target, STM32_FLASH_SR, error);
- retval = ERROR_FAIL;
- }
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t words_remaining = (count / 2);
- uint32_t bytes_remaining = (count & 0x00000001);
- uint32_t address = bank->base + offset;
- uint32_t bytes_written = 0;
- int retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x1) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- retval = stm32x_unlock_reg(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* multiple half words (2-byte) to be programmed? */
- if (words_remaining > 0) {
- /* try using a block write */
- retval = stm32x_write_block(bank, buffer, offset, words_remaining);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single dword accesses */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
- }
- } else {
- buffer += words_remaining * 2;
- address += words_remaining * 2;
- words_remaining = 0;
- }
- }
-
- if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE))
- return retval;
-
- /*
- Standard programming
- The Flash memory programming sequence is as follows:
- 1. Check that no main Flash memory operation is ongoing by checking the BSY bit in the
- FLASH_SR register.
- 2. Set the PG bit in the FLASH_CR register
- 3. Perform the data write operation(s) to the desired memory address (inside main
- memory block or OTP area):
- – – Half-word access in case of x16 parallelism
- – Word access in case of x32 parallelism
- –
- 4.
- Byte access in case of x8 parallelism
- Double word access in case of x64 parallelism
- Wait for the BSY bit to be cleared
- */
- while (words_remaining > 0) {
- uint16_t value;
- memcpy(&value, buffer + bytes_written, sizeof(uint16_t));
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
- FLASH_PG | FLASH_PSIZE_16);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u16(target, address, value);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32x_wait_status_busy(bank, FLASH_WRITE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- bytes_written += 2;
- words_remaining--;
- address += 2;
- }
-
- if (bytes_remaining) {
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
- FLASH_PG | FLASH_PSIZE_8);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u8(target, address, buffer[bytes_written]);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32x_wait_status_busy(bank, FLASH_WRITE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
-}
-
-static int setup_sector(struct flash_bank *bank, int start, int num, int size)
-{
-
- for (int i = start; i < (start + num) ; i++) {
- assert(i < bank->num_sectors);
- bank->sectors[i].offset = bank->size;
- bank->sectors[i].size = size;
- bank->size += bank->sectors[i].size;
- LOG_DEBUG("sector %d: %dkBytes", i, size >> 10);
- }
-
- return start + num;
-}
-
-static void setup_bank(struct flash_bank *bank, int start,
- uint16_t flash_size_in_kb, uint16_t max_sector_size_in_kb)
-{
- int remain;
-
- start = setup_sector(bank, start, 4, (max_sector_size_in_kb / 8) * 1024);
- start = setup_sector(bank, start, 1, (max_sector_size_in_kb / 2) * 1024);
-
- /* remaining sectors all of size max_sector_size_in_kb */
- remain = (flash_size_in_kb / max_sector_size_in_kb) - 1;
- start = setup_sector(bank, start, remain, max_sector_size_in_kb * 1024);
-}
-
-static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
-{
- /* this checks for a stm32f4x errata issue where a
- * stm32f2x DBGMCU_IDCODE is incorrectly returned.
- * If the issue is detected target is forced to stm32f4x Rev A.
- * Only effects Rev A silicon */
-
- struct target *target = bank->target;
- uint32_t cpuid;
-
- /* read stm32 device id register */
- int retval = target_read_u32(target, 0xE0042000, device_id);
- if (retval != ERROR_OK)
- return retval;
-
- if ((*device_id & 0xfff) == 0x411) {
- /* read CPUID reg to check core type */
- retval = target_read_u32(target, 0xE000ED00, &cpuid);
- if (retval != ERROR_OK)
- return retval;
-
- /* check for cortex_m4 */
- if (((cpuid >> 4) & 0xFFF) == 0xC24) {
- *device_id &= ~((0xFFFF << 16) | 0xfff);
- *device_id |= (0x1000 << 16) | 0x413;
- LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE");
- }
- }
- return retval;
-}
-
-static int stm32x_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
- int i;
- uint16_t flash_size_in_kb;
- uint32_t flash_size_reg = 0x1FFF7A22;
- uint16_t max_sector_size_in_kb = 128;
- uint16_t max_flash_size_in_kb;
- uint32_t device_id;
- uint32_t base_address = 0x08000000;
-
- stm32x_info->probed = 0;
- stm32x_info->has_large_mem = false;
- stm32x_info->has_boot_addr = false;
- stm32x_info->has_extra_options = false;
-
- /* read stm32 device id register */
- int retval = stm32x_get_device_id(bank, &device_id);
- if (retval != ERROR_OK)
- return retval;
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
-
- /* set max flash size depending on family, id taken from AN2606 */
- switch (device_id & 0xfff) {
- case 0x411: /* F20x/21x */
- case 0x413: /* F40x/41x */
- max_flash_size_in_kb = 1024;
- break;
-
- case 0x419: /* F42x/43x */
- case 0x434: /* F469/479 */
- stm32x_info->has_extra_options = true;
- max_flash_size_in_kb = 2048;
- break;
-
- case 0x423: /* F401xB/C */
- max_flash_size_in_kb = 256;
- break;
-
- case 0x421: /* F446 */
- case 0x431: /* F411 */
- case 0x433: /* F401xD/E */
- case 0x441: /* F412 */
- max_flash_size_in_kb = 512;
- break;
-
- case 0x458: /* F410 */
- max_flash_size_in_kb = 128;
- break;
-
- case 0x449: /* F74x/75x */
- max_flash_size_in_kb = 1024;
- max_sector_size_in_kb = 256;
- flash_size_reg = 0x1FF0F442;
- stm32x_info->has_extra_options = true;
- stm32x_info->has_boot_addr = true;
- break;
-
- case 0x451: /* F76x/77x */
- max_flash_size_in_kb = 2048;
- max_sector_size_in_kb = 256;
- flash_size_reg = 0x1FF0F442;
- stm32x_info->has_extra_options = true;
- stm32x_info->has_boot_addr = true;
- break;
-
- default:
- LOG_WARNING("Cannot identify target as a STM32 family.");
- return ERROR_FAIL;
- }
-
- /* get flash size from target. */
- retval = target_read_u16(target, flash_size_reg, &flash_size_in_kb);
-
- /* failed reading flash size or flash size invalid (early silicon),
- * default to max target family */
- if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
- LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash",
- max_flash_size_in_kb);
- flash_size_in_kb = max_flash_size_in_kb;
- }
-
- /* if the user sets the size manually then ignore the probed value
- * this allows us to work around devices that have a invalid flash size register value */
- if (stm32x_info->user_bank_size) {
- LOG_INFO("ignoring flash probed value, using configured bank size");
- flash_size_in_kb = stm32x_info->user_bank_size / 1024;
- }
-
- LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
-
- /* did we assign flash size? */
- assert(flash_size_in_kb != 0xffff);
-
- /* Devices with > 1024 kiByte always are dual-banked */
- if (flash_size_in_kb > 1024)
- stm32x_info->has_large_mem = true;
-
- /* F42x/43x/469/479 1024 kiByte devices have a dual bank option */
- if ((device_id & 0xfff) == 0x419 || (device_id & 0xfff) == 0x434) {
- uint32_t optiondata;
- retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
- if (retval != ERROR_OK) {
- LOG_DEBUG("unable to read option bytes");
- return retval;
- }
- if ((flash_size_in_kb > 1024) || (optiondata & OPTCR_DB1M)) {
- stm32x_info->has_large_mem = true;
- LOG_INFO("Dual Bank %d kiB STM32F42x/43x/469/479 found", flash_size_in_kb);
- } else {
- stm32x_info->has_large_mem = false;
- LOG_INFO("Single Bank %d kiB STM32F42x/43x/469/479 found", flash_size_in_kb);
- }
- }
-
- /* F76x/77x devices have a dual bank option */
- if ((device_id & 0xfff) == 0x451) {
- uint32_t optiondata;
- retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
- if (retval != ERROR_OK) {
- LOG_DEBUG("unable to read option bytes");
- return retval;
- }
- if (optiondata & OPTCR_NDBANK) {
- stm32x_info->has_large_mem = false;
- LOG_INFO("Single Bank %d kiB STM32F76x/77x found", flash_size_in_kb);
- } else {
- stm32x_info->has_large_mem = true;
- max_sector_size_in_kb >>= 1; /* sector size divided by 2 in dual-bank mode */
- LOG_INFO("Dual Bank %d kiB STM32F76x/77x found", flash_size_in_kb);
- }
- }
-
- /* calculate numbers of pages */
- int num_pages = flash_size_in_kb / max_sector_size_in_kb
- + (stm32x_info->has_large_mem ? 8 : 4);
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->base = base_address;
- bank->num_sectors = num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
- for (i = 0; i < num_pages; i++) {
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 0;
- }
- bank->size = 0;
- LOG_DEBUG("allocated %d sectors", num_pages);
-
- if (stm32x_info->has_large_mem) {
- /* dual-bank */
- setup_bank(bank, 0, flash_size_in_kb >> 1, max_sector_size_in_kb);
- setup_bank(bank, num_pages >> 1, flash_size_in_kb >> 1,
- max_sector_size_in_kb);
- } else {
- /* single-bank */
- setup_bank(bank, 0, flash_size_in_kb, max_sector_size_in_kb);
- }
- assert((bank->size >> 10) == flash_size_in_kb);
-
- stm32x_info->probed = 1;
- return ERROR_OK;
-}
-
-static int stm32x_auto_probe(struct flash_bank *bank)
-{
- struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
- if (stm32x_info->probed)
- return ERROR_OK;
- return stm32x_probe(bank);
-}
-
-static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- uint32_t dbgmcu_idcode;
-
- /* read stm32 device id register */
- int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
- if (retval != ERROR_OK)
- return retval;
-
- uint16_t device_id = dbgmcu_idcode & 0xfff;
- uint16_t rev_id = dbgmcu_idcode >> 16;
- const char *device_str;
- const char *rev_str = NULL;
-
- switch (device_id) {
- case 0x411:
- device_str = "STM32F2xx";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x2000:
- rev_str = "B";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
-
- case 0x2001:
- rev_str = "Y";
- break;
-
- case 0x2003:
- rev_str = "X";
- break;
-
- case 0x2007:
- rev_str = "1";
- break;
-
- case 0x200F:
- rev_str = "V";
- break;
-
- case 0x201F:
- rev_str = "2";
- break;
- }
- break;
-
- case 0x413:
- case 0x419:
- case 0x434:
- device_str = "STM32F4xx";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
-
- case 0x1003:
- rev_str = "Y";
- break;
-
- case 0x1007:
- rev_str = "1";
- break;
-
- case 0x2001:
- rev_str = "3";
- break;
- }
- break;
-
- case 0x421:
- device_str = "STM32F446";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
- }
- break;
-
- case 0x423:
- case 0x431:
- case 0x433:
- case 0x458:
- case 0x441:
- device_str = "STM32F4xx (Low Power)";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
- }
- break;
-
- case 0x449:
- device_str = "STM32F7[4|5]x";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
-
- case 0x1001:
- rev_str = "Z";
- break;
- }
- break;
-
- case 0x451:
- device_str = "STM32F7[6|7]x";
-
- switch (rev_id) {
- case 0x1000:
- rev_str = "A";
- break;
- }
- break;
-
- default:
- snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4/7\n");
- return ERROR_FAIL;
- }
-
- if (rev_str != NULL)
- snprintf(buf, buf_size, "%s - Rev: %s", device_str, rev_str);
- else
- snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)", device_str, rev_id);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_lock_command)
-{
- struct target *target = NULL;
- struct stm32x_flash_bank *stm32x_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32x_info = bank->driver_priv;
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (stm32x_read_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to read options", bank->driver->name);
- return ERROR_OK;
- }
-
- /* set readout protection */
- stm32x_info->option_bytes.RDP = 0;
-
- if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to lock device", bank->driver->name);
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "%s locked", bank->driver->name);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_unlock_command)
-{
- struct target *target = NULL;
- struct stm32x_flash_bank *stm32x_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32x_info = bank->driver_priv;
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (stm32x_read_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to read options", bank->driver->name);
- return ERROR_OK;
- }
-
- /* clear readout protection and complementary option bytes
- * this will also force a device unlock if set */
- stm32x_info->option_bytes.RDP = 0xAA;
-
- if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to unlock device", bank->driver->name);
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "%s unlocked.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.", bank->driver->name);
-
- return ERROR_OK;
-}
-
-static int stm32x_mass_erase(struct flash_bank *bank)
-{
- int retval;
- uint32_t flash_mer;
- struct target *target = bank->target;
- struct stm32x_flash_bank *stm32x_info = NULL;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- stm32x_info = bank->driver_priv;
-
- retval = stm32x_unlock_reg(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* mass erase flash memory */
- if (stm32x_info->has_large_mem)
- flash_mer = FLASH_MER | FLASH_MER1;
- else
- flash_mer = FLASH_MER;
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), flash_mer);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
- flash_mer | FLASH_STRT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32x_wait_status_busy(bank, 30000);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32x_handle_mass_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1) {
- command_print(CMD_CTX, "stm32x mass_erase <bank>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32x_mass_erase(bank);
- if (retval == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "stm32x mass erase complete");
- } else {
- command_print(CMD_CTX, "stm32x mass erase failed");
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(stm32f2x_handle_options_read_command)
-{
- int retval;
- struct flash_bank *bank;
- struct stm32x_flash_bank *stm32x_info = NULL;
-
- if (CMD_ARGC != 1) {
- command_print(CMD_CTX, "stm32f2x options_read <bank>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32x_read_options(bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32x_info = bank->driver_priv;
- if (stm32x_info->has_extra_options) {
- if (stm32x_info->has_boot_addr) {
- uint32_t boot_addr = stm32x_info->option_bytes.boot_addr;
-
- command_print(CMD_CTX, "stm32f2x user_options 0x%03X,"
- " boot_add0 0x%04X, boot_add1 0x%04X",
- stm32x_info->option_bytes.user_options,
- boot_addr & 0xffff, (boot_addr & 0xffff0000) >> 16);
- } else {
- command_print(CMD_CTX, "stm32f2x user_options 0x%03X,",
- stm32x_info->option_bytes.user_options);
- }
- } else {
- command_print(CMD_CTX, "stm32f2x user_options 0x%02X",
- stm32x_info->option_bytes.user_options);
-
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(stm32f2x_handle_options_write_command)
-{
- int retval;
- struct flash_bank *bank;
- struct stm32x_flash_bank *stm32x_info = NULL;
- uint16_t user_options, boot_addr0, boot_addr1;
-
- if (CMD_ARGC < 1) {
- command_print(CMD_CTX, "stm32f2x options_write <bank> ...");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32x_read_options(bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32x_info = bank->driver_priv;
- if (stm32x_info->has_boot_addr) {
- if (CMD_ARGC != 4) {
- command_print(CMD_CTX, "stm32f2x options_write <bank> <user_options>"
- " <boot_addr0> <boot_addr1>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], boot_addr0);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], boot_addr1);
- stm32x_info->option_bytes.boot_addr = boot_addr0 | (((uint32_t) boot_addr1) << 16);
- } else {
- if (CMD_ARGC != 2) {
- command_print(CMD_CTX, "stm32f2x options_write <bank> <user_options>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options);
- if (user_options & (stm32x_info->has_extra_options ? ~0xffc : ~0xfc)) {
- command_print(CMD_CTX, "stm32f2x invalid user_options");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- stm32x_info->option_bytes.user_options = user_options;
-
- if (stm32x_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "stm32f2x failed to write options");
- return ERROR_OK;
- }
-
- /* switching between single- and dual-bank modes requires re-probe */
- /* ... and reprogramming of whole flash */
- stm32x_info->probed = 0;
-
- command_print(CMD_CTX, "stm32f2x write options complete.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.");
- return retval;
-}
-
-static const struct command_registration stm32x_exec_command_handlers[] = {
- {
- .name = "lock",
- .handler = stm32x_handle_lock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Lock entire flash device.",
- },
- {
- .name = "unlock",
- .handler = stm32x_handle_unlock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Unlock entire protected flash device.",
- },
- {
- .name = "mass_erase",
- .handler = stm32x_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Erase entire flash device.",
- },
- {
- .name = "options_read",
- .handler = stm32f2x_handle_options_read_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Read and display device option bytes.",
- },
- {
- .name = "options_write",
- .handler = stm32f2x_handle_options_write_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id user_options [ boot_add0 boot_add1]",
- .help = "Write option bytes",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration stm32x_command_handlers[] = {
- {
- .name = "stm32f2x",
- .mode = COMMAND_ANY,
- .help = "stm32f2x flash command group",
- .usage = "",
- .chain = stm32x_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver stm32f2x_flash = {
- .name = "stm32f2x",
- .commands = stm32x_command_handlers,
- .flash_bank_command = stm32x_flash_bank_command,
- .erase = stm32x_erase,
- .protect = stm32x_protect,
- .write = stm32x_write,
- .read = default_flash_read,
- .probe = stm32x_probe,
- .auto_probe = stm32x_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = stm32x_protect_check,
- .info = get_stm32x_info,
-};
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
deleted file mode 100644
index 129b281..0000000
--- a/src/flash/nor/stm32l4x.c
+++ /dev/null
@@ -1,930 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Uwe Bonnes *
- * bon@elektron.ikp.physik.tu-darmstadt.de *
- *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-/* STM32L4xxx series for reference.
- *
- * RM0351
- * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00083560.pdf
- *
- * STM32L476RG Datasheet (for erase timing)
- * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00108832.pdf
- *
- *
- * The device has normally two banks, but on 512 and 256 kiB devices an
- * option byte is available to map all sectors to the first bank.
- * Both STM32 banks are treated as one OpenOCD bank, as other STM32 devices
- * handlers do!
- *
- */
-
-/* Erase time can be as high as 25ms, 10x this and assume it's toast... */
-
-#define FLASH_ERASE_TIMEOUT 250
-
-#define STM32_FLASH_BASE 0x40022000
-#define STM32_FLASH_ACR 0x40022000
-#define STM32_FLASH_KEYR 0x40022008
-#define STM32_FLASH_OPTKEYR 0x4002200c
-#define STM32_FLASH_SR 0x40022010
-#define STM32_FLASH_CR 0x40022014
-#define STM32_FLASH_OPTR 0x40022020
-#define STM32_FLASH_WRP1AR 0x4002202c
-#define STM32_FLASH_WRP2AR 0x40022030
-#define STM32_FLASH_WRP1BR 0x4002204c
-#define STM32_FLASH_WRP2BR 0x40022050
-
-/* FLASH_CR register bits */
-
-#define FLASH_PG (1 << 0)
-#define FLASH_PER (1 << 1)
-#define FLASH_MER1 (1 << 2)
-#define FLASH_PAGE_SHIFT 3
-#define FLASH_CR_BKER (1 << 11)
-#define FLASH_MER2 (1 << 15)
-#define FLASH_STRT (1 << 16)
-#define FLASH_EOPIE (1 << 24)
-#define FLASH_ERRIE (1 << 25)
-#define FLASH_OPTLOCK (1 << 30)
-#define FLASH_LOCK (1 << 31)
-
-/* FLASH_SR register bits */
-
-#define FLASH_BSY (1 << 16)
-/* Fast programming not used => related errors not used*/
-#define FLASH_PGSERR (1 << 7) /* Programming sequence error */
-#define FLASH_SIZERR (1 << 6) /* Size error */
-#define FLASH_PGAERR (1 << 5) /* Programming alignment error */
-#define FLASH_WRPERR (1 << 4) /* Write protection error */
-#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)
-
-/* STM32_FLASH_OBR bit definitions (reading) */
-
-#define OPT_DUALBANK 21 /* dual flash bank only */
-
-/* register unlock keys */
-
-#define KEY1 0x45670123
-#define KEY2 0xCDEF89AB
-
-/* option register unlock key */
-#define OPTKEY1 0x08192A3B
-#define OPTKEY2 0x4C5D6E7F
-
-
-/* other registers */
-#define DBGMCU_IDCODE 0xE0042000
-#define FLASH_SIZE_REG 0x1FFF75E0
-
-struct stm32l4_options {
- uint8_t RDP;
- uint16_t bank_b_start;
- uint8_t user_options;
- uint8_t wpr1a_start;
- uint8_t wpr1a_end;
- uint8_t wpr1b_start;
- uint8_t wpr1b_end;
- uint8_t wpr2a_start;
- uint8_t wpr2a_end;
- uint8_t wpr2b_start;
- uint8_t wpr2b_end;
- /* Fixme: Handle PCROP */
-};
-
-struct stm32l4_flash_bank {
- struct stm32l4_options option_bytes;
- int probed;
-};
-
-/* flash bank stm32l4x <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command)
-{
- struct stm32l4_flash_bank *stm32l4_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- stm32l4_info = malloc(sizeof(struct stm32l4_flash_bank));
- if (!stm32l4_info)
- return ERROR_FAIL; /* Checkme: What better error to use?*/
- bank->driver_priv = stm32l4_info;
-
- stm32l4_info->probed = 0;
-
- return ERROR_OK;
-}
-
-static inline int stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg)
-{
- return reg;
-}
-
-static inline int stm32l4_get_flash_status(struct flash_bank *bank, uint32_t *status)
-{
- struct target *target = bank->target;
- return target_read_u32(
- target, stm32l4_get_flash_reg(bank, STM32_FLASH_SR), status);
-}
-
-static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
-{
- struct target *target = bank->target;
- uint32_t status;
- int retval = ERROR_OK;
-
- /* wait for busy to clear */
- for (;;) {
- retval = stm32l4_get_flash_status(bank, &status);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if ((status & FLASH_BSY) == 0)
- break;
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
-
- if (status & FLASH_WRPERR) {
- LOG_ERROR("stm32x device protected");
- retval = ERROR_FAIL;
- }
-
- /* Clear but report errors */
- if (status & FLASH_ERROR) {
- /* If this operation fails, we ignore it and report the original
- * retval
- */
- target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_SR),
- status & FLASH_ERROR);
- }
- return retval;
-}
-
-static int stm32l4_unlock_reg(struct target *target)
-{
- uint32_t ctrl;
-
- /* first check if not already unlocked
- * otherwise writing on STM32_FLASH_KEYR will fail
- */
- int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if ((ctrl & FLASH_LOCK) == 0)
- return ERROR_OK;
-
- /* unlock flash registers */
- retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if (ctrl & FLASH_LOCK) {
- LOG_ERROR("flash not unlocked STM32_FLASH_CR: %" PRIx32, ctrl);
- return ERROR_TARGET_FAILURE;
- }
-
- return ERROR_OK;
-}
-
-static int stm32l4_unlock_option_reg(struct target *target)
-{
- uint32_t ctrl;
-
- int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if ((ctrl & FLASH_OPTLOCK) == 0)
- return ERROR_OK;
-
- /* unlock option registers */
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY2);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if (ctrl & FLASH_OPTLOCK) {
- LOG_ERROR("options not unlocked STM32_FLASH_CR: %" PRIx32, ctrl);
- return ERROR_TARGET_FAILURE;
- }
-
- return ERROR_OK;
-}
-
-static int stm32l4_read_options(struct flash_bank *bank)
-{
- uint32_t optiondata;
- struct stm32l4_flash_bank *stm32l4_info = NULL;
- struct target *target = bank->target;
-
- stm32l4_info = bank->driver_priv;
-
- /* read current option bytes */
- int retval = target_read_u32(target, STM32_FLASH_OPTR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
-
- stm32l4_info->option_bytes.user_options = (optiondata >> 8) & 0x3ffff;
- stm32l4_info->option_bytes.RDP = optiondata & 0xff;
-
- retval = target_read_u32(target, STM32_FLASH_WRP1AR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
- stm32l4_info->option_bytes.wpr1a_start = optiondata & 0xff;
- stm32l4_info->option_bytes.wpr1a_end = (optiondata >> 16) & 0xff;
-
- retval = target_read_u32(target, STM32_FLASH_WRP2AR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
- stm32l4_info->option_bytes.wpr2a_start = optiondata & 0xff;
- stm32l4_info->option_bytes.wpr2a_end = (optiondata >> 16) & 0xff;
-
- retval = target_read_u32(target, STM32_FLASH_WRP1BR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
- stm32l4_info->option_bytes.wpr1b_start = optiondata & 0xff;
- stm32l4_info->option_bytes.wpr1b_end = (optiondata >> 16) & 0xff;
-
- retval = target_read_u32(target, STM32_FLASH_WRP2BR, &optiondata);
- if (retval != ERROR_OK)
- return retval;
- stm32l4_info->option_bytes.wpr2b_start = optiondata & 0xff;
- stm32l4_info->option_bytes.wpr2b_end = (optiondata >> 16) & 0xff;
-
- if (stm32l4_info->option_bytes.RDP != 0xAA)
- LOG_INFO("Device Security Bit Set");
-
- return ERROR_OK;
-}
-
-static int stm32l4_write_options(struct flash_bank *bank)
-{
- struct stm32l4_flash_bank *stm32l4_info = NULL;
- struct target *target = bank->target;
- uint32_t optiondata;
-
- stm32l4_info = bank->driver_priv;
-
- (void) optiondata;
- (void) stm32l4_info;
-
- int retval = stm32l4_unlock_option_reg(target);
- if (retval != ERROR_OK)
- return retval;
- /* FIXME: Implement Option writing!*/
- return ERROR_OK;
-}
-
-static int stm32l4_protect_check(struct flash_bank *bank)
-{
- struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
-
- /* read write protection settings */
- int retval = stm32l4_read_options(bank);
- if (retval != ERROR_OK) {
- LOG_DEBUG("unable to read option bytes");
- return retval;
- }
-
- for (int i = 0; i < bank->num_sectors; i++) {
- if (i < stm32l4_info->option_bytes.bank_b_start) {
- if (((i >= stm32l4_info->option_bytes.wpr1a_start) &&
- (i <= stm32l4_info->option_bytes.wpr1a_end)) ||
- ((i >= stm32l4_info->option_bytes.wpr2a_start) &&
- (i <= stm32l4_info->option_bytes.wpr2a_end)))
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- } else {
- uint8_t snb;
- snb = i - stm32l4_info->option_bytes.bank_b_start + 256;
- if (((snb >= stm32l4_info->option_bytes.wpr1b_start) &&
- (snb <= stm32l4_info->option_bytes.wpr1b_end)) ||
- ((snb >= stm32l4_info->option_bytes.wpr2b_start) &&
- (snb <= stm32l4_info->option_bytes.wpr2b_end)))
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- }
- }
- return ERROR_OK;
-}
-
-static int stm32l4_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- int i;
-
- assert(first < bank->num_sectors);
- assert(last < bank->num_sectors);
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int retval;
- retval = stm32l4_unlock_reg(target);
- if (retval != ERROR_OK)
- return retval;
-
- /*
- Sector Erase
- To erase a sector, follow the procedure below:
- 1. Check that no Flash memory operation is ongoing by
- checking the BSY bit in the FLASH_SR register
- 2. Set the PER bit and select the page and bank
- you wish to erase in the FLASH_CR register
- 3. Set the STRT bit in the FLASH_CR register
- 4. Wait for the BSY bit to be cleared
- */
- struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
-
- for (i = first; i <= last; i++) {
- uint32_t erase_flags;
- erase_flags = FLASH_PER | FLASH_STRT;
-
- if (i >= stm32l4_info->option_bytes.bank_b_start) {
- uint8_t snb;
- snb = (i - stm32l4_info->option_bytes.bank_b_start) + 256;
- erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER;
- } else
- erase_flags |= i << FLASH_PAGE_SHIFT;
- retval = target_write_u32(target,
- stm32l4_get_flash_reg(bank, STM32_FLASH_CR), erase_flags);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- bank->sectors[i].is_erased = 1;
- }
-
- retval = target_write_u32(
- target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32l4_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct target *target = bank->target;
- struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* read protection settings */
- int retval = stm32l4_read_options(bank);
- if (retval != ERROR_OK) {
- LOG_DEBUG("unable to read option bytes");
- return retval;
- }
-
- (void)stm32l4_info;
- /* FIXME: Write First and last in a valid WRPxx_start/end combo*/
- retval = stm32l4_write_options(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-/* Count is in halfwords */
-static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[5];
- struct armv7m_algorithm armv7m_info;
- int retval = ERROR_OK;
-
- /* See contrib/loaders/flash/stm32l4x.S for source and
- * hints how to generate the data!
- */
-
- static const uint8_t stm32l4_flash_write_code[] = {
- 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x21, 0xd0, 0x45, 0x68,
- 0xb8, 0xeb, 0x05, 0x06, 0x44, 0xbf, 0x76, 0x18, 0x36, 0x1a, 0x08, 0x2e,
- 0xf2, 0xd3, 0xdf, 0xf8, 0x36, 0x60, 0x66, 0x61, 0xf5, 0xe8, 0x02, 0x67,
- 0xe2, 0xe8, 0x02, 0x67, 0xbf, 0xf3, 0x4f, 0x8f, 0x26, 0x69, 0x16, 0xf4,
- 0x80, 0x3f, 0xfb, 0xd1, 0x16, 0xf0, 0xfa, 0x0f, 0x07, 0xd1, 0x8d, 0x42,
- 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x05, 0x45, 0x60, 0x01, 0x3b, 0x13, 0xb1,
- 0xda, 0xe7, 0x00, 0x21, 0x41, 0x60, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x00,
- 0x00, 0x00
- };
-
- if (target_alloc_working_area(target, sizeof(stm32l4_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = target_write_buffer(target, write_algorithm->address,
- sizeof(stm32l4_flash_write_code),
- stm32l4_flash_write_code);
- if (retval != ERROR_OK)
- return retval;
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) !=
- ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */
- 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 */
-
- 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[4].value, 0, 32, STM32_FLASH_BASE);
-
- retval = target_run_flash_async_algorithm(target, buffer, count, 2,
- 0, NULL,
- 5, reg_params,
- source->address, source->size,
- write_algorithm->address, 0,
- &armv7m_info);
-
- if (retval == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("error executing stm32l4 flash write algorithm");
-
- uint32_t error = buf_get_u32(reg_params[0].value, 0, 32) & FLASH_ERROR;
-
- if (error & FLASH_WRPERR)
- LOG_ERROR("flash memory write protected");
-
- if (error != 0) {
- LOG_ERROR("flash write failed = %08" PRIx32, error);
- /* Clear but report errors */
- target_write_u32(target, STM32_FLASH_SR, error);
- retval = ERROR_FAIL;
- }
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
-
- return retval;
-}
-
-static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- int retval;
-
- 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!
- */
- }
-
- retval = stm32l4_unlock_reg(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* 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");
- return retval;
- }
-
- LOG_WARNING("block write succeeded");
- return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
-}
-
-static int stm32l4_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
- int i;
- uint16_t flash_size_in_kb = 0xffff;
- uint16_t max_flash_size_in_kb;
- uint32_t device_id;
- uint32_t options;
- uint32_t base_address = 0x08000000;
-
- stm32l4_info->probed = 0;
-
- /* read stm32 device id register */
- int retval = target_read_u32(target, DBGMCU_IDCODE, &device_id);
- if (retval != ERROR_OK)
- return retval;
- LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
-
- /* set max flash size depending on family */
- switch (device_id & 0xfff) {
- case 0x415:
- max_flash_size_in_kb = 1024;
- break;
- default:
- LOG_WARNING("Cannot identify target as a STM32L4 family.");
- return ERROR_FAIL;
- }
-
- /* get flash size from target. */
- retval = target_read_u16(target, FLASH_SIZE_REG, &flash_size_in_kb);
-
- /* failed reading flash size or flash size invalid (early silicon),
- * default to max target family */
- if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
- LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash",
- max_flash_size_in_kb);
- flash_size_in_kb = max_flash_size_in_kb;
- }
-
- LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
-
- /* did we assign flash size? */
- assert(flash_size_in_kb != 0xffff);
-
- /* get options to for DUAL BANK. */
- retval = target_read_u32(target, STM32_FLASH_OPTR, &options);
-
- /* only devices with < 1024 kiB may be set to single bank dual banks */
- if ((flash_size_in_kb == 1024) || !(options & OPT_DUALBANK))
- stm32l4_info->option_bytes.bank_b_start = 256;
- else
- stm32l4_info->option_bytes.bank_b_start = flash_size_in_kb << 9;
-
- /* did we assign flash size? */
- assert((flash_size_in_kb != 0xffff) && flash_size_in_kb);
-
- /* calculate numbers of pages */
- int num_pages = flash_size_in_kb / 2;
-
- /* check that calculation result makes sense */
- assert(num_pages > 0);
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->base = base_address;
- bank->size = num_pages * (1 << 11);
- bank->num_sectors = num_pages;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
- if (!bank->sectors)
- return ERROR_FAIL; /* Checkme: What better error to use?*/
-
- for (i = 0; i < num_pages; i++) {
- bank->sectors[i].offset = i << 11;
- bank->sectors[i].size = 1 << 11;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = 1;
- }
-
- stm32l4_info->probed = 1;
-
- return ERROR_OK;
-}
-
-static int stm32l4_auto_probe(struct flash_bank *bank)
-{
- struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
- if (stm32l4_info->probed)
- return ERROR_OK;
- return stm32l4_probe(bank);
-}
-
-static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct target *target = bank->target;
- uint32_t dbgmcu_idcode;
-
- /* read stm32 device id register */
- int retval = target_read_u32(target, DBGMCU_IDCODE, &dbgmcu_idcode);
- if (retval != ERROR_OK)
- return retval;
-
- uint16_t device_id = dbgmcu_idcode & 0xffff;
- uint8_t rev_id = dbgmcu_idcode >> 28;
- uint8_t rev_minor = 0;
- int i;
-
- for (i = 16; i < 28; i++) {
- if (dbgmcu_idcode & (1 << i))
- rev_minor++;
- else
- break;
- }
-
- const char *device_str;
-
- switch (device_id) {
- case 0x6415:
- device_str = "STM32L4xx";
- break;
-
- default:
- snprintf(buf, buf_size, "Cannot identify target as a STM32L4\n");
- return ERROR_FAIL;
- }
-
- snprintf(buf, buf_size, "%s - Rev: %1d.%02d",
- device_str, rev_id, rev_minor);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32l4_handle_lock_command)
-{
- struct target *target = NULL;
- struct stm32l4_flash_bank *stm32l4_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32l4_info = bank->driver_priv;
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (stm32l4_read_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to read options",
- bank->driver->name);
- return ERROR_OK;
- }
-
- /* set readout protection */
- stm32l4_info->option_bytes.RDP = 0;
-
- if (stm32l4_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to lock device", bank->driver->name);
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "%s locked", bank->driver->name);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32l4_handle_unlock_command)
-{
- struct target *target = NULL;
- struct stm32l4_flash_bank *stm32l4_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- stm32l4_info = bank->driver_priv;
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (stm32l4_read_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to read options", bank->driver->name);
- return ERROR_OK;
- }
-
- /* clear readout protection and complementary option bytes
- * this will also force a device unlock if set */
- stm32l4_info->option_bytes.RDP = 0xAA;
-
- if (stm32l4_write_options(bank) != ERROR_OK) {
- command_print(CMD_CTX, "%s failed to unlock device",
- bank->driver->name);
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "%s unlocked.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.", bank->driver->name);
-
- return ERROR_OK;
-}
-
-static int stm32l4_mass_erase(struct flash_bank *bank, uint32_t action)
-{
- int retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = stm32l4_unlock_reg(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* mass erase flash memory */
- retval = target_write_u32(
- target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), action);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(
- target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR),
- action | FLASH_STRT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(
- target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32l4_handle_mass_erase_command)
-{
- int i;
- uint32_t action;
-
- if (CMD_ARGC < 1) {
- command_print(CMD_CTX, "stm32x mass_erase <STM32L4 bank>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- action = FLASH_MER1 | FLASH_MER2;
- retval = stm32l4_mass_erase(bank, action);
- if (retval == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "stm32x mass erase complete");
- } else {
- command_print(CMD_CTX, "stm32x mass erase failed");
- }
-
- return retval;
-}
-
-static const struct command_registration stm32l4_exec_command_handlers[] = {
- {
- .name = "lock",
- .handler = stm32l4_handle_lock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Lock entire flash device.",
- },
- {
- .name = "unlock",
- .handler = stm32l4_handle_unlock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Unlock entire protected flash device.",
- },
- {
- .name = "mass_erase",
- .handler = stm32l4_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Erase entire flash device.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration stm32l4_command_handlers[] = {
- {
- .name = "stm32l4x",
- .mode = COMMAND_ANY,
- .help = "stm32l4x flash command group",
- .usage = "",
- .chain = stm32l4_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver stm32l4x_flash = {
- .name = "stm32l4x",
- .commands = stm32l4_command_handlers,
- .flash_bank_command = stm32l4_flash_bank_command,
- .erase = stm32l4_erase,
- .protect = stm32l4_protect,
- .write = stm32l4_write,
- .read = default_flash_read,
- .probe = stm32l4_probe,
- .auto_probe = stm32l4_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = stm32l4_protect_check,
- .info = get_stm32l4_info,
-};
diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c
deleted file mode 100644
index 376c0f8..0000000
--- a/src/flash/nor/stm32lx.c
+++ /dev/null
@@ -1,1421 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Clement Burin des Roziers *
- * clement.burin-des-roziers@hikob.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-#include <target/cortex_m.h>
-
-/* stm32lx flash register locations */
-
-#define FLASH_ACR 0x00
-#define FLASH_PECR 0x04
-#define FLASH_PDKEYR 0x08
-#define FLASH_PEKEYR 0x0C
-#define FLASH_PRGKEYR 0x10
-#define FLASH_OPTKEYR 0x14
-#define FLASH_SR 0x18
-#define FLASH_OBR 0x1C
-#define FLASH_WRPR 0x20
-
-/* FLASH_ACR bites */
-#define FLASH_ACR__LATENCY (1<<0)
-#define FLASH_ACR__PRFTEN (1<<1)
-#define FLASH_ACR__ACC64 (1<<2)
-#define FLASH_ACR__SLEEP_PD (1<<3)
-#define FLASH_ACR__RUN_PD (1<<4)
-
-/* FLASH_PECR bits */
-#define FLASH_PECR__PELOCK (1<<0)
-#define FLASH_PECR__PRGLOCK (1<<1)
-#define FLASH_PECR__OPTLOCK (1<<2)
-#define FLASH_PECR__PROG (1<<3)
-#define FLASH_PECR__DATA (1<<4)
-#define FLASH_PECR__FTDW (1<<8)
-#define FLASH_PECR__ERASE (1<<9)
-#define FLASH_PECR__FPRG (1<<10)
-#define FLASH_PECR__EOPIE (1<<16)
-#define FLASH_PECR__ERRIE (1<<17)
-#define FLASH_PECR__OBL_LAUNCH (1<<18)
-
-/* FLASH_SR bits */
-#define FLASH_SR__BSY (1<<0)
-#define FLASH_SR__EOP (1<<1)
-#define FLASH_SR__ENDHV (1<<2)
-#define FLASH_SR__READY (1<<3)
-#define FLASH_SR__WRPERR (1<<8)
-#define FLASH_SR__PGAERR (1<<9)
-#define FLASH_SR__SIZERR (1<<10)
-#define FLASH_SR__OPTVERR (1<<11)
-
-/* Unlock keys */
-#define PEKEY1 0x89ABCDEF
-#define PEKEY2 0x02030405
-#define PRGKEY1 0x8C9DAEBF
-#define PRGKEY2 0x13141516
-#define OPTKEY1 0xFBEAD9C8
-#define OPTKEY2 0x24252627
-
-/* other registers */
-#define DBGMCU_IDCODE 0xE0042000
-#define DBGMCU_IDCODE_L0 0x40015800
-
-/* Constants */
-#define FLASH_SECTOR_SIZE 4096
-#define FLASH_BANK0_ADDRESS 0x08000000
-
-/* option bytes */
-#define OPTION_BYTES_ADDRESS 0x1FF80000
-
-#define OPTION_BYTE_0_PR1 0xFFFF0000
-#define OPTION_BYTE_0_PR0 0xFF5500AA
-
-static int stm32lx_unlock_program_memory(struct flash_bank *bank);
-static int stm32lx_lock_program_memory(struct flash_bank *bank);
-static int stm32lx_enable_write_half_page(struct flash_bank *bank);
-static int stm32lx_erase_sector(struct flash_bank *bank, int sector);
-static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank);
-static int stm32lx_lock(struct flash_bank *bank);
-static int stm32lx_unlock(struct flash_bank *bank);
-static int stm32lx_mass_erase(struct flash_bank *bank);
-static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout);
-
-struct stm32lx_rev {
- uint16_t rev;
- const char *str;
-};
-
-struct stm32lx_part_info {
- uint16_t id;
- const char *device_str;
- const struct stm32lx_rev *revs;
- size_t num_revs;
- unsigned int page_size;
- unsigned int pages_per_sector;
- uint16_t max_flash_size_kb;
- uint16_t first_bank_size_kb; /* used when has_dual_banks is true */
- bool has_dual_banks;
-
- uint32_t flash_base; /* Flash controller registers location */
- uint32_t fsize_base; /* Location of FSIZE register */
-};
-
-struct stm32lx_flash_bank {
- int probed;
- uint32_t idcode;
- uint32_t user_bank_size;
- uint32_t flash_base;
-
- const struct stm32lx_part_info *part_info;
-};
-
-static const struct stm32lx_rev stm32_416_revs[] = {
- { 0x1000, "A" }, { 0x1008, "Y" }, { 0x1038, "W" }, { 0x1078, "V" },
-};
-static const struct stm32lx_rev stm32_417_revs[] = {
- { 0x1000, "A" }, { 0x1008, "Z" }, { 0x1018, "Y" }, { 0x1038, "X" }
-};
-static const struct stm32lx_rev stm32_425_revs[] = {
- { 0x1000, "A" }, { 0x2000, "B" }, { 0x2008, "Y" },
-};
-static const struct stm32lx_rev stm32_427_revs[] = {
- { 0x1000, "A" }, { 0x1018, "Y" }, { 0x1038, "X" },
-};
-static const struct stm32lx_rev stm32_429_revs[] = {
- { 0x1000, "A" }, { 0x1018, "Z" },
-};
-static const struct stm32lx_rev stm32_436_revs[] = {
- { 0x1000, "A" }, { 0x1008, "Z" }, { 0x1018, "Y" },
-};
-static const struct stm32lx_rev stm32_437_revs[] = {
- { 0x1000, "A" },
-};
-static const struct stm32lx_rev stm32_447_revs[] = {
- { 0x1000, "A" }, { 0x2000, "B" }, { 0x2008, "Z" },
-};
-static const struct stm32lx_rev stm32_457_revs[] = {
- { 0x1000, "A" }, { 0x1008, "Z" },
-};
-
-static const struct stm32lx_part_info stm32lx_parts[] = {
- {
- .id = 0x416,
- .revs = stm32_416_revs,
- .num_revs = ARRAY_SIZE(stm32_416_revs),
- .device_str = "STM32L1xx (Cat.1 - Low/Medium Density)",
- .page_size = 256,
- .pages_per_sector = 16,
- .max_flash_size_kb = 128,
- .has_dual_banks = false,
- .flash_base = 0x40023C00,
- .fsize_base = 0x1FF8004C,
- },
- {
- .id = 0x417,
- .revs = stm32_417_revs,
- .num_revs = ARRAY_SIZE(stm32_417_revs),
- .device_str = "STM32L0xx (Cat. 3)",
- .page_size = 128,
- .pages_per_sector = 32,
- .max_flash_size_kb = 64,
- .has_dual_banks = false,
- .flash_base = 0x40022000,
- .fsize_base = 0x1FF8007C,
- },
- {
- .id = 0x425,
- .revs = stm32_425_revs,
- .num_revs = ARRAY_SIZE(stm32_425_revs),
- .device_str = "STM32L0xx (Cat. 2)",
- .page_size = 128,
- .pages_per_sector = 32,
- .max_flash_size_kb = 32,
- .has_dual_banks = false,
- .flash_base = 0x40022000,
- .fsize_base = 0x1FF8007C,
- },
- {
- .id = 0x427,
- .revs = stm32_427_revs,
- .num_revs = ARRAY_SIZE(stm32_427_revs),
- .device_str = "STM32L1xx (Cat.3 - Medium+ Density)",
- .page_size = 256,
- .pages_per_sector = 16,
- .max_flash_size_kb = 256,
- .has_dual_banks = false,
- .flash_base = 0x40023C00,
- .fsize_base = 0x1FF800CC,
- },
- {
- .id = 0x429,
- .revs = stm32_429_revs,
- .num_revs = ARRAY_SIZE(stm32_429_revs),
- .device_str = "STM32L1xx (Cat.2)",
- .page_size = 256,
- .pages_per_sector = 16,
- .max_flash_size_kb = 128,
- .has_dual_banks = false,
- .flash_base = 0x40023C00,
- .fsize_base = 0x1FF8004C,
- },
- {
- .id = 0x436,
- .revs = stm32_436_revs,
- .num_revs = ARRAY_SIZE(stm32_436_revs),
- .device_str = "STM32L1xx (Cat.4/Cat.3 - Medium+/High Density)",
- .page_size = 256,
- .pages_per_sector = 16,
- .max_flash_size_kb = 384,
- .first_bank_size_kb = 192,
- .has_dual_banks = true,
- .flash_base = 0x40023C00,
- .fsize_base = 0x1FF800CC,
- },
- {
- .id = 0x437,
- .revs = stm32_437_revs,
- .num_revs = ARRAY_SIZE(stm32_437_revs),
- .device_str = "STM32L1xx (Cat.5/Cat.6)",
- .page_size = 256,
- .pages_per_sector = 16,
- .max_flash_size_kb = 512,
- .first_bank_size_kb = 256,
- .has_dual_banks = true,
- .flash_base = 0x40023C00,
- .fsize_base = 0x1FF800CC,
- },
- {
- .id = 0x447,
- .revs = stm32_447_revs,
- .num_revs = ARRAY_SIZE(stm32_447_revs),
- .device_str = "STM32L0xx (Cat.5)",
- .page_size = 128,
- .pages_per_sector = 32,
- .max_flash_size_kb = 192,
- .first_bank_size_kb = 128,
- .has_dual_banks = true,
- .flash_base = 0x40022000,
- .fsize_base = 0x1FF8007C,
- },
- {
- .id = 0x457,
- .revs = stm32_457_revs,
- .num_revs = ARRAY_SIZE(stm32_457_revs),
- .device_str = "STM32L0xx (Cat.1)",
- .page_size = 128,
- .pages_per_sector = 32,
- .max_flash_size_kb = 16,
- .has_dual_banks = false,
- .flash_base = 0x40022000,
- .fsize_base = 0x1FF8007C,
- },
-};
-
-/* flash bank stm32lx <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
-{
- struct stm32lx_flash_bank *stm32lx_info;
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* Create the bank structure */
- stm32lx_info = calloc(1, sizeof(*stm32lx_info));
-
- /* Check allocation */
- if (stm32lx_info == NULL) {
- LOG_ERROR("failed to allocate bank structure");
- return ERROR_FAIL;
- }
-
- bank->driver_priv = stm32lx_info;
-
- stm32lx_info->probed = 0;
- stm32lx_info->user_bank_size = bank->size;
-
- /* the stm32l erased value is 0x00 */
- bank->default_padded_value = 0x00;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(stm32lx_handle_mass_erase_command)
-{
- int i;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32lx_mass_erase(bank);
- if (retval == ERROR_OK) {
- /* set all sectors as erased */
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_erased = 1;
-
- command_print(CMD_CTX, "stm32lx mass erase complete");
- } else {
- command_print(CMD_CTX, "stm32lx mass erase failed");
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(stm32lx_handle_lock_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32lx_lock(bank);
-
- if (retval == ERROR_OK)
- command_print(CMD_CTX, "STM32Lx locked, takes effect after power cycle.");
- else
- command_print(CMD_CTX, "STM32Lx lock failed");
-
- return retval;
-}
-
-COMMAND_HANDLER(stm32lx_handle_unlock_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- retval = stm32lx_unlock(bank);
-
- if (retval == ERROR_OK)
- command_print(CMD_CTX, "STM32Lx unlocked, takes effect after power cycle.");
- else
- command_print(CMD_CTX, "STM32Lx unlock failed");
-
- return retval;
-}
-
-static int stm32lx_protect_check(struct flash_bank *bank)
-{
- int retval;
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-
- uint32_t wrpr;
-
- /*
- * Read the WRPR word, and check each bit (corresponding to each
- * flash sector
- */
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_WRPR,
- &wrpr);
- if (retval != ERROR_OK)
- return retval;
-
- for (int i = 0; i < bank->num_sectors; i++) {
- if (wrpr & (1 << i))
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- }
- return ERROR_OK;
-}
-
-static int stm32lx_erase(struct flash_bank *bank, int first, int last)
-{
- int retval;
-
- /*
- * It could be possible to do a mass erase if all sectors must be
- * erased, but it is not implemented yet.
- */
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /*
- * Loop over the selected sectors and erase them
- */
- for (int i = first; i <= last; i++) {
- retval = stm32lx_erase_sector(bank, i);
- if (retval != ERROR_OK)
- return retval;
- bank->sectors[i].is_erased = 1;
- }
- return ERROR_OK;
-}
-
-static int stm32lx_protect(struct flash_bank *bank, int set, int first,
- int last)
-{
- LOG_WARNING("protection of the STM32L flash is not implemented");
- return ERROR_OK;
-}
-
-static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-
- uint32_t hp_nb = stm32lx_info->part_info->page_size / 2;
- uint32_t buffer_size = 16384;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
-
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
-
- int retval = ERROR_OK;
-
- /* see contib/loaders/flash/stm32lx.S for src */
-
- static const uint8_t stm32lx_flash_write_code[] = {
- /* write_word: */
- 0x00, 0x23, /* movs r3, #0 */
- 0x04, 0xe0, /* b test_done */
-
- /* write_word: */
- 0x51, 0xf8, 0x04, 0xcb, /* ldr ip, [r1], #4 */
- 0x40, 0xf8, 0x04, 0xcb, /* str ip, [r0], #4 */
- 0x01, 0x33, /* adds r3, #1 */
-
- /* test_done: */
- 0x93, 0x42, /* cmp r3, r2 */
- 0xf8, 0xd3, /* bcc write_word */
- 0x00, 0xbe, /* bkpt 0 */
- };
-
- /* Make sure we're performing a half-page aligned write. */
- if (count % hp_nb) {
- LOG_ERROR("The byte count must be %" PRIu32 "B-aligned but count is %" PRIi32 "B)", hp_nb, count);
- return ERROR_FAIL;
- }
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(stm32lx_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_DEBUG("no working area for block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* Write the flashing code */
- retval = target_write_buffer(target,
- write_algorithm->address,
- sizeof(stm32lx_flash_write_code),
- stm32lx_flash_write_code);
- if (retval != ERROR_OK) {
- target_free_working_area(target, write_algorithm);
- return retval;
- }
-
- /* Allocate half pages memory */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- if (buffer_size > 1024)
- buffer_size -= 1024;
- else
- buffer_size /= 2;
-
- if (buffer_size <= stm32lx_info->part_info->page_size) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
- 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);
-
- /* Enable half-page write */
- retval = stm32lx_enable_write_half_page(bank);
- if (retval != ERROR_OK) {
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- return retval;
- }
-
- struct armv7m_common *armv7m = target_to_armv7m(target);
- if (armv7m == NULL) {
-
- /* something is very wrong if armv7m is NULL */
- LOG_ERROR("unable to get armv7m target");
- return retval;
- }
-
- /* save any DEMCR flags and configure target to catch any Hard Faults */
- uint32_t demcr_save = armv7m->demcr;
- armv7m->demcr = VC_HARDERR;
-
- /* Loop while there are bytes to write */
- while (count > 0) {
- uint32_t this_count;
- this_count = (count > buffer_size) ? buffer_size : count;
-
- /* Write the next half pages */
- retval = target_write_buffer(target, source->address, this_count, buffer);
- if (retval != ERROR_OK)
- break;
-
- /* 4: Store useful information in the registers */
- /* the destination address of the copy (R0) */
- buf_set_u32(reg_params[0].value, 0, 32, address);
- /* The source address of the copy (R1) */
- buf_set_u32(reg_params[1].value, 0, 32, source->address);
- /* The length of the copy (R2) */
- buf_set_u32(reg_params[2].value, 0, 32, this_count / 4);
-
- /* 5: Execute the bunch of code */
- retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params)
- / sizeof(*reg_params), reg_params,
- write_algorithm->address, 0, 10000, &armv7m_info);
- if (retval != ERROR_OK)
- break;
-
- /* check for Hard Fault */
- if (armv7m->exception_number == 3)
- break;
-
- /* 6: Wait while busy */
- retval = stm32lx_wait_until_bsy_clear(bank);
- if (retval != ERROR_OK)
- break;
-
- buffer += this_count;
- address += this_count;
- count -= this_count;
- }
-
- /* restore previous flags */
- armv7m->demcr = demcr_save;
-
- if (armv7m->exception_number == 3) {
-
- /* the stm32l15x devices seem to have an issue when blank.
- * if a ram loader is executed on a blank device it will
- * Hard Fault, this issue does not happen for a already programmed device.
- * A related issue is described in the stm32l151xx errata (Doc ID 17721 Rev 6 - 2.1.3).
- * The workaround of handling the Hard Fault exception does work, but makes the
- * loader more complicated, as a compromise we manually write the pages, programming time
- * is reduced by 50% using this slower method.
- */
-
- LOG_WARNING("couldn't use loader, falling back to page memory writes");
-
- while (count > 0) {
- uint32_t this_count;
- this_count = (count > hp_nb) ? hp_nb : count;
-
- /* Write the next half pages */
- retval = target_write_buffer(target, address, this_count, buffer);
- if (retval != ERROR_OK)
- break;
-
- /* Wait while busy */
- retval = stm32lx_wait_until_bsy_clear(bank);
- if (retval != ERROR_OK)
- break;
-
- buffer += this_count;
- address += this_count;
- count -= this_count;
- }
- }
-
- if (retval == ERROR_OK)
- retval = stm32lx_lock_program_memory(bank);
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- return retval;
-}
-
-static int stm32lx_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-
- uint32_t hp_nb = stm32lx_info->part_info->page_size / 2;
- uint32_t halfpages_number;
- uint32_t bytes_remaining = 0;
- uint32_t address = bank->base + offset;
- uint32_t bytes_written = 0;
- int retval, retval2;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x3) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- retval = stm32lx_unlock_program_memory(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* first we need to write any unaligned head bytes upto
- * the next 128 byte page */
-
- if (offset % hp_nb)
- bytes_remaining = MIN(count, hp_nb - (offset % hp_nb));
-
- while (bytes_remaining > 0) {
- uint8_t value[4] = {0xff, 0xff, 0xff, 0xff};
-
- /* copy remaining bytes into the write buffer */
- uint32_t bytes_to_write = MIN(4, bytes_remaining);
- memcpy(value, buffer + bytes_written, bytes_to_write);
-
- retval = target_write_buffer(target, address, 4, value);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- bytes_written += bytes_to_write;
- bytes_remaining -= bytes_to_write;
- address += 4;
-
- retval = stm32lx_wait_until_bsy_clear(bank);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- }
-
- offset += bytes_written;
- count -= bytes_written;
-
- /* this should always pass this check here */
- assert((offset % hp_nb) == 0);
-
- /* calculate half pages */
- halfpages_number = count / hp_nb;
-
- if (halfpages_number) {
- retval = stm32lx_write_half_pages(bank, buffer + bytes_written, offset, hp_nb * halfpages_number);
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* attempt slow memory writes */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
- halfpages_number = 0;
- } else {
- if (retval != ERROR_OK)
- return ERROR_FAIL;
- }
- }
-
- /* write any remaining bytes */
- uint32_t page_bytes_written = hp_nb * halfpages_number;
- bytes_written += page_bytes_written;
- address += page_bytes_written;
- bytes_remaining = count - page_bytes_written;
-
- retval = stm32lx_unlock_program_memory(bank);
- if (retval != ERROR_OK)
- return retval;
-
- while (bytes_remaining > 0) {
- uint8_t value[4] = {0xff, 0xff, 0xff, 0xff};
-
- /* copy remaining bytes into the write buffer */
- uint32_t bytes_to_write = MIN(4, bytes_remaining);
- memcpy(value, buffer + bytes_written, bytes_to_write);
-
- retval = target_write_buffer(target, address, 4, value);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
-
- bytes_written += bytes_to_write;
- bytes_remaining -= bytes_to_write;
- address += 4;
-
- retval = stm32lx_wait_until_bsy_clear(bank);
- if (retval != ERROR_OK)
- goto reset_pg_and_lock;
- }
-
-reset_pg_and_lock:
- retval2 = stm32lx_lock_program_memory(bank);
- if (retval == ERROR_OK)
- retval = retval2;
-
- return retval;
-}
-
-static int stm32lx_read_id_code(struct target *target, uint32_t *id)
-{
- /* read stm32 device id register */
- int retval = target_read_u32(target, DBGMCU_IDCODE, id);
- if (retval != ERROR_OK)
- return retval;
-
- /* STM32L0 parts will have 0 there, try reading the L0's location for
- * DBG_IDCODE in case this is an L0 part. */
- if (*id == 0)
- retval = target_read_u32(target, DBGMCU_IDCODE_L0, id);
-
- return retval;
-}
-
-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;
-
- stm32lx_info->probed = 0;
- stm32lx_info->part_info = NULL;
-
- int retval = stm32lx_read_id_code(bank->target, &device_id);
- if (retval != ERROR_OK)
- return retval;
-
- stm32lx_info->idcode = device_id;
-
- LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id);
-
- for (unsigned int n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) {
- if ((device_id & 0xfff) == stm32lx_parts[n].id)
- stm32lx_info->part_info = &stm32lx_parts[n];
- }
-
- if (!stm32lx_info->part_info) {
- LOG_WARNING("Cannot identify target as a STM32L family.");
- return ERROR_FAIL;
- } else {
- LOG_INFO("Device: %s", stm32lx_info->part_info->device_str);
- }
-
- stm32lx_info->flash_base = stm32lx_info->part_info->flash_base;
-
- /* Get the flash size from target. */
- retval = target_read_u16(target, stm32lx_info->part_info->fsize_base,
- &flash_size_in_kb);
-
- /* 0x436 devices report their flash size as a 0 or 1 code indicating 384K
- * or 256K, respectively. Please see RM0038 r8 or newer and refer to
- * section 30.1.1. */
- if (retval == ERROR_OK && (device_id & 0xfff) == 0x436) {
- if (flash_size_in_kb == 0)
- flash_size_in_kb = 384;
- else if (flash_size_in_kb == 1)
- flash_size_in_kb = 256;
- }
-
- /* Failed reading flash size or flash size invalid (early silicon),
- * default to max target family */
- if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
- LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash",
- stm32lx_info->part_info->max_flash_size_kb);
- flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb;
- } else if (flash_size_in_kb > stm32lx_info->part_info->max_flash_size_kb) {
- LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash",
- flash_size_in_kb, stm32lx_info->part_info->max_flash_size_kb,
- stm32lx_info->part_info->max_flash_size_kb);
- flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb;
- }
-
- if (stm32lx_info->part_info->has_dual_banks) {
- /* Use the configured base address to determine if this is the first or second flash bank.
- * Verify that the base address is reasonably correct and determine the flash bank size
- */
- second_bank_base = base_address +
- stm32lx_info->part_info->first_bank_size_kb * 1024;
- if (bank->base == second_bank_base || !bank->base) {
- /* This is the second bank */
- base_address = second_bank_base;
- flash_size_in_kb = flash_size_in_kb -
- stm32lx_info->part_info->first_bank_size_kb;
- } else if (bank->base == base_address) {
- /* This is the first bank */
- flash_size_in_kb = stm32lx_info->part_info->first_bank_size_kb;
- } else {
- LOG_WARNING("STM32L flash bank base address config is incorrect."
- " 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32,
- bank->base, base_address, second_bank_base);
- return ERROR_FAIL;
- }
- LOG_INFO("STM32L flash has dual banks. Bank (%d) size is %dkb, base address is 0x%" PRIx32,
- bank->bank_number, flash_size_in_kb, base_address);
- } else {
- LOG_INFO("STM32L flash size is %dkb, base address is 0x%" PRIx32, flash_size_in_kb, base_address);
- }
-
- /* if the user sets the size manually then ignore the probed value
- * this allows us to work around devices that have a invalid flash size register value */
- if (stm32lx_info->user_bank_size) {
- flash_size_in_kb = stm32lx_info->user_bank_size / 1024;
- LOG_INFO("ignoring flash probed value, using configured bank size: %dkbytes", flash_size_in_kb);
- }
-
- /* calculate numbers of sectors (4kB per sector) */
- int num_sectors = (flash_size_in_kb * 1024) / FLASH_SECTOR_SIZE;
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- bank->size = flash_size_in_kb * 1024;
- bank->base = base_address;
- bank->num_sectors = num_sectors;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
- if (bank->sectors == NULL) {
- LOG_ERROR("failed to allocate bank sectors");
- return ERROR_FAIL;
- }
-
- for (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;
-
- return ERROR_OK;
-}
-
-static int stm32lx_auto_probe(struct flash_bank *bank)
-{
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-
- if (stm32lx_info->probed)
- return ERROR_OK;
-
- return stm32lx_probe(bank);
-}
-
-static int stm32lx_erase_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- const int buffer_size = 4096;
- int i;
- uint32_t nBytes;
- int retval = ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint8_t *buffer = malloc(buffer_size);
- if (buffer == NULL) {
- LOG_ERROR("failed to allocate read buffer");
- return ERROR_FAIL;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t j;
- bank->sectors[i].is_erased = 1;
-
- /* Loop chunk by chunk over the sector */
- for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
- uint32_t chunk;
- chunk = buffer_size;
- if (chunk > (j - bank->sectors[i].size))
- chunk = (j - bank->sectors[i].size);
-
- retval = target_read_memory(target, bank->base
- + bank->sectors[i].offset + j, 4, chunk / 4, buffer);
- if (retval != ERROR_OK)
- break;
-
- for (nBytes = 0; nBytes < chunk; nBytes++) {
- if (buffer[nBytes] != 0x00) {
- bank->sectors[i].is_erased = 0;
- break;
- }
- }
- }
- if (retval != ERROR_OK)
- break;
- }
- free(buffer);
-
- return retval;
-}
-
-/* This method must return a string displaying information about the bank */
-static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-
- if (!stm32lx_info->probed) {
- int retval = stm32lx_probe(bank);
- if (retval != ERROR_OK) {
- snprintf(buf, buf_size,
- "Unable to find bank information.");
- return retval;
- }
- }
-
- const struct stm32lx_part_info *info = stm32lx_info->part_info;
-
- if (info) {
- const char *rev_str = NULL;
- uint16_t rev_id = stm32lx_info->idcode >> 16;
-
- for (unsigned int i = 0; i < info->num_revs; i++)
- if (rev_id == info->revs[i].rev)
- rev_str = info->revs[i].str;
-
- if (rev_str != NULL) {
- snprintf(buf, buf_size,
- "%s - Rev: %s",
- stm32lx_info->part_info->device_str, rev_str);
- } else {
- snprintf(buf, buf_size,
- "%s - Rev: unknown (0x%04x)",
- stm32lx_info->part_info->device_str, rev_id);
- }
-
- return ERROR_OK;
- } else {
- snprintf(buf, buf_size, "Cannot identify target as a STM32Lx");
-
- return ERROR_FAIL;
- }
-}
-
-static const struct command_registration stm32lx_exec_command_handlers[] = {
- {
- .name = "mass_erase",
- .handler = stm32lx_handle_mass_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Erase entire flash device. including available EEPROM",
- },
- {
- .name = "lock",
- .handler = stm32lx_handle_lock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Increase the readout protection to Level 1.",
- },
- {
- .name = "unlock",
- .handler = stm32lx_handle_unlock_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Lower the readout protection from Level 1 to 0.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration stm32lx_command_handlers[] = {
- {
- .name = "stm32lx",
- .mode = COMMAND_ANY,
- .help = "stm32lx flash command group",
- .usage = "",
- .chain = stm32lx_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver stm32lx_flash = {
- .name = "stm32lx",
- .commands = stm32lx_command_handlers,
- .flash_bank_command = stm32lx_flash_bank_command,
- .erase = stm32lx_erase,
- .protect = stm32lx_protect,
- .write = stm32lx_write,
- .read = default_flash_read,
- .probe = stm32lx_probe,
- .auto_probe = stm32lx_auto_probe,
- .erase_check = stm32lx_erase_check,
- .protect_check = stm32lx_protect_check,
- .info = stm32lx_get_info,
-};
-
-/* Static methods implementation */
-static int stm32lx_unlock_program_memory(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
- int retval;
- uint32_t reg32;
-
- /*
- * Unlocking the program memory is done by unlocking the PECR,
- * then by writing the 2 PRGKEY to the PRGKEYR register
- */
-
- /* check flash is not already unlocked */
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- if ((reg32 & FLASH_PECR__PRGLOCK) == 0)
- return ERROR_OK;
-
- /* To unlock the PECR write the 2 PEKEY to the PEKEYR register */
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR,
- PEKEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR,
- PEKEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* Make sure it worked */
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- if (reg32 & FLASH_PECR__PELOCK) {
- LOG_ERROR("PELOCK is not cleared :(");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PRGKEYR,
- PRGKEY1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PRGKEYR,
- PRGKEY2);
- if (retval != ERROR_OK)
- return retval;
-
- /* Make sure it worked */
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- if (reg32 & FLASH_PECR__PRGLOCK) {
- LOG_ERROR("PRGLOCK is not cleared :(");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int stm32lx_enable_write_half_page(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
- int retval;
- uint32_t reg32;
-
- /**
- * Unlock the program memory, then set the FPRG bit in the PECR register.
- */
- retval = stm32lx_unlock_program_memory(bank);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- reg32 |= FLASH_PECR__FPRG;
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- reg32);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- reg32 |= FLASH_PECR__PROG;
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- reg32);
-
- return retval;
-}
-
-static int stm32lx_lock_program_memory(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
- int retval;
- uint32_t reg32;
-
- /* To lock the program memory, simply set the lock bit and lock PECR */
-
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- reg32 |= FLASH_PECR__PRGLOCK;
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- reg32);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- reg32 |= FLASH_PECR__PELOCK;
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- reg32);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
- int retval;
- uint32_t reg32;
-
- /*
- * To erase a sector (i.e. stm32lx_info->part_info.pages_per_sector pages),
- * first unlock the memory, loop over the pages of this sector
- * and write 0x0 to its first word.
- */
-
- retval = stm32lx_unlock_program_memory(bank);
- if (retval != ERROR_OK)
- return retval;
-
- for (int page = 0; page < (int)stm32lx_info->part_info->pages_per_sector;
- page++) {
- reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
- retval = target_write_u32(target,
- stm32lx_info->flash_base + FLASH_PECR, reg32);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32lx_wait_until_bsy_clear(bank);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t addr = bank->base + bank->sectors[sector].offset + (page
- * stm32lx_info->part_info->page_size);
- retval = target_write_u32(target, addr, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32lx_wait_until_bsy_clear(bank);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = stm32lx_lock_program_memory(bank);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static inline int stm32lx_get_flash_status(struct flash_bank *bank, uint32_t *status)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-
- return target_read_u32(target, stm32lx_info->flash_base + FLASH_SR, status);
-}
-
-static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank)
-{
- return stm32lx_wait_until_bsy_clear_timeout(bank, 100);
-}
-
-static int stm32lx_unlock_options_bytes(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
- int retval;
- uint32_t reg32;
-
- /*
- * Unlocking the options bytes is done by unlocking the PECR,
- * then by writing the 2 FLASH_PEKEYR to the FLASH_OPTKEYR register
- */
-
- /* check flash is not already unlocked */
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- if ((reg32 & FLASH_PECR__OPTLOCK) == 0)
- return ERROR_OK;
-
- if ((reg32 & FLASH_PECR__PELOCK) != 0) {
-
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR, PEKEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PEKEYR, PEKEY2);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* To unlock the PECR write the 2 OPTKEY to the FLASH_OPTKEYR register */
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_OPTKEYR, OPTKEY1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_OPTKEYR, OPTKEY2);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
- uint32_t status;
- int retval = ERROR_OK;
-
- /* wait for busy to clear */
- for (;;) {
- retval = stm32lx_get_flash_status(bank, &status);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("status: 0x%" PRIx32 "", status);
- if ((status & FLASH_SR__BSY) == 0)
- break;
-
- if (timeout-- <= 0) {
- LOG_ERROR("timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- }
-
- if (status & FLASH_SR__WRPERR) {
- LOG_ERROR("access denied / write protected");
- retval = ERROR_FAIL;
- }
-
- if (status & FLASH_SR__PGAERR) {
- LOG_ERROR("invalid program address");
- retval = ERROR_FAIL;
- }
-
- /* Clear but report errors */
- if (status & FLASH_SR__OPTVERR) {
- /* If this operation fails, we ignore it and report the original retval */
- target_write_u32(target, stm32lx_info->flash_base + FLASH_SR, status & FLASH_SR__OPTVERR);
- }
-
- return retval;
-}
-
-static int stm32lx_obl_launch(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
- int retval;
-
- /* This will fail as the target gets immediately rebooted */
- target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR,
- FLASH_PECR__OBL_LAUNCH);
-
- size_t tries = 10;
- do {
- target_halt(target);
- retval = target_poll(target);
- } while (--tries > 0 &&
- (retval != ERROR_OK || target->state != TARGET_HALTED));
-
- return tries ? ERROR_OK : ERROR_FAIL;
-}
-
-static int stm32lx_lock(struct flash_bank *bank)
-{
- int retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = stm32lx_unlock_options_bytes(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* set the RDP protection level to 1 */
- retval = target_write_u32(target, OPTION_BYTES_ADDRESS, OPTION_BYTE_0_PR1);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32lx_unlock(struct flash_bank *bank)
-{
- int retval;
- struct target *target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = stm32lx_unlock_options_bytes(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* set the RDP protection level to 0 */
- retval = target_write_u32(target, OPTION_BYTES_ADDRESS, OPTION_BYTE_0_PR0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32lx_wait_until_bsy_clear_timeout(bank, 30000);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stm32lx_mass_erase(struct flash_bank *bank)
-{
- int retval;
- struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = NULL;
- uint32_t reg32;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- stm32lx_info = bank->driver_priv;
-
- retval = stm32lx_lock(bank);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32lx_obl_launch(bank);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32lx_unlock(bank);
- if (retval != ERROR_OK)
- return retval;
-
- retval = stm32lx_obl_launch(bank);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, &reg32);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, reg32 | FLASH_PECR__OPTLOCK);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
diff --git a/src/flash/nor/stmsmi.c b/src/flash/nor/stmsmi.c
deleted file mode 100644
index 781ea3b..0000000
--- a/src/flash/nor/stmsmi.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* STM Serial Memory Interface (SMI) controller is a SPI bus controller
- * specifically designed for SPI memories.
- * Only SPI "mode 3" (CPOL=1 and CPHA=1) is supported.
- * Two working modes are available:
- * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
- * on the bus.
- * - HW mode: the SPI but is under SMI control. Memory content is directly
- * accessible in CPU memory space. CPU can read, write and execute memory
- * content. */
-
-/* ATTENTION:
- * To have flash memory mapped in CPU memory space, the SMI controller
- * have to be in "HW mode". This requires following constraints:
- * 1) The command "reset init" have to initialize SMI controller and put
- * it in HW mode;
- * 2) every command in this file have to return to prompt in HW mode. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include "spi.h"
-#include <jtag/jtag.h>
-#include <helper/time_support.h>
-
-#define SMI_READ_REG(a) (_SMI_READ_REG(a))
-#define _SMI_READ_REG(a) \
-{ \
- int __a; \
- uint32_t __v; \
- \
- __a = target_read_u32(target, io_base + (a), &__v); \
- if (__a != ERROR_OK) \
- return __a; \
- __v; \
-}
-
-#define SMI_WRITE_REG(a, v) \
-{ \
- int __r; \
- \
- __r = target_write_u32(target, io_base + (a), (v)); \
- if (__r != ERROR_OK) \
- return __r; \
-}
-
-#define SMI_POLL_TFF(timeout) \
-{ \
- int __r; \
- \
- __r = poll_tff(target, io_base, timeout); \
- if (__r != ERROR_OK) \
- return __r; \
-}
-
-#define SMI_SET_SW_MODE() SMI_WRITE_REG(SMI_CR1, \
- SMI_READ_REG(SMI_CR1) | SMI_SW_MODE)
-#define SMI_SET_HWWB_MODE() SMI_WRITE_REG(SMI_CR1, \
- (SMI_READ_REG(SMI_CR1) | SMI_WB_MODE) & ~SMI_SW_MODE)
-#define SMI_SET_HW_MODE() SMI_WRITE_REG(SMI_CR1, \
- SMI_READ_REG(SMI_CR1) & ~(SMI_SW_MODE | SMI_WB_MODE))
-#define SMI_CLEAR_TFF() SMI_WRITE_REG(SMI_SR, ~SMI_TFF)
-
-#define SMI_BANK_SIZE (0x01000000)
-
-#define SMI_CR1 (0x00) /* Control register 1 */
-#define SMI_CR2 (0x04) /* Control register 2 */
-#define SMI_SR (0x08) /* Status register */
-#define SMI_TR (0x0c) /* TX */
-#define SMI_RR (0x10) /* RX */
-
-/* fields in SMI_CR1 */
-#define SMI_SW_MODE 0x10000000 /* set to enable SW Mode */
-#define SMI_WB_MODE 0x20000000 /* Write Burst Mode */
-
-/* fields in SMI_CR2 */
-#define SMI_TX_LEN_1 0x00000001 /* data length = 1 byte */
-#define SMI_TX_LEN_4 0x00000004 /* data length = 4 byte */
-#define SMI_RX_LEN_3 0x00000030 /* data length = 3 byte */
-#define SMI_SEND 0x00000080 /* Send data */
-#define SMI_RSR 0x00000400 /* reads status reg */
-#define SMI_WE 0x00000800 /* Write Enable */
-#define SMI_SEL_BANK0 0x00000000 /* Select Bank0 */
-#define SMI_SEL_BANK1 0x00001000 /* Select Bank1 */
-#define SMI_SEL_BANK2 0x00002000 /* Select Bank2 */
-#define SMI_SEL_BANK3 0x00003000 /* Select Bank3 */
-
-/* fields in SMI_SR */
-#define SMI_TFF 0x00000100 /* Transfer Finished Flag */
-
-/* Commands */
-#define SMI_READ_ID 0x0000009F /* Read Flash Identification */
-
-/* Timeout in ms */
-#define SMI_CMD_TIMEOUT (100)
-#define SMI_PROBE_TIMEOUT (100)
-#define SMI_MAX_TIMEOUT (3000)
-
-struct stmsmi_flash_bank {
- int probed;
- uint32_t io_base;
- uint32_t bank_num;
- const struct flash_device *dev;
-};
-
-struct stmsmi_target {
- char *name;
- uint32_t tap_idcode;
- uint32_t smi_base;
- uint32_t io_base;
-};
-
-static const struct stmsmi_target target_devices[] = {
- /* name, tap_idcode, smi_base, io_base */
- { "SPEAr3xx/6xx", 0x07926041, 0xf8000000, 0xfc000000 },
- { "STR75x", 0x4f1f0041, 0x80000000, 0x90000000 },
- { NULL, 0, 0, 0 }
-};
-
-FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command)
-{
- struct stmsmi_flash_bank *stmsmi_info;
-
- LOG_DEBUG("%s", __func__);
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- stmsmi_info = malloc(sizeof(struct stmsmi_flash_bank));
- if (stmsmi_info == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- bank->driver_priv = stmsmi_info;
- stmsmi_info->probed = 0;
-
- return ERROR_OK;
-}
-
-/* Poll transmit finished flag */
-/* timeout in ms */
-static int poll_tff(struct target *target, uint32_t io_base, int timeout)
-{
- int64_t endtime;
-
- if (SMI_READ_REG(SMI_SR) & SMI_TFF)
- return ERROR_OK;
-
- endtime = timeval_ms() + timeout;
- do {
- alive_sleep(1);
- if (SMI_READ_REG(SMI_SR) & SMI_TFF)
- return ERROR_OK;
- } while (timeval_ms() < endtime);
-
- LOG_ERROR("Timeout while polling TFF");
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-/* Read the status register of the external SPI flash chip.
- * The operation is triggered by setting SMI_RSR bit.
- * SMI sends the proper SPI command (0x05) and returns value in SMI_SR */
-static int read_status_reg(struct flash_bank *bank, uint32_t *status)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base = stmsmi_info->io_base;
-
- /* clear transmit finished flag */
- SMI_CLEAR_TFF();
-
- /* Read status */
- SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_RSR);
-
- /* Poll transmit finished flag */
- SMI_POLL_TFF(SMI_CMD_TIMEOUT);
-
- /* clear transmit finished flag */
- SMI_CLEAR_TFF();
-
- *status = SMI_READ_REG(SMI_SR) & 0x0000ffff;
-
- /* clean-up SMI_CR2 */
- SMI_WRITE_REG(SMI_CR2, 0); /* AB: Required ? */
-
- 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)
-{
- uint32_t status;
- int retval;
- int64_t endtime;
-
- endtime = timeval_ms() + timeout;
- do {
- /* read flash status register */
- retval = read_status_reg(bank, &status);
- if (retval != ERROR_OK)
- return retval;
-
- if ((status & SPIFLASH_BSY_BIT) == 0)
- return ERROR_OK;
- alive_sleep(1);
- } while (timeval_ms() < endtime);
-
- LOG_ERROR("timeout");
- return ERROR_FAIL;
-}
-
-/* Send "write enable" command to SPI flash chip.
- * The operation is triggered by setting SMI_WE bit, and SMI sends
- * the proper SPI command (0x06) */
-static int smi_write_enable(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base = stmsmi_info->io_base;
- uint32_t status;
- int retval;
-
- /* Enter in HW mode */
- SMI_SET_HW_MODE(); /* AB: is this correct ?*/
-
- /* clear transmit finished flag */
- SMI_CLEAR_TFF();
-
- /* Send write enable command */
- SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_WE);
-
- /* Poll transmit finished flag */
- SMI_POLL_TFF(SMI_CMD_TIMEOUT);
-
- /* read flash status register */
- retval = read_status_reg(bank, &status);
- if (retval != ERROR_OK)
- return retval;
-
- /* Check write enabled */
- if ((status & SPIFLASH_WE_BIT) == 0) {
- LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static uint32_t erase_command(struct stmsmi_flash_bank *stmsmi_info,
- uint32_t offset)
-{
- union {
- uint32_t command;
- uint8_t x[4];
- } cmd;
-
- cmd.x[0] = stmsmi_info->dev->erase_cmd;
- cmd.x[1] = offset >> 16;
- cmd.x[2] = offset >> 8;
- cmd.x[3] = offset;
-
- return cmd.command;
-}
-
-static int smi_erase_sector(struct flash_bank *bank, int sector)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base = stmsmi_info->io_base;
- uint32_t cmd;
- int retval;
-
- retval = smi_write_enable(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* Switch to SW mode to send sector erase command */
- SMI_SET_SW_MODE();
-
- /* clear transmit finished flag */
- SMI_CLEAR_TFF();
-
- /* send SPI command "block erase" */
- cmd = erase_command(stmsmi_info, bank->sectors[sector].offset);
- SMI_WRITE_REG(SMI_TR, cmd);
- SMI_WRITE_REG(SMI_CR2, stmsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4);
-
- /* Poll transmit finished flag */
- SMI_POLL_TFF(SMI_CMD_TIMEOUT);
-
- /* poll WIP for end of self timed Sector Erase cycle */
- retval = wait_till_ready(bank, SMI_MAX_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stmsmi_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base = stmsmi_info->io_base;
- 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 (!(stmsmi_info->probed)) {
- LOG_ERROR("Flash bank not probed");
- return ERROR_FLASH_BANK_NOT_PROBED;
- }
-
- 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 = smi_erase_sector(bank, sector);
- if (retval != ERROR_OK)
- break;
- keep_alive();
- }
-
- /* Switch to HW mode before return to prompt */
- SMI_SET_HW_MODE();
- return retval;
-}
-
-static int stmsmi_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 smi_write_buffer(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t address, uint32_t len)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base = stmsmi_info->io_base;
- int retval;
-
- LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
- __func__, address, len);
-
- retval = smi_write_enable(bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* HW mode, write burst mode */
- SMI_SET_HWWB_MODE();
-
- retval = target_write_buffer(target, address, len, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int stmsmi_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base = stmsmi_info->io_base;
- uint32_t cur_count, page_size, page_offset;
- int sector;
- int retval = 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 > stmsmi_info->dev->size_in_bytes) {
- LOG_WARNING("Write pasts end of flash. Extra data discarded.");
- count = stmsmi_info->dev->size_in_bytes - offset;
- }
-
- /* 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? */
- if ((offset <
- (bank->sectors[sector].offset + bank->sectors[sector].size))
- && ((offset + count - 1) >= bank->sectors[sector].offset)
- && bank->sectors[sector].is_protected) {
- LOG_ERROR("Flash sector %d protected", sector);
- return ERROR_FAIL;
- }
- }
-
- page_size = stmsmi_info->dev->pagesize;
-
- /* unaligned buffer head */
- if (count > 0 && (offset & 3) != 0) {
- cur_count = 4 - (offset & 3);
- if (cur_count > count)
- cur_count = count;
- retval = smi_write_buffer(bank, buffer, bank->base + offset,
- cur_count);
- if (retval != ERROR_OK)
- goto err;
- offset += cur_count;
- buffer += cur_count;
- count -= cur_count;
- }
-
- page_offset = offset % page_size;
- /* central part, aligned words */
- while (count >= 4) {
- /* clip block at page boundary */
- if (page_offset + count > page_size)
- cur_count = page_size - page_offset;
- else
- cur_count = count & ~3;
-
- retval = smi_write_buffer(bank, buffer, bank->base + offset,
- cur_count);
- if (retval != ERROR_OK)
- goto err;
-
- page_offset = 0;
- buffer += cur_count;
- offset += cur_count;
- count -= cur_count;
-
- keep_alive();
- }
-
- /* buffer tail */
- if (count > 0)
- retval = smi_write_buffer(bank, buffer, bank->base + offset, count);
-
-err:
- /* Switch to HW mode before return to prompt */
- SMI_SET_HW_MODE();
- return retval;
-}
-
-/* Return ID of flash device */
-/* On exit, SW mode is kept */
-static int read_flash_id(struct flash_bank *bank, uint32_t *id)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base = stmsmi_info->io_base;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* poll WIP */
- retval = wait_till_ready(bank, SMI_PROBE_TIMEOUT);
- if (retval != ERROR_OK)
- return retval;
-
- /* enter in SW mode */
- SMI_SET_SW_MODE();
-
- /* clear transmit finished flag */
- SMI_CLEAR_TFF();
-
- /* Send SPI command "read ID" */
- SMI_WRITE_REG(SMI_TR, SMI_READ_ID);
- SMI_WRITE_REG(SMI_CR2,
- stmsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1);
-
- /* Poll transmit finished flag */
- SMI_POLL_TFF(SMI_CMD_TIMEOUT);
-
- /* clear transmit finished flag */
- SMI_CLEAR_TFF();
-
- /* read ID from Receive Register */
- *id = SMI_READ_REG(SMI_RR) & 0x00ffffff;
- return ERROR_OK;
-}
-
-static int stmsmi_probe(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- uint32_t io_base;
- struct flash_sector *sectors;
- uint32_t id = 0; /* silence uninitialized warning */
- const struct stmsmi_target *target_device;
- int retval;
-
- if (stmsmi_info->probed)
- free(bank->sectors);
- stmsmi_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 as SMI capable",
- target->tap->idcode);
- return ERROR_FAIL;
- }
-
- switch (bank->base - target_device->smi_base) {
- case 0:
- stmsmi_info->bank_num = SMI_SEL_BANK0;
- break;
- case SMI_BANK_SIZE:
- stmsmi_info->bank_num = SMI_SEL_BANK1;
- break;
- case 2*SMI_BANK_SIZE:
- stmsmi_info->bank_num = SMI_SEL_BANK2;
- break;
- case 3*SMI_BANK_SIZE:
- stmsmi_info->bank_num = SMI_SEL_BANK3;
- break;
- default:
- LOG_ERROR("Invalid SMI base address 0x%" PRIx32, bank->base);
- return ERROR_FAIL;
- }
- io_base = target_device->io_base;
- stmsmi_info->io_base = io_base;
-
- LOG_DEBUG("Valid SMI on device %s at address 0x%" PRIx32,
- target_device->name, bank->base);
-
- /* read and decode flash ID; returns in SW mode */
- retval = read_flash_id(bank, &id);
- SMI_SET_HW_MODE();
- if (retval != ERROR_OK)
- return retval;
-
- stmsmi_info->dev = NULL;
- for (const struct flash_device *p = flash_devices; p->name ; p++)
- if (p->device_id == id) {
- stmsmi_info->dev = p;
- break;
- }
-
- if (!stmsmi_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 ")",
- stmsmi_info->dev->name, stmsmi_info->dev->device_id);
-
- /* Set correct size value */
- bank->size = stmsmi_info->dev->size_in_bytes;
-
- /* create and fill sectors array */
- bank->num_sectors =
- stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize;
- sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- if (sectors == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
-
- for (int sector = 0; sector < bank->num_sectors; sector++) {
- sectors[sector].offset = sector * stmsmi_info->dev->sectorsize;
- sectors[sector].size = stmsmi_info->dev->sectorsize;
- sectors[sector].is_erased = -1;
- sectors[sector].is_protected = 1;
- }
-
- bank->sectors = sectors;
- stmsmi_info->probed = 1;
- return ERROR_OK;
-}
-
-static int stmsmi_auto_probe(struct flash_bank *bank)
-{
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
- if (stmsmi_info->probed)
- return ERROR_OK;
- return stmsmi_probe(bank);
-}
-
-static int stmsmi_protect_check(struct flash_bank *bank)
-{
- /* Nothing to do. Protection is only handled in SW. */
- return ERROR_OK;
-}
-
-static int get_stmsmi_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
-
- if (!(stmsmi_info->probed)) {
- snprintf(buf, buf_size,
- "\nSMI flash bank not probed yet\n");
- return ERROR_OK;
- }
-
- snprintf(buf, buf_size, "\nSMI flash information:\n"
- " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
- stmsmi_info->dev->name, stmsmi_info->dev->device_id);
-
- return ERROR_OK;
-}
-
-struct flash_driver stmsmi_flash = {
- .name = "stmsmi",
- .flash_bank_command = stmsmi_flash_bank_command,
- .erase = stmsmi_erase,
- .protect = stmsmi_protect,
- .write = stmsmi_write,
- .read = default_flash_read,
- .probe = stmsmi_probe,
- .auto_probe = stmsmi_auto_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = stmsmi_protect_check,
- .info = get_stmsmi_info,
-};
diff --git a/src/flash/nor/str7x.c b/src/flash/nor/str7x.c
deleted file mode 100644
index 11179f5..0000000
--- a/src/flash/nor/str7x.c
+++ /dev/null
@@ -1,815 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <target/arm.h>
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-
-/* Flash registers */
-
-#define FLASH_CR0 0x00000000
-#define FLASH_CR1 0x00000004
-#define FLASH_DR0 0x00000008
-#define FLASH_DR1 0x0000000C
-#define FLASH_AR 0x00000010
-#define FLASH_ER 0x00000014
-#define FLASH_NVWPAR 0x0000DFB0
-#define FLASH_NVAPR0 0x0000DFB8
-#define FLASH_NVAPR1 0x0000DFBC
-
-/* FLASH_CR0 register bits */
-
-#define FLASH_WMS 0x80000000
-#define FLASH_SUSP 0x40000000
-#define FLASH_WPG 0x20000000
-#define FLASH_DWPG 0x10000000
-#define FLASH_SER 0x08000000
-#define FLASH_SPR 0x01000000
-#define FLASH_BER 0x04000000
-#define FLASH_MER 0x02000000
-#define FLASH_LOCK 0x00000010
-#define FLASH_BSYA1 0x00000004
-#define FLASH_BSYA0 0x00000002
-
-/* FLASH_CR1 register bits */
-
-#define FLASH_B1S 0x02000000
-#define FLASH_B0S 0x01000000
-#define FLASH_B1F1 0x00020000
-#define FLASH_B1F0 0x00010000
-#define FLASH_B0F7 0x00000080
-#define FLASH_B0F6 0x00000040
-#define FLASH_B0F5 0x00000020
-#define FLASH_B0F4 0x00000010
-#define FLASH_B0F3 0x00000008
-#define FLASH_B0F2 0x00000004
-#define FLASH_B0F1 0x00000002
-#define FLASH_B0F0 0x00000001
-
-/* FLASH_ER register bits */
-
-#define FLASH_WPF 0x00000100
-#define FLASH_RESER 0x00000080
-#define FLASH_SEQER 0x00000040
-#define FLASH_10ER 0x00000008
-#define FLASH_PGER 0x00000004
-#define FLASH_ERER 0x00000002
-#define FLASH_ERR 0x00000001
-
-
-struct str7x_flash_bank {
- uint32_t *sector_bits;
- uint32_t disable_bit;
- uint32_t busy_bits;
- uint32_t register_base;
-};
-
-struct str7x_mem_layout {
- uint32_t sector_start;
- uint32_t sector_size;
- uint32_t sector_bit;
-};
-
-enum str7x_status_codes {
- STR7X_CMD_SUCCESS = 0,
- STR7X_INVALID_COMMAND = 1,
- STR7X_SRC_ADDR_ERROR = 2,
- STR7X_DST_ADDR_ERROR = 3,
- STR7X_SRC_ADDR_NOT_MAPPED = 4,
- STR7X_DST_ADDR_NOT_MAPPED = 5,
- STR7X_COUNT_ERROR = 6,
- STR7X_INVALID_SECTOR = 7,
- STR7X_SECTOR_NOT_BLANK = 8,
- STR7X_SECTOR_NOT_PREPARED = 9,
- STR7X_COMPARE_ERROR = 10,
- STR7X_BUSY = 11
-};
-
-static const struct str7x_mem_layout mem_layout_str7bank0[] = {
- {0x00000000, 0x02000, 0x01},
- {0x00002000, 0x02000, 0x02},
- {0x00004000, 0x02000, 0x04},
- {0x00006000, 0x02000, 0x08},
- {0x00008000, 0x08000, 0x10},
- {0x00010000, 0x10000, 0x20},
- {0x00020000, 0x10000, 0x40},
- {0x00030000, 0x10000, 0x80}
-};
-
-static const struct str7x_mem_layout mem_layout_str7bank1[] = {
- {0x00000000, 0x02000, 0x10000},
- {0x00002000, 0x02000, 0x20000}
-};
-
-static int str7x_get_flash_adr(struct flash_bank *bank, uint32_t reg)
-{
- struct str7x_flash_bank *str7x_info = bank->driver_priv;
- return str7x_info->register_base | reg;
-}
-
-static int str7x_build_block_list(struct flash_bank *bank)
-{
- struct str7x_flash_bank *str7x_info = bank->driver_priv;
-
- int i;
- int num_sectors;
- int b0_sectors = 0, b1_sectors = 0;
-
- switch (bank->size) {
- case 16 * 1024:
- b1_sectors = 2;
- break;
- case 64 * 1024:
- b0_sectors = 5;
- break;
- case 128 * 1024:
- b0_sectors = 6;
- break;
- case 256 * 1024:
- b0_sectors = 8;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- num_sectors = b0_sectors + b1_sectors;
-
- bank->num_sectors = num_sectors;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
- str7x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
-
- num_sectors = 0;
-
- for (i = 0; i < b0_sectors; i++) {
- bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
- bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
- bank->sectors[num_sectors].is_erased = -1;
- /* the reset_init handler marks all the sectors unprotected,
- * matching hardware after reset; keep the driver in sync
- */
- bank->sectors[num_sectors].is_protected = 0;
- str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
- }
-
- for (i = 0; i < b1_sectors; i++) {
- bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
- bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
- bank->sectors[num_sectors].is_erased = -1;
- /* the reset_init handler marks all the sectors unprotected,
- * matching hardware after reset; keep the driver in sync
- */
- bank->sectors[num_sectors].is_protected = 0;
- str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit;
- }
-
- return ERROR_OK;
-}
-
-/* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
- */
-FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
-{
- struct str7x_flash_bank *str7x_info;
-
- if (CMD_ARGC < 7)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- str7x_info = malloc(sizeof(struct str7x_flash_bank));
- bank->driver_priv = str7x_info;
-
- /* set default bits for str71x flash */
- str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA1 | FLASH_BSYA0);
- str7x_info->disable_bit = (1 << 1);
-
- if (strcmp(CMD_ARGV[6], "STR71x") == 0)
- str7x_info->register_base = 0x40100000;
- else if (strcmp(CMD_ARGV[6], "STR73x") == 0) {
- str7x_info->register_base = 0x80100000;
- str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0);
- } else if (strcmp(CMD_ARGV[6], "STR75x") == 0) {
- str7x_info->register_base = 0x20100000;
- str7x_info->disable_bit = (1 << 0);
- } else {
- LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV[6]);
- free(str7x_info);
- return ERROR_FLASH_BANK_INVALID;
- }
-
- str7x_build_block_list(bank);
-
- return ERROR_OK;
-}
-
-/* wait for flash to become idle or report errors.
-
- FIX!!! what's the maximum timeout??? The documentation doesn't
- state any maximum time.... by inspection it seems > 1000ms is to be
- expected.
-
- 10000ms is long enough that it should cover anything, yet not
- quite be equivalent to an infinite loop.
-
- */
-static int str7x_waitbusy(struct flash_bank *bank)
-{
- int err;
- int i;
- struct target *target = bank->target;
- struct str7x_flash_bank *str7x_info = bank->driver_priv;
-
- for (i = 0 ; i < 10000; i++) {
- uint32_t retval;
- err = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
- if (err != ERROR_OK)
- return err;
-
- if ((retval & str7x_info->busy_bits) == 0)
- return ERROR_OK;
-
- alive_sleep(1);
- }
- LOG_ERROR("Timed out waiting for str7x flash");
- return ERROR_FAIL;
-}
-
-
-static int str7x_result(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- uint32_t flash_flags;
-
- int retval;
- retval = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_ER), &flash_flags);
- if (retval != ERROR_OK)
- return retval;
-
- if (flash_flags & FLASH_WPF) {
- LOG_ERROR("str7x hw write protection set");
- retval = ERROR_FAIL;
- }
- if (flash_flags & FLASH_RESER) {
- LOG_ERROR("str7x suspended program erase not resumed");
- retval = ERROR_FAIL;
- }
- if (flash_flags & FLASH_10ER) {
- LOG_ERROR("str7x trying to set bit to 1 when it is already 0");
- retval = ERROR_FAIL;
- }
- if (flash_flags & FLASH_PGER) {
- LOG_ERROR("str7x program error");
- retval = ERROR_FAIL;
- }
- if (flash_flags & FLASH_ERER) {
- LOG_ERROR("str7x erase error");
- retval = ERROR_FAIL;
- }
- if (retval == ERROR_OK) {
- if (flash_flags & FLASH_ERR) {
- /* this should always be set if one of the others are set... */
- LOG_ERROR("str7x write operation failed / bad setup");
- retval = ERROR_FAIL;
- }
- }
-
- return retval;
-}
-
-static int str7x_protect_check(struct flash_bank *bank)
-{
- struct str7x_flash_bank *str7x_info = bank->driver_priv;
- struct target *target = bank->target;
-
- int i;
- uint32_t flash_flags;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int retval;
- retval = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), &flash_flags);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < bank->num_sectors; i++) {
- if (flash_flags & str7x_info->sector_bits[i])
- bank->sectors[i].is_protected = 0;
- else
- bank->sectors[i].is_protected = 1;
- }
-
- return ERROR_OK;
-}
-
-static int str7x_erase(struct flash_bank *bank, int first, int last)
-{
- struct str7x_flash_bank *str7x_info = bank->driver_priv;
- struct target *target = bank->target;
-
- int i;
- uint32_t cmd;
- uint32_t sectors = 0;
- int err;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- for (i = first; i <= last; i++)
- sectors |= str7x_info->sector_bits[i];
-
- LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);
-
- /* clear FLASH_ER register */
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
- if (err != ERROR_OK)
- return err;
-
- cmd = FLASH_SER;
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
- if (err != ERROR_OK)
- return err;
-
- cmd = sectors;
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR1), cmd);
- if (err != ERROR_OK)
- return err;
-
- cmd = FLASH_SER | FLASH_WMS;
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
- if (err != ERROR_OK)
- return err;
-
- err = str7x_waitbusy(bank);
- if (err != ERROR_OK)
- return err;
-
- err = str7x_result(bank);
- if (err != ERROR_OK)
- return err;
-
- for (i = first; i <= last; i++)
- bank->sectors[i].is_erased = 1;
-
- return ERROR_OK;
-}
-
-static int str7x_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct str7x_flash_bank *str7x_info = bank->driver_priv;
- struct target *target = bank->target;
- int i;
- uint32_t cmd;
- uint32_t protect_blocks;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- protect_blocks = 0xFFFFFFFF;
-
- if (set) {
- for (i = first; i <= last; i++)
- protect_blocks &= ~(str7x_info->sector_bits[i]);
- }
-
- /* clear FLASH_ER register */
- int err;
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
- if (err != ERROR_OK)
- return err;
-
- cmd = FLASH_SPR;
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
- if (err != ERROR_OK)
- return err;
-
- cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), cmd);
- if (err != ERROR_OK)
- return err;
-
- cmd = protect_blocks;
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), cmd);
- if (err != ERROR_OK)
- return err;
-
- cmd = FLASH_SPR | FLASH_WMS;
- err = target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
- if (err != ERROR_OK)
- return err;
-
- err = str7x_waitbusy(bank);
- if (err != ERROR_OK)
- return err;
-
- err = str7x_result(bank);
- if (err != ERROR_OK)
- return err;
-
- return ERROR_OK;
-}
-
-static int str7x_write_block(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct str7x_flash_bank *str7x_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t buffer_size = 32768;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[6];
- struct arm_algorithm arm_algo;
- int retval = ERROR_OK;
-
- /* see contib/loaders/flash/str7x.s for src */
-
- static const uint32_t str7x_flash_write_code[] = {
- /* write: */
- 0xe3a04201, /* mov r4, #0x10000000 */
- 0xe5824000, /* str r4, [r2, #0x0] */
- 0xe5821010, /* str r1, [r2, #0x10] */
- 0xe4904004, /* ldr r4, [r0], #4 */
- 0xe5824008, /* str r4, [r2, #0x8] */
- 0xe4904004, /* ldr r4, [r0], #4 */
- 0xe582400c, /* str r4, [r2, #0xc] */
- 0xe3a04209, /* mov r4, #0x90000000 */
- 0xe5824000, /* str r4, [r2, #0x0] */
- /* busy: */
- 0xe5924000, /* ldr r4, [r2, #0x0] */
- 0xe1140005, /* tst r4, r5 */
- 0x1afffffc, /* bne busy */
- 0xe5924014, /* ldr r4, [r2, #0x14] */
- 0xe31400ff, /* tst r4, #0xff */
- 0x03140c01, /* tsteq r4, #0x100 */
- 0x1a000002, /* bne exit */
- 0xe2811008, /* add r1, r1, #0x8 */
- 0xe2533001, /* subs r3, r3, #1 */
- 0x1affffec, /* bne write */
- /* exit: */
- 0xeafffffe, /* b exit */
- };
-
- /* flash write code */
- if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- uint8_t code[sizeof(str7x_flash_write_code)];
- target_buffer_set_u32_array(target, code, ARRAY_SIZE(str7x_flash_write_code),
- str7x_flash_write_code);
- target_write_buffer(target, write_algorithm->address, sizeof(code), code);
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- 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);
- init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
- init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
-
- while (count > 0) {
- uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;
-
- target_write_buffer(target, source->address, thisrun_count * 8, buffer);
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, str7x_get_flash_adr(bank, FLASH_CR0));
- buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
- buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);
-
- retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
- write_algorithm->address,
- write_algorithm->address + (sizeof(str7x_flash_write_code) - 4),
- 10000, &arm_algo);
- if (retval != ERROR_OK)
- break;
-
- if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00) {
- retval = str7x_result(bank);
- break;
- }
-
- buffer += thisrun_count * 8;
- address += thisrun_count * 8;
- count -= thisrun_count;
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
- destroy_reg_param(&reg_params[3]);
- destroy_reg_param(&reg_params[4]);
- destroy_reg_param(&reg_params[5]);
-
- return retval;
-}
-
-static int str7x_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t dwords_remaining = (count / 8);
- uint32_t bytes_remaining = (count & 0x00000007);
- uint32_t address = bank->base + offset;
- uint32_t bytes_written = 0;
- uint32_t cmd;
- int retval;
- uint32_t check_address = offset;
- int i;
-
- 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;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t sec_start = bank->sectors[i].offset;
- uint32_t sec_end = sec_start + bank->sectors[i].size;
-
- /* check if destination falls within the current sector */
- if ((check_address >= sec_start) && (check_address < sec_end)) {
- /* check if destination ends in the current sector */
- if (offset + count < sec_end)
- check_address = offset + count;
- else
- check_address = sec_end;
- }
- }
-
- if (check_address != offset + count)
- return ERROR_FLASH_DST_OUT_OF_BANK;
-
- /* clear FLASH_ER register */
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
-
- /* multiple dwords (8-byte) to be programmed? */
- if (dwords_remaining > 0) {
- /* try using a block write */
- retval = str7x_write_block(bank, buffer, offset, dwords_remaining);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single dword accesses */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
- } else {
- return retval;
- }
- } else {
- buffer += dwords_remaining * 8;
- address += dwords_remaining * 8;
- dwords_remaining = 0;
- }
- }
-
- while (dwords_remaining > 0) {
- /* command */
- cmd = FLASH_DWPG;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
-
- /* address */
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
-
- /* data word 1 */
- target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0),
- 4, 1, buffer + bytes_written);
- bytes_written += 4;
-
- /* data word 2 */
- target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1),
- 4, 1, buffer + bytes_written);
- bytes_written += 4;
-
- /* start programming cycle */
- cmd = FLASH_DWPG | FLASH_WMS;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
-
- int err;
- err = str7x_waitbusy(bank);
- if (err != ERROR_OK)
- return err;
-
- err = str7x_result(bank);
- if (err != ERROR_OK)
- return err;
-
- dwords_remaining--;
- address += 8;
- }
-
- if (bytes_remaining) {
- uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
- /* copy the last remaining bytes into the write buffer */
- memcpy(last_dword, buffer+bytes_written, bytes_remaining);
-
- /* command */
- cmd = FLASH_DWPG;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
-
- /* address */
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
-
- /* data word 1 */
- target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0),
- 4, 1, last_dword);
-
- /* data word 2 */
- target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1),
- 4, 1, last_dword + 4);
-
- /* start programming cycle */
- cmd = FLASH_DWPG | FLASH_WMS;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
-
- int err;
- err = str7x_waitbusy(bank);
- if (err != ERROR_OK)
- return err;
-
- err = str7x_result(bank);
- if (err != ERROR_OK)
- return err;
- }
-
- return ERROR_OK;
-}
-
-static int str7x_probe(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-#if 0
-COMMAND_HANDLER(str7x_handle_part_id_command)
-{
- return ERROR_OK;
-}
-#endif
-
-static int get_str7x_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- /* Setting the write protection on a sector is a permanent change but it
- * can be disabled temporarily. FLASH_NVWPAR reflects the permanent
- * protection state of the sectors, not the temporary.
- */
- snprintf(buf, buf_size, "STR7x flash protection info is only valid after a power cycle, "
- "clearing the protection is only temporary and may not be reflected in the current "
- "info returned.");
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str7x_handle_disable_jtag_command)
-{
- struct target *target = NULL;
- struct str7x_flash_bank *str7x_info = NULL;
-
- uint32_t flash_cmd;
- uint16_t ProtectionLevel = 0;
- uint16_t ProtectionRegs;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str7x_info = bank->driver_priv;
-
- target = bank->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* first we get protection status */
- uint32_t reg;
- target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), &reg);
-
- if (!(reg & str7x_info->disable_bit))
- ProtectionLevel = 1;
-
- target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &reg);
- ProtectionRegs = ~(reg >> 16);
-
- while (((ProtectionRegs) != 0) && (ProtectionLevel < 16)) {
- ProtectionRegs >>= 1;
- ProtectionLevel++;
- }
-
- if (ProtectionLevel == 0) {
- flash_cmd = FLASH_SPR;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
- flash_cmd = FLASH_SPR | FLASH_WMS;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
- } else {
- flash_cmd = FLASH_SPR;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0),
- ~(1 << (15 + ProtectionLevel)));
- flash_cmd = FLASH_SPR | FLASH_WMS;
- target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration str7x_exec_command_handlers[] = {
- {
- .name = "disable_jtag",
- .usage = "<bank>",
- .handler = str7x_handle_disable_jtag_command,
- .mode = COMMAND_EXEC,
- .help = "disable jtag access",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration str7x_command_handlers[] = {
- {
- .name = "str7x",
- .mode = COMMAND_ANY,
- .help = "str7x flash command group",
- .usage = "",
- .chain = str7x_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver str7x_flash = {
- .name = "str7x",
- .commands = str7x_command_handlers,
- .flash_bank_command = str7x_flash_bank_command,
- .erase = str7x_erase,
- .protect = str7x_protect,
- .write = str7x_write,
- .read = default_flash_read,
- .probe = str7x_probe,
- .auto_probe = str7x_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = str7x_protect_check,
- .info = get_str7x_info,
-};
diff --git a/src/flash/nor/str9x.c b/src/flash/nor/str9x.c
deleted file mode 100644
index 3b7ca2a..0000000
--- a/src/flash/nor/str9x.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- *
- * Copyright (C) 2008 by Oyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <target/arm966e.h>
-#include <target/algorithm.h>
-
-/* Flash registers */
-
-#define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */
-#define FLASH_NBBSR 0x54000004 /* Non-Boot Bank Size Register */
-#define FLASH_BBADR 0x5400000C /* Boot Bank Base Address Register */
-#define FLASH_NBBADR 0x54000010 /* Non-Boot Bank Base Address Register */
-#define FLASH_CR 0x54000018 /* Control Register */
-#define FLASH_SR 0x5400001C /* Status Register */
-#define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */
-
-struct str9x_flash_bank {
- uint32_t *sector_bits;
- int variant;
- int bank1;
-};
-
-enum str9x_status_codes {
- STR9X_CMD_SUCCESS = 0,
- STR9X_INVALID_COMMAND = 1,
- STR9X_SRC_ADDR_ERROR = 2,
- STR9X_DST_ADDR_ERROR = 3,
- STR9X_SRC_ADDR_NOT_MAPPED = 4,
- STR9X_DST_ADDR_NOT_MAPPED = 5,
- STR9X_COUNT_ERROR = 6,
- STR9X_INVALID_SECTOR = 7,
- STR9X_SECTOR_NOT_BLANK = 8,
- STR9X_SECTOR_NOT_PREPARED = 9,
- STR9X_COMPARE_ERROR = 10,
- STR9X_BUSY = 11
-};
-
-static uint32_t bank1start = 0x00080000;
-
-static int str9x_build_block_list(struct flash_bank *bank)
-{
- struct str9x_flash_bank *str9x_info = bank->driver_priv;
-
- int i;
- int num_sectors;
- int b0_sectors = 0, b1_sectors = 0;
- uint32_t offset = 0;
-
- /* set if we have large flash str9 */
- str9x_info->variant = 0;
- str9x_info->bank1 = 0;
-
- switch (bank->size) {
- case (256 * 1024):
- b0_sectors = 4;
- break;
- case (512 * 1024):
- b0_sectors = 8;
- break;
- case (1024 * 1024):
- bank1start = 0x00100000;
- str9x_info->variant = 1;
- b0_sectors = 16;
- break;
- case (2048 * 1024):
- bank1start = 0x00200000;
- str9x_info->variant = 1;
- b0_sectors = 32;
- break;
- case (128 * 1024):
- str9x_info->variant = 1;
- str9x_info->bank1 = 1;
- b1_sectors = 8;
- bank1start = bank->base;
- break;
- case (32 * 1024):
- str9x_info->bank1 = 1;
- b1_sectors = 4;
- bank1start = bank->base;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- num_sectors = b0_sectors + b1_sectors;
-
- bank->num_sectors = num_sectors;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
- str9x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
-
- num_sectors = 0;
-
- for (i = 0; i < b0_sectors; i++) {
- bank->sectors[num_sectors].offset = offset;
- bank->sectors[num_sectors].size = 0x10000;
- offset += bank->sectors[i].size;
- bank->sectors[num_sectors].is_erased = -1;
- bank->sectors[num_sectors].is_protected = 1;
- str9x_info->sector_bits[num_sectors++] = (1 << i);
- }
-
- for (i = 0; i < b1_sectors; i++) {
- bank->sectors[num_sectors].offset = offset;
- bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
- offset += bank->sectors[i].size;
- bank->sectors[num_sectors].is_erased = -1;
- bank->sectors[num_sectors].is_protected = 1;
- if (str9x_info->variant)
- str9x_info->sector_bits[num_sectors++] = (1 << i);
- else
- str9x_info->sector_bits[num_sectors++] = (1 << (i + 8));
- }
-
- return ERROR_OK;
-}
-
-/* flash bank str9x <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command)
-{
- struct str9x_flash_bank *str9x_info;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- str9x_info = malloc(sizeof(struct str9x_flash_bank));
- bank->driver_priv = str9x_info;
-
- str9x_build_block_list(bank);
-
- return ERROR_OK;
-}
-
-static int str9x_protect_check(struct flash_bank *bank)
-{
- int retval;
- struct str9x_flash_bank *str9x_info = bank->driver_priv;
- struct target *target = bank->target;
-
- int i;
- uint32_t adr;
- uint32_t status = 0;
- uint16_t hstatus = 0;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* read level one protection */
-
- if (str9x_info->variant) {
- if (str9x_info->bank1) {
- adr = bank1start + 0x18;
- retval = target_write_u16(target, adr, 0x90);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u16(target, adr, &hstatus);
- if (retval != ERROR_OK)
- return retval;
- status = hstatus;
- } else {
- adr = bank1start + 0x14;
- retval = target_write_u16(target, adr, 0x90);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, adr, &status);
- if (retval != ERROR_OK)
- return retval;
- }
- } else {
- adr = bank1start + 0x10;
- retval = target_write_u16(target, adr, 0x90);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u16(target, adr, &hstatus);
- if (retval != ERROR_OK)
- return retval;
- status = hstatus;
- }
-
- /* read array command */
- retval = target_write_u16(target, adr, 0xFF);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < bank->num_sectors; i++) {
- if (status & str9x_info->sector_bits[i])
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- }
-
- return ERROR_OK;
-}
-
-static int str9x_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- int i;
- uint32_t adr;
- uint8_t status;
- uint8_t erase_cmd;
- int total_timeout;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Check if we can erase whole bank */
- if ((first == 0) && (last == (bank->num_sectors - 1))) {
- /* Optimize to run erase bank command instead of sector */
- erase_cmd = 0x80;
- /* Add timeout duration since erase bank takes more time */
- total_timeout = 1000 * bank->num_sectors;
- } else {
- /* Erase sector command */
- erase_cmd = 0x20;
- total_timeout = 1000;
- }
-
- /* this is so the compiler can *know* */
- assert(total_timeout > 0);
-
- for (i = first; i <= last; i++) {
- int retval;
- adr = bank->base + bank->sectors[i].offset;
-
- /* erase sectors or block */
- retval = target_write_u16(target, adr, erase_cmd);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u16(target, adr, 0xD0);
- if (retval != ERROR_OK)
- return retval;
-
- /* get status */
- retval = target_write_u16(target, adr, 0x70);
- if (retval != ERROR_OK)
- return retval;
-
- int timeout;
- for (timeout = 0; timeout < total_timeout; timeout++) {
- retval = target_read_u8(target, adr, &status);
- if (retval != ERROR_OK)
- return retval;
- if (status & 0x80)
- break;
- alive_sleep(1);
- }
- if (timeout == total_timeout) {
- LOG_ERROR("erase timed out");
- return ERROR_FAIL;
- }
-
- /* clear status, also clear read array */
- retval = target_write_u16(target, adr, 0x50);
- if (retval != ERROR_OK)
- return retval;
-
- /* read array command */
- retval = target_write_u16(target, adr, 0xFF);
- if (retval != ERROR_OK)
- return retval;
-
- if (status & 0x22) {
- LOG_ERROR("error erasing flash bank, status: 0x%x", status);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* If we ran erase bank command, we are finished */
- if (erase_cmd == 0x80)
- break;
- }
-
- for (i = first; i <= last; i++)
- bank->sectors[i].is_erased = 1;
-
- return ERROR_OK;
-}
-
-static int str9x_protect(struct flash_bank *bank,
- int set, int first, int last)
-{
- struct target *target = bank->target;
- int i;
- uint32_t adr;
- uint8_t status;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- for (i = first; i <= last; i++) {
- /* Level One Protection */
-
- adr = bank->base + bank->sectors[i].offset;
-
- target_write_u16(target, adr, 0x60);
- if (set)
- target_write_u16(target, adr, 0x01);
- else
- target_write_u16(target, adr, 0xD0);
-
- /* query status */
- target_read_u8(target, adr, &status);
-
- /* clear status, also clear read array */
- target_write_u16(target, adr, 0x50);
-
- /* read array command */
- target_write_u16(target, adr, 0xFF);
- }
-
- return ERROR_OK;
-}
-
-static int str9x_write_block(struct flash_bank *bank,
- const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t buffer_size = 32768;
- struct working_area *write_algorithm;
- struct working_area *source;
- uint32_t address = bank->base + offset;
- struct reg_param reg_params[4];
- struct arm_algorithm arm_algo;
- int retval = ERROR_OK;
-
- /* see contib/loaders/flash/str9x.s for src */
-
- static const uint32_t str9x_flash_write_code[] = {
- /* write: */
- 0xe3c14003, /* bic r4, r1, #3 */
- 0xe3a03040, /* mov r3, #0x40 */
- 0xe1c430b0, /* strh r3, [r4, #0] */
- 0xe0d030b2, /* ldrh r3, [r0], #2 */
- 0xe0c130b2, /* strh r3, [r1], #2 */
- 0xe3a03070, /* mov r3, #0x70 */
- 0xe1c430b0, /* strh r3, [r4, #0] */
- /* busy: */
- 0xe5d43000, /* ldrb r3, [r4, #0] */
- 0xe3130080, /* tst r3, #0x80 */
- 0x0afffffc, /* beq busy */
- 0xe3a05050, /* mov r5, #0x50 */
- 0xe1c450b0, /* strh r5, [r4, #0] */
- 0xe3a050ff, /* mov r5, #0xFF */
- 0xe1c450b0, /* strh r5, [r4, #0] */
- 0xe3130012, /* tst r3, #0x12 */
- 0x1a000001, /* bne exit */
- 0xe2522001, /* subs r2, r2, #1 */
- 0x1affffed, /* bne write */
- /* exit: */
- 0xe1200070, /* bkpt #0 */
- };
-
- /* flash write code */
- if (target_alloc_working_area(target, sizeof(str9x_flash_write_code),
- &write_algorithm) != ERROR_OK) {
- LOG_WARNING("no working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- uint8_t code[sizeof(str9x_flash_write_code)];
- target_buffer_set_u32_array(target, code, ARRAY_SIZE(str9x_flash_write_code),
- str9x_flash_write_code);
- target_write_buffer(target, write_algorithm->address, sizeof(code), code);
-
- /* memory buffer */
- while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
- buffer_size /= 2;
- if (buffer_size <= 256) {
- /* we already allocated the writing code, but failed to get a
- * buffer, free the algorithm */
- target_free_working_area(target, write_algorithm);
-
- LOG_WARNING("no large enough working area available, can't do block memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- 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_IN);
-
- while (count > 0) {
- uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
-
- target_write_buffer(target, source->address, thisrun_count * 2, buffer);
-
- buf_set_u32(reg_params[0].value, 0, 32, source->address);
- buf_set_u32(reg_params[1].value, 0, 32, address);
- buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
-
- retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
- write_algorithm->address,
- 0, 10000, &arm_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("error executing str9x flash write algorithm");
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80) {
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- buffer += thisrun_count * 2;
- address += thisrun_count * 2;
- count -= thisrun_count;
- }
-
- target_free_working_area(target, source);
- target_free_working_area(target, write_algorithm);
-
- 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 retval;
-}
-
-static int str9x_write(struct flash_bank *bank,
- const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t words_remaining = (count / 2);
- uint32_t bytes_remaining = (count & 0x00000001);
- uint32_t address = bank->base + offset;
- uint32_t bytes_written = 0;
- uint8_t status;
- int retval;
- uint32_t check_address = offset;
- uint32_t bank_adr;
- int i;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (offset & 0x1) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t sec_start = bank->sectors[i].offset;
- uint32_t sec_end = sec_start + bank->sectors[i].size;
-
- /* check if destination falls within the current sector */
- if ((check_address >= sec_start) && (check_address < sec_end)) {
- /* check if destination ends in the current sector */
- if (offset + count < sec_end)
- check_address = offset + count;
- else
- check_address = sec_end;
- }
- }
-
- if (check_address != offset + count)
- return ERROR_FLASH_DST_OUT_OF_BANK;
-
- /* multiple half words (2-byte) to be programmed? */
- if (words_remaining > 0) {
- /* try using a block write */
- retval = str9x_write_block(bank, buffer, offset, words_remaining);
- if (retval != ERROR_OK) {
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- /* if block write failed (no sufficient working area),
- * we use normal (slow) single dword accesses */
- LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
- } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
- LOG_ERROR("flash writing failed");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- } else {
- buffer += words_remaining * 2;
- address += words_remaining * 2;
- words_remaining = 0;
- }
- }
-
- while (words_remaining > 0) {
- bank_adr = address & ~0x03;
-
- /* write data command */
- target_write_u16(target, bank_adr, 0x40);
- target_write_memory(target, address, 2, 1, buffer + bytes_written);
-
- /* get status command */
- target_write_u16(target, bank_adr, 0x70);
-
- int timeout;
- for (timeout = 0; timeout < 1000; timeout++) {
- target_read_u8(target, bank_adr, &status);
- if (status & 0x80)
- break;
- alive_sleep(1);
- }
- if (timeout == 1000) {
- LOG_ERROR("write timed out");
- return ERROR_FAIL;
- }
-
- /* clear status reg and read array */
- target_write_u16(target, bank_adr, 0x50);
- target_write_u16(target, bank_adr, 0xFF);
-
- if (status & 0x10)
- return ERROR_FLASH_OPERATION_FAILED;
- else if (status & 0x02)
- return ERROR_FLASH_OPERATION_FAILED;
-
- bytes_written += 2;
- words_remaining--;
- address += 2;
- }
-
- if (bytes_remaining) {
- uint8_t last_halfword[2] = {0xff, 0xff};
-
- /* copy the last remaining bytes into the write buffer */
- memcpy(last_halfword, buffer+bytes_written, bytes_remaining);
-
- bank_adr = address & ~0x03;
-
- /* write data command */
- target_write_u16(target, bank_adr, 0x40);
- target_write_memory(target, address, 2, 1, last_halfword);
-
- /* query status command */
- target_write_u16(target, bank_adr, 0x70);
-
- int timeout;
- for (timeout = 0; timeout < 1000; timeout++) {
- target_read_u8(target, bank_adr, &status);
- if (status & 0x80)
- break;
- alive_sleep(1);
- }
- if (timeout == 1000) {
- LOG_ERROR("write timed out");
- return ERROR_FAIL;
- }
-
- /* clear status reg and read array */
- target_write_u16(target, bank_adr, 0x50);
- target_write_u16(target, bank_adr, 0xFF);
-
- if (status & 0x10)
- return ERROR_FLASH_OPERATION_FAILED;
- else if (status & 0x02)
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int str9x_probe(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-#if 0
-COMMAND_HANDLER(str9x_handle_part_id_command)
-{
- return ERROR_OK;
-}
-#endif
-
-COMMAND_HANDLER(str9x_handle_flash_config_command)
-{
- struct target *target = NULL;
-
- if (CMD_ARGC < 5)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- uint32_t bbsr, nbbsr, bbadr, nbbadr;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], bbsr);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], nbbsr);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], bbadr);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], nbbadr);
-
- target = bank->target;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* config flash controller */
- target_write_u32(target, FLASH_BBSR, bbsr);
- target_write_u32(target, FLASH_NBBSR, nbbsr);
- target_write_u32(target, FLASH_BBADR, bbadr >> 2);
- target_write_u32(target, FLASH_NBBADR, nbbadr >> 2);
-
- /* set bit 18 instruction TCM order as per flash programming manual */
- arm966e_write_cp15(target, 62, 0x40000);
-
- /* enable flash bank 1 */
- target_write_u32(target, FLASH_CR, 0x18);
- return ERROR_OK;
-}
-
-static const struct command_registration str9x_config_command_handlers[] = {
- {
- .name = "flash_config",
- .handler = str9x_handle_flash_config_command,
- .mode = COMMAND_EXEC,
- .help = "Configure str9x flash controller, prior to "
- "programming the flash.",
- .usage = "bank_id BBSR NBBSR BBADR NBBADR",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration str9x_command_handlers[] = {
- {
- .name = "str9x",
- .mode = COMMAND_ANY,
- .help = "str9x flash command group",
- .usage = "",
- .chain = str9x_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver str9x_flash = {
- .name = "str9x",
- .commands = str9x_command_handlers,
- .flash_bank_command = str9x_flash_bank_command,
- .erase = str9x_erase,
- .protect = str9x_protect,
- .write = str9x_write,
- .read = default_flash_read,
- .probe = str9x_probe,
- .auto_probe = str9x_probe,
- .erase_check = default_flash_blank_check,
- .protect_check = str9x_protect_check,
-};
diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c
deleted file mode 100644
index eb391e8..0000000
--- a/src/flash/nor/str9xpec.c
+++ /dev/null
@@ -1,1210 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <target/arm7_9_common.h>
-
-/* ISC commands */
-
-#define ISC_IDCODE 0xFE
-#define ISC_MFG_READ 0x4C
-#define ISC_CONFIGURATION 0x07
-#define ISC_ENABLE 0x0C
-#define ISC_DISABLE 0x0F
-#define ISC_NOOP 0x10
-#define ISC_ADDRESS_SHIFT 0x11
-#define ISC_CLR_STATUS 0x13
-#define ISC_PROGRAM 0x20
-#define ISC_PROGRAM_SECURITY 0x22
-#define ISC_PROGRAM_UC 0x23
-#define ISC_ERASE 0x30
-#define ISC_READ 0x50
-#define ISC_BLANK_CHECK 0x60
-
-/* ISC_DEFAULT bit definitions */
-
-#define ISC_STATUS_SECURITY 0x40
-#define ISC_STATUS_INT_ERROR 0x30
-#define ISC_STATUS_MODE 0x08
-#define ISC_STATUS_BUSY 0x04
-#define ISC_STATUS_ERROR 0x03
-
-/* Option bytes definitions */
-
-#define STR9XPEC_OPT_CSMAPBIT 48
-#define STR9XPEC_OPT_LVDTHRESBIT 49
-#define STR9XPEC_OPT_LVDSELBIT 50
-#define STR9XPEC_OPT_LVDWARNBIT 51
-#define STR9XPEC_OPT_OTPBIT 63
-
-enum str9xpec_status_codes {
- STR9XPEC_INVALID_COMMAND = 1,
- STR9XPEC_ISC_SUCCESS = 2,
- STR9XPEC_ISC_DISABLED = 3,
- STR9XPEC_ISC_INTFAIL = 32,
-};
-
-struct str9xpec_flash_controller {
- struct jtag_tap *tap;
- uint32_t *sector_bits;
- int chain_pos;
- int isc_enable;
- uint8_t options[8];
-};
-
-static int str9xpec_erase_area(struct flash_bank *bank, int first, int last);
-static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector);
-static int str9xpec_write_options(struct flash_bank *bank);
-
-static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state)
-{
- if (tap == NULL)
- return ERROR_TARGET_INVALID;
-
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
- struct scan_field field;
-
- field.num_bits = tap->ir_length;
- void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_instr);
- field.in_value = NULL;
-
- jtag_add_ir_scan(tap, &field, end_state);
-
- free(t);
- }
-
- return ERROR_OK;
-}
-
-static uint8_t str9xpec_isc_status(struct jtag_tap *tap)
-{
- struct scan_field field;
- uint8_t status;
-
- if (str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE) != ERROR_OK)
- return ISC_STATUS_ERROR;
-
- field.num_bits = 8;
- field.out_value = NULL;
- field.in_value = &status;
-
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- jtag_execute_queue();
-
- LOG_DEBUG("status: 0x%2.2x", status);
-
- if (status & ISC_STATUS_SECURITY)
- LOG_INFO("Device Security Bit Set");
-
- return status;
-}
-
-static int str9xpec_isc_enable(struct flash_bank *bank)
-{
- uint8_t status;
- struct jtag_tap *tap;
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- tap = str9xpec_info->tap;
-
- if (str9xpec_info->isc_enable)
- return ERROR_OK;
-
- /* enter isc mode */
- if (str9xpec_set_instr(tap, ISC_ENABLE, TAP_IDLE) != ERROR_OK)
- return ERROR_TARGET_INVALID;
-
- /* check ISC status */
- status = str9xpec_isc_status(tap);
- if (status & ISC_STATUS_MODE) {
- /* we have entered isc mode */
- str9xpec_info->isc_enable = 1;
- LOG_DEBUG("ISC_MODE Enabled");
- }
-
- return ERROR_OK;
-}
-
-static int str9xpec_isc_disable(struct flash_bank *bank)
-{
- uint8_t status;
- struct jtag_tap *tap;
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- tap = str9xpec_info->tap;
-
- if (!str9xpec_info->isc_enable)
- return ERROR_OK;
-
- if (str9xpec_set_instr(tap, ISC_DISABLE, TAP_IDLE) != ERROR_OK)
- return ERROR_TARGET_INVALID;
-
- /* delay to handle aborts */
- jtag_add_sleep(50);
-
- /* check ISC status */
- status = str9xpec_isc_status(tap);
- if (!(status & ISC_STATUS_MODE)) {
- /* we have left isc mode */
- str9xpec_info->isc_enable = 0;
- LOG_DEBUG("ISC_MODE Disabled");
- }
-
- return ERROR_OK;
-}
-
-static int str9xpec_read_config(struct flash_bank *bank)
-{
- struct scan_field field;
- uint8_t status;
- struct jtag_tap *tap;
-
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- tap = str9xpec_info->tap;
-
- LOG_DEBUG("ISC_CONFIGURATION");
-
- /* execute ISC_CONFIGURATION command */
- str9xpec_set_instr(tap, ISC_CONFIGURATION, TAP_IRPAUSE);
-
- field.num_bits = 64;
- field.out_value = NULL;
- field.in_value = str9xpec_info->options;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- jtag_execute_queue();
-
- status = str9xpec_isc_status(tap);
-
- return status;
-}
-
-static int str9xpec_build_block_list(struct flash_bank *bank)
-{
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- int i;
- int num_sectors;
- int b0_sectors = 0, b1_sectors = 0;
- uint32_t offset = 0;
- int b1_size = 0x2000;
-
- switch (bank->size) {
- case (256 * 1024):
- b0_sectors = 4;
- break;
- case (512 * 1024):
- b0_sectors = 8;
- break;
- case (1024 * 1024):
- b0_sectors = 16;
- break;
- case (2048 * 1024):
- b0_sectors = 32;
- break;
- case (128 * 1024):
- b1_size = 0x4000;
- b1_sectors = 8;
- break;
- case (32 * 1024):
- b1_sectors = 4;
- break;
- default:
- LOG_ERROR("BUG: unknown bank->size encountered");
- exit(-1);
- }
-
- num_sectors = b0_sectors + b1_sectors;
-
- bank->num_sectors = num_sectors;
- bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
- str9xpec_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
-
- num_sectors = 0;
-
- for (i = 0; i < b0_sectors; i++) {
- bank->sectors[num_sectors].offset = offset;
- bank->sectors[num_sectors].size = 0x10000;
- offset += bank->sectors[i].size;
- bank->sectors[num_sectors].is_erased = -1;
- bank->sectors[num_sectors].is_protected = 1;
- str9xpec_info->sector_bits[num_sectors++] = i;
- }
-
- for (i = 0; i < b1_sectors; i++) {
- bank->sectors[num_sectors].offset = offset;
- bank->sectors[num_sectors].size = b1_size;
- offset += bank->sectors[i].size;
- bank->sectors[num_sectors].is_erased = -1;
- bank->sectors[num_sectors].is_protected = 1;
- str9xpec_info->sector_bits[num_sectors++] = i + 32;
- }
-
- return ERROR_OK;
-}
-
-/* flash bank str9x <base> <size> 0 0 <target#>
- */
-FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command)
-{
- struct str9xpec_flash_controller *str9xpec_info;
- struct arm *arm = NULL;
- struct arm7_9_common *arm7_9 = NULL;
- struct arm_jtag *jtag_info = NULL;
-
- if (CMD_ARGC < 6)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller));
- bank->driver_priv = str9xpec_info;
-
- /* REVISIT verify that the jtag position of flash controller is
- * right after *THIS* core, which must be a STR9xx core ...
- */
- arm = bank->target->arch_info;
- arm7_9 = arm->arch_info;
- jtag_info = &arm7_9->jtag_info;
-
- /* The core is the next tap after the flash controller in the chain */
- str9xpec_info->tap = jtag_tap_by_position(jtag_info->tap->abs_chain_position - 1);
- str9xpec_info->isc_enable = 0;
-
- str9xpec_build_block_list(bank);
-
- /* clear option byte register */
- buf_set_u32(str9xpec_info->options, 0, 64, 0);
-
- return ERROR_OK;
-}
-
-static int str9xpec_blank_check(struct flash_bank *bank, int first, int last)
-{
- struct scan_field field;
- uint8_t status;
- struct jtag_tap *tap;
- int i;
- uint8_t *buffer = NULL;
-
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- tap = str9xpec_info->tap;
-
- if (!str9xpec_info->isc_enable)
- str9xpec_isc_enable(bank);
-
- if (!str9xpec_info->isc_enable)
- return ERROR_FLASH_OPERATION_FAILED;
-
- buffer = calloc(DIV_ROUND_UP(64, 8), 1);
-
- LOG_DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
-
- for (i = first; i <= last; i++)
- buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
-
- /* execute ISC_BLANK_CHECK command */
- str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE);
-
- field.num_bits = 64;
- field.out_value = buffer;
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- jtag_add_sleep(40000);
-
- /* read blank check result */
- field.num_bits = 64;
- field.out_value = NULL;
- field.in_value = buffer;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
- jtag_execute_queue();
-
- status = str9xpec_isc_status(tap);
-
- for (i = first; i <= last; i++) {
- if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
- bank->sectors[i].is_erased = 0;
- else
- bank->sectors[i].is_erased = 1;
- }
-
- free(buffer);
-
- str9xpec_isc_disable(bank);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
- return ERROR_OK;
-}
-
-static int str9xpec_protect_check(struct flash_bank *bank)
-{
- uint8_t status;
- int i;
-
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- status = str9xpec_read_config(bank);
-
- for (i = 0; i < bank->num_sectors; i++) {
- if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
- bank->sectors[i].is_protected = 1;
- else
- bank->sectors[i].is_protected = 0;
- }
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
- return ERROR_OK;
-}
-
-static int str9xpec_erase_area(struct flash_bank *bank, int first, int last)
-{
- struct scan_field field;
- uint8_t status;
- struct jtag_tap *tap;
- int i;
- uint8_t *buffer = NULL;
-
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- tap = str9xpec_info->tap;
-
- if (!str9xpec_info->isc_enable)
- str9xpec_isc_enable(bank);
-
- if (!str9xpec_info->isc_enable)
- return ISC_STATUS_ERROR;
-
- buffer = calloc(DIV_ROUND_UP(64, 8), 1);
-
- LOG_DEBUG("erase: first_bank: %i, last_bank: %i", first, last);
-
- /* last bank: 0xFF signals a full erase (unlock complete device) */
- /* last bank: 0xFE signals a option byte erase */
- if (last == 0xFF) {
- for (i = 0; i < 64; i++)
- buf_set_u32(buffer, i, 1, 1);
- } else if (last == 0xFE)
- buf_set_u32(buffer, 49, 1, 1);
- else {
- for (i = first; i <= last; i++)
- buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
- }
-
- LOG_DEBUG("ISC_ERASE");
-
- /* execute ISC_ERASE command */
- str9xpec_set_instr(tap, ISC_ERASE, TAP_IRPAUSE);
-
- field.num_bits = 64;
- field.out_value = buffer;
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- jtag_execute_queue();
-
- jtag_add_sleep(10);
-
- /* wait for erase completion */
- while (!((status = str9xpec_isc_status(tap)) & ISC_STATUS_BUSY))
- alive_sleep(1);
-
- free(buffer);
-
- str9xpec_isc_disable(bank);
-
- return status;
-}
-
-static int str9xpec_erase(struct flash_bank *bank, int first, int last)
-{
- int status;
-
- status = str9xpec_erase_area(bank, first, last);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- return ERROR_OK;
-}
-
-static int str9xpec_lock_device(struct flash_bank *bank)
-{
- struct scan_field field;
- uint8_t status;
- struct jtag_tap *tap;
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- str9xpec_info = bank->driver_priv;
- tap = str9xpec_info->tap;
-
- if (!str9xpec_info->isc_enable)
- str9xpec_isc_enable(bank);
-
- if (!str9xpec_info->isc_enable)
- return ISC_STATUS_ERROR;
-
- /* set security address */
- str9xpec_set_address(bank, 0x80);
-
- /* execute ISC_PROGRAM command */
- str9xpec_set_instr(tap, ISC_PROGRAM_SECURITY, TAP_IDLE);
-
- str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
-
- do {
- field.num_bits = 8;
- field.out_value = NULL;
- field.in_value = &status;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- jtag_execute_queue();
-
- } while (!(status & ISC_STATUS_BUSY));
-
- str9xpec_isc_disable(bank);
-
- return status;
-}
-
-static int str9xpec_unlock_device(struct flash_bank *bank)
-{
- uint8_t status;
-
- status = str9xpec_erase_area(bank, 0, 255);
-
- return status;
-}
-
-static int str9xpec_protect(struct flash_bank *bank, int set, int first, int last)
-{
- uint8_t status;
- int i;
-
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- status = str9xpec_read_config(bank);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- LOG_DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
-
- /* last bank: 0xFF signals a full device protect */
- if (last == 0xFF) {
- if (set)
- status = str9xpec_lock_device(bank);
- else {
- /* perform full erase to unlock device */
- status = str9xpec_unlock_device(bank);
- }
- } else {
- for (i = first; i <= last; i++) {
- if (set)
- buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
- else
- buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);
- }
-
- status = str9xpec_write_options(bank);
- }
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- return ERROR_OK;
-}
-
-static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector)
-{
- struct jtag_tap *tap;
- struct scan_field field;
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
-
- tap = str9xpec_info->tap;
-
- /* set flash controller address */
- str9xpec_set_instr(tap, ISC_ADDRESS_SHIFT, TAP_IRPAUSE);
-
- field.num_bits = 8;
- field.out_value = &sector;
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
-
- return ERROR_OK;
-}
-
-static int str9xpec_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv;
- uint32_t dwords_remaining = (count / 8);
- uint32_t bytes_remaining = (count & 0x00000007);
- uint32_t bytes_written = 0;
- uint8_t status;
- uint32_t check_address = offset;
- struct jtag_tap *tap;
- struct scan_field field;
- uint8_t *scanbuf;
- int i;
- int first_sector = 0;
- int last_sector = 0;
-
- tap = str9xpec_info->tap;
-
- if (!str9xpec_info->isc_enable)
- str9xpec_isc_enable(bank);
-
- if (!str9xpec_info->isc_enable)
- return ERROR_FLASH_OPERATION_FAILED;
-
- if (offset & 0x7) {
- LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t sec_start = bank->sectors[i].offset;
- uint32_t sec_end = sec_start + bank->sectors[i].size;
-
- /* check if destination falls within the current sector */
- if ((check_address >= sec_start) && (check_address < sec_end)) {
- /* check if destination ends in the current sector */
- if (offset + count < sec_end)
- check_address = offset + count;
- else
- check_address = sec_end;
- }
-
- if ((offset >= sec_start) && (offset < sec_end))
- first_sector = i;
-
- if ((offset + count >= sec_start) && (offset + count < sec_end))
- last_sector = i;
- }
-
- if (check_address != offset + count)
- return ERROR_FLASH_DST_OUT_OF_BANK;
-
- LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
-
- scanbuf = calloc(DIV_ROUND_UP(64, 8), 1);
-
- LOG_DEBUG("ISC_PROGRAM");
-
- for (i = first_sector; i <= last_sector; i++) {
- str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
-
- dwords_remaining = dwords_remaining < (bank->sectors[i].size/8)
- ? dwords_remaining : (bank->sectors[i].size/8);
-
- while (dwords_remaining > 0) {
- str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
-
- field.num_bits = 64;
- field.out_value = (buffer + bytes_written);
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- /* small delay before polling */
- jtag_add_sleep(50);
-
- str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
-
- do {
- field.num_bits = 8;
- field.out_value = NULL;
- field.in_value = scanbuf;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
- jtag_execute_queue();
-
- status = buf_get_u32(scanbuf, 0, 8);
-
- } while (!(status & ISC_STATUS_BUSY));
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
- return ERROR_FLASH_OPERATION_FAILED; */
-
- dwords_remaining--;
- bytes_written += 8;
- }
- }
-
- if (bytes_remaining) {
- uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
- /* copy the last remaining bytes into the write buffer */
- memcpy(last_dword, buffer+bytes_written, bytes_remaining);
-
- str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
-
- field.num_bits = 64;
- field.out_value = last_dword;
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- /* small delay before polling */
- jtag_add_sleep(50);
-
- str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
-
- do {
- field.num_bits = 8;
- field.out_value = NULL;
- field.in_value = scanbuf;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
- jtag_execute_queue();
-
- status = buf_get_u32(scanbuf, 0, 8);
-
- } while (!(status & ISC_STATUS_BUSY));
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
- return ERROR_FLASH_OPERATION_FAILED; */
- }
-
- free(scanbuf);
-
- str9xpec_isc_disable(bank);
-
- return ERROR_OK;
-}
-
-static int str9xpec_probe(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_part_id_command)
-{
- struct scan_field field;
- uint8_t *buffer = NULL;
- struct jtag_tap *tap;
- uint32_t idcode;
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
- tap = str9xpec_info->tap;
-
- buffer = calloc(DIV_ROUND_UP(32, 8), 1);
-
- str9xpec_set_instr(tap, ISC_IDCODE, TAP_IRPAUSE);
-
- field.num_bits = 32;
- field.out_value = NULL;
- field.in_value = buffer;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- jtag_execute_queue();
-
- idcode = buf_get_u32(buffer, 0, 32);
-
- command_print(CMD_CTX, "str9xpec part id: 0x%8.8" PRIx32 "", idcode);
-
- free(buffer);
-
- return ERROR_OK;
-}
-
-static int str9xpec_erase_check(struct flash_bank *bank)
-{
- return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_options_read_command)
-{
- uint8_t status;
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
-
- status = str9xpec_read_config(bank);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* boot bank */
- if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
- command_print(CMD_CTX, "CS Map: bank1");
- else
- command_print(CMD_CTX, "CS Map: bank0");
-
- /* OTP lock */
- if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
- command_print(CMD_CTX, "OTP Lock: OTP Locked");
- else
- command_print(CMD_CTX, "OTP Lock: OTP Unlocked");
-
- /* LVD Threshold */
- if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
- command_print(CMD_CTX, "LVD Threshold: 2.7v");
- else
- command_print(CMD_CTX, "LVD Threshold: 2.4v");
-
- /* LVD reset warning */
- if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
- command_print(CMD_CTX, "LVD Reset Warning: VDD or VDDQ Inputs");
- else
- command_print(CMD_CTX, "LVD Reset Warning: VDD Input Only");
-
- /* LVD reset select */
- if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
- command_print(CMD_CTX, "LVD Reset Selection: VDD or VDDQ Inputs");
- else
- command_print(CMD_CTX, "LVD Reset Selection: VDD Input Only");
-
- return ERROR_OK;
-}
-
-static int str9xpec_write_options(struct flash_bank *bank)
-{
- struct scan_field field;
- uint8_t status;
- struct jtag_tap *tap;
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- str9xpec_info = bank->driver_priv;
- tap = str9xpec_info->tap;
-
- /* erase config options first */
- status = str9xpec_erase_area(bank, 0xFE, 0xFE);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return status;
-
- if (!str9xpec_info->isc_enable)
- str9xpec_isc_enable(bank);
-
- if (!str9xpec_info->isc_enable)
- return ISC_STATUS_ERROR;
-
- /* according to data 64th bit has to be set */
- buf_set_u32(str9xpec_info->options, 63, 1, 1);
-
- /* set option byte address */
- str9xpec_set_address(bank, 0x50);
-
- /* execute ISC_PROGRAM command */
- str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE);
-
- field.num_bits = 64;
- field.out_value = str9xpec_info->options;
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- /* small delay before polling */
- jtag_add_sleep(50);
-
- str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE);
-
- do {
- field.num_bits = 8;
- field.out_value = NULL;
- field.in_value = &status;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE);
- jtag_execute_queue();
-
- } while (!(status & ISC_STATUS_BUSY));
-
- str9xpec_isc_disable(bank);
-
- return status;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
-{
- uint8_t status;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- status = str9xpec_write_options(bank);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- command_print(CMD_CTX, "str9xpec write options complete.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command)
-{
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
-
- if (strcmp(CMD_ARGV[1], "bank1") == 0)
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
- else
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command)
-{
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
-
- if (strcmp(CMD_ARGV[1], "2.7v") == 0)
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
- else
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command)
-{
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
-
- if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
- else
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command)
-{
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
-
- if (strcmp(CMD_ARGV[1], "vdd_vddq") == 0)
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
- else
- buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_lock_command)
-{
- uint8_t status;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- status = str9xpec_lock_device(bank);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
-{
- uint8_t status;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- status = str9xpec_unlock_device(bank);
-
- if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
- return ERROR_FLASH_OPERATION_FAILED;
-
- command_print(CMD_CTX, "str9xpec unlocked.\n"
- "INFO: a reset or power cycle is required "
- "for the new settings to take effect.");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command)
-{
- struct jtag_tap *tap0;
- struct jtag_tap *tap1;
- struct jtag_tap *tap2;
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
-
- /* remove arm core from chain - enter turbo mode */
- tap0 = str9xpec_info->tap;
- if (tap0 == NULL) {
- /* things are *WRONG* */
- command_print(CMD_CTX, "**STR9FLASH** (tap0) invalid chain?");
- return ERROR_FAIL;
- }
- tap1 = tap0->next_tap;
- if (tap1 == NULL) {
- /* things are *WRONG* */
- command_print(CMD_CTX, "**STR9FLASH** (tap1) invalid chain?");
- return ERROR_FAIL;
- }
- tap2 = tap1->next_tap;
- if (tap2 == NULL) {
- /* things are *WRONG* */
- command_print(CMD_CTX, "**STR9FLASH** (tap2) invalid chain?");
- return ERROR_FAIL;
- }
-
- /* enable turbo mode - TURBO-PROG-ENABLE */
- str9xpec_set_instr(tap2, 0xD, TAP_IDLE);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* modify scan chain - str9 core has been removed */
- tap1->enabled = 0;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command)
-{
- struct jtag_tap *tap;
- struct str9xpec_flash_controller *str9xpec_info = NULL;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *bank;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
- return retval;
-
- str9xpec_info = bank->driver_priv;
- tap = str9xpec_info->tap;
-
- if (tap == NULL)
- return ERROR_FAIL;
-
- /* exit turbo mode via RESET */
- str9xpec_set_instr(tap, ISC_NOOP, TAP_IDLE);
- jtag_add_tlr();
- jtag_execute_queue();
-
- /* restore previous scan chain */
- if (tap->next_tap)
- tap->next_tap->enabled = 1;
-
- return ERROR_OK;
-}
-
-static const struct command_registration str9xpec_config_command_handlers[] = {
- {
- .name = "enable_turbo",
- .usage = "<bank>",
- .handler = str9xpec_handle_flash_enable_turbo_command,
- .mode = COMMAND_EXEC,
- .help = "enable str9xpec turbo mode",
- },
- {
- .name = "disable_turbo",
- .usage = "<bank>",
- .handler = str9xpec_handle_flash_disable_turbo_command,
- .mode = COMMAND_EXEC,
- .help = "disable str9xpec turbo mode",
- },
- {
- .name = "options_cmap",
- .usage = "<bank> <bank0 | bank1>",
- .handler = str9xpec_handle_flash_options_cmap_command,
- .mode = COMMAND_EXEC,
- .help = "configure str9xpec boot sector",
- },
- {
- .name = "options_lvdthd",
- .usage = "<bank> <2.4v | 2.7v>",
- .handler = str9xpec_handle_flash_options_lvdthd_command,
- .mode = COMMAND_EXEC,
- .help = "configure str9xpec lvd threshold",
- },
- {
- .name = "options_lvdsel",
- .usage = "<bank> <vdd | vdd_vddq>",
- .handler = str9xpec_handle_flash_options_lvdsel_command,
- .mode = COMMAND_EXEC,
- .help = "configure str9xpec lvd selection",
- },
- {
- .name = "options_lvdwarn",
- .usage = "<bank> <vdd | vdd_vddq>",
- .handler = str9xpec_handle_flash_options_lvdwarn_command,
- .mode = COMMAND_EXEC,
- .help = "configure str9xpec lvd warning",
- },
- {
- .name = "options_read",
- .usage = "<bank>",
- .handler = str9xpec_handle_flash_options_read_command,
- .mode = COMMAND_EXEC,
- .help = "read str9xpec options",
- },
- {
- .name = "options_write",
- .usage = "<bank>",
- .handler = str9xpec_handle_flash_options_write_command,
- .mode = COMMAND_EXEC,
- .help = "write str9xpec options",
- },
- {
- .name = "lock",
- .usage = "<bank>",
- .handler = str9xpec_handle_flash_lock_command,
- .mode = COMMAND_EXEC,
- .help = "lock str9xpec device",
- },
- {
- .name = "unlock",
- .usage = "<bank>",
- .handler = str9xpec_handle_flash_unlock_command,
- .mode = COMMAND_EXEC,
- .help = "unlock str9xpec device",
- },
- {
- .name = "part_id",
- .handler = str9xpec_handle_part_id_command,
- .mode = COMMAND_EXEC,
- .help = "print part id of str9xpec flash bank <num>",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration str9xpec_command_handlers[] = {
- {
- .name = "str9xpec",
- .mode = COMMAND_ANY,
- .help = "str9xpec flash command group",
- .usage = "",
- .chain = str9xpec_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver str9xpec_flash = {
- .name = "str9xpec",
- .commands = str9xpec_command_handlers,
- .flash_bank_command = str9xpec_flash_bank_command,
- .erase = str9xpec_erase,
- .protect = str9xpec_protect,
- .write = str9xpec_write,
- .read = default_flash_read,
- .probe = str9xpec_probe,
- .auto_probe = str9xpec_probe,
- .erase_check = str9xpec_erase_check,
- .protect_check = str9xpec_protect_check,
-};
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
deleted file mode 100644
index 6dd2140..0000000
--- a/src/flash/nor/tcl.c
+++ /dev/null
@@ -1,1146 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "imp.h"
-#include <helper/time_support.h>
-#include <target/image.h>
-
-/**
- * @file
- * Implements Tcl commands used to access NOR flash facilities.
- */
-
-COMMAND_HELPER(flash_command_get_bank_maybe_probe, unsigned name_index,
- struct flash_bank **bank, bool do_probe)
-{
- const char *name = CMD_ARGV[name_index];
- int retval;
- if (do_probe) {
- retval = get_flash_bank_by_name(name, bank);
- } else {
- *bank = get_flash_bank_by_name_noprobe(name);
- retval = ERROR_OK;
- }
-
- if (retval != ERROR_OK)
- return retval;
- if (*bank)
- return ERROR_OK;
-
- unsigned bank_num;
- COMMAND_PARSE_NUMBER(uint, name, bank_num);
-
- if (do_probe) {
- return get_flash_bank_by_num(bank_num, bank);
- } else {
- *bank = get_flash_bank_by_num_noprobe(bank_num);
- retval = (bank) ? ERROR_OK : ERROR_FAIL;
- return retval;
- }
-}
-
-COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
- struct flash_bank **bank)
-{
- return CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe,
- name_index, bank, true);
-}
-
-COMMAND_HANDLER(handle_flash_info_command)
-{
- struct flash_bank *p;
- int j = 0;
- int retval;
- bool show_sectors = false;
- bool prot_block_available;
-
- if (CMD_ARGC < 1 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 2) {
- if (strcmp("sectors", CMD_ARGV[1]) == 0)
- show_sectors = true;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (retval != ERROR_OK)
- return retval;
-
- if (p != NULL) {
- char buf[1024];
- int num_blocks;
- struct flash_sector *block_array;
-
- /* attempt auto probe */
- retval = p->driver->auto_probe(p);
- if (retval != ERROR_OK)
- return retval;
-
- /* We must query the hardware to avoid printing stale information! */
- retval = p->driver->protect_check(p);
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX,
- "#%d : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32
- ", buswidth %i, chipwidth %i",
- p->bank_number,
- p->driver->name,
- p->base,
- p->size,
- p->bus_width,
- p->chip_width);
-
- prot_block_available = p->num_prot_blocks && p->prot_blocks;
- if (!show_sectors && prot_block_available) {
- block_array = p->prot_blocks;
- num_blocks = p->num_prot_blocks;
- } else {
- block_array = p->sectors;
- num_blocks = p->num_sectors;
- }
-
- for (j = 0; j < num_blocks; j++) {
- char *protect_state = "";
-
- if (block_array[j].is_protected == 0)
- protect_state = "not protected";
- else if (block_array[j].is_protected == 1)
- protect_state = "protected";
- else if (!show_sectors || !prot_block_available)
- protect_state = "protection state unknown";
-
- command_print(CMD_CTX,
- "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
- j,
- block_array[j].offset,
- block_array[j].size,
- block_array[j].size >> 10,
- protect_state);
- }
-
- if (p->driver->info != NULL) {
- retval = p->driver->info(p, buf, sizeof(buf));
- if (retval == ERROR_OK)
- command_print(CMD_CTX, "%s", buf);
- else
- LOG_ERROR("error retrieving flash info");
- }
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_flash_probe_command)
-{
- struct flash_bank *p;
- int retval;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- retval = CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe, 0, &p, false);
- if (retval != ERROR_OK)
- return retval;
-
- if (p) {
- retval = p->driver->probe(p);
- if (retval == ERROR_OK)
- command_print(CMD_CTX,
- "flash '%s' found at 0x%8.8" PRIx32,
- p->driver->name,
- p->base);
- } else {
- command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
- retval = ERROR_FAIL;
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_flash_erase_check_command)
-{
- bool blank = true;
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *p;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- int j;
- retval = p->driver->erase_check(p);
- if (retval == ERROR_OK)
- command_print(CMD_CTX, "successfully checked erase state");
- else {
- command_print(CMD_CTX,
- "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
- CMD_ARGV[0],
- p->base);
- }
-
- for (j = 0; j < p->num_sectors; j++) {
- char *erase_state;
-
- if (p->sectors[j].is_erased == 0)
- erase_state = "not erased";
- else if (p->sectors[j].is_erased == 1)
- continue;
- else
- erase_state = "erase state unknown";
-
- blank = false;
- command_print(CMD_CTX,
- "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
- j,
- p->sectors[j].offset,
- p->sectors[j].size,
- p->sectors[j].size >> 10,
- erase_state);
- }
-
- if (blank)
- command_print(CMD_CTX, "\tBank is erased");
- return retval;
-}
-
-COMMAND_HANDLER(handle_flash_erase_address_command)
-{
- struct flash_bank *p;
- int retval = ERROR_OK;
- uint32_t address;
- uint32_t length;
- bool do_pad = false;
- bool do_unlock = false;
- struct target *target = get_current_target(CMD_CTX);
-
- while (CMD_ARGC >= 3) {
- /* Optionally pad out the address range to block/sector
- * boundaries. We can't know if there's data in that part
- * of the flash; only do padding if we're told to.
- */
- if (strcmp("pad", CMD_ARGV[0]) == 0)
- do_pad = true;
- else if (strcmp("unlock", CMD_ARGV[0]) == 0)
- do_unlock = true;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
- CMD_ARGC--;
- CMD_ARGV++;
- }
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
-
- if (length <= 0) {
- command_print(CMD_CTX, "Length must be >0");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- retval = get_flash_bank_by_addr(target, address, true, &p);
- if (retval != ERROR_OK)
- return retval;
-
- /* We can't know if we did a resume + halt, in which case we no longer know the erased state
- **/
- flash_set_dirty();
-
- struct duration bench;
- duration_start(&bench);
-
- if (do_unlock)
- retval = flash_unlock_address_range(target, address, length);
-
- if (retval == ERROR_OK)
- retval = flash_erase_address_range(target, do_pad, address, length);
-
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "erased address 0x%8.8" PRIx32 " (length %" PRIi32 ")"
- " in %fs (%0.3f KiB/s)", address, length,
- duration_elapsed(&bench), duration_kbps(&bench, length));
- }
-
- return retval;
-}
-
-static int flash_check_sector_parameters(struct command_context *cmd_ctx,
- uint32_t first, uint32_t last, uint32_t num_sectors)
-{
- if (!(first <= last)) {
- command_print(cmd_ctx, "ERROR: "
- "first sector must be <= last sector");
- return ERROR_FAIL;
- }
-
- if (!(last <= (num_sectors - 1))) {
- command_print(cmd_ctx, "ERROR: last sector must be <= %d",
- (int) num_sectors - 1);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_flash_erase_command)
-{
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t first;
- uint32_t last;
-
- struct flash_bank *p;
- int retval;
-
- retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (retval != ERROR_OK)
- return retval;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
- if (strcmp(CMD_ARGV[2], "last") == 0)
- last = p->num_sectors - 1;
- else
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
-
- retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors);
- if (retval != ERROR_OK)
- return retval;
-
- struct duration bench;
- duration_start(&bench);
-
- retval = flash_driver_erase(p, first, last);
-
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "erased sectors %" PRIu32 " "
- "through %" PRIu32 " on flash bank %d "
- "in %fs", first, last, p->bank_number, duration_elapsed(&bench));
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_flash_protect_command)
-{
- if (CMD_ARGC != 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t first;
- uint32_t last;
-
- struct flash_bank *p;
- int retval;
- int num_blocks;
-
- retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (retval != ERROR_OK)
- return retval;
-
- if (p->num_prot_blocks)
- num_blocks = p->num_prot_blocks;
- else
- num_blocks = p->num_sectors;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
- if (strcmp(CMD_ARGV[2], "last") == 0)
- last = num_blocks - 1;
- else
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
-
- bool set;
- COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
-
- retval = flash_check_sector_parameters(CMD_CTX, first, last, num_blocks);
- if (retval != ERROR_OK)
- return retval;
-
- retval = flash_driver_protect(p, set, first, last);
- if (retval == ERROR_OK) {
- command_print(CMD_CTX, "%s protection for sectors %i "
- "through %i on flash bank %d",
- (set) ? "set" : "cleared", (int) first,
- (int) last, p->bank_number);
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_flash_write_image_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- struct image image;
- uint32_t written;
-
- int retval;
-
- /* flash auto-erase is disabled by default*/
- int auto_erase = 0;
- bool auto_unlock = false;
-
- while (CMD_ARGC) {
- if (strcmp(CMD_ARGV[0], "erase") == 0) {
- auto_erase = 1;
- CMD_ARGV++;
- CMD_ARGC--;
- command_print(CMD_CTX, "auto erase enabled");
- } else if (strcmp(CMD_ARGV[0], "unlock") == 0) {
- auto_unlock = true;
- CMD_ARGV++;
- CMD_ARGC--;
- command_print(CMD_CTX, "auto unlock enabled");
- } else
- break;
- }
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (!target) {
- LOG_ERROR("no target selected");
- return ERROR_FAIL;
- }
-
- struct duration bench;
- duration_start(&bench);
-
- if (CMD_ARGC >= 2) {
- image.base_address_set = 1;
- COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
- } else {
- image.base_address_set = 0;
- image.base_address = 0x0;
- }
-
- image.start_address_set = 0;
-
- retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
- if (retval != ERROR_OK)
- return retval;
-
- retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
- if (retval != ERROR_OK) {
- image_close(&image);
- return retval;
- }
-
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
- "in %fs (%0.3f KiB/s)", written, CMD_ARGV[0],
- duration_elapsed(&bench), duration_kbps(&bench, written));
- }
-
- image_close(&image);
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_flash_fill_command)
-{
- int err = ERROR_OK;
- uint32_t address;
- uint32_t pattern;
- uint32_t count;
- uint32_t wrote = 0;
- uint32_t cur_size = 0;
- uint32_t chunk_count;
- struct target *target = get_current_target(CMD_CTX);
- unsigned i;
- uint32_t wordsize;
- int retval = ERROR_OK;
-
- static size_t const chunksize = 1024;
- uint8_t *chunk = NULL, *readback = NULL;
-
- if (CMD_ARGC != 3) {
- retval = ERROR_COMMAND_SYNTAX_ERROR;
- goto done;
- }
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
-
- chunk = malloc(chunksize);
- if (chunk == NULL)
- return ERROR_FAIL;
-
- readback = malloc(chunksize);
- if (readback == NULL) {
- free(chunk);
- return ERROR_FAIL;
- }
-
- if (count == 0)
- goto done;
-
- switch (CMD_NAME[4]) {
- case 'w':
- wordsize = 4;
- break;
- case 'h':
- wordsize = 2;
- break;
- case 'b':
- wordsize = 1;
- break;
- default:
- retval = ERROR_COMMAND_SYNTAX_ERROR;
- goto done;
- }
-
- chunk_count = MIN(count, (chunksize / wordsize));
- switch (wordsize) {
- case 4:
- for (i = 0; i < chunk_count; i++)
- target_buffer_set_u32(target, chunk + i * wordsize, pattern);
- break;
- case 2:
- for (i = 0; i < chunk_count; i++)
- target_buffer_set_u16(target, chunk + i * wordsize, pattern);
- break;
- case 1:
- memset(chunk, pattern, chunk_count);
- break;
- default:
- LOG_ERROR("BUG: can't happen");
- exit(-1);
- }
-
- struct duration bench;
- duration_start(&bench);
-
- for (wrote = 0; wrote < (count*wordsize); wrote += cur_size) {
- struct flash_bank *bank;
-
- retval = get_flash_bank_by_addr(target, address, true, &bank);
- if (retval != ERROR_OK)
- goto done;
-
- cur_size = MIN((count * wordsize - wrote), chunksize);
- err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size);
- if (err != ERROR_OK) {
- retval = err;
- goto done;
- }
-
- err = flash_driver_read(bank, readback, address - bank->base + wrote, cur_size);
- if (err != ERROR_OK) {
- retval = err;
- goto done;
- }
-
- for (i = 0; i < cur_size; i++) {
- if (readback[i] != chunk[i]) {
- LOG_ERROR(
- "Verification error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
- address + wrote + i,
- readback[i],
- chunk[i]);
- retval = ERROR_FAIL;
- goto done;
- }
- }
- }
-
- if ((retval == ERROR_OK) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32
- " in %fs (%0.3f KiB/s)", wrote, address,
- duration_elapsed(&bench), duration_kbps(&bench, wrote));
- }
-
-done:
- free(readback);
- free(chunk);
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_flash_write_bank_command)
-{
- uint32_t offset;
- uint8_t *buffer;
- struct fileio *fileio;
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct duration bench;
- duration_start(&bench);
-
- struct flash_bank *p;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
-
- if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
- return ERROR_OK;
-
- size_t filesize;
- retval = fileio_size(fileio, &filesize);
- if (retval != ERROR_OK) {
- fileio_close(fileio);
- return retval;
- }
-
- buffer = malloc(filesize);
- if (buffer == NULL) {
- fileio_close(fileio);
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- size_t buf_cnt;
- if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) {
- free(buffer);
- fileio_close(fileio);
- return ERROR_OK;
- }
-
- retval = flash_driver_write(p, buffer, offset, buf_cnt);
-
- free(buffer);
- buffer = NULL;
-
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "wrote %zu bytes from file %s to flash bank %u"
- " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
- filesize, CMD_ARGV[1], p->bank_number, offset,
- duration_elapsed(&bench), duration_kbps(&bench, filesize));
- }
-
- fileio_close(fileio);
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_flash_read_bank_command)
-{
- uint32_t offset;
- uint8_t *buffer;
- struct fileio *fileio;
- uint32_t length;
- size_t written;
-
- if (CMD_ARGC != 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct duration bench;
- duration_start(&bench);
-
- struct flash_bank *p;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length);
-
- buffer = malloc(length);
- if (buffer == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- retval = flash_driver_read(p, buffer, offset, length);
- if (retval != ERROR_OK) {
- LOG_ERROR("Read error");
- free(buffer);
- return retval;
- }
-
- retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not open file");
- free(buffer);
- return retval;
- }
-
- retval = fileio_write(fileio, length, buffer, &written);
- fileio_close(fileio);
- free(buffer);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not write file");
- return ERROR_FAIL;
- }
-
- if (duration_measure(&bench) == ERROR_OK)
- command_print(CMD_CTX, "wrote %ld bytes to file %s from flash bank %u"
- " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
- (long)written, CMD_ARGV[1], p->bank_number, offset,
- duration_elapsed(&bench), duration_kbps(&bench, written));
-
- return retval;
-}
-
-
-COMMAND_HANDLER(handle_flash_verify_bank_command)
-{
- uint32_t offset;
- uint8_t *buffer_file, *buffer_flash;
- struct fileio *fileio;
- size_t read_cnt;
- size_t filesize;
- int differ;
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct duration bench;
- duration_start(&bench);
-
- struct flash_bank *p;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
-
- retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not open file");
- return retval;
- }
-
- retval = fileio_size(fileio, &filesize);
- if (retval != ERROR_OK) {
- fileio_close(fileio);
- return retval;
- }
-
- buffer_file = malloc(filesize);
- if (buffer_file == NULL) {
- LOG_ERROR("Out of memory");
- fileio_close(fileio);
- return ERROR_FAIL;
- }
-
- retval = fileio_read(fileio, filesize, buffer_file, &read_cnt);
- fileio_close(fileio);
- if (retval != ERROR_OK) {
- LOG_ERROR("File read failure");
- free(buffer_file);
- return retval;
- }
-
- if (read_cnt != filesize) {
- LOG_ERROR("Short read");
- free(buffer_file);
- return ERROR_FAIL;
- }
-
- buffer_flash = malloc(filesize);
- if (buffer_flash == NULL) {
- LOG_ERROR("Out of memory");
- free(buffer_file);
- return ERROR_FAIL;
- }
-
- retval = flash_driver_read(p, buffer_flash, offset, read_cnt);
- if (retval != ERROR_OK) {
- LOG_ERROR("Flash read error");
- free(buffer_flash);
- free(buffer_file);
- return retval;
- }
-
- if (duration_measure(&bench) == ERROR_OK)
- command_print(CMD_CTX, "read %ld bytes from file %s and flash bank %u"
- " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
- (long)read_cnt, CMD_ARGV[1], p->bank_number, offset,
- duration_elapsed(&bench), duration_kbps(&bench, read_cnt));
-
- differ = memcmp(buffer_file, buffer_flash, read_cnt);
- command_print(CMD_CTX, "contents %s", differ ? "differ" : "match");
- if (differ) {
- uint32_t t;
- int diffs = 0;
- for (t = 0; t < read_cnt; t++) {
- if (buffer_flash[t] == buffer_file[t])
- continue;
- command_print(CMD_CTX, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x",
- diffs, t + offset, buffer_flash[t], buffer_file[t]);
- if (diffs++ >= 127) {
- command_print(CMD_CTX, "More than 128 errors, the rest are not printed.");
- break;
- }
- keep_alive();
- }
- }
- free(buffer_flash);
- free(buffer_file);
-
- return differ ? ERROR_FAIL : ERROR_OK;
-}
-
-void flash_set_dirty(void)
-{
- struct flash_bank *c;
- int i;
-
- /* set all flash to require erasing */
- for (c = flash_bank_list(); c; c = c->next) {
- for (i = 0; i < c->num_sectors; i++)
- c->sectors[i].is_erased = 0;
- }
-}
-
-COMMAND_HANDLER(handle_flash_padded_value_command)
-{
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct flash_bank *p;
- int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
- if (ERROR_OK != retval)
- return retval;
-
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], p->default_padded_value);
-
- command_print(CMD_CTX, "Default padded value set to 0x%" PRIx8 " for flash bank %u", \
- p->default_padded_value, p->bank_number);
-
- return retval;
-}
-
-static const struct command_registration flash_exec_command_handlers[] = {
- {
- .name = "probe",
- .handler = handle_flash_probe_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Identify a flash bank.",
- },
- {
- .name = "info",
- .handler = handle_flash_info_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id ['sectors']",
- .help = "Print information about a flash bank.",
- },
- {
- .name = "erase_check",
- .handler = handle_flash_erase_check_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id",
- .help = "Check erase state of all blocks in a "
- "flash bank.",
- },
- {
- .name = "erase_sector",
- .handler = handle_flash_erase_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id first_sector_num last_sector_num",
- .help = "Erase a range of sectors in a flash bank.",
- },
- {
- .name = "erase_address",
- .handler = handle_flash_erase_address_command,
- .mode = COMMAND_EXEC,
- .usage = "['pad'] ['unlock'] address length",
- .help = "Erase flash sectors starting at address and "
- "continuing for length bytes. If 'pad' is specified, "
- "data outside that range may also be erased: the start "
- "address may be decreased, and length increased, so "
- "that all of the first and last sectors are erased. "
- "If 'unlock' is specified, then the flash is unprotected "
- "before erasing.",
-
- },
- {
- .name = "fillw",
- .handler = handle_flash_fill_command,
- .mode = COMMAND_EXEC,
- .usage = "address value n",
- .help = "Fill n words with 32-bit value, starting at "
- "word address. (No autoerase.)",
- },
- {
- .name = "fillh",
- .handler = handle_flash_fill_command,
- .mode = COMMAND_EXEC,
- .usage = "address value n",
- .help = "Fill n halfwords with 16-bit value, starting at "
- "word address. (No autoerase.)",
- },
- {
- .name = "fillb",
- .handler = handle_flash_fill_command,
- .mode = COMMAND_EXEC,
- .usage = "address value n",
- .help = "Fill n bytes with 8-bit value, starting at "
- "word address. (No autoerase.)",
- },
- {
- .name = "write_bank",
- .handler = handle_flash_write_bank_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename offset",
- .help = "Write binary data from file to flash bank, "
- "starting at specified byte offset from the "
- "beginning of the bank.",
- },
- {
- .name = "write_image",
- .handler = handle_flash_write_image_command,
- .mode = COMMAND_EXEC,
- .usage = "[erase] [unlock] filename [offset [file_type]]",
- .help = "Write an image to flash. Optionally first unprotect "
- "and/or erase the region to be used. Allow optional "
- "offset from beginning of bank (defaults to zero)",
- },
- {
- .name = "read_bank",
- .handler = handle_flash_read_bank_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename offset length",
- .help = "Read binary data from flash bank to file, "
- "starting at specified byte offset from the "
- "beginning of the bank.",
- },
- {
- .name = "verify_bank",
- .handler = handle_flash_verify_bank_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id filename offset",
- .help = "Read binary data from flash bank and file, "
- "starting at specified byte offset from the "
- "beginning of the bank. Compare the contents.",
- },
- {
- .name = "protect",
- .handler = handle_flash_protect_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id first_sector [last_sector|'last'] "
- "('on'|'off')",
- .help = "Turn protection on or off for a range of sectors "
- "in a given flash bank.",
- },
- {
- .name = "padded_value",
- .handler = handle_flash_padded_value_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id value",
- .help = "Set default flash padded value",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int flash_init_drivers(struct command_context *cmd_ctx)
-{
- if (!flash_bank_list())
- return ERROR_OK;
-
- struct command *parent = command_find_in_context(cmd_ctx, "flash");
- return register_commands(cmd_ctx, parent, flash_exec_command_handlers);
-}
-
-COMMAND_HANDLER(handle_flash_bank_command)
-{
- if (CMD_ARGC < 7) {
- LOG_ERROR("usage: flash bank <name> <driver> "
- "<base> <size> <chip_width> <bus_width> <target>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- /* save bank name and advance arguments for compatibility */
- const char *bank_name = *CMD_ARGV++;
- CMD_ARGC--;
-
- struct target *target = get_target(CMD_ARGV[5]);
- if (target == NULL) {
- LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
- return ERROR_FAIL;
- }
-
- const char *driver_name = CMD_ARGV[0];
- struct flash_driver *driver = flash_driver_find_by_name(driver_name);
- if (NULL == driver) {
- /* no matching flash driver found */
- LOG_ERROR("flash driver '%s' not found", driver_name);
- return ERROR_FAIL;
- }
-
- /* check the flash bank name is unique */
- if (get_flash_bank_by_name_noprobe(bank_name) != NULL) {
- /* flash bank name already exists */
- LOG_ERROR("flash bank name '%s' already exists", bank_name);
- return ERROR_FAIL;
- }
-
- /* register flash specific commands */
- if (NULL != driver->commands) {
- int retval = register_commands(CMD_CTX, NULL,
- driver->commands);
- if (ERROR_OK != retval) {
- LOG_ERROR("couldn't register '%s' commands",
- driver_name);
- return ERROR_FAIL;
- }
- }
-
- struct flash_bank *c = malloc(sizeof(*c));
- c->name = strdup(bank_name);
- c->target = target;
- c->driver = driver;
- c->driver_priv = NULL;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], c->base);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
- c->default_padded_value = 0xff;
- c->num_sectors = 0;
- c->sectors = NULL;
- c->num_prot_blocks = 0;
- c->prot_blocks = NULL;
- c->next = NULL;
-
- int retval;
- retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
- if (ERROR_OK != retval) {
- LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "; usage: %s",
- driver_name, c->base, driver->usage);
- free(c);
- return retval;
- }
-
- if (driver->usage == NULL)
- LOG_DEBUG("'%s' driver usage field missing", driver_name);
-
- flash_bank_add(c);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_flash_banks_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned n = 0;
- for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) {
- LOG_USER("#%d : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
- "buswidth %u, chipwidth %u", p->bank_number,
- p->name, p->driver->name, p->base, p->size,
- p->bus_width, p->chip_width);
- }
- return ERROR_OK;
-}
-
-static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv,
- "no arguments to 'flash list' command");
- return JIM_ERR;
- }
-
- Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
-
- for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
- Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
-
- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
-
- Jim_ListAppendElement(interp, list, elem);
- }
-
- Jim_SetResult(interp, list);
-
- return JIM_OK;
-}
-
-COMMAND_HANDLER(handle_flash_init_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- static bool flash_initialized;
- if (flash_initialized) {
- LOG_INFO("'flash init' has already been called");
- return ERROR_OK;
- }
- flash_initialized = true;
-
- LOG_DEBUG("Initializing flash devices...");
- return flash_init_drivers(CMD_CTX);
-}
-
-static const struct command_registration flash_config_command_handlers[] = {
- {
- .name = "bank",
- .handler = handle_flash_bank_command,
- .mode = COMMAND_CONFIG,
- .usage = "bank_id driver_name base_address size_bytes "
- "chip_width_bytes bus_width_bytes target "
- "[driver_options ...]",
- .help = "Define a new bank with the given name, "
- "using the specified NOR flash driver.",
- },
- {
- .name = "init",
- .mode = COMMAND_CONFIG,
- .handler = handle_flash_init_command,
- .help = "Initialize flash devices.",
- },
- {
- .name = "banks",
- .mode = COMMAND_ANY,
- .handler = handle_flash_banks_command,
- .help = "Display table with information about flash banks.",
- },
- {
- .name = "list",
- .mode = COMMAND_ANY,
- .jim_handler = jim_flash_list,
- .help = "Returns a list of details about the flash banks.",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration flash_command_handlers[] = {
- {
- .name = "flash",
- .mode = COMMAND_ANY,
- .help = "NOR flash command group",
- .chain = flash_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int flash_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, flash_command_handlers);
-}
diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c
deleted file mode 100644
index a70891e..0000000
--- a/src/flash/nor/tms470.c
+++ /dev/null
@@ -1,1189 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007,2008 by Christopher Kilgour *
- * techie |_at_| whiterocker |_dot_| com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-
-/* ----------------------------------------------------------------------
- * Internal Support, Helpers
- * ---------------------------------------------------------------------- */
-
-struct tms470_flash_bank {
- unsigned ordinal;
-
- /* device identification register */
- uint32_t device_ident_reg;
- uint32_t silicon_version;
- uint32_t technology_family;
- uint32_t rom_flash;
- uint32_t part_number;
- const char *part_name;
-
-};
-
-static const struct flash_sector TMS470R1A256_SECTORS[] = {
- {0x00000000, 0x00002000, -1, -1},
- {0x00002000, 0x00002000, -1, -1},
- {0x00004000, 0x00002000, -1, -1},
- {0x00006000, 0x00002000, -1, -1},
- {0x00008000, 0x00008000, -1, -1},
- {0x00010000, 0x00008000, -1, -1},
- {0x00018000, 0x00008000, -1, -1},
- {0x00020000, 0x00008000, -1, -1},
- {0x00028000, 0x00008000, -1, -1},
- {0x00030000, 0x00008000, -1, -1},
- {0x00038000, 0x00002000, -1, -1},
- {0x0003A000, 0x00002000, -1, -1},
- {0x0003C000, 0x00002000, -1, -1},
- {0x0003E000, 0x00002000, -1, -1},
-};
-
-#define TMS470R1A256_NUM_SECTORS \
- ARRAY_SIZE(TMS470R1A256_SECTORS)
-
-static const struct flash_sector TMS470R1A288_BANK0_SECTORS[] = {
- {0x00000000, 0x00002000, -1, -1},
- {0x00002000, 0x00002000, -1, -1},
- {0x00004000, 0x00002000, -1, -1},
- {0x00006000, 0x00002000, -1, -1},
-};
-
-#define TMS470R1A288_BANK0_NUM_SECTORS \
- ARRAY_SIZE(TMS470R1A288_BANK0_SECTORS)
-
-static const struct flash_sector TMS470R1A288_BANK1_SECTORS[] = {
- {0x00040000, 0x00010000, -1, -1},
- {0x00050000, 0x00010000, -1, -1},
- {0x00060000, 0x00010000, -1, -1},
- {0x00070000, 0x00010000, -1, -1},
-};
-
-#define TMS470R1A288_BANK1_NUM_SECTORS \
- ARRAY_SIZE(TMS470R1A288_BANK1_SECTORS)
-
-static const struct flash_sector TMS470R1A384_BANK0_SECTORS[] = {
- {0x00000000, 0x00002000, -1, -1},
- {0x00002000, 0x00002000, -1, -1},
- {0x00004000, 0x00004000, -1, -1},
- {0x00008000, 0x00004000, -1, -1},
- {0x0000C000, 0x00004000, -1, -1},
- {0x00010000, 0x00004000, -1, -1},
- {0x00014000, 0x00004000, -1, -1},
- {0x00018000, 0x00002000, -1, -1},
- {0x0001C000, 0x00002000, -1, -1},
- {0x0001E000, 0x00002000, -1, -1},
-};
-
-#define TMS470R1A384_BANK0_NUM_SECTORS \
- ARRAY_SIZE(TMS470R1A384_BANK0_SECTORS)
-
-static const struct flash_sector TMS470R1A384_BANK1_SECTORS[] = {
- {0x00020000, 0x00008000, -1, -1},
- {0x00028000, 0x00008000, -1, -1},
- {0x00030000, 0x00008000, -1, -1},
- {0x00038000, 0x00008000, -1, -1},
-};
-
-#define TMS470R1A384_BANK1_NUM_SECTORS \
- ARRAY_SIZE(TMS470R1A384_BANK1_SECTORS)
-
-static const struct flash_sector TMS470R1A384_BANK2_SECTORS[] = {
- {0x00040000, 0x00008000, -1, -1},
- {0x00048000, 0x00008000, -1, -1},
- {0x00050000, 0x00008000, -1, -1},
- {0x00058000, 0x00008000, -1, -1},
-};
-
-#define TMS470R1A384_BANK2_NUM_SECTORS \
- ARRAY_SIZE(TMS470R1A384_BANK2_SECTORS)
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_read_part_info(struct flash_bank *bank)
-{
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t device_ident_reg;
- uint32_t silicon_version;
- uint32_t technology_family;
- uint32_t rom_flash;
- uint32_t part_number;
- const char *part_name;
-
- /* we shall not rely on the caller in this test, this function allocates memory,
- thus and executing the code more than once may cause memory leak */
- if (tms470_info->device_ident_reg)
- return ERROR_OK;
-
- /* read and parse the device identification register */
- target_read_u32(target, 0xFFFFFFF0, &device_ident_reg);
-
- LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg);
-
- if ((device_ident_reg & 7) == 0) {
- LOG_WARNING("Cannot identify target as a TMS470 family.");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- silicon_version = (device_ident_reg >> 12) & 0xF;
- technology_family = (device_ident_reg >> 11) & 1;
- rom_flash = (device_ident_reg >> 10) & 1;
- part_number = (device_ident_reg >> 3) & 0x7f;
-
- if (bank->sectors) {
- free(bank->sectors);
- bank->sectors = NULL;
- }
-
- /*
- * If the part number is known, determine if the flash bank is valid
- * based on the base address being within the known flash bank
- * ranges. Then fixup/complete the remaining fields of the flash
- * bank structure.
- */
- switch (part_number) {
- case 0x0a:
- part_name = "TMS470R1A256";
-
- if (bank->base >= 0x00040000) {
- LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
- part_name,
- bank->base);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- tms470_info->ordinal = 0;
- bank->base = 0x00000000;
- bank->size = 256 * 1024;
- bank->num_sectors = TMS470R1A256_NUM_SECTORS;
- bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
- break;
-
- case 0x2b:
- part_name = "TMS470R1A288";
-
- if (bank->base < 0x00008000) {
- tms470_info->ordinal = 0;
- bank->base = 0x00000000;
- bank->size = 32 * 1024;
- bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
- bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS,
- sizeof(TMS470R1A288_BANK0_SECTORS));
- } else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000)) {
- tms470_info->ordinal = 1;
- bank->base = 0x00040000;
- bank->size = 256 * 1024;
- bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
- bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS,
- sizeof(TMS470R1A288_BANK1_SECTORS));
- } else {
- LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
- part_name, bank->base);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- break;
-
- case 0x2d:
- part_name = "TMS470R1A384";
-
- if (bank->base < 0x00020000) {
- tms470_info->ordinal = 0;
- bank->base = 0x00000000;
- bank->size = 128 * 1024;
- bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
- bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS,
- sizeof(TMS470R1A384_BANK0_SECTORS));
- } else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000)) {
- tms470_info->ordinal = 1;
- bank->base = 0x00020000;
- bank->size = 128 * 1024;
- bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
- bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS,
- sizeof(TMS470R1A384_BANK1_SECTORS));
- } else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000)) {
- tms470_info->ordinal = 2;
- bank->base = 0x00040000;
- bank->size = 128 * 1024;
- bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
- bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
- if (!bank->sectors)
- return ERROR_FLASH_OPERATION_FAILED;
- (void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS,
- sizeof(TMS470R1A384_BANK2_SECTORS));
- } else {
- LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".",
- part_name, bank->base);
- return ERROR_FLASH_OPERATION_FAILED;
- }
- break;
-
- default:
- LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.",
- (unsigned)part_number);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* turn off memory selects */
- target_write_u32(target, 0xFFFFFFE4, 0x00000000);
- target_write_u32(target, 0xFFFFFFE0, 0x00000000);
-
- bank->chip_width = 32;
- bank->bus_width = 32;
-
- LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.",
- part_name,
- (int)(silicon_version),
- (technology_family ? "1.8v" : "3.3v"),
- (rom_flash ? "rom" : "flash"));
-
- tms470_info->device_ident_reg = device_ident_reg;
- tms470_info->silicon_version = silicon_version;
- tms470_info->technology_family = technology_family;
- tms470_info->rom_flash = rom_flash;
- tms470_info->part_number = part_number;
- tms470_info->part_name = part_name;
-
- /*
- * Disable reset on address access violation.
- */
- target_write_u32(target, 0xFFFFFFE0, 0x00004007);
-
- return ERROR_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static uint32_t keysSet;
-static uint32_t flashKeys[4];
-
-COMMAND_HANDLER(tms470_handle_flash_keyset_command)
-{
- if (CMD_ARGC > 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
- else if (CMD_ARGC == 4) {
- int i;
-
- for (i = 0; i < 4; i++) {
- int start = (0 == strncmp(CMD_ARGV[i], "0x", 2)) ? 2 : 0;
-
- if (1 != sscanf(&CMD_ARGV[i][start], "%" SCNx32 "", &flashKeys[i])) {
- command_print(CMD_CTX, "could not process flash key %s",
- CMD_ARGV[i]);
- LOG_ERROR("could not process flash key %s", CMD_ARGV[i]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- keysSet = 1;
- } else if (CMD_ARGC != 0) {
- command_print(CMD_CTX, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (keysSet) {
- command_print(CMD_CTX,
- "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "",
- flashKeys[0],
- flashKeys[1],
- flashKeys[2],
- flashKeys[3]);
- } else
- command_print(CMD_CTX, "flash keys not set");
-
- return ERROR_OK;
-}
-
-static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
- 0xFFFFFFFF, 0xFFFFFFFF,};
-
-static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
- 0x00000000, 0x00000000,};
-
-static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
- 0xf0fff0ff, 0xf0fff0ff};
-
-static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
- 0x0000ffff, 0x0000ffff};
-
-/* ---------------------------------------------------------------------- */
-
-static int oscMHz = 12;
-
-COMMAND_HANDLER(tms470_handle_osc_megahertz_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- else if (CMD_ARGC == 1)
- sscanf(CMD_ARGV[0], "%d", &oscMHz);
-
- if (oscMHz <= 0) {
- LOG_ERROR("osc_megahertz must be positive and non-zero!");
- command_print(CMD_CTX, "osc_megahertz must be positive and non-zero!");
- oscMHz = 12;
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- command_print(CMD_CTX, "osc_megahertz=%d", oscMHz);
-
- return ERROR_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int plldis;
-
-COMMAND_HANDLER(tms470_handle_plldis_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- else if (CMD_ARGC == 1) {
- sscanf(CMD_ARGV[0], "%d", &plldis);
- plldis = plldis ? 1 : 0;
- }
-
- command_print(CMD_CTX, "plldis=%d", plldis);
-
- return ERROR_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_check_flash_unlocked(struct target *target)
-{
- uint32_t fmbbusy;
-
- target_read_u32(target, 0xFFE89C08, &fmbbusy);
- LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s",
- fmbbusy,
- fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
- return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_try_flash_keys(struct target *target, const uint32_t *key_set)
-{
- uint32_t glbctrl, fmmstat;
- int retval = ERROR_FLASH_OPERATION_FAILED;
-
- /* set GLBCTRL.4 */
- target_read_u32(target, 0xFFFFFFDC, &glbctrl);
- target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
-
- /* only perform the key match when 3VSTAT is clear */
- target_read_u32(target, 0xFFE8BC0C, &fmmstat);
- if (!(fmmstat & 0x08)) {
- unsigned i;
- uint32_t fmbptr, fmbac2, orig_fmregopt;
-
- target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);
-
- /* wait for pump ready */
- do {
- target_read_u32(target, 0xFFE8A814, &fmbptr);
- alive_sleep(1);
- } while (!(fmbptr & 0x0200));
-
- /* force max wait states */
- target_read_u32(target, 0xFFE88004, &fmbac2);
- target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
-
- /* save current access mode, force normal read mode */
- target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
- target_write_u32(target, 0xFFE89C00, 0x00);
-
- for (i = 0; i < 4; i++) {
- uint32_t tmp;
-
- /* There is no point displaying the value of tmp, it is
- * filtered by the chip. The purpose of this read is to
- * prime the unlocking logic rather than read out the value.
- */
- target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
-
- LOG_INFO("tms470 writing fmpkey = 0x%08" PRIx32 "", key_set[i]);
- target_write_u32(target, 0xFFE89C0C, key_set[i]);
- }
-
- if (ERROR_OK == tms470_check_flash_unlocked(target)) {
- /*
- * There seems to be a side-effect of reading the FMPKEY
- * register in that it re-enables the protection. So we
- * re-enable it.
- */
- for (i = 0; i < 4; i++) {
- uint32_t tmp;
-
- target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
- target_write_u32(target, 0xFFE89C0C, key_set[i]);
- }
- retval = ERROR_OK;
- }
-
- /* restore settings */
- target_write_u32(target, 0xFFE89C00, orig_fmregopt);
- target_write_u32(target, 0xFFE88004, fmbac2);
- }
-
- /* clear config bit */
- target_write_u32(target, 0xFFFFFFDC, glbctrl);
-
- return retval;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_unlock_flash(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- const uint32_t *p_key_sets[5];
- unsigned i, key_set_count;
-
- if (keysSet) {
- key_set_count = 5;
- p_key_sets[0] = flashKeys;
- p_key_sets[1] = FLASH_KEYS_ALL_ONES;
- p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
- p_key_sets[3] = FLASH_KEYS_MIX1;
- p_key_sets[4] = FLASH_KEYS_MIX2;
- } else {
- key_set_count = 4;
- p_key_sets[0] = FLASH_KEYS_ALL_ONES;
- p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
- p_key_sets[2] = FLASH_KEYS_MIX1;
- p_key_sets[3] = FLASH_KEYS_MIX2;
- }
-
- for (i = 0; i < key_set_count; i++) {
- if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK) {
- LOG_INFO("tms470 flash is unlocked");
- return ERROR_OK;
- }
- }
-
- LOG_WARNING("tms470 could not unlock flash memory protection level 2");
- return ERROR_FLASH_OPERATION_FAILED;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_flash_initialize_internal_state_machine(struct flash_bank *bank)
-{
- uint32_t fmmac2, fmmac1, fmmaxep, k, delay, glbctrl, sysclk;
- struct target *target = bank->target;
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
- int result = ERROR_OK;
-
- /*
- * Select the desired bank to be programmed by writing BANK[2:0] of
- * FMMAC2.
- */
- target_read_u32(target, 0xFFE8BC04, &fmmac2);
- fmmac2 &= ~0x0007;
- fmmac2 |= (tms470_info->ordinal & 7);
- target_write_u32(target, 0xFFE8BC04, fmmac2);
- LOG_DEBUG("set fmmac2 = 0x%04" PRIx32 "", fmmac2);
-
- /*
- * Disable level 1 sector protection by setting bit 15 of FMMAC1.
- */
- target_read_u32(target, 0xFFE8BC00, &fmmac1);
- fmmac1 |= 0x8000;
- target_write_u32(target, 0xFFE8BC00, fmmac1);
- LOG_DEBUG("set fmmac1 = 0x%04" PRIx32 "", fmmac1);
-
- /*
- * FMTCREG = 0x2fc0;
- */
- target_write_u32(target, 0xFFE8BC10, 0x2fc0);
- LOG_DEBUG("set fmtcreg = 0x2fc0");
-
- /*
- * MAXPP = 50
- */
- target_write_u32(target, 0xFFE8A07C, 50);
- LOG_DEBUG("set fmmaxpp = 50");
-
- /*
- * MAXCP = 0xf000 + 2000
- */
- target_write_u32(target, 0xFFE8A084, 0xf000 + 2000);
- LOG_DEBUG("set fmmaxcp = 0x%04x", 0xf000 + 2000);
-
- /*
- * configure VHV
- */
- target_read_u32(target, 0xFFE8A080, &fmmaxep);
- if (fmmaxep == 0xf000) {
- fmmaxep = 0xf000 + 4095;
- target_write_u32(target, 0xFFE8A80C, 0x9964);
- LOG_DEBUG("set fmptr3 = 0x9964");
- } else {
- fmmaxep = 0xa000 + 4095;
- target_write_u32(target, 0xFFE8A80C, 0x9b64);
- LOG_DEBUG("set fmptr3 = 0x9b64");
- }
- target_write_u32(target, 0xFFE8A080, fmmaxep);
- LOG_DEBUG("set fmmaxep = 0x%04" PRIx32 "", fmmaxep);
-
- /*
- * FMPTR4 = 0xa000
- */
- target_write_u32(target, 0xFFE8A810, 0xa000);
- LOG_DEBUG("set fmptr4 = 0xa000");
-
- /*
- * FMPESETUP, delay parameter selected based on clock frequency.
- *
- * According to the TI App Note SPNU257 and flashing code, delay is
- * int((sysclk(MHz) + 1) / 2), with a minimum of 5. The system
- * clock is usually derived from the ZPLL module, and selected by
- * the plldis global.
- */
- target_read_u32(target, 0xFFFFFFDC, &glbctrl);
- sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8) * oscMHz / (1 + (glbctrl & 7));
- delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5;
- target_write_u32(target, 0xFFE8A018, (delay << 4) | (delay << 8));
- LOG_DEBUG("set fmpsetup = 0x%04" PRIx32 "", (delay << 4) | (delay << 8));
-
- /*
- * FMPVEVACCESS, based on delay.
- */
- k = delay | (delay << 8);
- target_write_u32(target, 0xFFE8A05C, k);
- LOG_DEBUG("set fmpvevaccess = 0x%04" PRIx32 "", k);
-
- /*
- * FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay.
- */
- k <<= 1;
- target_write_u32(target, 0xFFE8A034, k);
- LOG_DEBUG("set fmpchold = 0x%04" PRIx32 "", k);
- target_write_u32(target, 0xFFE8A040, k);
- LOG_DEBUG("set fmpvevhold = 0x%04" PRIx32 "", k);
- target_write_u32(target, 0xFFE8A024, k);
- LOG_DEBUG("set fmpvevsetup = 0x%04" PRIx32 "", k);
-
- /*
- * FMCVACCESS, based on delay.
- */
- k = delay * 16;
- target_write_u32(target, 0xFFE8A060, k);
- LOG_DEBUG("set fmcvaccess = 0x%04" PRIx32 "", k);
-
- /*
- * FMCSETUP, based on delay.
- */
- k = 0x3000 | delay * 20;
- target_write_u32(target, 0xFFE8A020, k);
- LOG_DEBUG("set fmcsetup = 0x%04" PRIx32 "", k);
-
- /*
- * FMEHOLD, based on delay.
- */
- k = (delay * 20) << 2;
- target_write_u32(target, 0xFFE8A038, k);
- LOG_DEBUG("set fmehold = 0x%04" PRIx32 "", k);
-
- /*
- * PWIDTH, CWIDTH, EWIDTH, based on delay.
- */
- target_write_u32(target, 0xFFE8A050, delay * 8);
- LOG_DEBUG("set fmpwidth = 0x%04" PRIx32 "", delay * 8);
- target_write_u32(target, 0xFFE8A058, delay * 1000);
- LOG_DEBUG("set fmcwidth = 0x%04" PRIx32 "", delay * 1000);
- target_write_u32(target, 0xFFE8A054, delay * 5400);
- LOG_DEBUG("set fmewidth = 0x%04" PRIx32 "", delay * 5400);
-
- return result;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_flash_status(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int result = ERROR_OK;
- uint32_t fmmstat;
-
- target_read_u32(target, 0xFFE8BC0C, &fmmstat);
- LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);
-
- if (fmmstat & 0x0080) {
- LOG_WARNING("tms470 flash command: erase still active after busy clear.");
- result = ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (fmmstat & 0x0040) {
- LOG_WARNING("tms470 flash command: program still active after busy clear.");
- result = ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (fmmstat & 0x0020) {
- LOG_WARNING("tms470 flash command: invalid data command.");
- result = ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (fmmstat & 0x0010) {
- LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
- result = ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (fmmstat & 0x0008) {
- LOG_WARNING("tms470 flash command: voltage instability detected.");
- result = ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (fmmstat & 0x0006) {
- LOG_WARNING("tms470 flash command: command suspend detected.");
- result = ERROR_FLASH_OPERATION_FAILED;
- }
-
- if (fmmstat & 0x0001) {
- LOG_WARNING("tms470 flash command: sector was locked.");
- result = ERROR_FLASH_OPERATION_FAILED;
- }
-
- return result;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_erase_sector(struct flash_bank *bank, int sector)
-{
- uint32_t glbctrl, orig_fmregopt, fmbsea, fmbseb, fmmstat;
- struct target *target = bank->target;
- uint32_t flashAddr = bank->base + bank->sectors[sector].offset;
- int result = ERROR_OK;
-
- /*
- * Set the bit GLBCTRL4 of the GLBCTRL register (in the System
- * module) to enable writing to the flash registers }.
- */
- target_read_u32(target, 0xFFFFFFDC, &glbctrl);
- target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
- LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl | 0x10);
-
- /* Force normal read mode. */
- target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
- target_write_u32(target, 0xFFE89C00, 0);
- LOG_DEBUG("set fmregopt = 0x%08x", 0);
-
- (void)tms470_flash_initialize_internal_state_machine(bank);
-
- /*
- * Select one or more bits in FMBSEA or FMBSEB to disable Level 1
- * protection for the particular sector to be erased/written.
- */
- if (sector < 16) {
- target_read_u32(target, 0xFFE88008, &fmbsea);
- target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
- LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
- } else {
- target_read_u32(target, 0xFFE8800C, &fmbseb);
- target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
- LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
- }
- bank->sectors[sector].is_protected = 0;
-
- /*
- * clear status regiser, sent erase command, kickoff erase
- */
- target_write_u16(target, flashAddr, 0x0040);
- LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0040", flashAddr);
- target_write_u16(target, flashAddr, 0x0020);
- LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0020", flashAddr);
- target_write_u16(target, flashAddr, 0xffff);
- LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0xffff", flashAddr);
-
- /*
- * Monitor FMMSTAT, busy until clear, then check and other flags for
- * ultimate result of the operation.
- */
- do {
- target_read_u32(target, 0xFFE8BC0C, &fmmstat);
- if (fmmstat & 0x0100)
- alive_sleep(1);
- } while (fmmstat & 0x0100);
-
- result = tms470_flash_status(bank);
-
- if (sector < 16) {
- target_write_u32(target, 0xFFE88008, fmbsea);
- LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
- bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
- } else {
- target_write_u32(target, 0xFFE8800C, fmbseb);
- LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
- bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
- }
- target_write_u32(target, 0xFFE89C00, orig_fmregopt);
- LOG_DEBUG("set fmregopt = 0x%08" PRIx32 "", orig_fmregopt);
- target_write_u32(target, 0xFFFFFFDC, glbctrl);
- LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
-
- if (result == ERROR_OK)
- bank->sectors[sector].is_erased = 1;
-
- return result;
-}
-
-/*----------------------------------------------------------------------
- * Implementation of Flash Driver Interfaces
- *---------------------------------------------------------------------- */
-
-static const struct command_registration tms470_any_command_handlers[] = {
- {
- .name = "flash_keyset",
- .usage = "<key0> <key1> <key2> <key3>",
- .handler = tms470_handle_flash_keyset_command,
- .mode = COMMAND_ANY,
- .help = "tms470 flash_keyset <key0> <key1> <key2> <key3>",
- },
- {
- .name = "osc_megahertz",
- .usage = "<MHz>",
- .handler = tms470_handle_osc_megahertz_command,
- .mode = COMMAND_ANY,
- .help = "tms470 osc_megahertz <MHz>",
- },
- {
- .name = "plldis",
- .usage = "<0 | 1>",
- .handler = tms470_handle_plldis_command,
- .mode = COMMAND_ANY,
- .help = "tms470 plldis <0/1>",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration tms470_command_handlers[] = {
- {
- .name = "tms470",
- .mode = COMMAND_ANY,
- .help = "TI tms470 flash command group",
- .usage = "",
- .chain = tms470_any_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_erase(struct flash_bank *bank, int first, int last)
-{
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
- int sector, result = ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- tms470_read_part_info(bank);
-
- if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
- (last >= bank->num_sectors) || (first > last)) {
- LOG_ERROR("Sector range %d to %d invalid.", first, last);
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- result = tms470_unlock_flash(bank);
- if (result != ERROR_OK)
- return result;
-
- for (sector = first; sector <= last; sector++) {
- LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector);
-
- result = tms470_erase_sector(bank, sector);
-
- if (result != ERROR_OK) {
- LOG_ERROR("tms470 could not erase flash sector.");
- break;
- } else
- LOG_INFO("sector erased successfully.");
- }
-
- return result;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
- struct target *target = bank->target;
- uint32_t fmmac2, fmbsea, fmbseb;
- int sector;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- tms470_read_part_info(bank);
-
- if ((first < 0) || (first >= bank->num_sectors) || (last < 0) ||
- (last >= bank->num_sectors) || (first > last)) {
- LOG_ERROR("Sector range %d to %d invalid.", first, last);
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- /* enable the appropriate bank */
- target_read_u32(target, 0xFFE8BC04, &fmmac2);
- target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
-
- /* get the original sector proection flags for this bank */
- target_read_u32(target, 0xFFE88008, &fmbsea);
- target_read_u32(target, 0xFFE8800C, &fmbseb);
-
- for (sector = 0; sector < bank->num_sectors; sector++) {
- if (sector < 16) {
- fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
- bank->sectors[sector].is_protected = set ? 1 : 0;
- } else {
- fmbseb = set ? fmbseb &
- ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
- bank->sectors[sector].is_protected = set ? 1 : 0;
- }
- }
-
- /* update the protection bits */
- target_write_u32(target, 0xFFE88008, fmbsea);
- target_write_u32(target, 0xFFE8800C, fmbseb);
-
- return ERROR_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct target *target = bank->target;
- uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
- int result = ERROR_OK;
- uint32_t i;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- tms470_read_part_info(bank);
-
- LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base +
- offset);
-
- /* set GLBCTRL.4 */
- target_read_u32(target, 0xFFFFFFDC, &glbctrl);
- target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
-
- (void)tms470_flash_initialize_internal_state_machine(bank);
-
- /* force max wait states */
- target_read_u32(target, 0xFFE88004, &fmbac2);
- target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
-
- /* save current access mode, force normal read mode */
- target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
- target_write_u32(target, 0xFFE89C00, 0x00);
-
- /*
- * Disable Level 1 protection for all sectors to be erased/written.
- */
- target_read_u32(target, 0xFFE88008, &fmbsea);
- target_write_u32(target, 0xFFE88008, 0xffff);
- target_read_u32(target, 0xFFE8800C, &fmbseb);
- target_write_u32(target, 0xFFE8800C, 0xffff);
-
- /* read MAXPP */
- target_read_u32(target, 0xFFE8A07C, &fmmaxpp);
-
- for (i = 0; i < count; i += 2) {
- uint32_t addr = bank->base + offset + i;
- uint16_t word = (((uint16_t) buffer[i]) << 8) | (uint16_t) buffer[i + 1];
-
- if (word != 0xffff) {
- LOG_INFO("writing 0x%04x at 0x%08" PRIx32 "", word, addr);
-
- /* clear status register */
- target_write_u16(target, addr, 0x0040);
- /* program flash command */
- target_write_u16(target, addr, 0x0010);
- /* burn the 16-bit word (big-endian) */
- target_write_u16(target, addr, word);
-
- /*
- * Monitor FMMSTAT, busy until clear, then check and other flags
- * for ultimate result of the operation.
- */
- do {
- target_read_u32(target, 0xFFE8BC0C, &fmmstat);
- if (fmmstat & 0x0100)
- alive_sleep(1);
- } while (fmmstat & 0x0100);
-
- if (fmmstat & 0x3ff) {
- LOG_ERROR("fmstat = 0x%04" PRIx32 "", fmmstat);
- LOG_ERROR(
- "Could not program word 0x%04x at address 0x%08" PRIx32 ".",
- word,
- addr);
- result = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
- } else
- LOG_INFO("skipping 0xffff at 0x%08" PRIx32 "", addr);
- }
-
- /* restore */
- target_write_u32(target, 0xFFE88008, fmbsea);
- target_write_u32(target, 0xFFE8800C, fmbseb);
- target_write_u32(target, 0xFFE88004, fmbac2);
- target_write_u32(target, 0xFFE89C00, orig_fmregopt);
- target_write_u32(target, 0xFFFFFFDC, glbctrl);
-
- return result;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_probe(struct flash_bank *bank)
-{
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- return tms470_read_part_info(bank);
-}
-
-static int tms470_auto_probe(struct flash_bank *bank)
-{
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
-
- if (tms470_info->device_ident_reg)
- return ERROR_OK;
- return tms470_probe(bank);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_erase_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
- int sector, result = ERROR_OK;
- uint32_t fmmac2, fmbac2, glbctrl, orig_fmregopt;
- static uint8_t buffer[64 * 1024];
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!tms470_info->device_ident_reg)
- tms470_read_part_info(bank);
-
- /* set GLBCTRL.4 */
- target_read_u32(target, 0xFFFFFFDC, &glbctrl);
- target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
-
- /* save current access mode, force normal read mode */
- target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
- target_write_u32(target, 0xFFE89C00, 0x00);
-
- /* enable the appropriate bank */
- target_read_u32(target, 0xFFE8BC04, &fmmac2);
- target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
-
- /* TCR = 0 */
- target_write_u32(target, 0xFFE8BC10, 0x2fc0);
-
- /* clear TEZ in fmbrdy */
- target_write_u32(target, 0xFFE88010, 0x0b);
-
- /* save current wait states, force max */
- target_read_u32(target, 0xFFE88004, &fmbac2);
- target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);
-
- /*
- * The TI primitives inspect the flash memory by reading one 32-bit
- * word at a time. Here we read an entire sector and inspect it in
- * an attempt to reduce the JTAG overhead.
- */
- for (sector = 0; sector < bank->num_sectors; sector++) {
- if (bank->sectors[sector].is_erased != 1) {
- uint32_t i, addr = bank->base + bank->sectors[sector].offset;
-
- LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector);
-
- target_read_buffer(target, addr, bank->sectors[sector].size, buffer);
-
- bank->sectors[sector].is_erased = 1;
- for (i = 0; i < bank->sectors[sector].size; i++) {
- if (buffer[i] != 0xff) {
- LOG_WARNING("tms470 bank %d, sector %d, not erased.",
- tms470_info->ordinal,
- sector);
- LOG_WARNING(
- "at location 0x%08" PRIx32 ": flash data is 0x%02x.",
- addr + i,
- buffer[i]);
-
- bank->sectors[sector].is_erased = 0;
- break;
- }
- }
- }
- if (bank->sectors[sector].is_erased != 1) {
- result = ERROR_FLASH_SECTOR_NOT_ERASED;
- break;
- } else
- LOG_INFO("sector erased");
- }
-
- /* reset TEZ, wait states, read mode, GLBCTRL.4 */
- target_write_u32(target, 0xFFE88010, 0x0f);
- target_write_u32(target, 0xFFE88004, fmbac2);
- target_write_u32(target, 0xFFE89C00, orig_fmregopt);
- target_write_u32(target, 0xFFFFFFDC, glbctrl);
-
- return result;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tms470_protect_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
- int sector, result = ERROR_OK;
- uint32_t fmmac2, fmbsea, fmbseb;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!tms470_info->device_ident_reg)
- tms470_read_part_info(bank);
-
- /* enable the appropriate bank */
- target_read_u32(target, 0xFFE8BC04, &fmmac2);
- target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);
-
- target_read_u32(target, 0xFFE88008, &fmbsea);
- target_read_u32(target, 0xFFE8800C, &fmbseb);
-
- for (sector = 0; sector < bank->num_sectors; sector++) {
- int protected;
-
- if (sector < 16) {
- protected = fmbsea & (1 << sector) ? 0 : 1;
- bank->sectors[sector].is_protected = protected;
- } else {
- protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
- bank->sectors[sector].is_protected = protected;
- }
-
- LOG_DEBUG("bank %d sector %d is %s",
- tms470_info->ordinal,
- sector,
- protected ? "protected" : "not protected");
- }
-
- return result;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int get_tms470_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- int used = 0;
- struct tms470_flash_bank *tms470_info = bank->driver_priv;
-
- if (!tms470_info->device_ident_reg)
- tms470_read_part_info(bank);
-
- if (!tms470_info->device_ident_reg) {
- (void)snprintf(buf, buf_size, "Cannot identify target as a TMS470\n");
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- used =
- snprintf(buf, buf_size, "\ntms470 information: Chip is %s\n",
- tms470_info->part_name);
- buf += used;
- buf_size -= used;
-
- snprintf(buf, buf_size, "Flash protection level 2 is %s\n",
- tms470_check_flash_unlocked(bank->target) == ERROR_OK ? "disabled" : "enabled");
-
- return ERROR_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-/*
- * flash bank tms470 <base> <size> <chip_width> <bus_width> <target>
- * [options...]
- */
-
-FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
-{
- bank->driver_priv = malloc(sizeof(struct tms470_flash_bank));
-
- if (!bank->driver_priv)
- return ERROR_FLASH_OPERATION_FAILED;
-
- (void)memset(bank->driver_priv, 0, sizeof(struct tms470_flash_bank));
-
- return ERROR_OK;
-}
-
-struct flash_driver tms470_flash = {
- .name = "tms470",
- .commands = tms470_command_handlers,
- .flash_bank_command = tms470_flash_bank_command,
- .erase = tms470_erase,
- .protect = tms470_protect,
- .write = tms470_write,
- .read = default_flash_read,
- .probe = tms470_probe,
- .auto_probe = tms470_auto_probe,
- .erase_check = tms470_erase_check,
- .protect_check = tms470_protect_check,
- .info = get_tms470_info,
-};
diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c
deleted file mode 100644
index 3cb793e..0000000
--- a/src/flash/nor/virtual.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-
-static struct flash_bank *virtual_get_master_bank(struct flash_bank *bank)
-{
- struct flash_bank *master_bank;
-
- master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv);
- if (master_bank == NULL)
- LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv);
-
- return master_bank;
-}
-
-static void virtual_update_bank_info(struct flash_bank *bank)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
-
- if (master_bank == NULL)
- return;
-
- /* update the info we do not have */
- bank->size = master_bank->size;
- bank->chip_width = master_bank->chip_width;
- bank->bus_width = master_bank->bus_width;
- bank->default_padded_value = master_bank->default_padded_value;
- bank->num_sectors = master_bank->num_sectors;
- bank->sectors = master_bank->sectors;
-}
-
-FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
-{
- if (CMD_ARGC < 7)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* get the master flash bank */
- const char *bank_name = CMD_ARGV[6];
- struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name);
-
- if (master_bank == NULL) {
- LOG_ERROR("master flash bank '%s' does not exist", bank_name);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- /* save master bank name - use this to get settings later */
- bank->driver_priv = strdup(bank_name);
-
- return ERROR_OK;
-}
-
-static int virtual_protect(struct flash_bank *bank, int set, int first, int last)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->protect(master_bank, set, first, last);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int virtual_protect_check(struct flash_bank *bank)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->protect_check(master_bank);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int virtual_erase(struct flash_bank *bank, int first, int last)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->erase(master_bank, first, last);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int virtual_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->write(master_bank, buffer, offset, count);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int virtual_probe(struct flash_bank *bank)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->probe(master_bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* update the info we do not have */
- virtual_update_bank_info(bank);
-
- return ERROR_OK;
-}
-
-static int virtual_auto_probe(struct flash_bank *bank)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->auto_probe(master_bank);
- if (retval != ERROR_OK)
- return retval;
-
- /* update the info we do not have */
- virtual_update_bank_info(bank);
-
- return ERROR_OK;
-}
-
-static int virtual_info(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
- bank->driver->name, master_bank->name, master_bank->base);
-
- return ERROR_OK;
-}
-
-static int virtual_blank_check(struct flash_bank *bank)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->erase_check(master_bank);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int virtual_flash_read(struct flash_bank *bank,
- uint8_t *buffer, uint32_t offset, uint32_t count)
-{
- struct flash_bank *master_bank = virtual_get_master_bank(bank);
- int retval;
-
- if (master_bank == NULL)
- return ERROR_FLASH_OPERATION_FAILED;
-
- /* call master handler */
- retval = master_bank->driver->read(master_bank, buffer, offset, count);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-struct flash_driver virtual_flash = {
- .name = "virtual",
- .flash_bank_command = virtual_flash_bank_command,
- .erase = virtual_erase,
- .protect = virtual_protect,
- .write = virtual_write,
- .read = virtual_flash_read,
- .probe = virtual_probe,
- .auto_probe = virtual_auto_probe,
- .erase_check = virtual_blank_check,
- .protect_check = virtual_protect_check,
- .info = virtual_info,
-};
diff --git a/src/flash/nor/xmc1xxx.c b/src/flash/nor/xmc1xxx.c
deleted file mode 100644
index bb2ec12..0000000
--- a/src/flash/nor/xmc1xxx.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * XMC1000 flash driver
- *
- * Copyright (c) 2016 Andreas Färber
- *
- * License: GPL-2.0+
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-#define FLASH_BASE 0x10000000
-#define PAU_BASE 0x40000000
-#define SCU_BASE 0x40010000
-#define NVM_BASE 0x40050000
-
-#define FLASH_CS0 (FLASH_BASE + 0xf00)
-
-#define PAU_FLSIZE (PAU_BASE + 0x404)
-
-#define SCU_IDCHIP (SCU_BASE + 0x004)
-
-#define NVMSTATUS (NVM_BASE + 0x00)
-#define NVMPROG (NVM_BASE + 0x04)
-#define NVMCONF (NVM_BASE + 0x08)
-
-#define NVMSTATUS_BUSY (1 << 0)
-#define NVMSTATUS_VERR_MASK (0x3 << 2)
-
-#define NVMPROG_ACTION_OPTYPE_IDLE_VERIFY (0 << 0)
-#define NVMPROG_ACTION_OPTYPE_WRITE (1 << 0)
-#define NVMPROG_ACTION_OPTYPE_PAGE_ERASE (2 << 0)
-
-#define NVMPROG_ACTION_ONE_SHOT_ONCE (1 << 4)
-#define NVMPROG_ACTION_ONE_SHOT_CONTINUOUS (2 << 4)
-
-#define NVMPROG_ACTION_VERIFY_EACH (1 << 6)
-#define NVMPROG_ACTION_VERIFY_NO (2 << 6)
-#define NVMPROG_ACTION_VERIFY_ARRAY (3 << 6)
-
-#define NVMPROG_ACTION_IDLE 0x00
-#define NVMPROG_ACTION_MASK 0xff
-
-#define NVM_WORD_SIZE 4
-#define NVM_BLOCK_SIZE (4 * NVM_WORD_SIZE)
-#define NVM_PAGE_SIZE (16 * NVM_BLOCK_SIZE)
-
-struct xmc1xxx_flash_bank {
- bool probed;
-};
-
-static int xmc1xxx_nvm_set_idle(struct target *target)
-{
- return target_write_u16(target, NVMPROG, NVMPROG_ACTION_IDLE);
-}
-
-static int xmc1xxx_nvm_check_idle(struct target *target)
-{
- uint16_t val;
- int retval;
-
- retval = target_read_u16(target, NVMPROG, &val);
- if (retval != ERROR_OK)
- return retval;
- if ((val & NVMPROG_ACTION_MASK) != NVMPROG_ACTION_IDLE) {
- LOG_WARNING("NVMPROG.ACTION");
- retval = xmc1xxx_nvm_set_idle(target);
- }
-
- return retval;
-}
-
-static int xmc1xxx_erase(struct flash_bank *bank, int first, int last)
-{
- struct target *target = bank->target;
- struct working_area *workarea;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_algo;
- unsigned i;
- int retval, sector;
- const uint8_t erase_code[] = {
-#include "../../../contrib/loaders/flash/xmc1xxx/erase.inc"
- };
-
- LOG_DEBUG("Infineon XMC1000 erase sectors %d to %d", first, last);
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = xmc1xxx_nvm_check_idle(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_alloc_working_area(target, sizeof(erase_code),
- &workarea);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available.");
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto err_alloc_code;
- }
- retval = target_write_buffer(target, workarea->address,
- sizeof(erase_code), erase_code);
- if (retval != ERROR_OK)
- goto err_write_code;
-
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
-
- 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);
-
- buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
- buf_set_u32(reg_params[1].value, 0, 32, bank->base +
- bank->sectors[first].offset);
- buf_set_u32(reg_params[2].value, 0, 32, bank->base +
- bank->sectors[last].offset + bank->sectors[last].size);
-
- retval = target_run_algorithm(target,
- 0, NULL,
- ARRAY_SIZE(reg_params), reg_params,
- workarea->address, 0,
- 1000, &armv7m_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing flash sector erase "
- "programming algorithm");
- retval = xmc1xxx_nvm_set_idle(target);
- if (retval != ERROR_OK)
- LOG_WARNING("Couldn't restore NVMPROG.ACTION");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run;
- }
-
- for (sector = first; sector <= last; sector++)
- bank->sectors[sector].is_erased = 1;
-
-err_run:
- for (i = 0; i < ARRAY_SIZE(reg_params); i++)
- destroy_reg_param(&reg_params[i]);
-
-err_write_code:
- target_free_working_area(target, workarea);
-
-err_alloc_code:
- return retval;
-}
-
-static int xmc1xxx_erase_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- struct working_area *workarea;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_algo;
- uint16_t val;
- unsigned i;
- int retval, sector;
- const uint8_t erase_check_code[] = {
-#include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc"
- };
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = target_alloc_working_area(target, sizeof(erase_check_code),
- &workarea);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available.");
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto err_alloc_code;
- }
- retval = target_write_buffer(target, workarea->address,
- sizeof(erase_check_code), erase_check_code);
- if (retval != ERROR_OK)
- goto err_write_code;
-
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
-
- 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);
-
- buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
-
- for (sector = 0; sector < bank->num_sectors; sector++) {
- uint32_t start = bank->base + bank->sectors[sector].offset;
- buf_set_u32(reg_params[1].value, 0, 32, start);
- buf_set_u32(reg_params[2].value, 0, 32, start + bank->sectors[sector].size);
-
- retval = xmc1xxx_nvm_check_idle(target);
- if (retval != ERROR_OK)
- goto err_nvmprog;
-
- LOG_DEBUG("Erase-checking 0x%08" PRIx32, start);
- retval = target_run_algorithm(target,
- 0, NULL,
- ARRAY_SIZE(reg_params), reg_params,
- workarea->address, 0,
- 1000, &armv7m_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing flash sector erase check "
- "programming algorithm");
- retval = xmc1xxx_nvm_set_idle(target);
- if (retval != ERROR_OK)
- LOG_WARNING("Couldn't restore NVMPROG.ACTION");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run;
- }
-
- retval = target_read_u16(target, NVMSTATUS, &val);
- if (retval != ERROR_OK) {
- LOG_ERROR("Couldn't read NVMSTATUS");
- goto err_nvmstatus;
- }
- bank->sectors[sector].is_erased = (val & NVMSTATUS_VERR_MASK) ? 0 : 1;
- }
-
-err_nvmstatus:
-err_run:
-err_nvmprog:
- for (i = 0; i < ARRAY_SIZE(reg_params); i++)
- destroy_reg_param(&reg_params[i]);
-
-err_write_code:
- target_free_working_area(target, workarea);
-
-err_alloc_code:
- return retval;
-}
-
-static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t byte_count)
-{
- struct target *target = bank->target;
- struct working_area *code_workarea, *data_workarea;
- struct reg_param reg_params[4];
- struct armv7m_algorithm armv7m_algo;
- uint32_t block_count = DIV_ROUND_UP(byte_count, NVM_BLOCK_SIZE);
- unsigned i;
- int retval;
- const uint8_t write_code[] = {
-#include "../../../contrib/loaders/flash/xmc1xxx/write.inc"
- };
-
- LOG_DEBUG("Infineon XMC1000 write at 0x%08" PRIx32 " (%" PRId32 " bytes)",
- offset, byte_count);
-
- if (offset & (NVM_BLOCK_SIZE - 1)) {
- LOG_ERROR("offset 0x%" PRIx32 " breaks required block alignment",
- offset);
- return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
- }
- if (byte_count & (NVM_BLOCK_SIZE - 1)) {
- LOG_WARNING("length %" PRId32 " is not block aligned, rounding up",
- byte_count);
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = target_alloc_working_area(target, sizeof(write_code),
- &code_workarea);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available for write code.");
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto err_alloc_code;
- }
- retval = target_write_buffer(target, code_workarea->address,
- sizeof(write_code), write_code);
- if (retval != ERROR_OK)
- goto err_write_code;
-
- retval = target_alloc_working_area(target, MAX(NVM_BLOCK_SIZE,
- MIN(block_count * NVM_BLOCK_SIZE, target_get_working_area_avail(target))),
- &data_workarea);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available for write data.");
- retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- goto err_alloc_data;
- }
-
- armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_algo.core_mode = ARM_MODE_THREAD;
-
- 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);
-
- buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
-
- while (byte_count > 0) {
- uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE);
- uint32_t addr = bank->base + offset;
-
- LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32,
- MIN(blocks * NVM_BLOCK_SIZE, byte_count),
- data_workarea->address);
-
- retval = target_write_buffer(target, data_workarea->address,
- MIN(blocks * NVM_BLOCK_SIZE, byte_count), buffer);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error writing data buffer");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_write_data;
- }
- if (byte_count < blocks * NVM_BLOCK_SIZE) {
- retval = target_write_memory(target,
- data_workarea->address + byte_count, 1,
- blocks * NVM_BLOCK_SIZE - byte_count,
- &bank->default_padded_value);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error writing data padding");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_write_pad;
- }
- }
-
- LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRId32 "x)",
- addr, addr + blocks * NVM_BLOCK_SIZE - 1, blocks);
-
- retval = xmc1xxx_nvm_check_idle(target);
- if (retval != ERROR_OK)
- goto err_nvmprog;
-
- buf_set_u32(reg_params[1].value, 0, 32, addr);
- buf_set_u32(reg_params[2].value, 0, 32, data_workarea->address);
- buf_set_u32(reg_params[3].value, 0, 32, blocks);
-
- retval = target_run_algorithm(target,
- 0, NULL,
- ARRAY_SIZE(reg_params), reg_params,
- code_workarea->address, 0,
- 5 * 60 * 1000, &armv7m_algo);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error executing flash write "
- "programming algorithm");
- retval = xmc1xxx_nvm_set_idle(target);
- if (retval != ERROR_OK)
- LOG_WARNING("Couldn't restore NVMPROG.ACTION");
- retval = ERROR_FLASH_OPERATION_FAILED;
- goto err_run;
- }
-
- block_count -= blocks;
- offset += blocks * NVM_BLOCK_SIZE;
- buffer += blocks * NVM_BLOCK_SIZE;
- byte_count -= MIN(blocks * NVM_BLOCK_SIZE, byte_count);
- }
-
-err_run:
-err_nvmprog:
-err_write_pad:
-err_write_data:
- for (i = 0; i < ARRAY_SIZE(reg_params); i++)
- destroy_reg_param(&reg_params[i]);
-
- target_free_working_area(target, data_workarea);
-err_alloc_data:
-err_write_code:
- target_free_working_area(target, code_workarea);
-
-err_alloc_code:
- return retval;
-}
-
-static int xmc1xxx_protect_check(struct flash_bank *bank)
-{
- uint32_t nvmconf;
- int i, num_protected, retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = target_read_u32(bank->target, NVMCONF, &nvmconf);
- if (retval != ERROR_OK) {
- LOG_ERROR("Cannot read NVMCONF register.");
- return retval;
- }
- LOG_DEBUG("NVMCONF = %08" PRIx32, nvmconf);
-
- num_protected = (nvmconf >> 4) & 0xff;
-
- for (i = 0; i < bank->num_sectors; i++)
- bank->sectors[i].is_protected = (i < num_protected) ? 1 : 0;
-
- return ERROR_OK;
-}
-
-static int xmc1xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
-{
- uint32_t chipid[8];
- int i, retval;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Obtain the 8-word Chip Identification Number */
- for (i = 0; i < 7; i++) {
- retval = target_read_u32(bank->target, FLASH_CS0 + i * 4, &chipid[i]);
- if (retval != ERROR_OK) {
- LOG_ERROR("Cannot read CS0 register %i.", i);
- return retval;
- }
- LOG_DEBUG("ID[%d] = %08" PRIX32, i, chipid[i]);
- }
- retval = target_read_u32(bank->target, SCU_BASE + 0x000, &chipid[7]);
- if (retval != ERROR_OK) {
- LOG_ERROR("Cannot read DBGROMID register.");
- return retval;
- }
- LOG_DEBUG("ID[7] = %08" PRIX32, chipid[7]);
-
- snprintf(buf, buf_size, "XMC%" PRIx32 "00 %X flash %uKB ROM %uKB SRAM %uKB",
- (chipid[0] >> 12) & 0xff,
- 0xAA + (chipid[7] >> 28) - 1,
- (((chipid[6] >> 12) & 0x3f) - 1) * 4,
- (((chipid[4] >> 8) & 0x3f) * 256) / 1024,
- (((chipid[5] >> 8) & 0x1f) * 256 * 4) / 1024);
-
- return ERROR_OK;
-}
-
-static int xmc1xxx_probe(struct flash_bank *bank)
-{
- struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
- uint32_t flash_addr = bank->base;
- uint32_t idchip, flsize;
- int i, retval;
-
- if (xmc_bank->probed)
- return ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = target_read_u32(bank->target, SCU_IDCHIP, &idchip);
- if (retval != ERROR_OK) {
- LOG_ERROR("Cannot read IDCHIP register.");
- return retval;
- }
-
- if ((idchip & 0xffff0000) != 0x10000) {
- LOG_ERROR("IDCHIP register does not match XMC1xxx.");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("IDCHIP = %08" PRIx32, idchip);
-
- retval = target_read_u32(bank->target, PAU_FLSIZE, &flsize);
- if (retval != ERROR_OK) {
- LOG_ERROR("Cannot read FLSIZE register.");
- return retval;
- }
-
- bank->num_sectors = 1 + ((flsize >> 12) & 0x3f) - 1;
- bank->size = bank->num_sectors * 4 * 1024;
- bank->sectors = calloc(bank->num_sectors,
- sizeof(struct flash_sector));
- for (i = 0; i < bank->num_sectors; i++) {
- if (i == 0) {
- bank->sectors[i].size = 0x200;
- bank->sectors[i].offset = 0xE00;
- flash_addr += 0x1000;
- } else {
- bank->sectors[i].size = 4 * 1024;
- bank->sectors[i].offset = flash_addr - bank->base;
- flash_addr += bank->sectors[i].size;
- }
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
- }
-
- xmc_bank->probed = true;
-
- return ERROR_OK;
-}
-
-static int xmc1xxx_auto_probe(struct flash_bank *bank)
-{
- struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
-
- if (xmc_bank->probed)
- return ERROR_OK;
-
- return xmc1xxx_probe(bank);
-}
-
-FLASH_BANK_COMMAND_HANDLER(xmc1xxx_flash_bank_command)
-{
- struct xmc1xxx_flash_bank *xmc_bank;
-
- xmc_bank = malloc(sizeof(struct xmc1xxx_flash_bank));
- if (!xmc_bank)
- return ERROR_FLASH_OPERATION_FAILED;
-
- xmc_bank->probed = false;
-
- bank->driver_priv = xmc_bank;
-
- return ERROR_OK;
-}
-
-static const struct command_registration xmc1xxx_exec_command_handlers[] = {
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration xmc1xxx_command_handlers[] = {
- {
- .name = "xmc1xxx",
- .mode = COMMAND_ANY,
- .help = "xmc1xxx flash command group",
- .usage = "",
- .chain = xmc1xxx_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver xmc1xxx_flash = {
- .name = "xmc1xxx",
- .commands = xmc1xxx_command_handlers,
- .flash_bank_command = xmc1xxx_flash_bank_command,
- .info = xmc1xxx_get_info_command,
- .probe = xmc1xxx_probe,
- .auto_probe = xmc1xxx_auto_probe,
- .protect_check = xmc1xxx_protect_check,
- .read = default_flash_read,
- .erase = xmc1xxx_erase,
- .erase_check = xmc1xxx_erase_check,
- .write = xmc1xxx_write,
-};
diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c
deleted file mode 100644
index 39aec79..0000000
--- a/src/flash/nor/xmc4xxx.c
+++ /dev/null
@@ -1,1444 +0,0 @@
-/**************************************************************************
-* Copyright (C) 2015 Jeff Ciesielski <jeffciesielski@gmail.com> *
-* *
-* This program is free software; you can redistribute it and/or modify *
-* it under the terms of the GNU General Public License as published by *
-* the Free Software Foundation; either version 2 of the License, or *
-* (at your option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-* GNU General Public License for more details. *
-* *
-* You should have received a copy of the GNU General Public License *
-* along with this program. If not, see <http://www.gnu.org/licenses/>. *
-***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "imp.h"
-#include <helper/binarybuffer.h>
-#include <target/algorithm.h>
-#include <target/armv7m.h>
-
-/* Maximum number of sectors */
-#define MAX_XMC_SECTORS 12
-
-/* System control unit registers */
-#define SCU_REG_BASE 0x50004000
-
-#define SCU_ID_CHIP 0x04
-
-/* Base of the non-cached flash memory */
-#define PFLASH_BASE 0x0C000000
-
-/* User configuration block offsets */
-#define UCB0_BASE 0x00000000
-#define UCB1_BASE 0x00000400
-#define UCB2_BASE 0x00000800
-
-/* Flash register base */
-#define FLASH_REG_BASE 0x58000000
-
-/* PMU ID Registers */
-#define FLASH_REG_PMU_ID (FLASH_REG_BASE | 0x0508)
-
-/* PMU Fields */
-#define PMU_MOD_REV_MASK 0xFF
-#define PMU_MOD_TYPE_MASK 0xFF00
-#define PMU_MOD_NO_MASK 0xFFFF0000
-
-/* Prefetch Config */
-#define FLASH_REG_PREF_PCON (FLASH_REG_BASE | 0x4000)
-
-/* Prefetch Fields */
-#define PCON_IBYP (1 << 0)
-#define PCON_IINV (1 << 1)
-
-/* Flash ID Register */
-#define FLASH_REG_FLASH0_ID (FLASH_REG_BASE | 0x2008)
-
-/* Flash Status Register */
-#define FLASH_REG_FLASH0_FSR (FLASH_REG_BASE | 0x2010)
-
-#define FSR_PBUSY (0)
-#define FSR_FABUSY (1)
-#define FSR_PROG (4)
-#define FSR_ERASE (5)
-#define FSR_PFPAGE (6)
-#define FSR_PFOPER (8)
-#define FSR_SQER (10)
-#define FSR_PROER (11)
-#define FSR_PFSBER (12)
-#define FSR_PFDBER (14)
-#define FSR_PROIN (16)
-#define FSR_RPROIN (18)
-#define FSR_RPRODIS (19)
-#define FSR_WPROIN0 (21)
-#define FSR_WPROIN1 (22)
-#define FSR_WPROIN2 (23)
-#define FSR_WPRODIS0 (25)
-#define FSR_WPRODIS1 (26)
-#define FSR_SLM (28)
-#define FSR_VER (31)
-
-#define FSR_PBUSY_MASK (0x01 << FSR_PBUSY)
-#define FSR_FABUSY_MASK (0x01 << FSR_FABUSY)
-#define FSR_PROG_MASK (0x01 << FSR_PROG)
-#define FSR_ERASE_MASK (0x01 << FSR_ERASE)
-#define FSR_PFPAGE_MASK (0x01 << FSR_PFPAGE)
-#define FSR_PFOPER_MASK (0x01 << FSR_PFOPER)
-#define FSR_SQER_MASK (0x01 << FSR_SQER)
-#define FSR_PROER_MASK (0x01 << FSR_PROER)
-#define FSR_PFSBER_MASK (0x01 << FSR_PFSBER)
-#define FSR_PFDBER_MASK (0x01 << FSR_PFDBER)
-#define FSR_PROIN_MASK (0x01 << FSR_PROIN)
-#define FSR_RPROIN_MASK (0x01 << FSR_RPROIN)
-#define FSR_RPRODIS_MASK (0x01 << FSR_RPRODIS)
-#define FSR_WPROIN0_MASK (0x01 << FSR_WPROIN0)
-#define FSR_WPROIN1_MASK (0x01 << FSR_WPROIN1)
-#define FSR_WPROIN2_MASK (0x01 << FSR_WPROIN2)
-#define FSR_WPRODIS0_MASK (0x01 << FSR_WPRODIS0)
-#define FSR_WPRODIS1_MASK (0x01 << FSR_WPRODIS1)
-#define FSR_SLM_MASK (0x01 << FSR_SLM)
-#define FSR_VER_MASK (0x01 << FSR_VER)
-
-/* Flash Config Register */
-#define FLASH_REG_FLASH0_FCON (FLASH_REG_BASE | 0x2014)
-
-#define FCON_WSPFLASH (0)
-#define FCON_WSECPF (4)
-#define FCON_IDLE (13)
-#define FCON_ESLDIS (14)
-#define FCON_SLEEP (15)
-#define FCON_RPA (16)
-#define FCON_DCF (17)
-#define FCON_DDF (18)
-#define FCON_VOPERM (24)
-#define FCON_SQERM (25)
-#define FCON_PROERM (26)
-#define FCON_PFSBERM (27)
-#define FCON_PFDBERM (29)
-#define FCON_EOBM (31)
-
-#define FCON_WSPFLASH_MASK (0x0f << FCON_WSPFLASH)
-#define FCON_WSECPF_MASK (0x01 << FCON_WSECPF)
-#define FCON_IDLE_MASK (0x01 << FCON_IDLE)
-#define FCON_ESLDIS_MASK (0x01 << FCON_ESLDIS)
-#define FCON_SLEEP_MASK (0x01 << FCON_SLEEP)
-#define FCON_RPA_MASK (0x01 << FCON_RPA)
-#define FCON_DCF_MASK (0x01 << FCON_DCF)
-#define FCON_DDF_MASK (0x01 << FCON_DDF)
-#define FCON_VOPERM_MASK (0x01 << FCON_VOPERM)
-#define FCON_SQERM_MASK (0x01 << FCON_SQERM)
-#define FCON_PROERM_MASK (0x01 << FCON_PROERM)
-#define FCON_PFSBERM_MASK (0x01 << FCON_PFSBERM)
-#define FCON_PFDBERM_MASK (0x01 << FCON_PFDBERM)
-#define FCON_EOBM_MASK (0x01 << FCON_EOBM)
-
-/* Flash Margin Control Register */
-#define FLASH_REG_FLASH0_MARP (FLASH_REG_BASE | 0x2018)
-
-#define MARP_MARGIN (0)
-#define MARP_TRAPDIS (15)
-
-#define MARP_MARGIN_MASK (0x0f << MARP_MARGIN)
-#define MARP_TRAPDIS_MASK (0x01 << MARP_TRAPDIS)
-
-/* Flash Protection Registers */
-#define FLASH_REG_FLASH0_PROCON0 (FLASH_REG_BASE | 0x2020)
-#define FLASH_REG_FLASH0_PROCON1 (FLASH_REG_BASE | 0x2024)
-#define FLASH_REG_FLASH0_PROCON2 (FLASH_REG_BASE | 0x2028)
-
-#define PROCON_S0L (0)
-#define PROCON_S1L (1)
-#define PROCON_S2L (2)
-#define PROCON_S3L (3)
-#define PROCON_S4L (4)
-#define PROCON_S5L (5)
-#define PROCON_S6L (6)
-#define PROCON_S7L (7)
-#define PROCON_S8L (8)
-#define PROCON_S9L (9)
-#define PROCON_S10_S11L (10)
-#define PROCON_RPRO (15)
-
-#define PROCON_S0L_MASK (0x01 << PROCON_S0L)
-#define PROCON_S1L_MASK (0x01 << PROCON_S1L)
-#define PROCON_S2L_MASK (0x01 << PROCON_S2L)
-#define PROCON_S3L_MASK (0x01 << PROCON_S3L)
-#define PROCON_S4L_MASK (0x01 << PROCON_S4L)
-#define PROCON_S5L_MASK (0x01 << PROCON_S5L)
-#define PROCON_S6L_MASK (0x01 << PROCON_S6L)
-#define PROCON_S7L_MASK (0x01 << PROCON_S7L)
-#define PROCON_S8L_MASK (0x01 << PROCON_S8L)
-#define PROCON_S9L_MASK (0x01 << PROCON_S9L)
-#define PROCON_S10_S11L_MASK (0x01 << PROCON_S10_S11L)
-#define PROCON_RPRO_MASK (0x01 << PROCON_RPRO)
-
-#define FLASH_PROTECT_CONFIRMATION_CODE 0x8AFE15C3
-
-/* Flash controller configuration values */
-#define FLASH_ID_XMC4500 0xA2
-#define FLASH_ID_XMC4700_4800 0x92
-#define FLASH_ID_XMC4100_4200 0x9C
-#define FLASH_ID_XMC4400 0x9F
-
-/* Timeouts */
-#define FLASH_OP_TIMEOUT 5000
-
-/* Flash commands (write/erase/protect) are performed using special
- * command sequences that are written to magic addresses in the flash controller */
-/* Command sequence addresses. See reference manual, section 8: Flash Command Sequences */
-#define FLASH_CMD_ERASE_1 0x0C005554
-#define FLASH_CMD_ERASE_2 0x0C00AAA8
-#define FLASH_CMD_ERASE_3 FLASH_CMD_ERASE_1
-#define FLASH_CMD_ERASE_4 FLASH_CMD_ERASE_1
-#define FLASH_CMD_ERASE_5 FLASH_CMD_ERASE_2
-/* ERASE_6 is the sector base address */
-
-#define FLASH_CMD_CLEAR_STATUS FLASH_CMD_ERASE_1
-
-#define FLASH_CMD_ENTER_PAGEMODE FLASH_CMD_ERASE_1
-
-#define FLASH_CMD_LOAD_PAGE_1 0x0C0055F0
-#define FLASH_CMD_LOAD_PAGE_2 0x0C0055F4
-
-#define FLASH_CMD_WRITE_PAGE_1 FLASH_CMD_ERASE_1
-#define FLASH_CMD_WRITE_PAGE_2 FLASH_CMD_ERASE_2
-#define FLASH_CMD_WRITE_PAGE_3 FLASH_CMD_ERASE_1
-/* WRITE_PAGE_4 is the page base address */
-
-#define FLASH_CMD_TEMP_UNPROT_1 FLASH_CMD_ERASE_1
-#define FLASH_CMD_TEMP_UNPROT_2 FLASH_CMD_ERASE_2
-#define FLASH_CMD_TEMP_UNPROT_3 0x0C00553C
-#define FLASH_CMD_TEMP_UNPROT_4 FLASH_CMD_ERASE_2
-#define FLASH_CMD_TEMP_UNPROT_5 FLASH_CMD_ERASE_2
-#define FLASH_CMD_TEMP_UNPROT_6 0x0C005558
-
-struct xmc4xxx_flash_bank {
- bool probed;
-
- /* We need the flash controller ID to choose the sector layout */
- uint32_t fcon_id;
-
- /* Passwords used for protection operations */
- uint32_t pw1;
- uint32_t pw2;
- bool pw_set;
-
- /* Protection flags */
- bool read_protected;
-
- bool write_prot_otp[MAX_XMC_SECTORS];
-};
-
-struct xmc4xxx_command_seq {
- uint32_t address;
- uint32_t magic;
-};
-
-/* Sector capacities. See section 8 of xmc4x00_rm */
-static const unsigned int sector_capacity_8[8] = {
- 16, 16, 16, 16, 16, 16, 16, 128
-};
-
-static const unsigned int sector_capacity_9[9] = {
- 16, 16, 16, 16, 16, 16, 16, 128, 256
-};
-
-static const unsigned int sector_capacity_12[12] = {
- 16, 16, 16, 16, 16, 16, 16, 16, 128, 256, 256, 256
-};
-
-static const unsigned int sector_capacity_16[16] = {
- 16, 16, 16, 16, 16, 16, 16, 16, 128, 256, 256, 256, 256, 256, 256, 256
-};
-
-static int xmc4xxx_write_command_sequence(struct flash_bank *bank,
- struct xmc4xxx_command_seq *seq,
- int seq_len)
-{
- int res = ERROR_OK;
-
- for (int i = 0; i < seq_len; i++) {
- res = target_write_u32(bank->target, seq[i].address,
- seq[i].magic);
- if (res != ERROR_OK)
- return res;
- }
-
- return ERROR_OK;
-}
-
-static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
-{
- const unsigned int *capacity = NULL;
-
- /* At this point, we know which flash controller ID we're
- * talking to and simply need to fill out the bank structure accordingly */
- LOG_DEBUG("%d sectors", bank->num_sectors);
-
- switch (bank->num_sectors) {
- case 8:
- capacity = sector_capacity_8;
- break;
- case 9:
- capacity = sector_capacity_9;
- break;
- case 12:
- capacity = sector_capacity_12;
- break;
- case 16:
- capacity = sector_capacity_16;
- break;
- default:
- LOG_ERROR("Unexpected number of sectors, %d\n",
- bank->num_sectors);
- return ERROR_FAIL;
- }
-
- /* This looks like a bank that we understand, now we know the
- * corresponding sector capacities and we can add those up into the
- * bank size. */
- uint32_t total_offset = 0;
- bank->sectors = calloc(bank->num_sectors,
- sizeof(struct flash_sector));
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].size = capacity[i] * 1024;
- bank->sectors[i].offset = total_offset;
- bank->sectors[i].is_erased = -1;
- bank->sectors[i].is_protected = -1;
-
- bank->size += bank->sectors[i].size;
- LOG_DEBUG("\t%d: %uk", i, capacity[i]);
- total_offset += bank->sectors[i].size;
- }
-
- /* This part doesn't follow the typical standard of 0xff
- * being the default padding value.*/
- bank->default_padded_value = 0x00;
-
- return ERROR_OK;
-}
-
-static int xmc4xxx_probe(struct flash_bank *bank)
-{
- int res;
- uint32_t devid, config;
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
- uint8_t flash_id;
-
- if (fb->probed)
- return ERROR_OK;
-
- /* It's not possible for the DAP to access the OTP locations needed for
- * probing the part info and Flash geometry so we require that the target
- * be halted before proceeding. */
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* The SCU registers contain the ID of the chip */
- res = target_read_u32(bank->target, SCU_REG_BASE + SCU_ID_CHIP, &devid);
- if (res != ERROR_OK) {
- LOG_ERROR("Cannot read device identification register.");
- return res;
- }
-
- /* Make sure this is a XMC4000 family device */
- if ((devid & 0xF0000) != 0x40000 && devid != 0) {
- LOG_ERROR("Platform ID doesn't match XMC4xxx: 0x%08" PRIx32, devid);
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("Found XMC4xxx with devid: 0x%08" PRIx32, devid);
-
- /* Now sanity-check the Flash controller itself. */
- res = target_read_u32(bank->target, FLASH_REG_FLASH0_ID,
- &config);
- if (res != ERROR_OK) {
- LOG_ERROR("Cannot read Flash bank configuration.");
- return res;
- }
- flash_id = (config & 0xff0000) >> 16;
-
- /* The Flash configuration register is our only means of
- * determining the sector layout. We need to make sure that
- * we understand the type of controller we're dealing with */
- switch (flash_id) {
- case FLASH_ID_XMC4100_4200:
- bank->num_sectors = 8;
- LOG_DEBUG("XMC4xxx: XMC4100/4200 detected.");
- break;
- case FLASH_ID_XMC4400:
- bank->num_sectors = 9;
- LOG_DEBUG("XMC4xxx: XMC4400 detected.");
- break;
- case FLASH_ID_XMC4500:
- bank->num_sectors = 12;
- LOG_DEBUG("XMC4xxx: XMC4500 detected.");
- break;
- case FLASH_ID_XMC4700_4800:
- bank->num_sectors = 16;
- LOG_DEBUG("XMC4xxx: XMC4700/4800 detected.");
- break;
- default:
- LOG_ERROR("XMC4xxx: Unexpected flash ID. got %02" PRIx8,
- flash_id);
- return ERROR_FAIL;
- }
-
- /* Retrieve information about the particular bank we're probing and fill in
- * the bank structure accordingly. */
- res = xmc4xxx_load_bank_layout(bank);
- if (res == ERROR_OK) {
- /* We're done */
- fb->probed = true;
- } else {
- LOG_ERROR("Unable to load bank information.");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int xmc4xxx_get_sector_start_addr(struct flash_bank *bank,
- int sector, uint32_t *ret_addr)
-{
- /* Make sure we understand this sector */
- if (sector > bank->num_sectors)
- return ERROR_FAIL;
-
- *ret_addr = bank->base + bank->sectors[sector].offset;
-
- return ERROR_OK;
-
-}
-
-static int xmc4xxx_clear_flash_status(struct flash_bank *bank)
-{
- int res;
- /* TODO: Do we need to check for sequence error? */
- LOG_INFO("Clearing flash status");
- res = target_write_u32(bank->target, FLASH_CMD_CLEAR_STATUS,
- 0xF5);
- if (res != ERROR_OK) {
- LOG_ERROR("Unable to write erase command sequence");
- return res;
- }
-
- return ERROR_OK;
-}
-
-static int xmc4xxx_get_flash_status(struct flash_bank *bank, uint32_t *status)
-{
- int res;
-
- res = target_read_u32(bank->target, FLASH_REG_FLASH0_FSR, status);
-
- if (res != ERROR_OK)
- LOG_ERROR("Cannot read flash status register.");
-
- return res;
-}
-
-static int xmc4xxx_wait_status_busy(struct flash_bank *bank, int timeout)
-{
- int res;
- uint32_t status;
-
- res = xmc4xxx_get_flash_status(bank, &status);
- if (res != ERROR_OK)
- return res;
-
- /* While the flash controller is busy, wait */
- while (status & FSR_PBUSY_MASK) {
- res = xmc4xxx_get_flash_status(bank, &status);
- if (res != ERROR_OK)
- return res;
-
- if (timeout-- <= 0) {
- LOG_ERROR("Timed out waiting for flash");
- return ERROR_FAIL;
- }
- alive_sleep(1);
- keep_alive();
- }
-
- if (status & FSR_PROER_MASK) {
- LOG_ERROR("XMC4xxx flash protected");
- res = ERROR_FAIL;
- }
-
- return res;
-}
-
-static int xmc4xxx_erase_sector(struct flash_bank *bank, uint32_t address,
- bool user_config)
-{
- int res;
- uint32_t status;
-
- /* See reference manual table 8.4: Command Sequences for Flash Control */
- struct xmc4xxx_command_seq erase_cmd_seq[6] = {
- {FLASH_CMD_ERASE_1, 0xAA},
- {FLASH_CMD_ERASE_2, 0x55},
- {FLASH_CMD_ERASE_3, 0x80},
- {FLASH_CMD_ERASE_4, 0xAA},
- {FLASH_CMD_ERASE_5, 0x55},
- {0xFF, 0xFF} /* Needs filled in */
- };
-
- /* We need to fill in the base address of the sector we'll be
- * erasing, as well as the magic code that determines whether
- * this is a standard flash sector or a user configuration block */
-
- erase_cmd_seq[5].address = address;
- if (user_config) {
- /* Removing flash protection requires the addition of
- * the base address */
- erase_cmd_seq[5].address += bank->base;
- erase_cmd_seq[5].magic = 0xC0;
- } else {
- erase_cmd_seq[5].magic = 0x30;
- }
-
- res = xmc4xxx_write_command_sequence(bank, erase_cmd_seq,
- ARRAY_SIZE(erase_cmd_seq));
- if (res != ERROR_OK)
- return res;
-
- /* Read the flash status register */
- res = target_read_u32(bank->target, FLASH_REG_FLASH0_FSR, &status);
- if (res != ERROR_OK) {
- LOG_ERROR("Cannot read flash status register.");
- return res;
- }
-
- /* Check for a sequence error */
- if (status & FSR_SQER_MASK) {
- LOG_ERROR("Error with flash erase sequence");
- return ERROR_FAIL;
- }
-
- /* Make sure a flash erase was triggered */
- if (!(status & FSR_ERASE_MASK)) {
- LOG_ERROR("Flash failed to erase");
- return ERROR_FAIL;
- }
-
- /* Now we must wait for the erase operation to end */
- res = xmc4xxx_wait_status_busy(bank, FLASH_OP_TIMEOUT);
-
- return res;
-}
-
-static int xmc4xxx_erase(struct flash_bank *bank, int first, int last)
-{
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
- int res;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Unable to erase, target is not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!fb->probed) {
- res = xmc4xxx_probe(bank);
- if (res != ERROR_OK)
- return res;
- }
-
- uint32_t tmp_addr;
- /* Loop through the sectors and erase each one */
- for (int i = first; i <= last; i++) {
- res = xmc4xxx_get_sector_start_addr(bank, i, &tmp_addr);
- if (res != ERROR_OK) {
- LOG_ERROR("Invalid sector %d", i);
- return res;
- }
-
- LOG_DEBUG("Erasing sector %d @ 0x%08"PRIx32, i, tmp_addr);
-
- res = xmc4xxx_erase_sector(bank, tmp_addr, false);
- if (res != ERROR_OK) {
- LOG_ERROR("Unable to write erase command sequence");
- goto clear_status_and_exit;
- }
-
- /* Now we must wait for the erase operation to end */
- res = xmc4xxx_wait_status_busy(bank, FLASH_OP_TIMEOUT);
-
- if (res != ERROR_OK)
- goto clear_status_and_exit;
-
- bank->sectors[i].is_erased = 1;
- }
-
-clear_status_and_exit:
- res = xmc4xxx_clear_flash_status(bank);
- return res;
-
-}
-
-static int xmc4xxx_enter_page_mode(struct flash_bank *bank)
-{
- int res;
- uint32_t status;
-
- res = target_write_u32(bank->target, FLASH_CMD_ENTER_PAGEMODE, 0x50);
- if (res != ERROR_OK) {
- LOG_ERROR("Unable to write enter page mode command");
- return ERROR_FAIL;
- }
-
- res = xmc4xxx_get_flash_status(bank, &status);
-
- if (res != ERROR_OK)
- return res;
-
- /* Make sure we're in page mode */
- if (!(status & FSR_PFPAGE_MASK)) {
- LOG_ERROR("Unable to enter page mode");
- return ERROR_FAIL;
- }
-
- /* Make sure we didn't encounter a sequence error */
- if (status & FSR_SQER_MASK) {
- LOG_ERROR("Sequence error while entering page mode");
- return ERROR_FAIL;
- }
-
- return res;
-}
-
-/* The logical erase value of an xmc4xxx memory cell is 0x00,
- * therefore, we cannot use the built in flash blank check and must
- * implement our own */
-
-/** Checks whether a memory region is zeroed. */
-static int xmc4xxx_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank)
-{
- struct working_area *erase_check_algorithm;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
- int retval;
-
- static const uint8_t erase_check_code[] = {
-#include "../../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
- };
-
- /* make sure we have a working area */
- if (target_alloc_working_area(target, sizeof(erase_check_code),
- &erase_check_algorithm) != ERROR_OK)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- retval = target_write_buffer(target, erase_check_algorithm->address,
- sizeof(erase_check_code), (uint8_t *)erase_check_code);
- if (retval != ERROR_OK)
- goto cleanup;
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
- buf_set_u32(reg_params[0].value, 0, 32, address);
-
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
- buf_set_u32(reg_params[2].value, 0, 32, 0x00);
-
- retval = target_run_algorithm(target,
- 0,
- NULL,
- 3,
- reg_params,
- erase_check_algorithm->address,
- erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
- 10000,
- &armv7m_info);
-
- if (retval == ERROR_OK)
- *blank = buf_get_u32(reg_params[2].value, 0, 32);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
-cleanup:
- target_free_working_area(target, erase_check_algorithm);
-
- return retval;
-}
-
-static int xmc4xxx_flash_blank_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int i;
- int retval = ERROR_OK;
- uint32_t blank;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t address = bank->base + bank->sectors[i].offset;
- uint32_t size = bank->sectors[i].size;
-
- LOG_DEBUG("Erase checking 0x%08"PRIx32, address);
- retval = xmc4xxx_blank_check_memory(target, address, size, &blank);
-
- if (retval != ERROR_OK)
- break;
-
- if (blank == 0x00)
- bank->sectors[i].is_erased = 1;
- else
- bank->sectors[i].is_erased = 0;
- }
-
- return retval;
-}
-
-static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf,
- uint32_t offset, bool user_config)
-{
- int res;
- uint32_t status;
-
- /* Base of the flash write command */
- struct xmc4xxx_command_seq write_cmd_seq[4] = {
- {FLASH_CMD_WRITE_PAGE_1, 0xAA},
- {FLASH_CMD_WRITE_PAGE_2, 0x55},
- {FLASH_CMD_WRITE_PAGE_3, 0xFF}, /* Needs filled in */
- {0xFF, 0xFF} /* Needs filled in */
- };
-
- /* The command sequence differs depending on whether this is
- * being written to standard flash or the user configuration
- * area */
- if (user_config)
- write_cmd_seq[2].magic = 0xC0;
- else
- write_cmd_seq[2].magic = 0xA0;
-
- /* Finally, we need to add the address that this page will be
- * written to */
- write_cmd_seq[3].address = bank->base + offset;
- write_cmd_seq[3].magic = 0xAA;
-
-
- /* Flash pages are written 256 bytes at a time. For each 256
- * byte chunk, we need to:
- * 1. Enter page mode. This activates the flash write buffer
- * 2. Load the page buffer with data (2x 32 bit words at a time)
- * 3. Burn the page buffer into its intended location
- * If the starting offset is not on a 256 byte boundary, we
- * will need to pad the beginning of the write buffer
- * accordingly. Likewise, if the last page does not fill the
- * buffer, we should pad it to avoid leftover data from being
- * written to flash
- */
- res = xmc4xxx_enter_page_mode(bank);
- if (res != ERROR_OK)
- return res;
-
- /* Copy the data into the page buffer*/
- for (int i = 0; i < 256; i += 8) {
- uint32_t w_lo = target_buffer_get_u32(bank->target, &pg_buf[i]);
- uint32_t w_hi = target_buffer_get_u32(bank->target, &pg_buf[i + 4]);
- LOG_DEBUG("WLO: %08"PRIx32, w_lo);
- LOG_DEBUG("WHI: %08"PRIx32, w_hi);
-
- /* Data is loaded 2x 32 bit words at a time */
- res = target_write_u32(bank->target, FLASH_CMD_LOAD_PAGE_1, w_lo);
- if (res != ERROR_OK)
- return res;
-
- res = target_write_u32(bank->target, FLASH_CMD_LOAD_PAGE_2, w_hi);
- if (res != ERROR_OK)
- return res;
-
- /* Check for an error */
- res = xmc4xxx_get_flash_status(bank, &status);
- if (res != ERROR_OK)
- return res;
-
- if (status & FSR_SQER_MASK) {
- LOG_ERROR("Error loading page buffer");
- return ERROR_FAIL;
- }
- }
-
- /* The page buffer is now full, time to commit it to flash */
-
- res = xmc4xxx_write_command_sequence(bank, write_cmd_seq, ARRAY_SIZE(write_cmd_seq));
- if (res != ERROR_OK) {
- LOG_ERROR("Unable to enter write command sequence");
- return res;
- }
-
- /* Read the flash status register */
- res = xmc4xxx_get_flash_status(bank, &status);
- if (res != ERROR_OK)
- return res;
-
- /* Check for a sequence error */
- if (status & FSR_SQER_MASK) {
- LOG_ERROR("Error with flash write sequence");
- return ERROR_FAIL;
- }
-
- /* Make sure a flash write was triggered */
- if (!(status & FSR_PROG_MASK)) {
- LOG_ERROR("Failed to write flash page");
- return ERROR_FAIL;
- }
-
- /* Wait for the write operation to end */
- res = xmc4xxx_wait_status_busy(bank, FLASH_OP_TIMEOUT);
- if (res != ERROR_OK)
- return res;
-
- /* TODO: Verify that page was written without error */
- return res;
-}
-
-static int xmc4xxx_write(struct flash_bank *bank, const uint8_t *buffer,
- uint32_t offset, uint32_t count)
-{
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
- int res = ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Unable to erase, target is not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!fb->probed) {
- res = xmc4xxx_probe(bank);
- if (res != ERROR_OK)
- return res;
- }
-
- /* Make sure we won't run off the end of the flash bank */
- if ((offset + count) > (bank->size)) {
- LOG_ERROR("Attempting to write past the end of flash");
- return ERROR_FAIL;
- }
-
-
- /* Attempt to write the passed in buffer to flash */
- /* Pages are written 256 bytes at a time, we need to handle
- * scenarios where padding is required at the beginning and
- * end of a page */
- while (count) {
- /* page working area */
- uint8_t tmp_buf[256] = {0};
-
- /* Amount of data we'll be writing to this page */
- int remaining;
- int end_pad;
-
- remaining = MIN(count, sizeof(tmp_buf));
- end_pad = sizeof(tmp_buf) - remaining;
-
- /* Make sure we're starting on a page boundary */
- int start_pad = offset % 256;
- if (start_pad) {
- LOG_INFO("Write does not start on a 256 byte boundary. "
- "Padding by %d bytes", start_pad);
- memset(tmp_buf, 0xff, start_pad);
- /* Subtract the amount of start offset from
- * the amount of data we'll need to write */
- remaining -= start_pad;
- }
-
- /* Remove the amount we'll be writing from the total count */
- count -= remaining;
-
- /* Now copy in the remaining data */
- memcpy(&tmp_buf[start_pad], buffer, remaining);
-
- if (end_pad) {
- LOG_INFO("Padding end of page @%08"PRIx32" by %d bytes",
- bank->base + offset, end_pad);
- memset(&tmp_buf[256 - end_pad], 0xff, end_pad);
- }
-
- /* Now commit this page to flash, if there was start
- * padding, we should subtract that from the target offset */
- res = xmc4xxx_write_page(bank, tmp_buf, (offset - start_pad), false);
- if (res != ERROR_OK) {
- LOG_ERROR("Unable to write flash page");
- goto abort_write_and_exit;
- }
-
- /* Advance the buffer pointer */
- buffer += remaining;
-
- /* Advance the offset */
- offset += remaining;
- }
-
-abort_write_and_exit:
- xmc4xxx_clear_flash_status(bank);
- return res;
-
-}
-
-static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
-{
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
- uint32_t scu_idcode;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_WARNING("Cannot communicate... target not halted.");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* The SCU registers contain the ID of the chip */
- int res = target_read_u32(bank->target, SCU_REG_BASE + SCU_ID_CHIP, &scu_idcode);
- if (res != ERROR_OK) {
- LOG_ERROR("Cannot read device identification register.");
- return res;
- }
-
- uint16_t dev_id = (scu_idcode & 0xfff0) >> 4;
- uint16_t rev_id = scu_idcode & 0xf;
- const char *dev_str;
- const char *rev_str = NULL;
-
- switch (dev_id) {
- case 0x100:
- dev_str = "XMC4100";
-
- switch (rev_id) {
- case 0x1:
- rev_str = "AA";
- break;
- case 0x2:
- rev_str = "AB";
- break;
- }
- break;
- case 0x200:
- dev_str = "XMC4200";
-
- switch (rev_id) {
- case 0x1:
- rev_str = "AA";
- break;
- case 0x2:
- rev_str = "AB";
- break;
- }
- break;
- case 0x400:
- dev_str = "XMC4400";
-
- switch (rev_id) {
- case 0x1:
- rev_str = "AA";
- break;
- case 0x2:
- rev_str = "AB";
- break;
- }
- break;
- case 0:
- /* XMC4500 EES AA13 with date codes before GE212
- * had zero SCU_IDCHIP
- */
- dev_str = "XMC4500 EES";
- rev_str = "AA13";
- break;
- case 0x500:
- dev_str = "XMC4500";
-
- switch (rev_id) {
- case 0x2:
- rev_str = "AA";
- break;
- case 0x3:
- rev_str = "AB";
- break;
- case 0x4:
- rev_str = "AC";
- break;
- }
- break;
- case 0x700:
- dev_str = "XMC4700";
-
- switch (rev_id) {
- case 0x1:
- rev_str = "EES-AA";
- break;
- }
- break;
- case 0x800:
- dev_str = "XMC4800";
-
- switch (rev_id) {
- case 0x1:
- rev_str = "EES-AA";
- break;
- }
- break;
-
- default:
- snprintf(buf, buf_size,
- "Cannot identify target as an XMC4xxx. SCU_ID: %"PRIx32"\n",
- scu_idcode);
- return ERROR_OK;
- }
-
- /* String to declare protection data held in the private driver */
- char prot_str[512] = {0};
- if (fb->read_protected)
- snprintf(prot_str, sizeof(prot_str), "\nFlash is read protected");
-
- bool otp_enabled = false;
- for (int i = 0; i < bank->num_sectors; i++)
- if (fb->write_prot_otp[i])
- otp_enabled = true;
-
- /* If OTP Write protection is enabled (User 2), list each
- * sector that has it enabled */
- char otp_str[8];
- if (otp_enabled) {
- strcat(prot_str, "\nOTP Protection is enabled for sectors:\n");
- for (int i = 0; i < bank->num_sectors; i++) {
- if (fb->write_prot_otp[i]) {
- snprintf(otp_str, sizeof(otp_str), "- %d\n", i);
- strncat(prot_str, otp_str, ARRAY_SIZE(otp_str));
- }
- }
- }
-
- if (rev_str != NULL)
- snprintf(buf, buf_size, "%s - Rev: %s%s",
- dev_str, rev_str, prot_str);
- else
- snprintf(buf, buf_size, "%s - Rev: unknown (0x%01x)%s",
- dev_str, rev_id, prot_str);
-
- return ERROR_OK;
-}
-
-static int xmc4xxx_temp_unprotect(struct flash_bank *bank, int user_level)
-{
- struct xmc4xxx_flash_bank *fb;
- int res = ERROR_OK;
- uint32_t status = 0;
-
- struct xmc4xxx_command_seq temp_unprot_seq[6] = {
- {FLASH_CMD_TEMP_UNPROT_1, 0xAA},
- {FLASH_CMD_TEMP_UNPROT_2, 0x55},
- {FLASH_CMD_TEMP_UNPROT_3, 0xFF}, /* Needs filled in */
- {FLASH_CMD_TEMP_UNPROT_4, 0xFF}, /* Needs filled in */
- {FLASH_CMD_TEMP_UNPROT_5, 0xFF}, /* Needs filled in */
- {FLASH_CMD_TEMP_UNPROT_6, 0x05}
- };
-
- if (user_level < 0 || user_level > 2) {
- LOG_ERROR("Invalid user level, must be 0-2");
- return ERROR_FAIL;
- }
-
- fb = bank->driver_priv;
-
- /* Fill in the user level and passwords */
- temp_unprot_seq[2].magic = user_level;
- temp_unprot_seq[3].magic = fb->pw1;
- temp_unprot_seq[4].magic = fb->pw2;
-
- res = xmc4xxx_write_command_sequence(bank, temp_unprot_seq,
- ARRAY_SIZE(temp_unprot_seq));
- if (res != ERROR_OK) {
- LOG_ERROR("Unable to write temp unprotect sequence");
- return res;
- }
-
- res = xmc4xxx_get_flash_status(bank, &status);
- if (res != ERROR_OK)
- return res;
-
- if (status & FSR_WPRODIS0) {
- LOG_INFO("Flash is temporarily unprotected");
- } else {
- LOG_INFO("Unable to disable flash protection");
- res = ERROR_FAIL;
- }
-
-
- return res;
-}
-
-static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level)
-{
- uint32_t addr;
- int res;
-
- switch (level) {
- case 0:
- addr = UCB0_BASE;
- break;
- case 1:
- addr = UCB1_BASE;
- break;
- default:
- LOG_ERROR("Invalid user level. Must be 0-1");
- return ERROR_FAIL;
- }
-
- res = xmc4xxx_erase_sector(bank, addr, true);
-
- if (res != ERROR_OK)
- LOG_ERROR("Error erasing user configuration block");
-
- return res;
-}
-
-/* Reference: "XMC4500 Flash Protection.pptx" app note */
-static int xmc4xxx_flash_protect(struct flash_bank *bank, int level, bool read_protect,
- int first, int last)
-{
- /* User configuration block buffers */
- uint8_t ucp0_buf[8 * sizeof(uint32_t)] = {0};
- uint32_t ucb_base = 0;
- uint32_t procon = 0;
- int res = ERROR_OK;
- uint32_t status = 0;
- bool proin = false;
-
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
-
- /* Read protect only works for user 0, make sure we don't try
- * to do something silly */
- if (level != 0 && read_protect) {
- LOG_ERROR("Read protection is for user level 0 only!");
- return ERROR_FAIL;
- }
-
- /* Check to see if protection is already installed for the
- * specified user level. If it is, the user configuration
- * block will need to be erased before we can continue */
-
- /* Grab the flash status register*/
- res = xmc4xxx_get_flash_status(bank, &status);
- if (res != ERROR_OK)
- return res;
-
- switch (level) {
- case 0:
- if ((status & FSR_RPROIN_MASK) || (status & FSR_WPROIN0_MASK))
- proin = true;
- break;
- case 1:
- if (status & FSR_WPROIN1_MASK)
- proin = true;
- break;
- case 2:
- if (status & FSR_WPROIN2_MASK)
- proin = true;
- break;
- }
-
- if (proin) {
- LOG_ERROR("Flash protection is installed for user %d"
- " and must be removed before continuing", level);
- return ERROR_FAIL;
- }
-
- /* If this device has 12 flash sectors, protection for
- * sectors 10 & 11 are handled jointly. If we are trying to
- * write all sectors, we should decrement
- * last to ensure we don't write to a register bit that
- * doesn't exist*/
- if ((bank->num_sectors == 12) && (last == 12))
- last--;
-
- /* We need to fill out the procon register representation
- * that we will be writing to the device */
- for (int i = first; i <= last; i++)
- procon |= 1 << i;
-
- /* If read protection is requested, set the appropriate bit
- * (we checked that this is allowed above) */
- if (read_protect)
- procon |= PROCON_RPRO_MASK;
-
- LOG_DEBUG("Setting flash protection with procon:");
- LOG_DEBUG("PROCON: %"PRIx32, procon);
-
- /* First we need to copy in the procon register to the buffer
- * we're going to attempt to write. This is written twice */
- target_buffer_set_u32(bank->target, &ucp0_buf[0 * 4], procon);
- target_buffer_set_u32(bank->target, &ucp0_buf[2 * 4], procon);
-
- /* Now we must copy in both flash passwords. As with the
- * procon data, this must be written twice (4 total words
- * worth of data) */
- target_buffer_set_u32(bank->target, &ucp0_buf[4 * 4], fb->pw1);
- target_buffer_set_u32(bank->target, &ucp0_buf[5 * 4], fb->pw2);
- target_buffer_set_u32(bank->target, &ucp0_buf[6 * 4], fb->pw1);
- target_buffer_set_u32(bank->target, &ucp0_buf[7 * 4], fb->pw2);
-
- /* Finally, (if requested) we copy in the confirmation
- * code so that the protection is permanent and will
- * require a password to undo. */
- target_buffer_set_u32(bank->target, &ucp0_buf[0 * 4], FLASH_PROTECT_CONFIRMATION_CODE);
- target_buffer_set_u32(bank->target, &ucp0_buf[2 * 4], FLASH_PROTECT_CONFIRMATION_CODE);
-
- /* Now that the data is copied into place, we must write
- * these pages into flash */
-
- /* The user configuration block base depends on what level of
- * protection we're trying to install, select the proper one */
- switch (level) {
- case 0:
- ucb_base = UCB0_BASE;
- break;
- case 1:
- ucb_base = UCB1_BASE;
- break;
- case 2:
- ucb_base = UCB2_BASE;
- break;
- }
-
- /* Write the user config pages */
- res = xmc4xxx_write_page(bank, ucp0_buf, ucb_base, true);
- if (res != ERROR_OK) {
- LOG_ERROR("Error writing user configuration block 0");
- return res;
- }
-
- return ERROR_OK;
-}
-
-static int xmc4xxx_protect(struct flash_bank *bank, int set, int first, int last)
-{
- int ret;
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
-
- /* Check for flash passwords */
- if (!fb->pw_set) {
- LOG_ERROR("Flash passwords not set, use xmc4xxx flash_password to set them");
- return ERROR_FAIL;
- }
-
- /* We want to clear flash protection temporarily*/
- if (set == 0) {
- LOG_WARNING("Flash protection will be temporarily disabled"
- " for all pages (User 0 only)!");
- ret = xmc4xxx_temp_unprotect(bank, 0);
- return ret;
- }
-
- /* Install write protection for user 0 on the specified pages */
- ret = xmc4xxx_flash_protect(bank, 0, false, first, last);
-
- return ret;
-}
-
-static int xmc4xxx_protect_check(struct flash_bank *bank)
-{
- int ret;
- uint32_t protection[3] = {0};
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
-
- ret = target_read_u32(bank->target, FLASH_REG_FLASH0_PROCON0, &protection[0]);
- if (ret != ERROR_OK) {
- LOG_ERROR("Unable to read flash User0 protection register");
- return ret;
- }
-
- ret = target_read_u32(bank->target, FLASH_REG_FLASH0_PROCON1, &protection[1]);
- if (ret != ERROR_OK) {
- LOG_ERROR("Unable to read flash User1 protection register");
- return ret;
- }
-
- ret = target_read_u32(bank->target, FLASH_REG_FLASH0_PROCON2, &protection[2]);
- if (ret != ERROR_OK) {
- LOG_ERROR("Unable to read flash User2 protection register");
- return ret;
- }
-
- int sectors = bank->num_sectors;
-
- /* On devices with 12 sectors, sectors 10 & 11 are ptected
- * together instead of individually */
- if (sectors == 12)
- sectors--;
-
- /* Clear the protection status */
- for (int i = 0; i < bank->num_sectors; i++) {
- bank->sectors[i].is_protected = 0;
- fb->write_prot_otp[i] = false;
- }
- fb->read_protected = false;
-
- /* The xmc4xxx series supports 3 levels of user protection
- * (User0, User1 (low priority), and User 2(OTP), we need to
- * check all 3 */
- for (unsigned int i = 0; i < ARRAY_SIZE(protection); i++) {
-
- /* Check for write protection on every available
- * sector */
- for (int j = 0; j < sectors; j++) {
- int set = (protection[i] & (1 << j)) ? 1 : 0;
- bank->sectors[j].is_protected |= set;
-
- /* Handle sector 11 */
- if (j == 10)
- bank->sectors[j + 1].is_protected |= set;
-
- /* User 2 indicates this protection is
- * permanent, make note in the private driver structure */
- if (i == 2 && set) {
- fb->write_prot_otp[j] = true;
-
- /* Handle sector 11 */
- if (j == 10)
- fb->write_prot_otp[j + 1] = true;
- }
-
- }
- }
-
- /* XMC4xxx also supports read proptection, make a note
- * in the private driver structure */
- if (protection[0] & PROCON_RPRO_MASK)
- fb->read_protected = true;
-
- return ERROR_OK;
-}
-
-FLASH_BANK_COMMAND_HANDLER(xmc4xxx_flash_bank_command)
-{
- bank->driver_priv = malloc(sizeof(struct xmc4xxx_flash_bank));
-
- if (!bank->driver_priv)
- return ERROR_FLASH_OPERATION_FAILED;
-
- (void)memset(bank->driver_priv, 0, sizeof(struct xmc4xxx_flash_bank));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xmc4xxx_handle_flash_password_command)
-{
- int res;
- struct flash_bank *bank;
-
- if (CMD_ARGC < 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- res = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (res != ERROR_OK)
- return res;
-
- struct xmc4xxx_flash_bank *fb = bank->driver_priv;
-
- errno = 0;
-
- /* We skip over the flash bank */
- fb->pw1 = strtol(CMD_ARGV[1], NULL, 16);
-
- if (errno)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- fb->pw2 = strtol(CMD_ARGV[2], NULL, 16);
-
- if (errno)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- fb->pw_set = true;
-
- command_print(CMD_CTX, "XMC4xxx flash passwords set to:\n");
- command_print(CMD_CTX, "-0x%08"PRIx32"\n", fb->pw1);
- command_print(CMD_CTX, "-0x%08"PRIx32"\n", fb->pw2);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xmc4xxx_handle_flash_unprotect_command)
-{
- struct flash_bank *bank;
- int res;
- int32_t level;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- res = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (res != ERROR_OK)
- return res;
-
- COMMAND_PARSE_NUMBER(s32, CMD_ARGV[1], level);
-
- res = xmc4xxx_flash_unprotect(bank, level);
-
- return res;
-}
-
-static const struct command_registration xmc4xxx_exec_command_handlers[] = {
- {
- .name = "flash_password",
- .handler = xmc4xxx_handle_flash_password_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id password1 password2",
- .help = "Set the flash passwords used for protect operations. "
- "Passwords should be in standard hex form (0x00000000). "
- "(You must call this before any other protect commands) "
- "NOTE: The xmc4xxx's UCB area only allows for FOUR cycles. "
- "Please use protection carefully!",
- },
- {
- .name = "flash_unprotect",
- .handler = xmc4xxx_handle_flash_unprotect_command,
- .mode = COMMAND_EXEC,
- .usage = "bank_id user_level[0-1]",
- .help = "Permanently Removes flash protection (read and write) "
- "for the specified user level",
- }, COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration xmc4xxx_command_handlers[] = {
- {
- .name = "xmc4xxx",
- .mode = COMMAND_ANY,
- .help = "xmc4xxx flash command group",
- .usage = "",
- .chain = xmc4xxx_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver xmc4xxx_flash = {
- .name = "xmc4xxx",
- .commands = xmc4xxx_command_handlers,
- .flash_bank_command = xmc4xxx_flash_bank_command,
- .erase = xmc4xxx_erase,
- .write = xmc4xxx_write,
- .read = default_flash_read,
- .probe = xmc4xxx_probe,
- .auto_probe = xmc4xxx_probe,
- .erase_check = xmc4xxx_flash_blank_check,
- .info = xmc4xxx_get_info_command,
- .protect_check = xmc4xxx_protect_check,
- .protect = xmc4xxx_protect,
-};
diff --git a/src/flash/startup.tcl b/src/flash/startup.tcl
deleted file mode 100644
index fbb8d8e..0000000
--- a/src/flash/startup.tcl
+++ /dev/null
@@ -1,110 +0,0 @@
-# Defines basic Tcl procs for OpenOCD flash module
-
-#
-# program utility proc
-# usage: program filename
-# optional args: verify, reset, exit and address
-#
-
-proc program_error {description exit} {
- if {$exit == 1} {
- echo $description
- shutdown error
- }
-
- error $description
-}
-
-proc program {filename args} {
- set exit 0
-
- foreach arg $args {
- if {[string equal $arg "verify"]} {
- set verify 1
- } elseif {[string equal $arg "reset"]} {
- set reset 1
- } elseif {[string equal $arg "exit"]} {
- set exit 1
- } else {
- set address $arg
- }
- }
-
- # make sure init is called
- if {[catch {init}] != 0} {
- program_error "** OpenOCD init failed **" 1
- }
-
- # reset target and call any init scripts
- if {[catch {reset init}] != 0} {
- program_error "** Unable to reset target **" $exit
- }
-
- # start programming phase
- echo "** Programming Started **"
- if {[info exists address]} {
- set flash_args "$filename $address"
- } else {
- set flash_args "$filename"
- }
-
- if {[catch {eval flash write_image erase $flash_args}] == 0} {
- echo "** Programming Finished **"
- if {[info exists verify]} {
- # verify phase
- echo "** Verify Started **"
- if {[catch {eval verify_image $flash_args}] == 0} {
- echo "** Verified OK **"
- } else {
- program_error "** Verify Failed **" $exit
- }
- }
-
- if {[info exists reset]} {
- # reset target if requested
- # also disable target polling, we are shutting down anyway
- poll off
- echo "** Resetting Target **"
- reset run
- }
- } else {
- program_error "** Programming Failed **" $exit
- }
-
- if {$exit == 1} {
- shutdown
- }
- return
-}
-
-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\] \[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
-}
-
-# stm32f3x uses the same flash driver as the stm32f1x
-# this alias enables the use of either name.
-proc stm32f3x args {
- eval stm32f1x $args
-}
-
-# stm32f4x uses the same flash driver as the stm32f2x
-# this alias enables the use of either name.
-proc stm32f4x args {
- eval stm32f2x $args
-}
-
-# ease migration to updated flash driver
-proc stm32x args {
- echo "DEPRECATED! use 'stm32f1x $args' not 'stm32x $args'"
- eval stm32f1x $args
-}
-
-proc stm32f2xxx args {
- echo "DEPRECATED! use 'stm32f2x $args' not 'stm32f2xxx $args'"
- eval stm32f2x $args
-}
diff --git a/src/hello.c b/src/hello.c
deleted file mode 100644
index 25938bc..0000000
--- a/src/hello.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <helper/log.h>
-
-COMMAND_HANDLER(handle_foo_command)
-{
- if (CMD_ARGC < 1 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
-
- const char *msg = "<unchanged>";
- if (CMD_ARGC == 2) {
- bool enable;
- COMMAND_PARSE_ENABLE(CMD_ARGV[1], enable);
- msg = enable ? "enable" : "disable";
- }
-
- LOG_INFO("%s: address=0x%8.8" PRIx32 " enabled=%s", CMD_NAME, address, msg);
- return ERROR_OK;
-}
-
-static bool foo_flag;
-
-COMMAND_HANDLER(handle_flag_command)
-{
- return CALL_COMMAND_HANDLER(handle_command_parse_bool,
- &foo_flag, "foo flag");
-}
-
-static const struct command_registration foo_command_handlers[] = {
- {
- .name = "bar",
- .handler = &handle_foo_command,
- .mode = COMMAND_ANY,
- .usage = "address ['enable'|'disable']",
- .help = "an example command",
- },
- {
- .name = "baz",
- .handler = &handle_foo_command,
- .mode = COMMAND_ANY,
- .usage = "address ['enable'|'disable']",
- .help = "a sample command",
- },
- {
- .name = "flag",
- .handler = &handle_flag_command,
- .mode = COMMAND_ANY,
- .usage = "[on|off]",
- .help = "set a flag",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static COMMAND_HELPER(handle_hello_args, const char **sep, const char **name)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (1 == CMD_ARGC) {
- *sep = " ";
- *name = CMD_ARGV[0];
- } else
- *sep = *name = "";
-
- return ERROR_OK;
-}
-COMMAND_HANDLER(handle_hello_command)
-{
- const char *sep, *name;
- int retval = CALL_COMMAND_HANDLER(handle_hello_args, &sep, &name);
- if (ERROR_OK == retval)
- command_print(CMD_CTX, "Greetings%s%s!", sep, name);
- return retval;
-}
-
-const struct command_registration hello_command_handlers[] = {
- {
- .name = "hello",
- .handler = handle_hello_command,
- .mode = COMMAND_ANY,
- .help = "prints a warm welcome",
- .usage = "[name]",
- },
- {
- .name = "foo",
- .mode = COMMAND_ANY,
- .help = "example command handler skeleton",
-
- .chain = foo_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/hello.h b/src/hello.h
deleted file mode 100644
index c88c89d..0000000
--- a/src/hello.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELLO_H
-#define OPENOCD_HELLO_H
-
-struct command_registration;
-
-/**
- * Export the registration for the hello command group, so it can be
- * embedded in example drivers.
- */
-extern const struct command_registration hello_command_handlers[];
-
-#endif /* OPENOCD_HELLO_H */
diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am
deleted file mode 100644
index 64caf98..0000000
--- a/src/helper/Makefile.am
+++ /dev/null
@@ -1,56 +0,0 @@
-include $(top_srcdir)/common.mk
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libhelper.la
-
-CONFIGFILES = options.c time_support_common.c
-
-libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS)
-
-libhelper_la_SOURCES = \
- binarybuffer.c \
- $(CONFIGFILES) \
- configuration.c \
- log.c \
- command.c \
- time_support.c \
- replacements.c \
- fileio.c \
- util.c \
- jep106.c \
- jim-nvp.c
-
-if IOUTIL
-libhelper_la_SOURCES += ioutil.c
-else
-libhelper_la_SOURCES += ioutil_stubs.c
-endif
-
-libhelper_la_CFLAGS =
-if IS_MINGW
-# FD_* macros are sloppy with their signs on MinGW32 platform
-libhelper_la_CFLAGS += -Wno-sign-compare
-endif
-
-noinst_HEADERS = \
- binarybuffer.h \
- configuration.h \
- ioutil.h \
- list.h \
- util.h \
- types.h \
- log.h \
- command.h \
- time_support.h \
- replacements.h \
- fileio.h \
- system.h \
- bin2char.sh \
- jep106.h \
- jep106.inc \
- update_jep106.pl \
- jim-nvp.h
-
-EXTRA_DIST = startup.tcl
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/helper/bin2char.sh b/src/helper/bin2char.sh
deleted file mode 100755
index 85a0fd6..0000000
--- a/src/helper/bin2char.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-[ $# != 0 ] && {
- echo "Usage: $0"
- echo
- echo "Read binary data from standard input and write it as a comma separated"
- echo "list of hexadecimal byte values to standard ouput. The output is usable"
- echo "as a C array initializer. It is terminated with a comma so it can be"
- echo "continued e.g. for zero termination."
- exit 1
-}
-
-echo "/* Autogenerated with $0 */"
-od -v -A n -t x1 | sed 's/ *\(..\) */0x\1,/g'
diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c
deleted file mode 100644
index c1e6322..0000000
--- a/src/helper/binarybuffer.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "log.h"
-#include "binarybuffer.h"
-
-static const unsigned char bit_reverse_table256[] = {
- 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
- 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
- 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
- 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
- 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
- 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
- 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
- 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
- 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
- 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
- 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
- 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
- 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
- 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
- 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
- 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
-};
-
-void *buf_cpy(const void *from, void *_to, unsigned size)
-{
- if (NULL == from || NULL == _to)
- return NULL;
-
- /* copy entire buffer */
- memcpy(_to, from, DIV_ROUND_UP(size, 8));
-
- /* mask out bits that don't belong to the buffer */
- unsigned trailing_bits = size % 8;
- if (trailing_bits) {
- uint8_t *to = _to;
- to[size / 8] &= (1 << trailing_bits) - 1;
- }
- return _to;
-}
-
-static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m)
-{
- return (a & m) != (b & m);
-}
-static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
-{
- uint8_t mask = (1 << trailing) - 1;
- return buf_cmp_masked(a, b, mask & m);
-}
-
-bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
-{
- if (!_buf1 || !_buf2)
- return _buf1 != _buf2;
-
- unsigned last = size / 8;
- if (memcmp(_buf1, _buf2, last) != 0)
- return false;
-
- unsigned trailing = size % 8;
- if (!trailing)
- return false;
-
- const uint8_t *buf1 = _buf1, *buf2 = _buf2;
- return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing);
-}
-
-bool buf_cmp_mask(const void *_buf1, const void *_buf2,
- const void *_mask, unsigned size)
-{
- if (!_buf1 || !_buf2)
- return _buf1 != _buf2 || _buf1 != _mask;
-
- const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask;
- unsigned last = size / 8;
- for (unsigned i = 0; i < last; i++) {
- if (buf_cmp_masked(buf1[i], buf2[i], mask[i]))
- return true;
- }
- unsigned trailing = size % 8;
- if (!trailing)
- return false;
- return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing);
-}
-
-
-void *buf_set_ones(void *_buf, unsigned size)
-{
- uint8_t *buf = _buf;
- if (!buf)
- return NULL;
-
- memset(buf, 0xff, size / 8);
-
- unsigned trailing_bits = size % 8;
- if (trailing_bits)
- buf[size / 8] = (1 << trailing_bits) - 1;
-
- return buf;
-}
-
-void *buf_set_buf(const void *_src, unsigned src_start,
- void *_dst, unsigned dst_start, unsigned len)
-{
- const uint8_t *src = _src;
- uint8_t *dst = _dst;
- unsigned i, sb, db, sq, dq, lb, lq;
-
- sb = src_start / 8;
- db = dst_start / 8;
- sq = src_start % 8;
- dq = dst_start % 8;
- lb = len / 8;
- lq = len % 8;
-
- src += sb;
- dst += db;
-
- /* check if both buffers are on byte boundary and
- * len is a multiple of 8bit so we can simple copy
- * the buffer */
- if ((sq == 0) && (dq == 0) && (lq == 0)) {
- for (i = 0; i < lb; i++)
- *dst++ = *src++;
- return _dst;
- }
-
- /* fallback to slow bit copy */
- for (i = 0; i < len; i++) {
- if (((*src >> (sq&7)) & 1) == 1)
- *dst |= 1 << (dq&7);
- else
- *dst &= ~(1 << (dq&7));
- if (sq++ == 7) {
- sq = 0;
- src++;
- }
- if (dq++ == 7) {
- dq = 0;
- dst++;
- }
- }
-
- return _dst;
-}
-
-uint32_t flip_u32(uint32_t value, unsigned int num)
-{
- uint32_t c = (bit_reverse_table256[value & 0xff] << 24) |
- (bit_reverse_table256[(value >> 8) & 0xff] << 16) |
- (bit_reverse_table256[(value >> 16) & 0xff] << 8) |
- (bit_reverse_table256[(value >> 24) & 0xff]);
-
- if (num < 32)
- c = c >> (32 - num);
-
- return c;
-}
-
-static int ceil_f_to_u32(float x)
-{
- if (x < 0) /* return zero for negative numbers */
- return 0;
-
- uint32_t y = x; /* cut off fraction */
-
- if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
- y++;
-
- return y;
-}
-
-char *buf_to_str(const void *_buf, unsigned buf_len, unsigned radix)
-{
- float factor;
- switch (radix) {
- case 16:
- factor = 2.0; /* log(256) / log(16) = 2.0 */
- break;
- case 10:
- factor = 2.40824; /* log(256) / log(10) = 2.40824 */
- break;
- case 8:
- factor = 2.66667; /* log(256) / log(8) = 2.66667 */
- break;
- default:
- return NULL;
- }
-
- unsigned str_len = ceil_f_to_u32(DIV_ROUND_UP(buf_len, 8) * factor);
- char *str = calloc(str_len + 1, 1);
-
- const uint8_t *buf = _buf;
- int b256_len = DIV_ROUND_UP(buf_len, 8);
- for (int i = b256_len - 1; i >= 0; i--) {
- uint32_t tmp = buf[i];
- if (((unsigned)i == (buf_len / 8)) && (buf_len % 8))
- tmp &= (0xff >> (8 - (buf_len % 8)));
-
- /* base-256 digits */
- for (unsigned j = str_len; j > 0; j--) {
- tmp += (uint32_t)str[j-1] * 256;
- str[j-1] = (uint8_t)(tmp % radix);
- tmp /= radix;
- }
- }
-
- const char * const DIGITS = "0123456789ABCDEF";
- for (unsigned j = 0; j < str_len; j++)
- str[j] = DIGITS[(int)str[j]];
-
- return str;
-}
-
-/** identify radix, and skip radix-prefix (0, 0x or 0X) */
-static void str_radix_guess(const char **_str, unsigned *_str_len,
- unsigned *_radix)
-{
- unsigned radix = *_radix;
- if (0 != radix)
- return;
- const char *str = *_str;
- unsigned str_len = *_str_len;
- if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
- radix = 16;
- str += 2;
- str_len -= 2;
- } else if ((str[0] == '0') && (str_len != 1)) {
- radix = 8;
- str += 1;
- str_len -= 1;
- } else
- radix = 10;
- *_str = str;
- *_str_len = str_len;
- *_radix = radix;
-}
-
-int str_to_buf(const char *str, unsigned str_len,
- void *_buf, unsigned buf_len, unsigned radix)
-{
- str_radix_guess(&str, &str_len, &radix);
-
- float factor;
- if (radix == 16)
- factor = 0.5; /* log(16) / log(256) = 0.5 */
- else if (radix == 10)
- factor = 0.41524; /* log(10) / log(256) = 0.41524 */
- else if (radix == 8)
- factor = 0.375; /* log(8) / log(256) = 0.375 */
- else
- return 0;
-
- /* copy to zero-terminated buffer */
- char *charbuf = strndup(str, str_len);
-
- /* number of digits in base-256 notation */
- unsigned b256_len = ceil_f_to_u32(str_len * factor);
- uint8_t *b256_buf = calloc(b256_len, 1);
-
- /* go through zero terminated buffer
- * input digits (ASCII) */
- unsigned i;
- for (i = 0; charbuf[i]; i++) {
- uint32_t tmp = charbuf[i];
- if ((tmp >= '0') && (tmp <= '9'))
- tmp = (tmp - '0');
- else if ((tmp >= 'a') && (tmp <= 'f'))
- tmp = (tmp - 'a' + 10);
- else if ((tmp >= 'A') && (tmp <= 'F'))
- tmp = (tmp - 'A' + 10);
- else
- continue; /* skip characters other than [0-9,a-f,A-F] */
-
- if (tmp >= radix)
- continue; /* skip digits invalid for the current radix */
-
- /* base-256 digits */
- for (unsigned j = 0; j < b256_len; j++) {
- tmp += (uint32_t)b256_buf[j] * radix;
- b256_buf[j] = (uint8_t)(tmp & 0xFF);
- tmp >>= 8;
- }
-
- }
-
- uint8_t *buf = _buf;
- for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) {
- if (j < b256_len)
- buf[j] = b256_buf[j];
- else
- buf[j] = 0;
- }
-
- /* mask out bits that don't belong to the buffer */
- if (buf_len % 8)
- buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
-
- free(b256_buf);
- free(charbuf);
-
- return i;
-}
-
-void bit_copy_queue_init(struct bit_copy_queue *q)
-{
- INIT_LIST_HEAD(&q->list);
-}
-
-int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src,
- unsigned src_offset, unsigned bit_count)
-{
- struct bit_copy_queue_entry *qe = malloc(sizeof(*qe));
- if (!qe)
- return ERROR_FAIL;
-
- qe->dst = dst;
- qe->dst_offset = dst_offset;
- qe->src = src;
- qe->src_offset = src_offset;
- qe->bit_count = bit_count;
- list_add_tail(&qe->list, &q->list);
-
- return ERROR_OK;
-}
-
-void bit_copy_execute(struct bit_copy_queue *q)
-{
- struct bit_copy_queue_entry *qe;
- struct bit_copy_queue_entry *tmp;
- list_for_each_entry_safe(qe, tmp, &q->list, list) {
- bit_copy(qe->dst, qe->dst_offset, qe->src, qe->src_offset, qe->bit_count);
- list_del(&qe->list);
- free(qe);
- }
-}
-
-void bit_copy_discard(struct bit_copy_queue *q)
-{
- struct bit_copy_queue_entry *qe;
- struct bit_copy_queue_entry *tmp;
- list_for_each_entry_safe(qe, tmp, &q->list, list) {
- list_del(&qe->list);
- free(qe);
- }
-}
-
-int unhexify(char *bin, const char *hex, int count)
-{
- int i, tmp;
-
- for (i = 0; i < count; i++) {
- if (sscanf(hex + (2 * i), "%02x", &tmp) != 1)
- return i;
- bin[i] = tmp;
- }
-
- return i;
-}
-
-int hexify(char *hex, const char *bin, int count, int out_maxlen)
-{
- int i, cmd_len = 0;
-
- /* May use a length, or a null-terminated string as input. */
- if (count == 0)
- count = strlen(bin);
-
- for (i = 0; i < count; i++)
- cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff);
-
- return cmd_len;
-}
-
-void buffer_shr(void *_buf, unsigned buf_len, unsigned count)
-{
- unsigned i;
- unsigned char *buf = _buf;
- unsigned bytes_to_remove;
- unsigned shift;
-
- bytes_to_remove = count / 8;
- shift = count - (bytes_to_remove * 8);
-
- for (i = 0; i < (buf_len - 1); i++)
- buf[i] = (buf[i] >> shift) | ((buf[i+1] << (8 - shift)) & 0xff);
-
- buf[(buf_len - 1)] = buf[(buf_len - 1)] >> shift;
-
- if (bytes_to_remove) {
- memmove(buf, &buf[bytes_to_remove], buf_len - bytes_to_remove);
- memset(&buf[buf_len - bytes_to_remove], 0, bytes_to_remove);
- }
-}
diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h
deleted file mode 100644
index dd0d275..0000000
--- a/src/helper/binarybuffer.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_BINARYBUFFER_H
-#define OPENOCD_HELPER_BINARYBUFFER_H
-
-#include "list.h"
-
-/** @file
- * Support functions to access arbitrary bits in a byte array
- */
-
-/**
- * Sets @c num bits in @c _buffer, starting at the @c first bit,
- * using the bits in @c value. This routine fast-paths writes
- * of little-endian, byte-aligned, 32-bit words.
- * @param _buffer The buffer whose bits will be set.
- * @param first The bit offset in @c _buffer to start writing (0-31).
- * @param num The number of bits from @c value to copy (1-32).
- * @param value Up to 32 bits that will be copied to _buffer.
- */
-static inline void buf_set_u32(uint8_t *_buffer,
- unsigned first, unsigned num, uint32_t value)
-{
- uint8_t *buffer = _buffer;
-
- if ((num == 32) && (first == 0)) {
- buffer[3] = (value >> 24) & 0xff;
- buffer[2] = (value >> 16) & 0xff;
- buffer[1] = (value >> 8) & 0xff;
- buffer[0] = (value >> 0) & 0xff;
- } else {
- for (unsigned i = first; i < first + num; i++) {
- if (((value >> (i - first)) & 1) == 1)
- buffer[i / 8] |= 1 << (i % 8);
- else
- buffer[i / 8] &= ~(1 << (i % 8));
- }
- }
-}
-
-/**
- * Sets @c num bits in @c _buffer, starting at the @c first bit,
- * using the bits in @c value. This routine fast-paths writes
- * of little-endian, byte-aligned, 64-bit words.
- * @param _buffer The buffer whose bits will be set.
- * @param first The bit offset in @c _buffer to start writing (0-63).
- * @param num The number of bits from @c value to copy (1-64).
- * @param value Up to 64 bits that will be copied to _buffer.
- */
-static inline void buf_set_u64(uint8_t *_buffer,
- unsigned first, unsigned num, uint64_t value)
-{
- uint8_t *buffer = _buffer;
-
- if ((num == 32) && (first == 0)) {
- buffer[3] = (value >> 24) & 0xff;
- buffer[2] = (value >> 16) & 0xff;
- buffer[1] = (value >> 8) & 0xff;
- buffer[0] = (value >> 0) & 0xff;
- } else if ((num == 64) && (first == 0)) {
- buffer[7] = (value >> 56) & 0xff;
- buffer[6] = (value >> 48) & 0xff;
- buffer[5] = (value >> 40) & 0xff;
- buffer[4] = (value >> 32) & 0xff;
- buffer[3] = (value >> 24) & 0xff;
- buffer[2] = (value >> 16) & 0xff;
- buffer[1] = (value >> 8) & 0xff;
- buffer[0] = (value >> 0) & 0xff;
- } else {
- for (unsigned i = first; i < first + num; i++) {
- if (((value >> (i - first)) & 1) == 1)
- buffer[i / 8] |= 1 << (i % 8);
- else
- buffer[i / 8] &= ~(1 << (i % 8));
- }
- }
-}
-
-/**
- * Retrieves @c num bits from @c _buffer, starting at the @c first bit,
- * returning the bits in a 32-bit word. This routine fast-paths reads
- * of little-endian, byte-aligned, 32-bit words.
- * @param _buffer The buffer whose bits will be read.
- * @param first The bit offset in @c _buffer to start reading (0-31).
- * @param num The number of bits from @c _buffer to read (1-32).
- * @returns Up to 32-bits that were read from @c _buffer.
- */
-static inline uint32_t buf_get_u32(const uint8_t *_buffer,
- unsigned first, unsigned num)
-{
- const uint8_t *buffer = _buffer;
-
- if ((num == 32) && (first == 0)) {
- return (((uint32_t)buffer[3]) << 24) |
- (((uint32_t)buffer[2]) << 16) |
- (((uint32_t)buffer[1]) << 8) |
- (((uint32_t)buffer[0]) << 0);
- } else {
- uint32_t result = 0;
- for (unsigned i = first; i < first + num; i++) {
- if (((buffer[i / 8] >> (i % 8)) & 1) == 1)
- result |= 1 << (i - first);
- }
- return result;
- }
-}
-
-/**
- * Retrieves @c num bits from @c _buffer, starting at the @c first bit,
- * returning the bits in a 64-bit word. This routine fast-paths reads
- * of little-endian, byte-aligned, 64-bit words.
- * @param _buffer The buffer whose bits will be read.
- * @param first The bit offset in @c _buffer to start reading (0-63).
- * @param num The number of bits from @c _buffer to read (1-64).
- * @returns Up to 64-bits that were read from @c _buffer.
- */
-static inline uint64_t buf_get_u64(const uint8_t *_buffer,
- unsigned first, unsigned num)
-{
- const uint8_t *buffer = _buffer;
-
- if ((num == 32) && (first == 0)) {
- return 0 + ((((uint32_t)buffer[3]) << 24) | /* Note - zero plus is to avoid a checkpatch bug */
- (((uint32_t)buffer[2]) << 16) |
- (((uint32_t)buffer[1]) << 8) |
- (((uint32_t)buffer[0]) << 0));
- } else if ((num == 64) && (first == 0)) {
- return 0 + ((((uint64_t)buffer[7]) << 56) | /* Note - zero plus is to avoid a checkpatch bug */
- (((uint64_t)buffer[6]) << 48) |
- (((uint64_t)buffer[5]) << 40) |
- (((uint64_t)buffer[4]) << 32) |
- (((uint64_t)buffer[3]) << 24) |
- (((uint64_t)buffer[2]) << 16) |
- (((uint64_t)buffer[1]) << 8) |
- (((uint64_t)buffer[0]) << 0));
- } else {
- uint64_t result = 0;
- for (unsigned i = first; i < first + num; i++) {
- if (((buffer[i / 8] >> (i % 8)) & 1) == 1)
- result = result | ((uint64_t)1 << (uint64_t)(i - first));
- }
- return result;
- }
-}
-
-
-/**
- * Inverts the ordering of bits inside a 32-bit word (e.g. 31..0 -> 0..31).
- * This routine can be used to flip smaller data types by using smaller
- * values for @c width.
- * @param value The word to flip.
- * @param width The number of bits in value (2-32).
- * @returns A 32-bit word with @c value in reversed bit-order.
- */
-uint32_t flip_u32(uint32_t value, unsigned width);
-
-bool buf_cmp(const void *buf1, const void *buf2, unsigned size);
-bool buf_cmp_mask(const void *buf1, const void *buf2,
- const void *mask, unsigned size);
-
-/**
- * Copies @c size bits out of @c from and into @c to. Any extra
- * bits in the final byte will be set to zero.
- * @param from The buffer to copy into @c to.
- * @param to The buffer that will receive the copy of @c from.
- * @param size The number of bits to copy.
- */
-void *buf_cpy(const void *from, void *to, unsigned size);
-
-/**
- * Set the contents of @c buf with @c count bits, all set to 1.
- * @param buf The buffer to fill with ones.
- * @param size The number of bits.
- * @returns The original buffer (@c buf).
- */
-void *buf_set_ones(void *buf, unsigned size);
-
-void *buf_set_buf(const void *src, unsigned src_start,
- void *dst, unsigned dst_start, unsigned len);
-
-int str_to_buf(const char *str, unsigned len,
- void *bin_buf, unsigned buf_size, unsigned radix);
-char *buf_to_str(const void *buf, unsigned size, unsigned radix);
-
-/* read a uint32_t from a buffer in target memory endianness */
-static inline uint32_t fast_target_buffer_get_u32(const void *p, bool le)
-{
- return le ? le_to_h_u32(p) : be_to_h_u32(p);
-}
-
-static inline void bit_copy(uint8_t *dst, unsigned dst_offset, const uint8_t *src,
- unsigned src_offset, unsigned bit_count)
-{
- buf_set_buf(src, src_offset, dst, dst_offset, bit_count);
-}
-
-struct bit_copy_queue {
- struct list_head list;
-};
-
-struct bit_copy_queue_entry {
- uint8_t *dst;
- unsigned dst_offset;
- const uint8_t *src;
- unsigned src_offset;
- unsigned bit_count;
- struct list_head list;
-};
-
-void bit_copy_queue_init(struct bit_copy_queue *q);
-int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src,
- unsigned src_offset, unsigned bit_count);
-void bit_copy_execute(struct bit_copy_queue *q);
-void bit_copy_discard(struct bit_copy_queue *q);
-
-/* functions to convert to/from hex encoded buffer
- * used in ti-icdi driver and gdb server */
-int unhexify(char *bin, const char *hex, int count);
-int hexify(char *hex, const char *bin, int count, int out_maxlen);
-void buffer_shr(void *_buf, unsigned buf_len, unsigned count);
-
-#endif /* OPENOCD_HELPER_BINARYBUFFER_H */
diff --git a/src/helper/command.c b/src/helper/command.c
deleted file mode 100644
index fc4aac7..0000000
--- a/src/helper/command.c
+++ /dev/null
@@ -1,1466 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008, Duane Ellis *
- * openocd@duaneeellis.com *
- * *
- * part of this file is taken from libcli (libcli.sourceforge.net) *
- * Copyright (C) David Parrish (david@dparrish.com) *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* see Embedded-HOWTO.txt in Jim Tcl project hosted on BerliOS*/
-#define JIM_EMBEDDED
-
-/* @todo the inclusion of target.h here is a layering violation */
-#include <jtag/jtag.h>
-#include <target/target.h>
-#include "command.h"
-#include "configuration.h"
-#include "log.h"
-#include "time_support.h"
-#include "jim-eventloop.h"
-
-/* nice short description of source file */
-#define __THIS__FILE__ "command.c"
-
-static int run_command(struct command_context *context,
- struct command *c, const char *words[], unsigned num_words);
-
-struct log_capture_state {
- Jim_Interp *interp;
- Jim_Obj *output;
-};
-
-static void tcl_output(void *privData, const char *file, unsigned line,
- const char *function, const char *string)
-{
- struct log_capture_state *state = privData;
- Jim_AppendString(state->interp, state->output, string, strlen(string));
-}
-
-static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
-{
- /* capture log output and return it. A garbage collect can
- * happen, so we need a reference count to this object */
- Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
- if (NULL == tclOutput)
- return NULL;
-
- struct log_capture_state *state = malloc(sizeof(*state));
- if (NULL == state)
- return NULL;
-
- state->interp = interp;
- Jim_IncrRefCount(tclOutput);
- state->output = tclOutput;
-
- log_add_callback(tcl_output, state);
-
- return state;
-}
-
-/* Classic openocd commands provide progress output which we
- * will capture and return as a Tcl return value.
- *
- * However, if a non-openocd command has been invoked, then it
- * makes sense to return the tcl return value from that command.
- *
- * The tcl return value is empty for openocd commands that provide
- * progress output.
- *
- * Therefore we set the tcl return value only if we actually
- * captured output.
- */
-static void command_log_capture_finish(struct log_capture_state *state)
-{
- if (NULL == state)
- return;
-
- log_remove_callback(tcl_output, state);
-
- int length;
- Jim_GetString(state->output, &length);
-
- if (length > 0)
- Jim_SetResult(state->interp, state->output);
- else {
- /* No output captured, use tcl return value (which could
- * be empty too). */
- }
- Jim_DecrRefCount(state->interp, state->output);
-
- free(state);
-}
-
-static int command_retval_set(Jim_Interp *interp, int retval)
-{
- int *return_retval = Jim_GetAssocData(interp, "retval");
- if (return_retval != NULL)
- *return_retval = retval;
-
- return (retval == ERROR_OK) ? JIM_OK : retval;
-}
-
-extern struct command_context *global_cmd_ctx;
-
-/* dump a single line to the log for the command.
- * Do nothing in case we are not at debug level 3 */
-void script_debug(Jim_Interp *interp, const char *name,
- unsigned argc, Jim_Obj * const *argv)
-{
- if (debug_level < LOG_LVL_DEBUG)
- return;
-
- char *dbg = alloc_printf("command - %s", name);
- for (unsigned i = 0; i < argc; i++) {
- int len;
- const char *w = Jim_GetString(argv[i], &len);
- char *t = alloc_printf("%s %s", dbg, w);
- free(dbg);
- dbg = t;
- }
- LOG_DEBUG("%s", dbg);
- free(dbg);
-}
-
-static void script_command_args_free(char **words, unsigned nwords)
-{
- for (unsigned i = 0; i < nwords; i++)
- free(words[i]);
- free(words);
-}
-
-static char **script_command_args_alloc(
- unsigned argc, Jim_Obj * const *argv, unsigned *nwords)
-{
- char **words = malloc(argc * sizeof(char *));
- if (NULL == words)
- return NULL;
-
- unsigned i;
- for (i = 0; i < argc; i++) {
- int len;
- const char *w = Jim_GetString(argv[i], &len);
- words[i] = strdup(w);
- if (words[i] == NULL) {
- script_command_args_free(words, i);
- return NULL;
- }
- }
- *nwords = i;
- return words;
-}
-
-struct command_context *current_command_context(Jim_Interp *interp)
-{
- /* grab the command context from the associated data */
- struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
- if (NULL == cmd_ctx) {
- /* Tcl can invoke commands directly instead of via command_run_line(). This would
- * happen when the Jim Tcl interpreter is provided by eCos or if we are running
- * commands in a startup script.
- *
- * A telnet or gdb server would provide a non-default command context to
- * handle piping of error output, have a separate current target, etc.
- */
- cmd_ctx = global_cmd_ctx;
- }
- return cmd_ctx;
-}
-
-static int script_command_run(Jim_Interp *interp,
- int argc, Jim_Obj * const *argv, struct command *c, bool capture)
-{
- target_call_timer_callbacks_now();
- LOG_USER_N("%s", ""); /* Keep GDB connection alive*/
-
- unsigned nwords;
- char **words = script_command_args_alloc(argc, argv, &nwords);
- if (NULL == words)
- return JIM_ERR;
-
- struct log_capture_state *state = NULL;
- if (capture)
- state = command_log_capture_start(interp);
-
- struct command_context *cmd_ctx = current_command_context(interp);
- int retval = run_command(cmd_ctx, c, (const char **)words, nwords);
-
- command_log_capture_finish(state);
-
- script_command_args_free(words, nwords);
- return command_retval_set(interp, retval);
-}
-
-static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- /* the private data is stashed in the interp structure */
-
- struct command *c = interp->cmdPrivData;
- assert(c);
- script_debug(interp, c->name, argc, argv);
- return script_command_run(interp, argc, argv, c, true);
-}
-
-static struct command *command_root(struct command *c)
-{
- while (NULL != c->parent)
- c = c->parent;
- return c;
-}
-
-/**
- * Find a command by name from a list of commands.
- * @returns Returns the named command if it exists in the list.
- * Returns NULL otherwise.
- */
-static struct command *command_find(struct command *head, const char *name)
-{
- for (struct command *cc = head; cc; cc = cc->next) {
- if (strcmp(cc->name, name) == 0)
- return cc;
- }
- return NULL;
-}
-
-struct command *command_find_in_context(struct command_context *cmd_ctx,
- const char *name)
-{
- return command_find(cmd_ctx->commands, name);
-}
-struct command *command_find_in_parent(struct command *parent,
- const char *name)
-{
- return command_find(parent->children, name);
-}
-
-/**
- * Add the command into the linked list, sorted by name.
- * @param head Address to head of command list pointer, which may be
- * updated if @c c gets inserted at the beginning of the list.
- * @param c The command to add to the list pointed to by @c head.
- */
-static void command_add_child(struct command **head, struct command *c)
-{
- assert(head);
- if (NULL == *head) {
- *head = c;
- return;
- }
-
- while ((*head)->next && (strcmp(c->name, (*head)->name) > 0))
- head = &(*head)->next;
-
- if (strcmp(c->name, (*head)->name) > 0) {
- c->next = (*head)->next;
- (*head)->next = c;
- } else {
- c->next = *head;
- *head = c;
- }
-}
-
-static struct command **command_list_for_parent(
- struct command_context *cmd_ctx, struct command *parent)
-{
- return parent ? &parent->children : &cmd_ctx->commands;
-}
-
-static void command_free(struct command *c)
-{
- /** @todo if command has a handler, unregister its jim command! */
-
- while (NULL != c->children) {
- struct command *tmp = c->children;
- c->children = tmp->next;
- command_free(tmp);
- }
-
- free(c->name);
- free(c->help);
- free(c->usage);
- free(c);
-}
-
-static struct command *command_new(struct command_context *cmd_ctx,
- struct command *parent, const struct command_registration *cr)
-{
- assert(cr->name);
-
- /*
- * If it is a non-jim command with no .usage specified,
- * log an error.
- *
- * strlen(.usage) == 0 means that the command takes no
- * arguments.
- */
- if ((cr->jim_handler == NULL) && (cr->usage == NULL)) {
- LOG_DEBUG("BUG: command '%s%s%s' does not have the "
- "'.usage' field filled out",
- parent && parent->name ? parent->name : "",
- parent && parent->name ? " " : "",
- cr->name);
- }
-
- struct command *c = calloc(1, sizeof(struct command));
- if (NULL == c)
- return NULL;
-
- c->name = strdup(cr->name);
- if (cr->help)
- c->help = strdup(cr->help);
- if (cr->usage)
- c->usage = strdup(cr->usage);
-
- if (!c->name || (cr->help && !c->help) || (cr->usage && !c->usage))
- goto command_new_error;
-
- c->parent = parent;
- c->handler = cr->handler;
- c->jim_handler = cr->jim_handler;
- c->jim_handler_data = cr->jim_handler_data;
- c->mode = cr->mode;
-
- command_add_child(command_list_for_parent(cmd_ctx, parent), c);
-
- return c;
-
-command_new_error:
- command_free(c);
- return NULL;
-}
-
-static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-
-static int register_command_handler(struct command_context *cmd_ctx,
- struct command *c)
-{
- Jim_Interp *interp = cmd_ctx->interp;
- char *ocd_name = alloc_printf("ocd_%s", c->name);
- if (NULL == ocd_name)
- return JIM_ERR;
-
- LOG_DEBUG("registering '%s'...", ocd_name);
-
- Jim_CmdProc *func = c->handler ? &script_command : &command_unknown;
- int retval = Jim_CreateCommand(interp, ocd_name, func, c, NULL);
- free(ocd_name);
- if (JIM_OK != retval)
- return retval;
-
- /* we now need to add an overrideable proc */
- char *override_name = alloc_printf(
- "proc %s {args} {eval ocd_bouncer %s $args}",
- c->name, c->name);
- if (NULL == override_name)
- return JIM_ERR;
-
- retval = Jim_Eval_Named(interp, override_name, 0, 0);
- free(override_name);
-
- return retval;
-}
-
-struct command *register_command(struct command_context *context,
- struct command *parent, const struct command_registration *cr)
-{
- if (!context || !cr->name)
- return NULL;
-
- const char *name = cr->name;
- struct command **head = command_list_for_parent(context, parent);
- struct command *c = command_find(*head, name);
- if (NULL != c) {
- /* TODO: originally we treated attempting to register a cmd twice as an error
- * Sometimes we need this behaviour, such as with flash banks.
- * http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html */
- LOG_DEBUG("command '%s' is already registered in '%s' context",
- name, parent ? parent->name : "<global>");
- return c;
- }
-
- c = command_new(context, parent, cr);
- if (NULL == c)
- return NULL;
-
- int retval = ERROR_OK;
- if (NULL != cr->jim_handler && NULL == parent) {
- retval = Jim_CreateCommand(context->interp, cr->name,
- cr->jim_handler, cr->jim_handler_data, NULL);
- } else if (NULL != cr->handler || NULL != parent)
- retval = register_command_handler(context, command_root(c));
-
- if (ERROR_OK != retval) {
- unregister_command(context, parent, name);
- c = NULL;
- }
- return c;
-}
-
-int register_commands(struct command_context *cmd_ctx, struct command *parent,
- const struct command_registration *cmds)
-{
- int retval = ERROR_OK;
- unsigned i;
- for (i = 0; cmds[i].name || cmds[i].chain; i++) {
- const struct command_registration *cr = cmds + i;
-
- struct command *c = NULL;
- if (NULL != cr->name) {
- c = register_command(cmd_ctx, parent, cr);
- if (NULL == c) {
- retval = ERROR_FAIL;
- break;
- }
- }
- if (NULL != cr->chain) {
- struct command *p = c ? : parent;
- retval = register_commands(cmd_ctx, p, cr->chain);
- if (ERROR_OK != retval)
- break;
- }
- }
- if (ERROR_OK != retval) {
- for (unsigned j = 0; j < i; j++)
- unregister_command(cmd_ctx, parent, cmds[j].name);
- }
- return retval;
-}
-
-int unregister_all_commands(struct command_context *context,
- struct command *parent)
-{
- if (context == NULL)
- return ERROR_OK;
-
- struct command **head = command_list_for_parent(context, parent);
- while (NULL != *head) {
- struct command *tmp = *head;
- *head = tmp->next;
- command_free(tmp);
- }
-
- return ERROR_OK;
-}
-
-int unregister_command(struct command_context *context,
- struct command *parent, const char *name)
-{
- if ((!context) || (!name))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct command *p = NULL;
- struct command **head = command_list_for_parent(context, parent);
- for (struct command *c = *head; NULL != c; p = c, c = c->next) {
- if (strcmp(name, c->name) != 0)
- continue;
-
- if (p)
- p->next = c->next;
- else
- *head = c->next;
-
- command_free(c);
- return ERROR_OK;
- }
-
- return ERROR_OK;
-}
-
-void command_set_handler_data(struct command *c, void *p)
-{
- if (NULL != c->handler || NULL != c->jim_handler)
- c->jim_handler_data = p;
- for (struct command *cc = c->children; NULL != cc; cc = cc->next)
- command_set_handler_data(cc, p);
-}
-
-void command_output_text(struct command_context *context, const char *data)
-{
- if (context && context->output_handler && data)
- context->output_handler(context, data);
-}
-
-void command_print_sameline(struct command_context *context, const char *format, ...)
-{
- char *string;
-
- va_list ap;
- va_start(ap, format);
-
- string = alloc_vprintf(format, ap);
- if (string != NULL) {
- /* we want this collected in the log + we also want to pick it up as a tcl return
- * value.
- *
- * The latter bit isn't precisely neat, but will do for now.
- */
- LOG_USER_N("%s", string);
- /* We already printed it above
- * command_output_text(context, string); */
- free(string);
- }
-
- va_end(ap);
-}
-
-void command_print(struct command_context *context, const char *format, ...)
-{
- char *string;
-
- va_list ap;
- va_start(ap, format);
-
- string = alloc_vprintf(format, ap);
- if (string != NULL) {
- strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one
- *char longer */
- /* we want this collected in the log + we also want to pick it up as a tcl return
- * value.
- *
- * The latter bit isn't precisely neat, but will do for now.
- */
- LOG_USER_N("%s", string);
- /* We already printed it above
- * command_output_text(context, string); */
- free(string);
- }
-
- va_end(ap);
-}
-
-static char *__command_name(struct command *c, char delim, unsigned extra)
-{
- char *name;
- unsigned len = strlen(c->name);
- if (NULL == c->parent) {
- /* allocate enough for the name, child names, and '\0' */
- name = malloc(len + extra + 1);
- strcpy(name, c->name);
- } else {
- /* parent's extra must include both the space and name */
- name = __command_name(c->parent, delim, 1 + len + extra);
- char dstr[2] = { delim, 0 };
- strcat(name, dstr);
- strcat(name, c->name);
- }
- return name;
-}
-
-char *command_name(struct command *c, char delim)
-{
- return __command_name(c, delim, 0);
-}
-
-static bool command_can_run(struct command_context *cmd_ctx, struct command *c)
-{
- return c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode;
-}
-
-static int run_command(struct command_context *context,
- struct command *c, const char *words[], unsigned num_words)
-{
- if (!command_can_run(context, c)) {
- /* Many commands may be run only before/after 'init' */
- const char *when;
- switch (c->mode) {
- case COMMAND_CONFIG:
- when = "before";
- break;
- case COMMAND_EXEC:
- when = "after";
- break;
- /* handle the impossible with humor; it guarantees a bug report! */
- default:
- when = "if Cthulhu is summoned by";
- break;
- }
- LOG_ERROR("The '%s' command must be used %s 'init'.",
- c->name, when);
- return ERROR_FAIL;
- }
-
- struct command_invocation cmd = {
- .ctx = context,
- .current = c,
- .name = c->name,
- .argc = num_words - 1,
- .argv = words + 1,
- };
- int retval = c->handler(&cmd);
- if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
- /* Print help for command */
- char *full_name = command_name(c, ' ');
- if (NULL != full_name) {
- command_run_linef(context, "usage %s", full_name);
- free(full_name);
- } else
- retval = -ENOMEM;
- } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) {
- /* just fall through for a shutdown request */
- } else if (retval != ERROR_OK) {
- /* we do not print out an error message because the command *should*
- * have printed out an error
- */
- LOG_DEBUG("Command failed with error code %d", retval);
- }
-
- return retval;
-}
-
-int command_run_line(struct command_context *context, char *line)
-{
- /* all the parent commands have been registered with the interpreter
- * so, can just evaluate the line as a script and check for
- * results
- */
- /* run the line thru a script engine */
- int retval = ERROR_FAIL;
- int retcode;
- /* Beware! This code needs to be reentrant. It is also possible
- * for OpenOCD commands to be invoked directly from Tcl. This would
- * happen when the Jim Tcl interpreter is provided by eCos for
- * instance.
- */
- Jim_Interp *interp = context->interp;
- Jim_DeleteAssocData(interp, "context");
- retcode = Jim_SetAssocData(interp, "context", NULL, context);
- if (retcode == JIM_OK) {
- /* associated the return value */
- Jim_DeleteAssocData(interp, "retval");
- retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
- if (retcode == JIM_OK) {
- retcode = Jim_Eval_Named(interp, line, 0, 0);
-
- Jim_DeleteAssocData(interp, "retval");
- }
- Jim_DeleteAssocData(interp, "context");
- }
- if (retcode == JIM_OK) {
- const char *result;
- int reslen;
-
- result = Jim_GetString(Jim_GetResult(interp), &reslen);
- if (reslen > 0) {
- int i;
- char buff[256 + 1];
- for (i = 0; i < reslen; i += 256) {
- int chunk;
- chunk = reslen - i;
- if (chunk > 256)
- chunk = 256;
- strncpy(buff, result + i, chunk);
- buff[chunk] = 0;
- LOG_USER_N("%s", buff);
- }
- LOG_USER_N("\n");
- }
- retval = ERROR_OK;
- } else if (retcode == JIM_EXIT) {
- /* ignore.
- * exit(Jim_GetExitCode(interp)); */
- } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) {
- return retcode;
- } else {
- Jim_MakeErrorMessage(interp);
- LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
-
- if (retval == ERROR_OK) {
- /* It wasn't a low level OpenOCD command that failed */
- return ERROR_FAIL;
- }
- return retval;
- }
-
- return retval;
-}
-
-int command_run_linef(struct command_context *context, const char *format, ...)
-{
- int retval = ERROR_FAIL;
- char *string;
- va_list ap;
- va_start(ap, format);
- string = alloc_vprintf(format, ap);
- if (string != NULL) {
- retval = command_run_line(context, string);
- free(string);
- }
- va_end(ap);
- return retval;
-}
-
-void command_set_output_handler(struct command_context *context,
- command_output_handler_t output_handler, void *priv)
-{
- context->output_handler = output_handler;
- context->output_handler_priv = priv;
-}
-
-struct command_context *copy_command_context(struct command_context *context)
-{
- struct command_context *copy_context = malloc(sizeof(struct command_context));
-
- *copy_context = *context;
-
- return copy_context;
-}
-
-void command_done(struct command_context *cmd_ctx)
-{
- if (NULL == cmd_ctx)
- return;
-
- free(cmd_ctx);
-}
-
-/* find full path to file */
-static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 2)
- return JIM_ERR;
- const char *file = Jim_GetString(argv[1], NULL);
- char *full_path = find_file(file);
- if (full_path == NULL)
- return JIM_ERR;
- Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
- free(full_path);
-
- Jim_SetResult(interp, result);
- return JIM_OK;
-}
-
-COMMAND_HANDLER(jim_echo)
-{
- if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n")) {
- LOG_USER_N("%s", CMD_ARGV[1]);
- return JIM_OK;
- }
- if (CMD_ARGC != 1)
- return JIM_ERR;
- LOG_USER("%s", CMD_ARGV[0]);
- return JIM_OK;
-}
-
-/* Capture progress output and return as tcl return value. If the
- * progress output was empty, return tcl return value.
- */
-static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 2)
- return JIM_ERR;
-
- struct log_capture_state *state = command_log_capture_start(interp);
-
- /* disable polling during capture. This avoids capturing output
- * from polling.
- *
- * This is necessary in order to avoid accidentally getting a non-empty
- * string for tcl fn's.
- */
- bool save_poll = jtag_poll_get_enabled();
-
- jtag_poll_set_enabled(false);
-
- const char *str = Jim_GetString(argv[1], NULL);
- int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
-
- jtag_poll_set_enabled(save_poll);
-
- command_log_capture_finish(state);
-
- return retcode;
-}
-
-static COMMAND_HELPER(command_help_find, struct command *head,
- struct command **out)
-{
- if (0 == CMD_ARGC)
- return ERROR_COMMAND_SYNTAX_ERROR;
- *out = command_find(head, CMD_ARGV[0]);
- if (NULL == *out && strncmp(CMD_ARGV[0], "ocd_", 4) == 0)
- *out = command_find(head, CMD_ARGV[0] + 4);
- if (NULL == *out)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (--CMD_ARGC == 0)
- return ERROR_OK;
- CMD_ARGV++;
- return CALL_COMMAND_HANDLER(command_help_find, (*out)->children, out);
-}
-
-static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
- bool show_help, const char *cmd_match);
-
-static COMMAND_HELPER(command_help_show_list, struct command *head, unsigned n,
- bool show_help, const char *cmd_match)
-{
- for (struct command *c = head; NULL != c; c = c->next)
- CALL_COMMAND_HANDLER(command_help_show, c, n, show_help, cmd_match);
- return ERROR_OK;
-}
-
-#define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n))
-
-static void command_help_show_indent(unsigned n)
-{
- for (unsigned i = 0; i < n; i++)
- LOG_USER_N(" ");
-}
-static void command_help_show_wrap(const char *str, unsigned n, unsigned n2)
-{
- const char *cp = str, *last = str;
- while (*cp) {
- const char *next = last;
- do {
- cp = next;
- do {
- next++;
- } while (*next != ' ' && *next != '\t' && *next != '\0');
- } while ((next - last < HELP_LINE_WIDTH(n)) && *next != '\0');
- if (next - last < HELP_LINE_WIDTH(n))
- cp = next;
- command_help_show_indent(n);
- LOG_USER("%.*s", (int)(cp - last), last);
- last = cp + 1;
- n = n2;
- }
-}
-
-static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
- bool show_help, const char *cmd_match)
-{
- char *cmd_name = command_name(c, ' ');
- if (NULL == cmd_name)
- return -ENOMEM;
-
- /* If the match string occurs anywhere, we print out
- * stuff for this command. */
- bool is_match = (strstr(cmd_name, cmd_match) != NULL) ||
- ((c->usage != NULL) && (strstr(c->usage, cmd_match) != NULL)) ||
- ((c->help != NULL) && (strstr(c->help, cmd_match) != NULL));
-
- if (is_match) {
- command_help_show_indent(n);
- LOG_USER_N("%s", cmd_name);
- }
- free(cmd_name);
-
- if (is_match) {
- if (c->usage && strlen(c->usage) > 0) {
- LOG_USER_N(" ");
- command_help_show_wrap(c->usage, 0, n + 5);
- } else
- LOG_USER_N("\n");
- }
-
- if (is_match && show_help) {
- char *msg;
-
- /* Normal commands are runtime-only; highlight exceptions */
- if (c->mode != COMMAND_EXEC) {
- const char *stage_msg = "";
-
- switch (c->mode) {
- case COMMAND_CONFIG:
- stage_msg = " (configuration command)";
- break;
- case COMMAND_ANY:
- stage_msg = " (command valid any time)";
- break;
- default:
- stage_msg = " (?mode error?)";
- break;
- }
- msg = alloc_printf("%s%s", c->help ? : "", stage_msg);
- } else
- msg = alloc_printf("%s", c->help ? : "");
-
- if (NULL != msg) {
- command_help_show_wrap(msg, n + 3, n + 3);
- free(msg);
- } else
- return -ENOMEM;
- }
-
- if (++n > 5) {
- LOG_ERROR("command recursion exceeded");
- return ERROR_FAIL;
- }
-
- return CALL_COMMAND_HANDLER(command_help_show_list,
- c->children, n, show_help, cmd_match);
-}
-
-COMMAND_HANDLER(handle_help_command)
-{
- bool full = strcmp(CMD_NAME, "help") == 0;
- int retval;
- struct command *c = CMD_CTX->commands;
- char *cmd_match = NULL;
-
- if (CMD_ARGC == 0)
- cmd_match = "";
- else if (CMD_ARGC >= 1) {
- unsigned i;
-
- for (i = 0; i < CMD_ARGC; ++i) {
- if (NULL != cmd_match) {
- char *prev = cmd_match;
-
- cmd_match = alloc_printf("%s %s", cmd_match, CMD_ARGV[i]);
- free(prev);
- if (NULL == cmd_match) {
- LOG_ERROR("unable to build search string");
- return -ENOMEM;
- }
- } else {
- cmd_match = alloc_printf("%s", CMD_ARGV[i]);
- if (NULL == cmd_match) {
- LOG_ERROR("unable to build search string");
- return -ENOMEM;
- }
- }
- }
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- retval = CALL_COMMAND_HANDLER(command_help_show_list,
- c, 0, full, cmd_match);
-
- if (CMD_ARGC >= 1)
- free(cmd_match);
- return retval;
-}
-
-static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
- struct command *head, struct command **out, bool top_level)
-{
- if (0 == argc)
- return argc;
- const char *cmd_name = Jim_GetString(argv[0], NULL);
- struct command *c = command_find(head, cmd_name);
- if (NULL == c && top_level && strncmp(cmd_name, "ocd_", 4) == 0)
- c = command_find(head, cmd_name + 4);
- if (NULL == c)
- return argc;
- *out = c;
- return command_unknown_find(--argc, ++argv, (*out)->children, out, false);
-}
-
-static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
- if (strcmp(cmd_name, "unknown") == 0) {
- if (argc == 1)
- return JIM_OK;
- argc--;
- argv++;
- }
- script_debug(interp, cmd_name, argc, argv);
-
- struct command_context *cmd_ctx = current_command_context(interp);
- struct command *c = cmd_ctx->commands;
- int remaining = command_unknown_find(argc, argv, c, &c, true);
- /* if nothing could be consumed, then it's really an unknown command */
- if (remaining == argc) {
- const char *cmd = Jim_GetString(argv[0], NULL);
- LOG_ERROR("Unknown command:\n %s", cmd);
- return JIM_OK;
- }
-
- bool found = true;
- Jim_Obj *const *start;
- unsigned count;
- if (c->handler || c->jim_handler) {
- /* include the command name in the list */
- count = remaining + 1;
- start = argv + (argc - remaining - 1);
- } else {
- c = command_find(cmd_ctx->commands, "usage");
- if (NULL == c) {
- LOG_ERROR("unknown command, but usage is missing too");
- return JIM_ERR;
- }
- count = argc - remaining;
- start = argv;
- found = false;
- }
- /* pass the command through to the intended handler */
- if (c->jim_handler) {
- interp->cmdPrivData = c->jim_handler_data;
- return (*c->jim_handler)(interp, count, start);
- }
-
- return script_command_run(interp, count, start, c, found);
-}
-
-static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- struct command_context *cmd_ctx = current_command_context(interp);
- enum command_mode mode;
-
- if (argc > 1) {
- struct command *c = cmd_ctx->commands;
- int remaining = command_unknown_find(argc - 1, argv + 1, c, &c, true);
- /* if nothing could be consumed, then it's an unknown command */
- if (remaining == argc - 1) {
- Jim_SetResultString(interp, "unknown", -1);
- return JIM_OK;
- }
- mode = c->mode;
- } else
- mode = cmd_ctx->mode;
-
- const char *mode_str;
- switch (mode) {
- case COMMAND_ANY:
- mode_str = "any";
- break;
- case COMMAND_CONFIG:
- mode_str = "config";
- break;
- case COMMAND_EXEC:
- mode_str = "exec";
- break;
- default:
- mode_str = "unknown";
- break;
- }
- Jim_SetResultString(interp, mode_str, -1);
- return JIM_OK;
-}
-
-static int jim_command_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (1 == argc)
- return JIM_ERR;
-
- struct command_context *cmd_ctx = current_command_context(interp);
- struct command *c = cmd_ctx->commands;
- int remaining = command_unknown_find(argc - 1, argv + 1, c, &c, true);
- /* if nothing could be consumed, then it's an unknown command */
- if (remaining == argc - 1) {
- Jim_SetResultString(interp, "unknown", -1);
- return JIM_OK;
- }
-
- if (c->jim_handler)
- Jim_SetResultString(interp, "native", -1);
- else if (c->handler)
- Jim_SetResultString(interp, "simple", -1);
- else if (remaining == 0)
- Jim_SetResultString(interp, "group", -1);
- else
- Jim_SetResultString(interp, "unknown", -1);
-
- return JIM_OK;
-}
-
-int help_add_command(struct command_context *cmd_ctx, struct command *parent,
- const char *cmd_name, const char *help_text, const char *usage)
-{
- struct command **head = command_list_for_parent(cmd_ctx, parent);
- struct command *nc = command_find(*head, cmd_name);
- if (NULL == nc) {
- /* add a new command with help text */
- struct command_registration cr = {
- .name = cmd_name,
- .mode = COMMAND_ANY,
- .help = help_text,
- .usage = usage,
- };
- nc = register_command(cmd_ctx, parent, &cr);
- if (NULL == nc) {
- LOG_ERROR("failed to add '%s' help text", cmd_name);
- return ERROR_FAIL;
- }
- LOG_DEBUG("added '%s' help text", cmd_name);
- return ERROR_OK;
- }
- if (help_text) {
- bool replaced = false;
- if (nc->help) {
- free(nc->help);
- replaced = true;
- }
- nc->help = strdup(help_text);
- if (replaced)
- LOG_INFO("replaced existing '%s' help", cmd_name);
- else
- LOG_DEBUG("added '%s' help text", cmd_name);
- }
- if (usage) {
- bool replaced = false;
- if (nc->usage) {
- free(nc->usage);
- replaced = true;
- }
- nc->usage = strdup(usage);
- if (replaced)
- LOG_INFO("replaced existing '%s' usage", cmd_name);
- else
- LOG_DEBUG("added '%s' usage text", cmd_name);
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_help_add_command)
-{
- if (CMD_ARGC < 2) {
- LOG_ERROR("%s: insufficient arguments", CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* save help text and remove it from argument list */
- const char *str = CMD_ARGV[--CMD_ARGC];
- const char *help = !strcmp(CMD_NAME, "add_help_text") ? str : NULL;
- const char *usage = !strcmp(CMD_NAME, "add_usage_text") ? str : NULL;
- if (!help && !usage) {
- LOG_ERROR("command name '%s' is unknown", CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- /* likewise for the leaf command name */
- const char *cmd_name = CMD_ARGV[--CMD_ARGC];
-
- struct command *c = NULL;
- if (CMD_ARGC > 0) {
- c = CMD_CTX->commands;
- int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c);
- if (ERROR_OK != retval)
- return retval;
- }
- return help_add_command(CMD_CTX, c, cmd_name, help, usage);
-}
-
-/* sleep command sleeps for <n> milliseconds
- * this is useful in target startup scripts
- */
-COMMAND_HANDLER(handle_sleep_command)
-{
- bool busy = false;
- if (CMD_ARGC == 2) {
- if (strcmp(CMD_ARGV[1], "busy") == 0)
- busy = true;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
- } else if (CMD_ARGC < 1 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned long duration = 0;
- int retval = parse_ulong(CMD_ARGV[0], &duration);
- if (ERROR_OK != retval)
- return retval;
-
- if (!busy) {
- int64_t then = timeval_ms();
- while (timeval_ms() - then < (int64_t)duration) {
- target_call_timer_callbacks_now();
- usleep(1000);
- }
- } else
- busy_sleep(duration);
-
- return ERROR_OK;
-}
-
-static const struct command_registration command_subcommand_handlers[] = {
- {
- .name = "mode",
- .mode = COMMAND_ANY,
- .jim_handler = jim_command_mode,
- .usage = "[command_name ...]",
- .help = "Returns the command modes allowed by a command:"
- "'any', 'config', or 'exec'. If no command is"
- "specified, returns the current command mode. "
- "Returns 'unknown' if an unknown command is given. "
- "Command can be multiple tokens.",
- },
- {
- .name = "type",
- .mode = COMMAND_ANY,
- .jim_handler = jim_command_type,
- .usage = "command_name [...]",
- .help = "Returns the type of built-in command:"
- "'native', 'simple', 'group', or 'unknown'. "
- "Command can be multiple tokens.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration command_builtin_handlers[] = {
- {
- .name = "echo",
- .handler = jim_echo,
- .mode = COMMAND_ANY,
- .help = "Logs a message at \"user\" priority. "
- "Output message to stdout. "
- "Option \"-n\" suppresses trailing newline",
- .usage = "[-n] string",
- },
- {
- .name = "add_help_text",
- .handler = handle_help_add_command,
- .mode = COMMAND_ANY,
- .help = "Add new command help text; "
- "Command can be multiple tokens.",
- .usage = "command_name helptext_string",
- },
- {
- .name = "add_usage_text",
- .handler = handle_help_add_command,
- .mode = COMMAND_ANY,
- .help = "Add new command usage text; "
- "command can be multiple tokens.",
- .usage = "command_name usage_string",
- },
- {
- .name = "sleep",
- .handler = handle_sleep_command,
- .mode = COMMAND_ANY,
- .help = "Sleep for specified number of milliseconds. "
- "\"busy\" will busy wait instead (avoid this).",
- .usage = "milliseconds ['busy']",
- },
- {
- .name = "help",
- .handler = handle_help_command,
- .mode = COMMAND_ANY,
- .help = "Show full command help; "
- "command can be multiple tokens.",
- .usage = "[command_name]",
- },
- {
- .name = "usage",
- .handler = handle_help_command,
- .mode = COMMAND_ANY,
- .help = "Show basic command usage; "
- "command can be multiple tokens.",
- .usage = "[command_name]",
- },
- {
- .name = "command",
- .mode = COMMAND_ANY,
- .help = "core command group (introspection)",
- .chain = command_subcommand_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp)
-{
- struct command_context *context = malloc(sizeof(struct command_context));
- const char *HostOs;
-
- context->mode = COMMAND_EXEC;
- context->commands = NULL;
- context->current_target = 0;
- context->output_handler = NULL;
- context->output_handler_priv = NULL;
-
- /* Create a jim interpreter if we were not handed one */
- if (interp == NULL) {
- /* Create an interpreter */
- interp = Jim_CreateInterp();
- /* Add all the Jim core commands */
- Jim_RegisterCoreCommands(interp);
- Jim_InitStaticExtensions(interp);
- }
-
- context->interp = interp;
-
- /* Stick to lowercase for HostOS strings. */
-#if defined(_MSC_VER)
- /* WinXX - is generic, the forward
- * looking problem is this:
- *
- * "win32" or "win64"
- *
- * "winxx" is generic.
- */
- HostOs = "winxx";
-#elif defined(__linux__)
- HostOs = "linux";
-#elif defined(__APPLE__) || defined(__DARWIN__)
- HostOs = "darwin";
-#elif defined(__CYGWIN__)
- HostOs = "cygwin";
-#elif defined(__MINGW32__)
- HostOs = "mingw32";
-#elif defined(__ECOS)
- HostOs = "ecos";
-#elif defined(__FreeBSD__)
- HostOs = "freebsd";
-#elif defined(__NetBSD__)
- HostOs = "netbsd";
-#elif defined(__OpenBSD__)
- HostOs = "openbsd";
-#else
-#warning "Unrecognized host OS..."
- HostOs = "other";
-#endif
- Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
- Jim_NewStringObj(interp, HostOs, strlen(HostOs)));
-
- Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL);
- Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL);
-
- register_commands(context, NULL, command_builtin_handlers);
-
- Jim_SetAssocData(interp, "context", NULL, context);
- if (Jim_Eval_Named(interp, startup_tcl, "embedded:startup.tcl", 1) == JIM_ERR) {
- LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD)");
- Jim_MakeErrorMessage(interp);
- LOG_USER_N("%s", Jim_GetString(Jim_GetResult(interp), NULL));
- exit(-1);
- }
- Jim_DeleteAssocData(interp, "context");
-
- return context;
-}
-
-int command_context_mode(struct command_context *cmd_ctx, enum command_mode mode)
-{
- if (!cmd_ctx)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- cmd_ctx->mode = mode;
- return ERROR_OK;
-}
-
-void process_jim_events(struct command_context *cmd_ctx)
-{
- static int recursion;
- if (recursion)
- return;
-
- recursion++;
- Jim_ProcessEvents(cmd_ctx->interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
- recursion--;
-}
-
-#define DEFINE_PARSE_NUM_TYPE(name, type, func, min, max) \
- int parse ## name(const char *str, type * ul) \
- { \
- if (!*str) { \
- LOG_ERROR("Invalid command argument"); \
- return ERROR_COMMAND_ARGUMENT_INVALID; \
- } \
- char *end; \
- *ul = func(str, &end, 0); \
- if (*end) { \
- LOG_ERROR("Invalid command argument"); \
- return ERROR_COMMAND_ARGUMENT_INVALID; \
- } \
- if ((max == *ul) && (ERANGE == errno)) { \
- LOG_ERROR("Argument overflow"); \
- return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
- } \
- if (min && (min == *ul) && (ERANGE == errno)) { \
- LOG_ERROR("Argument underflow"); \
- return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
- } \
- return ERROR_OK; \
- }
-DEFINE_PARSE_NUM_TYPE(_ulong, unsigned long, strtoul, 0, ULONG_MAX)
-DEFINE_PARSE_NUM_TYPE(_ullong, unsigned long long, strtoull, 0, ULLONG_MAX)
-DEFINE_PARSE_NUM_TYPE(_long, long, strtol, LONG_MIN, LONG_MAX)
-DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX)
-
-#define DEFINE_PARSE_WRAPPER(name, type, min, max, functype, funcname) \
- int parse ## name(const char *str, type * ul) \
- { \
- functype n; \
- int retval = parse ## funcname(str, &n); \
- if (ERROR_OK != retval) \
- return retval; \
- if (n > max) \
- return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
- if (min) \
- return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
- *ul = n; \
- return ERROR_OK; \
- }
-
-#define DEFINE_PARSE_ULONGLONG(name, type, min, max) \
- DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long long, _ullong)
-DEFINE_PARSE_ULONGLONG(_uint, unsigned, 0, UINT_MAX)
-DEFINE_PARSE_ULONGLONG(_u64, uint64_t, 0, UINT64_MAX)
-DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX)
-DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX)
-DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX)
-
-#define DEFINE_PARSE_LONGLONG(name, type, min, max) \
- DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong)
-DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX)
-DEFINE_PARSE_LONGLONG(_s64, int64_t, n < INT64_MIN, INT64_MAX)
-DEFINE_PARSE_LONGLONG(_s32, int32_t, n < INT32_MIN, INT32_MAX)
-DEFINE_PARSE_LONGLONG(_s16, int16_t, n < INT16_MIN, INT16_MAX)
-DEFINE_PARSE_LONGLONG(_s8, int8_t, n < INT8_MIN, INT8_MAX)
-
-static int command_parse_bool(const char *in, bool *out,
- const char *on, const char *off)
-{
- if (strcasecmp(in, on) == 0)
- *out = true;
- else if (strcasecmp(in, off) == 0)
- *out = false;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
- return ERROR_OK;
-}
-
-int command_parse_bool_arg(const char *in, bool *out)
-{
- if (command_parse_bool(in, out, "on", "off") == ERROR_OK)
- return ERROR_OK;
- if (command_parse_bool(in, out, "enable", "disable") == ERROR_OK)
- return ERROR_OK;
- if (command_parse_bool(in, out, "true", "false") == ERROR_OK)
- return ERROR_OK;
- if (command_parse_bool(in, out, "yes", "no") == ERROR_OK)
- return ERROR_OK;
- if (command_parse_bool(in, out, "1", "0") == ERROR_OK)
- return ERROR_OK;
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
-{
- switch (CMD_ARGC) {
- case 1: {
- const char *in = CMD_ARGV[0];
- if (command_parse_bool_arg(in, out) != ERROR_OK) {
- LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- /* fall through */
- }
- case 0:
- LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled");
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return ERROR_OK;
-}
diff --git a/src/helper/command.h b/src/helper/command.h
deleted file mode 100644
index 5c39660..0000000
--- a/src/helper/command.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_COMMAND_H
-#define OPENOCD_HELPER_COMMAND_H
-
-#include <jim-nvp.h>
-
-/* To achieve C99 printf compatibility in MinGW, gnu_printf should be
- * used for __attribute__((format( ... ))), with GCC v4.4 or later
- */
-#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004))
-#define PRINTF_ATTRIBUTE_FORMAT gnu_printf
-#else
-#define PRINTF_ATTRIBUTE_FORMAT printf
-#endif
-
-enum command_mode {
- COMMAND_EXEC,
- COMMAND_CONFIG,
- COMMAND_ANY,
-};
-
-struct command_context;
-
-/** The type signature for command context's output handler. */
-typedef int (*command_output_handler_t)(struct command_context *context,
- const char *line);
-
-struct command_context {
- Jim_Interp *interp;
- enum command_mode mode;
- struct command *commands;
- int current_target;
- command_output_handler_t output_handler;
- void *output_handler_priv;
-};
-
-struct command;
-
-/**
- * When run_command is called, a new instance will be created on the
- * stack, filled with the proper values, and passed by reference to the
- * required COMMAND_HANDLER routine.
- */
-struct command_invocation {
- struct command_context *ctx;
- struct command *current;
- const char *name;
- unsigned argc;
- const char **argv;
-};
-
-/**
- * Command handlers may be defined with more parameters than the base
- * set provided by command.c. This macro uses C99 magic to allow
- * defining all such derivative types using this macro.
- */
-#define __COMMAND_HANDLER(name, extra ...) \
- int name(struct command_invocation *cmd, ## extra)
-
-/**
- * Use this to macro to call a command helper (or a nested handler).
- * It provides command handler authors protection against reordering or
- * removal of unused parameters.
- *
- * @b Note: This macro uses lexical capture to provide some arguments.
- * As a result, this macro should be used @b only within functions
- * defined by the COMMAND_HANDLER or COMMAND_HELPER macros. Those
- * macros provide the expected lexical context captured by this macro.
- * Furthermore, it should be used only from the top-level of handler or
- * helper function, or care must be taken to avoid redefining the same
- * variables in intervening scope(s) by accident.
- */
-#define CALL_COMMAND_HANDLER(name, extra ...) \
- name(cmd, ## extra)
-
-/**
- * Always use this macro to define new command handler functions.
- * It ensures the parameters are ordered, typed, and named properly, so
- * they be can be used by other macros (e.g. COMMAND_PARSE_NUMBER).
- * All command handler functions must be defined as static in scope.
- */
-#define COMMAND_HANDLER(name) \
- static __COMMAND_HANDLER(name)
-
-/**
- * Similar to COMMAND_HANDLER, except some parameters are expected.
- * A helper is globally-scoped because it may be shared between several
- * source files (e.g. the s3c24xx device command helper).
- */
-#define COMMAND_HELPER(name, extra ...) __COMMAND_HANDLER(name, extra)
-
-/**
- * Use this macro to access the context of the command being handled,
- * rather than accessing the variable directly. It may be moved.
- */
-#define CMD_CTX (cmd->ctx)
-/**
- * Use this macro to access the number of arguments for the command being
- * handled, rather than accessing the variable directly. It may be moved.
- */
-#define CMD_ARGC (cmd->argc)
-/**
- * Use this macro to access the arguments for the command being handled,
- * rather than accessing the variable directly. It may be moved.
- */
-#define CMD_ARGV (cmd->argv)
-/**
- * Use this macro to access the name of the command being handled,
- * rather than accessing the variable directly. It may be moved.
- */
-#define CMD_NAME (cmd->name)
-/**
- * Use this macro to access the current command being handled,
- * rather than accessing the variable directly. It may be moved.
- */
-#define CMD_CURRENT (cmd->current)
-/**
- * Use this macro to access the invoked command handler's data pointer,
- * rather than accessing the variable directly. It may be moved.
- */
-#define CMD_DATA (CMD_CURRENT->jim_handler_data)
-
-/**
- * The type signature for command handling functions. They are
- * usually registered as part of command_registration, providing
- * a high-level means for executing a command.
- *
- * If the command fails, it *MUST* return a value != ERROR_OK
- * (many commands break this rule, patches welcome!)
- *
- * This is *especially* important for commands such as writing
- * to flash or verifying memory. The reason is that those commands
- * can be used by programs to determine if the operation succeded
- * or not. If the operation failed, then a program can try
- * an alternative approach.
- *
- * Returning ERROR_COMMAND_SYNTAX_ERROR will have the effect of
- * printing out the syntax of the command.
- */
-typedef __COMMAND_HANDLER((*command_handler_t));
-
-struct command {
- char *name;
- char *help;
- char *usage;
- struct command *parent;
- struct command *children;
- command_handler_t handler;
- Jim_CmdProc *jim_handler;
- void *jim_handler_data;
- enum command_mode mode;
- struct command *next;
-};
-
-/**
- * @param c The command to be named.
- * @param delim The character to place between command names.
- * @returns A malloc'd string containing the full command name,
- * which may include one or more ancestor components. Multiple names
- * are separated by single spaces. The caller must free() the string
- * when done with it.
- */
-char *command_name(struct command *c, char delim);
-
-/*
- * Commands should be registered by filling in one or more of these
- * structures and passing them to register_command().
- *
- * A conventioal format should be used for help strings, to provide both
- * usage and basic information:
- * @code
- * "@<options@> ... - some explanation text"
- * @endcode
- *
- * @param name The name of the command to register, which must not have
- * been registered previously in the intended context.
- * @param handler The callback function that will be called. If NULL,
- * then the command serves as a placeholder for its children or a script.
- * @param mode The command mode(s) in which this command may be run.
- * @param help The help text that will be displayed to the user.
- */
-struct command_registration {
- const char *name;
- command_handler_t handler;
- Jim_CmdProc *jim_handler;
- void *jim_handler_data;
- enum command_mode mode;
- const char *help;
- /** a string listing the options and arguments, required or optional */
- const char *usage;
-
- /**
- * If non-NULL, the commands in @c chain will be registered in
- * the same context and scope of this registration record.
- * This allows modules to inherit lists commands from other
- * modules.
- */
- const struct command_registration *chain;
-};
-
-/** Use this as the last entry in an array of command_registration records. */
-#define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL }
-
-/**
- * Register a command @c handler that can be called from scripts during
- * the execution @c mode specified.
- *
- * If @c parent is non-NULL, the new command will be registered as a
- * sub-command under it; otherwise, it will be available as a top-level
- * command.
- *
- * @param cmd_ctx The command_context in which to register the command.
- * @param parent Register this command as a child of this, or NULL to
- * register a top-level command.
- * @param rec A command_registration record that contains the desired
- * command parameters.
- * @returns The new command, if successful; otherwise, NULL.
- */
-struct command *register_command(struct command_context *cmd_ctx,
- struct command *parent, const struct command_registration *rec);
-
-/**
- * Register one or more commands in the specified context, as children
- * of @c parent (or top-level commends, if NULL). In a registration's
- * record contains a non-NULL @c chain member and name is NULL, the
- * commands on the chain will be registered in the same context.
- * Otherwise, the chained commands are added as children of the command.
- *
- * @param cmd_ctx The command_context in which to register the command.
- * @param parent Register this command as a child of this, or NULL to
- * register a top-level command.
- * @param cmds Pointer to an array of command_registration records that
- * contains the desired command parameters. The last record must have
- * NULL for all fields.
- * @returns ERROR_OK on success; ERROR_FAIL if any registration fails.
- */
-int register_commands(struct command_context *cmd_ctx, struct command *parent,
- const struct command_registration *cmds);
-
-
-/**
- * Unregisters command @c name from the given context, @c cmd_ctx.
- * @param cmd_ctx The context of the registered command.
- * @param parent The parent of the given command, or NULL.
- * @param name The name of the command to unregister.
- * @returns ERROR_OK on success, or an error code.
- */
-int unregister_command(struct command_context *cmd_ctx,
- struct command *parent, const char *name);
-/**
- * Unregisters all commands from the specfied context.
- * @param cmd_ctx The context that will be cleared of registered commands.
- * @param parent If given, only clear commands from under this one command.
- * @returns ERROR_OK on success, or an error code.
- */
-int unregister_all_commands(struct command_context *cmd_ctx,
- struct command *parent);
-
-struct command *command_find_in_context(struct command_context *cmd_ctx,
- const char *name);
-struct command *command_find_in_parent(struct command *parent,
- const char *name);
-
-/**
- * Update the private command data field for a command and all descendents.
- * This is used when creating a new heirarchy of commands that depends
- * on obtaining a dynamically created context. The value will be available
- * in command handlers by using the CMD_DATA macro.
- * @param c The command (group) whose data pointer(s) will be updated.
- * @param p The new data pointer to use for the command or its descendents.
- */
-void command_set_handler_data(struct command *c, void *p);
-
-void command_set_output_handler(struct command_context *context,
- command_output_handler_t output_handler, void *priv);
-
-
-int command_context_mode(struct command_context *context, enum command_mode mode);
-
-/* Return the current command context associated with the Jim interpreter or
- * alternatively the global default command interpreter
- */
-struct command_context *current_command_context(Jim_Interp *interp);
-/**
- * Creates a new command context using the startup TCL provided and
- * the existing Jim interpreter, if any. If interp == NULL, then command_init
- * creates a command interpreter.
- */
-struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp);
-/**
- * Creates a copy of an existing command context. This does not create
- * a deep copy of the command list, so modifications in one context will
- * affect all shared contexts. The caller must track reference counting
- * and ensure the commands are freed before destroying the last instance.
- * @param cmd_ctx The command_context that will be copied.
- * @returns A new command_context with the same state as the original.
- */
-struct command_context *copy_command_context(struct command_context *cmd_ctx);
-/**
- * Frees the resources associated with a command context. The commands
- * are not removed, so unregister_all_commands() must be called first.
- * @param context The command_context that will be destroyed.
- */
-void command_done(struct command_context *context);
-
-void command_print(struct command_context *context, const char *format, ...)
-__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
-void command_print_sameline(struct command_context *context, const char *format, ...)
-__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
-int command_run_line(struct command_context *context, char *line);
-int command_run_linef(struct command_context *context, const char *format, ...)
-__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
-void command_output_text(struct command_context *context, const char *data);
-
-void process_jim_events(struct command_context *cmd_ctx);
-
-#define ERROR_COMMAND_CLOSE_CONNECTION (-600)
-#define ERROR_COMMAND_SYNTAX_ERROR (-601)
-#define ERROR_COMMAND_NOTFOUND (-602)
-#define ERROR_COMMAND_ARGUMENT_INVALID (-603)
-#define ERROR_COMMAND_ARGUMENT_OVERFLOW (-604)
-#define ERROR_COMMAND_ARGUMENT_UNDERFLOW (-605)
-
-int parse_ulong(const char *str, unsigned long *ul);
-int parse_ullong(const char *str, unsigned long long *ul);
-
-int parse_long(const char *str, long *ul);
-int parse_llong(const char *str, long long *ul);
-
-#define DECLARE_PARSE_WRAPPER(name, type) \
- int parse ## name(const char *str, type * ul)
-
-DECLARE_PARSE_WRAPPER(_uint, unsigned);
-DECLARE_PARSE_WRAPPER(_u64, uint64_t);
-DECLARE_PARSE_WRAPPER(_u32, uint32_t);
-DECLARE_PARSE_WRAPPER(_u16, uint16_t);
-DECLARE_PARSE_WRAPPER(_u8, uint8_t);
-
-DECLARE_PARSE_WRAPPER(_int, int);
-DECLARE_PARSE_WRAPPER(_s32, int32_t);
-DECLARE_PARSE_WRAPPER(_s16, int16_t);
-DECLARE_PARSE_WRAPPER(_s8, int8_t);
-
-/**
- * @brief parses the string @a in into @a out as a @a type, or prints
- * a command error and passes the error code to the caller. If an error
- * does occur, the calling function will return the error code produced
- * by the parsing function (one of ERROR_COMMAND_ARGUMENT_*).
- *
- * This function may cause the calling function to return immediately,
- * so it should be used carefully to avoid leaking resources. In most
- * situations, parsing should be completed in full before proceding
- * to allocate resources, and this strategy will most prevents leaks.
- */
-#define COMMAND_PARSE_NUMBER(type, in, out) \
- do { \
- int retval_macro_tmp = parse_ ## type(in, &(out)); \
- if (ERROR_OK != retval_macro_tmp) { \
- command_print(CMD_CTX, stringify(out) \
- " option value ('%s') is not valid", in); \
- return retval_macro_tmp; \
- } \
- } while (0)
-
-/**
- * Parse the string @c as a binary parameter, storing the boolean value
- * in @c out. The strings @c on and @c off are used to match different
- * strings for true and false options (e.g. "on" and "off" or
- * "enable" and "disable").
- */
-#define COMMAND_PARSE_BOOL(in, out, on, off) \
- do { \
- bool value; \
- int retval_macro_tmp = command_parse_bool_arg(in, &value); \
- if (ERROR_OK != retval_macro_tmp) { \
- command_print(CMD_CTX, stringify(out) \
- " option value ('%s') is not valid", in); \
- command_print(CMD_CTX, " choices are '%s' or '%s'", \
- on, off); \
- return retval_macro_tmp; \
- } \
- out = value; \
- } while (0)
-
-int command_parse_bool_arg(const char *in, bool *out);
-COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label);
-
-/** parses an on/off command argument */
-#define COMMAND_PARSE_ON_OFF(in, out) \
- COMMAND_PARSE_BOOL(in, out, "on", "off")
-/** parses an enable/disable command argument */
-#define COMMAND_PARSE_ENABLE(in, out) \
- COMMAND_PARSE_BOOL(in, out, "enable", "disable")
-
-void script_debug(Jim_Interp *interp, const char *cmd,
- unsigned argc, Jim_Obj * const *argv);
-
-#endif /* OPENOCD_HELPER_COMMAND_H */
diff --git a/src/helper/configuration.c b/src/helper/configuration.c
deleted file mode 100644
index 2a27883..0000000
--- a/src/helper/configuration.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "configuration.h"
-#include "log.h"
-
-static size_t num_config_files;
-static char **config_file_names;
-
-static size_t num_script_dirs;
-static char **script_search_dirs;
-
-void add_script_search_dir(const char *dir)
-{
- num_script_dirs++;
- script_search_dirs = realloc(script_search_dirs, (num_script_dirs + 1) * sizeof(char *));
-
- script_search_dirs[num_script_dirs-1] = strdup(dir);
- script_search_dirs[num_script_dirs] = NULL;
-
- LOG_DEBUG("adding %s", dir);
-}
-
-void add_config_command(const char *cfg)
-{
- num_config_files++;
- config_file_names = realloc(config_file_names, (num_config_files + 1) * sizeof(char *));
-
- config_file_names[num_config_files-1] = strdup(cfg);
- config_file_names[num_config_files] = NULL;
-}
-
-/* return full path or NULL according to search rules */
-char *find_file(const char *file)
-{
- FILE *fp = NULL;
- char **search_dirs = script_search_dirs;
- char *dir;
- char const *mode = "r";
- char *full_path;
-
- /* Check absolute and relative to current working dir first.
- * This keeps full_path reporting belowing working. */
- full_path = alloc_printf("%s", file);
- fp = fopen(full_path, mode);
-
- while (!fp) {
- free(full_path);
- full_path = NULL;
- dir = *search_dirs++;
-
- if (!dir)
- break;
-
- full_path = alloc_printf("%s/%s", dir, file);
- fp = fopen(full_path, mode);
- }
-
- if (fp) {
- fclose(fp);
- LOG_DEBUG("found %s", full_path);
- return full_path;
- }
-
- free(full_path);
-
- return NULL;
-}
-
-FILE *open_file_from_path(const char *file, const char *mode)
-{
- if (mode[0] != 'r')
- return fopen(file, mode);
- else {
- char *full_path = find_file(file);
- if (full_path == NULL)
- return NULL;
- FILE *fp = NULL;
- fp = fopen(full_path, mode);
- free(full_path);
- return fp;
- }
-}
-
-int parse_config_file(struct command_context *cmd_ctx)
-{
- int retval;
- char **cfg;
-
- if (!config_file_names) {
- command_run_line(cmd_ctx, "script openocd.cfg");
- return ERROR_OK;
- }
-
- cfg = config_file_names;
-
- while (*cfg) {
- retval = command_run_line(cmd_ctx, *cfg);
- if (retval != ERROR_OK)
- return retval;
- cfg++;
- }
-
- return ERROR_OK;
-}
-
-#ifndef _WIN32
-#include <pwd.h>
-#endif
-
-char *get_home_dir(const char *append_path)
-{
- char *home = getenv("HOME");
-
- if (home == NULL) {
-
-#ifdef _WIN32
- home = getenv("USERPROFILE");
-
- if (home == NULL) {
-
- char homepath[MAX_PATH];
- char *drive = getenv("HOMEDRIVE");
- char *path = getenv("HOMEPATH");
- if (drive && path) {
- snprintf(homepath, MAX_PATH, "%s/%s", drive, path);
- home = homepath;
- }
- }
-#else
- struct passwd *pwd = getpwuid(getuid());
- if (pwd)
- home = pwd->pw_dir;
-
-#endif
- }
-
- if (home == NULL)
- return home;
-
- char *home_path;
-
- if (append_path)
- home_path = alloc_printf("%s/%s", home, append_path);
- else
- home_path = alloc_printf("%s", home);
-
- return home_path;
-}
diff --git a/src/helper/configuration.h b/src/helper/configuration.h
deleted file mode 100644
index 3cbcd41..0000000
--- a/src/helper/configuration.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_CONFIGURATION_H
-#define OPENOCD_HELPER_CONFIGURATION_H
-
-#include <helper/command.h>
-
-int parse_cmdline_args(struct command_context *cmd_ctx,
- int argc, char *argv[]);
-
-int parse_config_file(struct command_context *cmd_ctx);
-void add_config_command(const char *cfg);
-
-void add_script_search_dir(const char *dir);
-
-int configuration_output_handler(struct command_context *cmd_ctx,
- const char *line);
-
-FILE *open_file_from_path(const char *file, const char *mode);
-
-char *find_file(const char *name);
-char *get_home_dir(const char *append_path);
-
-#endif /* OPENOCD_HELPER_CONFIGURATION_H */
diff --git a/src/helper/fileio.c b/src/helper/fileio.c
deleted file mode 100644
index 47494df..0000000
--- a/src/helper/fileio.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "log.h"
-#include "configuration.h"
-#include "fileio.h"
-
-struct fileio {
- char *url;
- size_t size;
- enum fileio_type type;
- enum fileio_access access;
- FILE *file;
-};
-
-static inline int fileio_close_local(struct fileio *fileio)
-{
- int retval = fclose(fileio->file);
- if (retval != 0) {
- if (retval == EBADF)
- LOG_ERROR("BUG: fileio->file not a valid file descriptor");
- else
- LOG_ERROR("couldn't close %s: %s", fileio->url, strerror(errno));
-
- return ERROR_FILEIO_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static inline int fileio_open_local(struct fileio *fileio)
-{
- char file_access[4];
- ssize_t file_size;
-
- switch (fileio->access) {
- case FILEIO_READ:
- strcpy(file_access, "r");
- break;
- case FILEIO_WRITE:
- strcpy(file_access, "w");
- break;
- case FILEIO_READWRITE:
- strcpy(file_access, "w+");
- break;
- case FILEIO_APPEND:
- strcpy(file_access, "a");
- break;
- case FILEIO_APPENDREAD:
- strcpy(file_access, "a+");
- break;
- default:
- LOG_ERROR("BUG: access neither read, write nor readwrite");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* win32 always opens in binary mode */
-#ifndef _WIN32
- if (fileio->type == FILEIO_BINARY)
-#endif
- strcat(file_access, "b");
-
- fileio->file = open_file_from_path(fileio->url, file_access);
- if (!fileio->file) {
- LOG_ERROR("couldn't open %s", fileio->url);
- return ERROR_FILEIO_OPERATION_FAILED;
- }
-
- file_size = 0;
-
- if ((fileio->access != FILEIO_WRITE) || (fileio->access == FILEIO_READWRITE)) {
- /* NB! Here we use fseek() instead of stat(), since stat is a
- * more advanced operation that might not apply to e.g. a disk path
- * that refers to e.g. a tftp client */
- int result, result2;
-
- result = fseek(fileio->file, 0, SEEK_END);
-
- file_size = ftell(fileio->file);
-
- result2 = fseek(fileio->file, 0, SEEK_SET);
-
- if ((file_size < 0) || (result < 0) || (result2 < 0)) {
- fileio_close_local(fileio);
- return ERROR_FILEIO_OPERATION_FAILED;
- }
- }
-
- fileio->size = file_size;
-
- return ERROR_OK;
-}
-
-int fileio_open(struct fileio **fileio, const char *url,
- enum fileio_access access_type, enum fileio_type type)
-{
- int retval;
- struct fileio *tmp;
-
- tmp = malloc(sizeof(struct fileio));
-
- tmp->type = type;
- tmp->access = access_type;
- tmp->url = strdup(url);
-
- retval = fileio_open_local(tmp);
-
- if (retval != ERROR_OK) {
- free(tmp->url);
- free(tmp);
- return retval;
- }
-
- *fileio = tmp;
-
- return ERROR_OK;
-}
-
-int fileio_close(struct fileio *fileio)
-{
- int retval;
-
- retval = fileio_close_local(fileio);
-
- free(fileio->url);
- free(fileio);
-
- return retval;
-}
-
-int fileio_seek(struct fileio *fileio, size_t position)
-{
- int retval;
-
- retval = fseek(fileio->file, position, SEEK_SET);
-
- if (retval != 0) {
- LOG_ERROR("couldn't seek file %s: %s", fileio->url, strerror(errno));
- return ERROR_FILEIO_OPERATION_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int fileio_local_read(struct fileio *fileio, size_t size, void *buffer,
- size_t *size_read)
-{
- ssize_t retval;
-
- retval = fread(buffer, 1, size, fileio->file);
- *size_read = (retval >= 0) ? retval : 0;
-
- return (retval < 0) ? retval : ERROR_OK;
-}
-
-int fileio_read(struct fileio *fileio, size_t size, void *buffer,
- size_t *size_read)
-{
- return fileio_local_read(fileio, size, buffer, size_read);
-}
-
-int fileio_read_u32(struct fileio *fileio, uint32_t *data)
-{
- int retval;
- uint8_t buf[4];
- size_t size_read;
-
- retval = fileio_local_read(fileio, sizeof(uint32_t), buf, &size_read);
-
- if (ERROR_OK == retval && sizeof(uint32_t) != size_read)
- retval = -EIO;
- if (ERROR_OK == retval)
- *data = be_to_h_u32(buf);
-
- return retval;
-}
-
-static int fileio_local_fgets(struct fileio *fileio, size_t size, void *buffer)
-{
- if (fgets(buffer, size, fileio->file) == NULL)
- return ERROR_FILEIO_OPERATION_FAILED;
-
- return ERROR_OK;
-}
-
-int fileio_fgets(struct fileio *fileio, size_t size, void *buffer)
-{
- return fileio_local_fgets(fileio, size, buffer);
-}
-
-static int fileio_local_write(struct fileio *fileio, size_t size,
- const void *buffer, size_t *size_written)
-{
- ssize_t retval;
-
- retval = fwrite(buffer, 1, size, fileio->file);
- *size_written = (retval >= 0) ? retval : 0;
-
- return (retval < 0) ? retval : ERROR_OK;
-}
-
-int fileio_write(struct fileio *fileio, size_t size, const void *buffer,
- size_t *size_written)
-{
- int retval;
-
- retval = fileio_local_write(fileio, size, buffer, size_written);
-
- if (retval == ERROR_OK)
- fileio->size += *size_written;
-
- return retval;
-}
-
-int fileio_write_u32(struct fileio *fileio, uint32_t data)
-{
- int retval;
- uint8_t buf[4];
- h_u32_to_be(buf, data);
- size_t size_written;
-
- retval = fileio_write(fileio, 4, buf, &size_written);
-
- if (ERROR_OK == retval && size_written != sizeof(uint32_t))
- retval = -EIO;
-
- return retval;
-}
-
-/**
- * FIX!!!!
- *
- * For now this can not fail, but that's because a seek was executed
- * on startup.
- *
- * Avoiding the seek on startup opens up for using streams.
- *
- */
-int fileio_size(struct fileio *fileio, size_t *size)
-{
- *size = fileio->size;
-
- return ERROR_OK;
-}
diff --git a/src/helper/fileio.h b/src/helper/fileio.h
deleted file mode 100644
index ae4a3ec..0000000
--- a/src/helper/fileio.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_FILEIO_H
-#define OPENOCD_HELPER_FILEIO_H
-
-#define FILEIO_MAX_ERROR_STRING (128)
-
-enum fileio_type {
- FILEIO_TEXT,
- FILEIO_BINARY,
-};
-
-enum fileio_access {
- FILEIO_NONE, /* open without any access (invalid mode) */
- FILEIO_READ, /* open for reading, position at beginning */
- FILEIO_WRITE, /* open for writing, position at beginning */
- FILEIO_READWRITE, /* open for writing, position at beginning, allow reading */
- FILEIO_APPEND, /* open for writing, position at end */
- FILEIO_APPENDREAD, /* open for writing, position at end, allow reading */
-};
-
-struct fileio;
-
-int fileio_open(struct fileio **fileio, const char *url,
- enum fileio_access access_type, enum fileio_type type);
-int fileio_close(struct fileio *fileio);
-
-int fileio_seek(struct fileio *fileio, size_t position);
-int fileio_fgets(struct fileio *fileio, size_t size, void *buffer);
-
-int fileio_read(struct fileio *fileio,
- size_t size, void *buffer, size_t *size_read);
-int fileio_write(struct fileio *fileio,
- size_t size, const void *buffer, size_t *size_written);
-
-int fileio_read_u32(struct fileio *fileio, uint32_t *data);
-int fileio_write_u32(struct fileio *fileio, uint32_t data);
-int fileio_size(struct fileio *fileio, size_t *size);
-
-#define ERROR_FILEIO_LOCATION_UNKNOWN (-1200)
-#define ERROR_FILEIO_NOT_FOUND (-1201)
-#define ERROR_FILEIO_OPERATION_FAILED (-1202)
-#define ERROR_FILEIO_ACCESS_NOT_SUPPORTED (-1203)
-#define ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN (-1204)
-#define ERROR_FILEIO_OPERATION_NOT_SUPPORTED (-1205)
-
-#endif /* OPENOCD_HELPER_FILEIO_H */
diff --git a/src/helper/ioutil.c b/src/helper/ioutil.c
deleted file mode 100644
index f1123cd..0000000
--- a/src/helper/ioutil.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007-2010 by Øyvind Harboe *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* this file contains various functionality useful to standalone systems */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "log.h"
-#include "time_support.h"
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-/* loads a file and returns a pointer to it in memory. The file contains
- * a 0 byte(sentinel) after len bytes - the length of the file. */
-static int load_file(const char *fileName, char **data, size_t *len)
-{
- /* ensure returned length is always sane */
- *len = 0;
-
- FILE *pFile;
- pFile = fopen(fileName, "rb");
- if (pFile == NULL) {
- LOG_ERROR("Can't open %s", fileName);
- return ERROR_FAIL;
- }
- if (fseek(pFile, 0, SEEK_END) != 0) {
- LOG_ERROR("Can't open %s", fileName);
- fclose(pFile);
- return ERROR_FAIL;
- }
- long fsize = ftell(pFile);
- if (fsize == -1) {
- LOG_ERROR("Can't open %s", fileName);
- fclose(pFile);
- return ERROR_FAIL;
- }
- *len = fsize;
-
- if (fseek(pFile, 0, SEEK_SET) != 0) {
- LOG_ERROR("Can't open %s", fileName);
- fclose(pFile);
- return ERROR_FAIL;
- }
- *data = malloc(*len + 1);
- if (*data == NULL) {
- LOG_ERROR("Can't open %s", fileName);
- fclose(pFile);
- return ERROR_FAIL;
- }
-
- if (fread(*data, 1, *len, pFile) != *len) {
- fclose(pFile);
- free(*data);
- LOG_ERROR("Can't open %s", fileName);
- return ERROR_FAIL;
- }
- fclose(pFile);
-
- /* 0-byte after buffer (not included in *len) serves as a sentinel */
- (*data)[*len] = 0;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_cat_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* NOTE!!! we only have line printing capability so we print the entire file as a single
- * line. */
- char *data;
- size_t len;
-
- int retval = load_file(CMD_ARGV[0], &data, &len);
- if (retval == ERROR_OK) {
- command_print(CMD_CTX, "%s", data);
- free(data);
- } else
- command_print(CMD_CTX, "%s not found", CMD_ARGV[0]);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_trunc_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- FILE *config_file = NULL;
- config_file = fopen(CMD_ARGV[0], "w");
- if (config_file != NULL)
- fclose(config_file);
-
- return ERROR_OK;
-}
-
-#ifdef HAVE_MALLOC_H
-COMMAND_HANDLER(handle_meminfo_command)
-{
- static int prev;
- struct mallinfo info;
-
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- info = mallinfo();
-
- if (prev > 0)
- command_print(CMD_CTX, "Diff: %d", prev - info.fordblks);
- prev = info.fordblks;
-
- command_print(CMD_CTX, "Available ram: %d", info.fordblks);
-
- return ERROR_OK;
-}
-#endif
-
-COMMAND_HANDLER(handle_append_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int retval = ERROR_FAIL;
- FILE *config_file = NULL;
-
- config_file = fopen(CMD_ARGV[0], "a");
- if (config_file != NULL) {
- fseek(config_file, 0, SEEK_END);
-
- unsigned i;
- for (i = 1; i < CMD_ARGC; i++) {
- if (fwrite(CMD_ARGV[i], 1, strlen(CMD_ARGV[i]),
- config_file) != strlen(CMD_ARGV[i]))
- break;
- if (i != CMD_ARGC - 1) {
- if (fwrite(" ", 1, 1, config_file) != 1)
- break;
- }
- }
- if ((i == CMD_ARGC) && (fwrite("\n", 1, 1, config_file) == 1))
- retval = ERROR_OK;
-
- fclose(config_file);
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_cp_command)
-{
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* NOTE!!! we only have line printing capability so we print the entire file as a single
- * line. */
- char *data;
- size_t len;
-
- int retval = load_file(CMD_ARGV[0], &data, &len);
- if (retval != ERROR_OK)
- return retval;
-
- FILE *f = fopen(CMD_ARGV[1], "wb");
- if (f == NULL)
- retval = ERROR_COMMAND_SYNTAX_ERROR;
-
- size_t pos = 0;
- for (;; ) {
- size_t chunk = len - pos;
- static const size_t maxChunk = 512 * 1024; /* ~1/sec */
- if (chunk > maxChunk)
- chunk = maxChunk;
-
- if ((retval == ERROR_OK) && (fwrite(data + pos, 1, chunk, f) != chunk))
- retval = ERROR_COMMAND_SYNTAX_ERROR;
-
- if (retval != ERROR_OK)
- break;
-
- command_print(CMD_CTX, "%zu", len - pos);
-
- pos += chunk;
-
- if (pos == len)
- break;
- }
-
- if (retval == ERROR_OK)
- command_print(CMD_CTX, "Copied %s to %s", CMD_ARGV[0], CMD_ARGV[1]);
- else
- command_print(CMD_CTX, "copy failed");
-
- if (data != NULL)
- free(data);
- if (f != NULL)
- fclose(f);
-
- if (retval != ERROR_OK)
- unlink(CMD_ARGV[1]);
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_rm_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- bool del = false;
- if (rmdir(CMD_ARGV[0]) == 0)
- del = true;
- else if (unlink(CMD_ARGV[0]) == 0)
- del = true;
-
- return del ? ERROR_OK : ERROR_FAIL;
-}
-
-static int ioutil_Jim_Command_ls(Jim_Interp *interp,
- int argc,
- Jim_Obj * const *argv)
-{
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
- return JIM_ERR;
- }
-
- const char *name = Jim_GetString(argv[1], NULL);
-
- DIR *dirp = NULL;
- dirp = opendir(name);
- if (dirp == NULL)
- return JIM_ERR;
- Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
-
- for (;; ) {
- struct dirent *entry = NULL;
- entry = readdir(dirp);
- if (entry == NULL)
- break;
-
- if ((strcmp(".", entry->d_name) == 0) || (strcmp("..", entry->d_name) == 0))
- continue;
-
- Jim_ListAppendElement(interp, objPtr,
- Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
- }
- closedir(dirp);
-
- Jim_SetResult(interp, objPtr);
-
- return JIM_OK;
-}
-
-static int ioutil_Jim_Command_peek(Jim_Interp *interp,
- int argc,
- Jim_Obj *const *argv)
-{
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
- return JIM_ERR;
- }
-
- long address;
- if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
- return JIM_ERR;
-
- int value = *((volatile int *) address);
-
- Jim_SetResult(interp, Jim_NewIntObj(interp, value));
-
- return JIM_OK;
-}
-
-static int ioutil_Jim_Command_poke(Jim_Interp *interp,
- int argc,
- Jim_Obj *const *argv)
-{
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
- return JIM_ERR;
- }
-
- long address;
- if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
- return JIM_ERR;
- long value;
- if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
- return JIM_ERR;
-
- *((volatile int *) address) = value;
-
- return JIM_OK;
-}
-
-/* not so pretty code to fish out ip number*/
-static int ioutil_Jim_Command_ip(Jim_Interp *interp, int argc,
- Jim_Obj *const *argv)
-{
-#if !defined(__CYGWIN__)
- Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
-
- struct ifaddrs *ifa = NULL, *ifp = NULL;
-
- if (getifaddrs(&ifp) < 0)
- return JIM_ERR;
-
- for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
- char ip[200];
- socklen_t salen;
-
- if (ifa->ifa_addr->sa_family == AF_INET)
- salen = sizeof(struct sockaddr_in);
- else if (ifa->ifa_addr->sa_family == AF_INET6)
- salen = sizeof(struct sockaddr_in6);
- else
- continue;
-
- if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
- NI_NUMERICHOST) < 0)
- continue;
-
- Jim_AppendString(interp, tclOutput, ip, strlen(ip));
- break;
-
- }
-
- freeifaddrs(ifp);
-#else
- Jim_Obj *tclOutput = Jim_NewStringObj(interp, "fixme!!!", 0);
- LOG_ERROR("NOT IMPLEMENTED!!!");
-#endif
- Jim_SetResult(interp, tclOutput);
-
- return JIM_OK;
-}
-
-#ifdef HAVE_SYS_IOCTL_H
-#ifdef SIOCGIFHWADDR
-/* not so pretty code to fish out eth0 mac address */
-static int ioutil_Jim_Command_mac(Jim_Interp *interp, int argc,
- Jim_Obj *const *argv)
-{
- struct ifreq *ifr, *ifend;
- struct ifreq ifreq;
- struct ifconf ifc;
- struct ifreq ifs[5];
- int SockFD;
-
- SockFD = socket(AF_INET, SOCK_DGRAM, 0);
- if (SockFD < 0)
- return JIM_ERR;
-
- ifc.ifc_len = sizeof(ifs);
- ifc.ifc_req = ifs;
- if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0) {
- close(SockFD);
- return JIM_ERR;
- }
-
- ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
- for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
- /* if (ifr->ifr_addr.sa_family == AF_INET) */
- {
- if (strcmp("eth0", ifr->ifr_name) != 0)
- continue;
- strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
- if (ioctl(SockFD, SIOCGIFHWADDR, &ifreq) < 0) {
- close(SockFD);
- return JIM_ERR;
- }
-
- close(SockFD);
-
- Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
-
- char buffer[256];
- sprintf(buffer, "%02x-%02x-%02x-%02x-%02x-%02x",
- ifreq.ifr_hwaddr.sa_data[0]&0xff,
- ifreq.ifr_hwaddr.sa_data[1]&0xff,
- ifreq.ifr_hwaddr.sa_data[2]&0xff,
- ifreq.ifr_hwaddr.sa_data[3]&0xff,
- ifreq.ifr_hwaddr.sa_data[4]&0xff,
- ifreq.ifr_hwaddr.sa_data[5]&0xff);
-
- Jim_AppendString(interp, tclOutput, buffer, strlen(buffer));
-
- Jim_SetResult(interp, tclOutput);
-
- return JIM_OK;
- }
- }
- close(SockFD);
-
- return JIM_ERR;
-
-}
-#endif
-#endif
-
-static const struct command_registration ioutil_command_handlers[] = {
- {
- .name = "cat",
- .handler = handle_cat_command,
- .mode = COMMAND_ANY,
- .help = "display text file content",
- .usage = "file_name",
- },
- {
- .name = "trunc",
- .handler = handle_trunc_command,
- .mode = COMMAND_ANY,
- .help = "truncate a file to zero length",
- .usage = "file_name",
- },
- {
- .name = "cp",
- .handler = handle_cp_command,
- .mode = COMMAND_ANY,
- .help = "copy a file",
- .usage = "src_file_name dst_file_name",
- },
- {
- .name = "append_file",
- .handler = handle_append_command,
- .mode = COMMAND_ANY,
- .help = "append a variable number of strings to a file",
- .usage = "file_name [<string1>, [<string2>, ...]]",
- },
-#ifdef HAVE_MALLOC_H
- {
- .name = "meminfo",
- .handler = handle_meminfo_command,
- .mode = COMMAND_ANY,
- .help = "display free heap space",
- },
-#endif
- {
- .name = "rm",
- .mode = COMMAND_ANY,
- .handler = handle_rm_command,
- .help = "remove a directory or file",
- .usage = "file_name",
- },
-
- /*
- * Peek and poke are security holes -- they manipulate
- * server-internal addresses.
- */
-
- /* jim handlers */
- {
- .name = "peek",
- .mode = COMMAND_ANY,
- .jim_handler = ioutil_Jim_Command_peek,
- .help = "peek at a memory address",
- .usage = "address",
- },
- {
- .name = "poke",
- .mode = COMMAND_ANY,
- .jim_handler = ioutil_Jim_Command_poke,
- .help = "poke at a memory address",
- .usage = "address value",
- },
- {
- .name = "ls",
- .mode = COMMAND_ANY,
- .jim_handler = ioutil_Jim_Command_ls,
- .help = "show a listing of files",
- .usage = "dirname",
- },
-#ifdef HAVE_SYS_IOCTL_H
-#ifdef SIOCGIFHWADDR
- {
- .name = "mac",
- .mode = COMMAND_ANY,
- .jim_handler = ioutil_Jim_Command_mac,
- .help = "show MAC address",
- },
-#endif
-#endif
- {
- .name = "ip",
- .jim_handler = ioutil_Jim_Command_ip,
- .mode = COMMAND_ANY,
- .help = "show IP address",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int ioutil_init(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, ioutil_command_handlers);
-}
diff --git a/src/helper/ioutil.h b/src/helper/ioutil.h
deleted file mode 100644
index f060aab..0000000
--- a/src/helper/ioutil.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_IOUTIL_H
-#define OPENOCD_HELPER_IOUTIL_H
-
-struct command_context;
-
-int ioutil_init(struct command_context *cmd_ctx);
-
-#endif /* OPENOCD_HELPER_IOUTIL_H */
diff --git a/src/helper/ioutil_stubs.c b/src/helper/ioutil_stubs.c
deleted file mode 100644
index 0d81fe6..0000000
--- a/src/helper/ioutil_stubs.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "ioutil.h"
-#include "log.h"
-
-int ioutil_init(struct command_context *cmd_ctx)
-{
- LOG_DEBUG("libocdhelper was built without I/O utility support");
- return ERROR_OK;
-}
diff --git a/src/helper/jep106.c b/src/helper/jep106.c
deleted file mode 100644
index 33dc61c..0000000
--- a/src/helper/jep106.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jep106.h"
-#include "log.h"
-
-static const char * const jep106[][126] = {
-#include "jep106.inc"
-};
-
-const char *jep106_manufacturer(unsigned bank, unsigned id)
-{
- if (id < 1 || id > 126) {
- LOG_DEBUG("BUG: Caller passed out-of-range JEP106 ID!");
- return "<invalid>";
- }
-
- /* index is zero based */
- id--;
-
- if (bank >= ARRAY_SIZE(jep106) || jep106[bank][id] == 0)
- return "<unknown>";
-
- return jep106[bank][id];
-}
diff --git a/src/helper/jep106.h b/src/helper/jep106.h
deleted file mode 100644
index 0844580..0000000
--- a/src/helper/jep106.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_JEP106_H
-#define OPENOCD_HELPER_JEP106_H
-
-/**
- * Get the manufacturer name associated with a JEP106 ID.
- * @param bank The bank (number of continuation codes) of the manufacturer ID.
- * @param id The 7-bit manufacturer ID (i.e. with parity stripped).
- * @return A pointer to static const storage containing the name of the
- * manufacturer associated with bank and id, or one of the strings
- * "<invalid>" and "<unknown>".
- */
-const char *jep106_manufacturer(unsigned bank, unsigned id);
-
-#endif /* OPENOCD_HELPER_JEP106_H */
diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc
deleted file mode 100644
index 1895005..0000000
--- a/src/helper/jep106.inc
+++ /dev/null
@@ -1,1119 +0,0 @@
-/* Autogenerated with update_jep106.pl*/
-[0][0x01 - 1] = "AMD",
-[0][0x02 - 1] = "AMI",
-[0][0x03 - 1] = "Fairchild",
-[0][0x04 - 1] = "Fujitsu",
-[0][0x05 - 1] = "GTE",
-[0][0x06 - 1] = "Harris",
-[0][0x07 - 1] = "Hitachi",
-[0][0x08 - 1] = "Inmos",
-[0][0x09 - 1] = "Intel",
-[0][0x0a - 1] = "I.T.T.",
-[0][0x0b - 1] = "Intersil",
-[0][0x0c - 1] = "Monolithic Memories",
-[0][0x0d - 1] = "Mostek",
-[0][0x0e - 1] = "Freescale (Motorola)",
-[0][0x0f - 1] = "National",
-[0][0x10 - 1] = "NEC",
-[0][0x11 - 1] = "RCA",
-[0][0x12 - 1] = "Raytheon",
-[0][0x13 - 1] = "Conexant (Rockwell)",
-[0][0x14 - 1] = "Seeq",
-[0][0x15 - 1] = "NXP (Philips)",
-[0][0x16 - 1] = "Synertek",
-[0][0x17 - 1] = "Texas Instruments",
-[0][0x18 - 1] = "Toshiba",
-[0][0x19 - 1] = "Xicor",
-[0][0x1a - 1] = "Zilog",
-[0][0x1b - 1] = "Eurotechnique",
-[0][0x1c - 1] = "Mitsubishi",
-[0][0x1d - 1] = "Lucent (AT&T)",
-[0][0x1e - 1] = "Exel",
-[0][0x1f - 1] = "Atmel",
-[0][0x20 - 1] = "STMicroelectronics",
-[0][0x21 - 1] = "Lattice Semi.",
-[0][0x22 - 1] = "NCR",
-[0][0x23 - 1] = "Wafer Scale Integration",
-[0][0x24 - 1] = "IBM",
-[0][0x25 - 1] = "Tristar",
-[0][0x26 - 1] = "Visic",
-[0][0x27 - 1] = "Intl. CMOS Technology",
-[0][0x28 - 1] = "SSSI",
-[0][0x29 - 1] = "MicrochipTechnology",
-[0][0x2a - 1] = "Ricoh Ltd.",
-[0][0x2b - 1] = "VLSI",
-[0][0x2c - 1] = "Micron Technology",
-[0][0x2d - 1] = "SK Hynix",
-[0][0x2e - 1] = "OKI Semiconductor",
-[0][0x2f - 1] = "ACTEL",
-[0][0x30 - 1] = "Sharp",
-[0][0x31 - 1] = "Catalyst",
-[0][0x32 - 1] = "Panasonic",
-[0][0x33 - 1] = "IDT",
-[0][0x34 - 1] = "Cypress",
-[0][0x35 - 1] = "DEC",
-[0][0x36 - 1] = "LSI Logic",
-[0][0x37 - 1] = "Zarlink (Plessey)",
-[0][0x38 - 1] = "UTMC",
-[0][0x39 - 1] = "Thinking Machine",
-[0][0x3a - 1] = "Thomson CSF",
-[0][0x3b - 1] = "Integrated CMOS (Vertex)",
-[0][0x3c - 1] = "Honeywell",
-[0][0x3d - 1] = "Tektronix",
-[0][0x3e - 1] = "Oracle Corporation",
-[0][0x3f - 1] = "Silicon Storage Technology",
-[0][0x40 - 1] = "ProMos/Mosel Vitelic",
-[0][0x41 - 1] = "Infineon (Siemens)",
-[0][0x42 - 1] = "Macronix",
-[0][0x43 - 1] = "Xerox",
-[0][0x44 - 1] = "Plus Logic",
-[0][0x45 - 1] = "SanDisk Corporation",
-[0][0x46 - 1] = "Elan Circuit Tech.",
-[0][0x47 - 1] = "European Silicon Str.",
-[0][0x48 - 1] = "Apple Computer",
-[0][0x49 - 1] = "Xilinx",
-[0][0x4a - 1] = "Compaq",
-[0][0x4b - 1] = "Protocol Engines",
-[0][0x4c - 1] = "SCI",
-[0][0x4d - 1] = "Seiko Instruments",
-[0][0x4e - 1] = "Samsung",
-[0][0x4f - 1] = "I3 Design System",
-[0][0x50 - 1] = "Klic",
-[0][0x51 - 1] = "Crosspoint Solutions",
-[0][0x52 - 1] = "Alliance Semiconductor",
-[0][0x53 - 1] = "Tandem",
-[0][0x54 - 1] = "Hewlett-Packard",
-[0][0x55 - 1] = "Integrated Silicon Solutions",
-[0][0x56 - 1] = "Brooktree",
-[0][0x57 - 1] = "New Media",
-[0][0x58 - 1] = "MHS Electronic",
-[0][0x59 - 1] = "Performance Semi.",
-[0][0x5a - 1] = "Winbond Electronic",
-[0][0x5b - 1] = "Kawasaki Steel",
-[0][0x5c - 1] = "Bright Micro",
-[0][0x5d - 1] = "TECMAR",
-[0][0x5e - 1] = "Exar",
-[0][0x5f - 1] = "PCMCIA",
-[0][0x60 - 1] = "LG Semi (Goldstar)",
-[0][0x61 - 1] = "Northern Telecom",
-[0][0x62 - 1] = "Sanyo",
-[0][0x63 - 1] = "Array Microsystems",
-[0][0x64 - 1] = "Crystal Semiconductor",
-[0][0x65 - 1] = "Analog Devices",
-[0][0x66 - 1] = "PMC-Sierra",
-[0][0x67 - 1] = "Asparix",
-[0][0x68 - 1] = "Convex Computer",
-[0][0x69 - 1] = "Quality Semiconductor",
-[0][0x6a - 1] = "Nimbus Technology",
-[0][0x6b - 1] = "Transwitch",
-[0][0x6c - 1] = "Micronas (ITT Intermetall)",
-[0][0x6d - 1] = "Cannon",
-[0][0x6e - 1] = "Altera",
-[0][0x6f - 1] = "NEXCOM",
-[0][0x70 - 1] = "Qualcomm",
-[0][0x71 - 1] = "Sony",
-[0][0x72 - 1] = "Cray Research",
-[0][0x73 - 1] = "AMS(Austria Micro)",
-[0][0x74 - 1] = "Vitesse",
-[0][0x75 - 1] = "Aster Electronics",
-[0][0x76 - 1] = "Bay Networks (Synoptic)",
-[0][0x77 - 1] = "Zentrum/ZMD",
-[0][0x78 - 1] = "TRW",
-[0][0x79 - 1] = "Thesys",
-[0][0x7a - 1] = "Solbourne Computer",
-[0][0x7b - 1] = "Allied-Signal",
-[0][0x7c - 1] = "Dialog Semiconductor",
-[0][0x7d - 1] = "Media Vision",
-[0][0x7e - 1] = "Numonyx Corporation",
-[1][0x01 - 1] = "Cirrus Logic",
-[1][0x02 - 1] = "National Instruments",
-[1][0x03 - 1] = "ILC Data Device",
-[1][0x04 - 1] = "Alcatel Mietec",
-[1][0x05 - 1] = "Micro Linear",
-[1][0x06 - 1] = "Univ. of NC",
-[1][0x07 - 1] = "JTAG Technologies",
-[1][0x08 - 1] = "BAE Systems (Loral)",
-[1][0x09 - 1] = "Nchip",
-[1][0x0a - 1] = "Galileo Tech",
-[1][0x0b - 1] = "Bestlink Systems",
-[1][0x0c - 1] = "Graychip",
-[1][0x0d - 1] = "GENNUM",
-[1][0x0e - 1] = "VideoLogic",
-[1][0x0f - 1] = "Robert Bosch",
-[1][0x10 - 1] = "Chip Express",
-[1][0x11 - 1] = "DATARAM",
-[1][0x12 - 1] = "United Microelectronics Corp.",
-[1][0x13 - 1] = "TCSI",
-[1][0x14 - 1] = "Smart Modular",
-[1][0x15 - 1] = "Hughes Aircraft",
-[1][0x16 - 1] = "Lanstar Semiconductor",
-[1][0x17 - 1] = "Qlogic",
-[1][0x18 - 1] = "Kingston",
-[1][0x19 - 1] = "Music Semi",
-[1][0x1a - 1] = "Ericsson Components",
-[1][0x1b - 1] = "SpaSE",
-[1][0x1c - 1] = "Eon Silicon Devices",
-[1][0x1d - 1] = "Integrated Silicon Solution (ISSI)",
-[1][0x1e - 1] = "DoD",
-[1][0x1f - 1] = "Integ. Memories Tech.",
-[1][0x20 - 1] = "Corollary Inc.",
-[1][0x21 - 1] = "Dallas Semiconductor",
-[1][0x22 - 1] = "Omnivision",
-[1][0x23 - 1] = "EIV(Switzerland)",
-[1][0x24 - 1] = "Novatel Wireless",
-[1][0x25 - 1] = "Zarlink (Mitel)",
-[1][0x26 - 1] = "Clearpoint",
-[1][0x27 - 1] = "Cabletron",
-[1][0x28 - 1] = "STEC (Silicon Tech)",
-[1][0x29 - 1] = "Vanguard",
-[1][0x2a - 1] = "Hagiwara Sys-Com",
-[1][0x2b - 1] = "Vantis",
-[1][0x2c - 1] = "Celestica",
-[1][0x2d - 1] = "Century",
-[1][0x2e - 1] = "Hal Computers",
-[1][0x2f - 1] = "Rohm Company Ltd.",
-[1][0x30 - 1] = "Juniper Networks",
-[1][0x31 - 1] = "Libit Signal Processing",
-[1][0x32 - 1] = "Mushkin Enhanced Memory",
-[1][0x33 - 1] = "Tundra Semiconductor",
-[1][0x34 - 1] = "Adaptec Inc.",
-[1][0x35 - 1] = "LightSpeed Semi.",
-[1][0x36 - 1] = "ZSP Corp.",
-[1][0x37 - 1] = "AMIC Technology",
-[1][0x38 - 1] = "Adobe Systems",
-[1][0x39 - 1] = "Dynachip",
-[1][0x3a - 1] = "PNY Technologies, Inc.",
-[1][0x3b - 1] = "Newport Digital",
-[1][0x3c - 1] = "MMC Networks",
-[1][0x3d - 1] = "T Square",
-[1][0x3e - 1] = "Seiko Epson",
-[1][0x3f - 1] = "Broadcom",
-[1][0x40 - 1] = "Viking Components",
-[1][0x41 - 1] = "V3 Semiconductor",
-[1][0x42 - 1] = "Flextronics (Orbit Semiconductor)",
-[1][0x43 - 1] = "Suwa Electronics",
-[1][0x44 - 1] = "Transmeta",
-[1][0x45 - 1] = "Micron CMS",
-[1][0x46 - 1] = "American Computer & Digital",
-[1][0x47 - 1] = "Enhance 3000 Inc.",
-[1][0x48 - 1] = "Tower Semiconductor",
-[1][0x49 - 1] = "CPU Design",
-[1][0x4a - 1] = "Price Point",
-[1][0x4b - 1] = "Maxim Integrated Product",
-[1][0x4c - 1] = "Tellabs",
-[1][0x4d - 1] = "Centaur Technology",
-[1][0x4e - 1] = "Unigen Corporation",
-[1][0x4f - 1] = "Transcend Information",
-[1][0x50 - 1] = "Memory Card Technology",
-[1][0x51 - 1] = "CKD Corporation Ltd.",
-[1][0x52 - 1] = "Capital Instruments, Inc.",
-[1][0x53 - 1] = "Aica Kogyo, Ltd.",
-[1][0x54 - 1] = "Linvex Technology",
-[1][0x55 - 1] = "MSC Vertriebs GmbH",
-[1][0x56 - 1] = "AKM Company, Ltd.",
-[1][0x57 - 1] = "Dynamem, Inc.",
-[1][0x58 - 1] = "NERA ASA",
-[1][0x59 - 1] = "GSI Technology",
-[1][0x5a - 1] = "Dane-Elec (C Memory)",
-[1][0x5b - 1] = "Acorn Computers",
-[1][0x5c - 1] = "Lara Technology",
-[1][0x5d - 1] = "Oak Technology, Inc.",
-[1][0x5e - 1] = "Itec Memory",
-[1][0x5f - 1] = "Tanisys Technology",
-[1][0x60 - 1] = "Truevision",
-[1][0x61 - 1] = "Wintec Industries",
-[1][0x62 - 1] = "Super PC Memory",
-[1][0x63 - 1] = "MGV Memory",
-[1][0x64 - 1] = "Galvantech",
-[1][0x65 - 1] = "Gadzoox Networks",
-[1][0x66 - 1] = "Multi Dimensional Cons.",
-[1][0x67 - 1] = "GateField",
-[1][0x68 - 1] = "Integrated Memory System",
-[1][0x69 - 1] = "Triscend",
-[1][0x6a - 1] = "XaQti",
-[1][0x6b - 1] = "Goldenram",
-[1][0x6c - 1] = "Clear Logic",
-[1][0x6d - 1] = "Cimaron Communications",
-[1][0x6e - 1] = "Nippon Steel Semi. Corp.",
-[1][0x6f - 1] = "Advantage Memory",
-[1][0x70 - 1] = "AMCC",
-[1][0x71 - 1] = "LeCroy",
-[1][0x72 - 1] = "Yamaha Corporation",
-[1][0x73 - 1] = "Digital Microwave",
-[1][0x74 - 1] = "NetLogic Microsystems",
-[1][0x75 - 1] = "MIMOS Semiconductor",
-[1][0x76 - 1] = "Advanced Fibre",
-[1][0x77 - 1] = "BF Goodrich Data.",
-[1][0x78 - 1] = "Epigram",
-[1][0x79 - 1] = "Acbel Polytech Inc.",
-[1][0x7a - 1] = "Apacer Technology",
-[1][0x7b - 1] = "Admor Memory",
-[1][0x7c - 1] = "FOXCONN",
-[1][0x7d - 1] = "Quadratics Superconductor",
-[1][0x7e - 1] = "3COM",
-[2][0x01 - 1] = "Camintonn Corporation",
-[2][0x02 - 1] = "ISOA Incorporated",
-[2][0x03 - 1] = "Agate Semiconductor",
-[2][0x04 - 1] = "ADMtek Incorporated",
-[2][0x05 - 1] = "HYPERTEC",
-[2][0x06 - 1] = "Adhoc Technologies",
-[2][0x07 - 1] = "MOSAID Technologies",
-[2][0x08 - 1] = "Ardent Technologies",
-[2][0x09 - 1] = "Switchcore",
-[2][0x0a - 1] = "Cisco Systems, Inc.",
-[2][0x0b - 1] = "Allayer Technologies",
-[2][0x0c - 1] = "WorkX AG (Wichman)",
-[2][0x0d - 1] = "Oasis Semiconductor",
-[2][0x0e - 1] = "Novanet Semiconductor",
-[2][0x0f - 1] = "E-M Solutions",
-[2][0x10 - 1] = "Power General",
-[2][0x11 - 1] = "Advanced Hardware Arch.",
-[2][0x12 - 1] = "Inova Semiconductors GmbH",
-[2][0x13 - 1] = "Telocity",
-[2][0x14 - 1] = "Delkin Devices",
-[2][0x15 - 1] = "Symagery Microsystems",
-[2][0x16 - 1] = "C-Port Corporation",
-[2][0x17 - 1] = "SiberCore Technologies",
-[2][0x18 - 1] = "Southland Microsystems",
-[2][0x19 - 1] = "Malleable Technologies",
-[2][0x1a - 1] = "Kendin Communications",
-[2][0x1b - 1] = "Great Technology Microcomputer",
-[2][0x1c - 1] = "Sanmina Corporation",
-[2][0x1d - 1] = "HADCO Corporation",
-[2][0x1e - 1] = "Corsair",
-[2][0x1f - 1] = "Actrans System Inc.",
-[2][0x20 - 1] = "ALPHA Technologies",
-[2][0x21 - 1] = "Silicon Laboratories, Inc. (Cygnal)",
-[2][0x22 - 1] = "Artesyn Technologies",
-[2][0x23 - 1] = "Align Manufacturing",
-[2][0x24 - 1] = "Peregrine Semiconductor",
-[2][0x25 - 1] = "Chameleon Systems",
-[2][0x26 - 1] = "Aplus Flash Technology",
-[2][0x27 - 1] = "MIPS Technologies",
-[2][0x28 - 1] = "Chrysalis ITS",
-[2][0x29 - 1] = "ADTEC Corporation",
-[2][0x2a - 1] = "Kentron Technologies",
-[2][0x2b - 1] = "Win Technologies",
-[2][0x2c - 1] = "Tezzaron Semiconductor",
-[2][0x2d - 1] = "Extreme Packet Devices",
-[2][0x2e - 1] = "RF Micro Devices",
-[2][0x2f - 1] = "Siemens AG",
-[2][0x30 - 1] = "Sarnoff Corporation",
-[2][0x31 - 1] = "Itautec SA",
-[2][0x32 - 1] = "Radiata Inc.",
-[2][0x33 - 1] = "Benchmark Elect. (AVEX)",
-[2][0x34 - 1] = "Legend",
-[2][0x35 - 1] = "SpecTek Incorporated",
-[2][0x36 - 1] = "Hi/fn",
-[2][0x37 - 1] = "Enikia Incorporated",
-[2][0x38 - 1] = "SwitchOn Networks",
-[2][0x39 - 1] = "AANetcom Incorporated",
-[2][0x3a - 1] = "Micro Memory Bank",
-[2][0x3b - 1] = "ESS Technology",
-[2][0x3c - 1] = "Virata Corporation",
-[2][0x3d - 1] = "Excess Bandwidth",
-[2][0x3e - 1] = "West Bay Semiconductor",
-[2][0x3f - 1] = "DSP Group",
-[2][0x40 - 1] = "Newport Communications",
-[2][0x41 - 1] = "Chip2Chip Incorporated",
-[2][0x42 - 1] = "Phobos Corporation",
-[2][0x43 - 1] = "Intellitech Corporation",
-[2][0x44 - 1] = "Nordic VLSI ASA",
-[2][0x45 - 1] = "Ishoni Networks",
-[2][0x46 - 1] = "Silicon Spice",
-[2][0x47 - 1] = "Alchemy Semiconductor",
-[2][0x48 - 1] = "Agilent Technologies",
-[2][0x49 - 1] = "Centillium Communications",
-[2][0x4a - 1] = "W.L. Gore",
-[2][0x4b - 1] = "HanBit Electronics",
-[2][0x4c - 1] = "GlobeSpan",
-[2][0x4d - 1] = "Element 14",
-[2][0x4e - 1] = "Pycon",
-[2][0x4f - 1] = "Saifun Semiconductors",
-[2][0x50 - 1] = "Sibyte, Incorporated",
-[2][0x51 - 1] = "MetaLink Technologies",
-[2][0x52 - 1] = "Feiya Technology",
-[2][0x53 - 1] = "I & C Technology",
-[2][0x54 - 1] = "Shikatronics",
-[2][0x55 - 1] = "Elektrobit",
-[2][0x56 - 1] = "Megic",
-[2][0x57 - 1] = "Com-Tier",
-[2][0x58 - 1] = "Malaysia Micro Solutions",
-[2][0x59 - 1] = "Hyperchip",
-[2][0x5a - 1] = "Gemstone Communications",
-[2][0x5b - 1] = "Anadigm (Anadyne)",
-[2][0x5c - 1] = "3ParData",
-[2][0x5d - 1] = "Mellanox Technologies",
-[2][0x5e - 1] = "Tenx Technologies",
-[2][0x5f - 1] = "Helix AG",
-[2][0x60 - 1] = "Domosys",
-[2][0x61 - 1] = "Skyup Technology",
-[2][0x62 - 1] = "HiNT Corporation",
-[2][0x63 - 1] = "Chiaro",
-[2][0x64 - 1] = "MDT Technologies GmbH",
-[2][0x65 - 1] = "Exbit Technology A/S",
-[2][0x66 - 1] = "Integrated Technology Express",
-[2][0x67 - 1] = "AVED Memory",
-[2][0x68 - 1] = "Legerity",
-[2][0x69 - 1] = "Jasmine Networks",
-[2][0x6a - 1] = "Caspian Networks",
-[2][0x6b - 1] = "nCUBE",
-[2][0x6c - 1] = "Silicon Access Networks",
-[2][0x6d - 1] = "FDK Corporation",
-[2][0x6e - 1] = "High Bandwidth Access",
-[2][0x6f - 1] = "MultiLink Technology",
-[2][0x70 - 1] = "BRECIS",
-[2][0x71 - 1] = "World Wide Packets",
-[2][0x72 - 1] = "APW",
-[2][0x73 - 1] = "Chicory Systems",
-[2][0x74 - 1] = "Xstream Logic",
-[2][0x75 - 1] = "Fast-Chip",
-[2][0x76 - 1] = "Zucotto Wireless",
-[2][0x77 - 1] = "Realchip",
-[2][0x78 - 1] = "Galaxy Power",
-[2][0x79 - 1] = "eSilicon",
-[2][0x7a - 1] = "Morphics Technology",
-[2][0x7b - 1] = "Accelerant Networks",
-[2][0x7c - 1] = "Silicon Wave",
-[2][0x7d - 1] = "SandCraft",
-[2][0x7e - 1] = "Elpida",
-[3][0x01 - 1] = "Solectron",
-[3][0x02 - 1] = "Optosys Technologies",
-[3][0x03 - 1] = "Buffalo (Formerly Melco)",
-[3][0x04 - 1] = "TriMedia Technologies",
-[3][0x05 - 1] = "Cyan Technologies",
-[3][0x06 - 1] = "Global Locate",
-[3][0x07 - 1] = "Optillion",
-[3][0x08 - 1] = "Terago Communications",
-[3][0x09 - 1] = "Ikanos Communications",
-[3][0x0a - 1] = "Princeton Technology",
-[3][0x0b - 1] = "Nanya Technology",
-[3][0x0c - 1] = "Elite Flash Storage",
-[3][0x0d - 1] = "Mysticom",
-[3][0x0e - 1] = "LightSand Communications",
-[3][0x0f - 1] = "ATI Technologies",
-[3][0x10 - 1] = "Agere Systems",
-[3][0x11 - 1] = "NeoMagic",
-[3][0x12 - 1] = "AuroraNetics",
-[3][0x13 - 1] = "Golden Empire",
-[3][0x14 - 1] = "Mushkin",
-[3][0x15 - 1] = "Tioga Technologies",
-[3][0x16 - 1] = "Netlist",
-[3][0x17 - 1] = "TeraLogic",
-[3][0x18 - 1] = "Cicada Semiconductor",
-[3][0x19 - 1] = "Centon Electronics",
-[3][0x1a - 1] = "Tyco Electronics",
-[3][0x1b - 1] = "Magis Works",
-[3][0x1c - 1] = "Zettacom",
-[3][0x1d - 1] = "Cogency Semiconductor",
-[3][0x1e - 1] = "Chipcon AS",
-[3][0x1f - 1] = "Aspex Technology",
-[3][0x20 - 1] = "F5 Networks",
-[3][0x21 - 1] = "Programmable Silicon Solutions",
-[3][0x22 - 1] = "ChipWrights",
-[3][0x23 - 1] = "Acorn Networks",
-[3][0x24 - 1] = "Quicklogic",
-[3][0x25 - 1] = "Kingmax Semiconductor",
-[3][0x26 - 1] = "BOPS",
-[3][0x27 - 1] = "Flasys",
-[3][0x28 - 1] = "BitBlitz Communications",
-[3][0x29 - 1] = "eMemory Technology",
-[3][0x2a - 1] = "Procket Networks",
-[3][0x2b - 1] = "Purple Ray",
-[3][0x2c - 1] = "Trebia Networks",
-[3][0x2d - 1] = "Delta Electronics",
-[3][0x2e - 1] = "Onex Communications",
-[3][0x2f - 1] = "Ample Communications",
-[3][0x30 - 1] = "Memory Experts Intl",
-[3][0x31 - 1] = "Astute Networks",
-[3][0x32 - 1] = "Azanda Network Devices",
-[3][0x33 - 1] = "Dibcom",
-[3][0x34 - 1] = "Tekmos",
-[3][0x35 - 1] = "API NetWorks",
-[3][0x36 - 1] = "Bay Microsystems",
-[3][0x37 - 1] = "Firecron Ltd",
-[3][0x38 - 1] = "Resonext Communications",
-[3][0x39 - 1] = "Tachys Technologies",
-[3][0x3a - 1] = "Equator Technology",
-[3][0x3b - 1] = "Concept Computer",
-[3][0x3c - 1] = "SILCOM",
-[3][0x3d - 1] = "3Dlabs",
-[3][0x3e - 1] = "c’t Magazine",
-[3][0x3f - 1] = "Sanera Systems",
-[3][0x40 - 1] = "Silicon Packets",
-[3][0x41 - 1] = "Viasystems Group",
-[3][0x42 - 1] = "Simtek",
-[3][0x43 - 1] = "Semicon Devices Singapore",
-[3][0x44 - 1] = "Satron Handelsges",
-[3][0x45 - 1] = "Improv Systems",
-[3][0x46 - 1] = "INDUSYS GmbH",
-[3][0x47 - 1] = "Corrent",
-[3][0x48 - 1] = "Infrant Technologies",
-[3][0x49 - 1] = "Ritek Corp",
-[3][0x4a - 1] = "empowerTel Networks",
-[3][0x4b - 1] = "Hypertec",
-[3][0x4c - 1] = "Cavium Networks",
-[3][0x4d - 1] = "PLX Technology",
-[3][0x4e - 1] = "Massana Design",
-[3][0x4f - 1] = "Intrinsity",
-[3][0x50 - 1] = "Valence Semiconductor",
-[3][0x51 - 1] = "Terawave Communications",
-[3][0x52 - 1] = "IceFyre Semiconductor",
-[3][0x53 - 1] = "Primarion",
-[3][0x54 - 1] = "Picochip Designs Ltd",
-[3][0x55 - 1] = "Silverback Systems",
-[3][0x56 - 1] = "Jade Star Technologies",
-[3][0x57 - 1] = "Pijnenburg Securealink",
-[3][0x58 - 1] = "takeMS - Ultron AG",
-[3][0x59 - 1] = "Cambridge Silicon Radio",
-[3][0x5a - 1] = "Swissbit",
-[3][0x5b - 1] = "Nazomi Communications",
-[3][0x5c - 1] = "eWave System",
-[3][0x5d - 1] = "Rockwell Collins",
-[3][0x5e - 1] = "Picocel Co. Ltd. (Paion)",
-[3][0x5f - 1] = "Alphamosaic Ltd",
-[3][0x60 - 1] = "Sandburst",
-[3][0x61 - 1] = "SiCon Video",
-[3][0x62 - 1] = "NanoAmp Solutions",
-[3][0x63 - 1] = "Ericsson Technology",
-[3][0x64 - 1] = "PrairieComm",
-[3][0x65 - 1] = "Mitac International",
-[3][0x66 - 1] = "Layer N Networks",
-[3][0x67 - 1] = "MtekVision (Atsana)",
-[3][0x68 - 1] = "Allegro Networks",
-[3][0x69 - 1] = "Marvell Semiconductors",
-[3][0x6a - 1] = "Netergy Microelectronic",
-[3][0x6b - 1] = "NVIDIA",
-[3][0x6c - 1] = "Internet Machines",
-[3][0x6d - 1] = "Memorysolution GmbH",
-[3][0x6e - 1] = "Litchfield Communication",
-[3][0x6f - 1] = "Accton Technology",
-[3][0x70 - 1] = "Teradiant Networks",
-[3][0x71 - 1] = "Scaleo Chip",
-[3][0x72 - 1] = "Cortina Systems",
-[3][0x73 - 1] = "RAM Components",
-[3][0x74 - 1] = "Raqia Networks",
-[3][0x75 - 1] = "ClearSpeed",
-[3][0x76 - 1] = "Matsushita Battery",
-[3][0x77 - 1] = "Xelerated",
-[3][0x78 - 1] = "SimpleTech",
-[3][0x79 - 1] = "Utron Technology",
-[3][0x7a - 1] = "Astec International",
-[3][0x7b - 1] = "AVM gmbH",
-[3][0x7c - 1] = "Redux Communications",
-[3][0x7d - 1] = "Dot Hill Systems",
-[3][0x7e - 1] = "TeraChip",
-[4][0x01 - 1] = "T-RAM Incorporated",
-[4][0x02 - 1] = "Innovics Wireless",
-[4][0x03 - 1] = "Teknovus",
-[4][0x04 - 1] = "KeyEye Communications",
-[4][0x05 - 1] = "Runcom Technologies",
-[4][0x06 - 1] = "RedSwitch",
-[4][0x07 - 1] = "Dotcast",
-[4][0x08 - 1] = "Silicon Mountain Memory",
-[4][0x09 - 1] = "Signia Technologies",
-[4][0x0a - 1] = "Pixim",
-[4][0x0b - 1] = "Galazar Networks",
-[4][0x0c - 1] = "White Electronic Designs",
-[4][0x0d - 1] = "Patriot Scientific",
-[4][0x0e - 1] = "Neoaxiom Corporation",
-[4][0x0f - 1] = "3Y Power Technology",
-[4][0x10 - 1] = "Scaleo Chip",
-[4][0x11 - 1] = "Potentia Power Systems",
-[4][0x12 - 1] = "C-guys Incorporated",
-[4][0x13 - 1] = "Digital Communications Technology",
-[4][0x14 - 1] = "Silicon-Based Technology",
-[4][0x15 - 1] = "Fulcrum Microsystems",
-[4][0x16 - 1] = "Positivo Informatica Ltd",
-[4][0x17 - 1] = "XIOtech Corporation",
-[4][0x18 - 1] = "PortalPlayer",
-[4][0x19 - 1] = "Zhiying Software",
-[4][0x1a - 1] = "ParkerVision, Inc.",
-[4][0x1b - 1] = "Phonex Broadband",
-[4][0x1c - 1] = "Skyworks Solutions",
-[4][0x1d - 1] = "Entropic Communications",
-[4][0x1e - 1] = "I’M Intelligent Memory Ltd.",
-[4][0x1f - 1] = "Zensys A/S",
-[4][0x20 - 1] = "Legend Silicon Corp.",
-[4][0x21 - 1] = "Sci-worx GmbH",
-[4][0x22 - 1] = "SMSC (Standard Microsystems)",
-[4][0x23 - 1] = "Renesas Electronics",
-[4][0x24 - 1] = "Raza Microelectronics",
-[4][0x25 - 1] = "Phyworks",
-[4][0x26 - 1] = "MediaTek",
-[4][0x27 - 1] = "Non-cents Productions",
-[4][0x28 - 1] = "US Modular",
-[4][0x29 - 1] = "Wintegra Ltd.",
-[4][0x2a - 1] = "Mathstar",
-[4][0x2b - 1] = "StarCore",
-[4][0x2c - 1] = "Oplus Technologies",
-[4][0x2d - 1] = "Mindspeed",
-[4][0x2e - 1] = "Just Young Computer",
-[4][0x2f - 1] = "Radia Communications",
-[4][0x30 - 1] = "OCZ",
-[4][0x31 - 1] = "Emuzed",
-[4][0x32 - 1] = "LOGIC Devices",
-[4][0x33 - 1] = "Inphi Corporation",
-[4][0x34 - 1] = "Quake Technologies",
-[4][0x35 - 1] = "Vixel",
-[4][0x36 - 1] = "SolusTek",
-[4][0x37 - 1] = "Kongsberg Maritime",
-[4][0x38 - 1] = "Faraday Technology",
-[4][0x39 - 1] = "Altium Ltd.",
-[4][0x3a - 1] = "Insyte",
-[4][0x3b - 1] = "ARM Ltd.",
-[4][0x3c - 1] = "DigiVision",
-[4][0x3d - 1] = "Vativ Technologies",
-[4][0x3e - 1] = "Endicott Interconnect Technologies",
-[4][0x3f - 1] = "Pericom",
-[4][0x40 - 1] = "Bandspeed",
-[4][0x41 - 1] = "LeWiz Communications",
-[4][0x42 - 1] = "CPU Technology",
-[4][0x43 - 1] = "Ramaxel Technology",
-[4][0x44 - 1] = "DSP Group",
-[4][0x45 - 1] = "Axis Communications",
-[4][0x46 - 1] = "Legacy Electronics",
-[4][0x47 - 1] = "Chrontel",
-[4][0x48 - 1] = "Powerchip Semiconductor",
-[4][0x49 - 1] = "MobilEye Technologies",
-[4][0x4a - 1] = "Excel Semiconductor",
-[4][0x4b - 1] = "A-DATA Technology",
-[4][0x4c - 1] = "VirtualDigm",
-[4][0x4d - 1] = "G Skill Intl",
-[4][0x4e - 1] = "Quanta Computer",
-[4][0x4f - 1] = "Yield Microelectronics",
-[4][0x50 - 1] = "Afa Technologies",
-[4][0x51 - 1] = "KINGBOX Technology Co. Ltd.",
-[4][0x52 - 1] = "Ceva",
-[4][0x53 - 1] = "iStor Networks",
-[4][0x54 - 1] = "Advance Modules",
-[4][0x55 - 1] = "Microsoft",
-[4][0x56 - 1] = "Open-Silicon",
-[4][0x57 - 1] = "Goal Semiconductor",
-[4][0x58 - 1] = "ARC International",
-[4][0x59 - 1] = "Simmtec",
-[4][0x5a - 1] = "Metanoia",
-[4][0x5b - 1] = "Key Stream",
-[4][0x5c - 1] = "Lowrance Electronics",
-[4][0x5d - 1] = "Adimos",
-[4][0x5e - 1] = "SiGe Semiconductor",
-[4][0x5f - 1] = "Fodus Communications",
-[4][0x60 - 1] = "Credence Systems Corp.",
-[4][0x61 - 1] = "Genesis Microchip Inc.",
-[4][0x62 - 1] = "Vihana, Inc.",
-[4][0x63 - 1] = "WIS Technologies",
-[4][0x64 - 1] = "GateChange Technologies",
-[4][0x65 - 1] = "High Density Devices AS",
-[4][0x66 - 1] = "Synopsys",
-[4][0x67 - 1] = "Gigaram",
-[4][0x68 - 1] = "Enigma Semiconductor Inc.",
-[4][0x69 - 1] = "Century Micro Inc.",
-[4][0x6a - 1] = "Icera Semiconductor",
-[4][0x6b - 1] = "Mediaworks Integrated Systems",
-[4][0x6c - 1] = "O’Neil Product Development",
-[4][0x6d - 1] = "Supreme Top Technology Ltd.",
-[4][0x6e - 1] = "MicroDisplay Corporation",
-[4][0x6f - 1] = "Team Group Inc.",
-[4][0x70 - 1] = "Sinett Corporation",
-[4][0x71 - 1] = "Toshiba Corporation",
-[4][0x72 - 1] = "Tensilica",
-[4][0x73 - 1] = "SiRF Technology",
-[4][0x74 - 1] = "Bacoc Inc.",
-[4][0x75 - 1] = "SMaL Camera Technologies",
-[4][0x76 - 1] = "Thomson SC",
-[4][0x77 - 1] = "Airgo Networks",
-[4][0x78 - 1] = "Wisair Ltd.",
-[4][0x79 - 1] = "SigmaTel",
-[4][0x7a - 1] = "Arkados",
-[4][0x7b - 1] = "Compete IT gmbH Co. KG",
-[4][0x7c - 1] = "Eudar Technology Inc.",
-[4][0x7d - 1] = "Focus Enhancements",
-[4][0x7e - 1] = "Xyratex",
-[5][0x01 - 1] = "Specular Networks",
-[5][0x02 - 1] = "Patriot Memory (PDP Systems)",
-[5][0x03 - 1] = "U-Chip Technology Corp.",
-[5][0x04 - 1] = "Silicon Optix",
-[5][0x05 - 1] = "Greenfield Networks",
-[5][0x06 - 1] = "CompuRAM GmbH",
-[5][0x07 - 1] = "Stargen, Inc.",
-[5][0x08 - 1] = "NetCell Corporation",
-[5][0x09 - 1] = "Excalibrus Technologies Ltd",
-[5][0x0a - 1] = "SCM Microsystems",
-[5][0x0b - 1] = "Xsigo Systems, Inc.",
-[5][0x0c - 1] = "CHIPS & Systems Inc",
-[5][0x0d - 1] = "Tier 1 Multichip Solutions",
-[5][0x0e - 1] = "CWRL Labs",
-[5][0x0f - 1] = "Teradici",
-[5][0x10 - 1] = "Gigaram, Inc.",
-[5][0x11 - 1] = "g2 Microsystems",
-[5][0x12 - 1] = "PowerFlash Semiconductor",
-[5][0x13 - 1] = "P.A. Semi, Inc.",
-[5][0x14 - 1] = "NovaTech Solutions, S.A.",
-[5][0x15 - 1] = "c2 Microsystems, Inc.",
-[5][0x16 - 1] = "Level5 Networks",
-[5][0x17 - 1] = "COS Memory AG",
-[5][0x18 - 1] = "Innovasic Semiconductor",
-[5][0x19 - 1] = "02IC Co. Ltd",
-[5][0x1a - 1] = "Tabula, Inc.",
-[5][0x1b - 1] = "Crucial Technology",
-[5][0x1c - 1] = "Chelsio Communications",
-[5][0x1d - 1] = "Solarflare Communications",
-[5][0x1e - 1] = "Xambala Inc.",
-[5][0x1f - 1] = "EADS Astrium",
-[5][0x20 - 1] = "Terra Semiconductor, Inc.",
-[5][0x21 - 1] = "Imaging Works, Inc.",
-[5][0x22 - 1] = "Astute Networks, Inc.",
-[5][0x23 - 1] = "Tzero",
-[5][0x24 - 1] = "Emulex",
-[5][0x25 - 1] = "Power-One",
-[5][0x26 - 1] = "Pulse~LINK Inc.",
-[5][0x27 - 1] = "Hon Hai Precision Industry",
-[5][0x28 - 1] = "White Rock Networks Inc.",
-[5][0x29 - 1] = "Telegent Systems USA, Inc.",
-[5][0x2a - 1] = "Atrua Technologies, Inc.",
-[5][0x2b - 1] = "Acbel Polytech Inc.",
-[5][0x2c - 1] = "eRide Inc.",
-[5][0x2d - 1] = "ULi Electronics Inc.",
-[5][0x2e - 1] = "Magnum Semiconductor Inc.",
-[5][0x2f - 1] = "neoOne Technology, Inc.",
-[5][0x30 - 1] = "Connex Technology, Inc.",
-[5][0x31 - 1] = "Stream Processors, Inc.",
-[5][0x32 - 1] = "Focus Enhancements",
-[5][0x33 - 1] = "Telecis Wireless, Inc.",
-[5][0x34 - 1] = "uNav Microelectronics",
-[5][0x35 - 1] = "Tarari, Inc.",
-[5][0x36 - 1] = "Ambric, Inc.",
-[5][0x37 - 1] = "Newport Media, Inc.",
-[5][0x38 - 1] = "VMTS",
-[5][0x39 - 1] = "Enuclia Semiconductor, Inc.",
-[5][0x3a - 1] = "Virtium Technology Inc.",
-[5][0x3b - 1] = "Solid State System Co., Ltd.",
-[5][0x3c - 1] = "Kian Tech LLC",
-[5][0x3d - 1] = "Artimi",
-[5][0x3e - 1] = "Power Quotient International",
-[5][0x3f - 1] = "Avago Technologies",
-[5][0x40 - 1] = "ADTechnology",
-[5][0x41 - 1] = "Sigma Designs",
-[5][0x42 - 1] = "SiCortex, Inc.",
-[5][0x43 - 1] = "Ventura Technology Group",
-[5][0x44 - 1] = "eASIC",
-[5][0x45 - 1] = "M.H.S. SAS",
-[5][0x46 - 1] = "Micro Star International",
-[5][0x47 - 1] = "Rapport Inc.",
-[5][0x48 - 1] = "Makway International",
-[5][0x49 - 1] = "Broad Reach Engineering Co.",
-[5][0x4a - 1] = "Semiconductor Mfg Intl Corp",
-[5][0x4b - 1] = "SiConnect",
-[5][0x4c - 1] = "FCI USA Inc.",
-[5][0x4d - 1] = "Validity Sensors",
-[5][0x4e - 1] = "Coney Technology Co. Ltd.",
-[5][0x4f - 1] = "Spans Logic",
-[5][0x50 - 1] = "Neterion Inc.",
-[5][0x51 - 1] = "Qimonda",
-[5][0x52 - 1] = "New Japan Radio Co. Ltd.",
-[5][0x53 - 1] = "Velogix",
-[5][0x54 - 1] = "Montalvo Systems",
-[5][0x55 - 1] = "iVivity Inc.",
-[5][0x56 - 1] = "Walton Chaintech",
-[5][0x57 - 1] = "AENEON",
-[5][0x58 - 1] = "Lorom Industrial Co. Ltd.",
-[5][0x59 - 1] = "Radiospire Networks",
-[5][0x5a - 1] = "Sensio Technologies, Inc.",
-[5][0x5b - 1] = "Nethra Imaging",
-[5][0x5c - 1] = "Hexon Technology Pte Ltd",
-[5][0x5d - 1] = "CompuStocx (CSX)",
-[5][0x5e - 1] = "Methode Electronics, Inc.",
-[5][0x5f - 1] = "Connect One Ltd.",
-[5][0x60 - 1] = "Opulan Technologies",
-[5][0x61 - 1] = "Septentrio NV",
-[5][0x62 - 1] = "Goldenmars Technology Inc.",
-[5][0x63 - 1] = "Kreton Corporation",
-[5][0x64 - 1] = "Cochlear Ltd.",
-[5][0x65 - 1] = "Altair Semiconductor",
-[5][0x66 - 1] = "NetEffect, Inc.",
-[5][0x67 - 1] = "Spansion, Inc.",
-[5][0x68 - 1] = "Taiwan Semiconductor Mfg",
-[5][0x69 - 1] = "Emphany Systems Inc.",
-[5][0x6a - 1] = "ApaceWave Technologies",
-[5][0x6b - 1] = "Mobilygen Corporation",
-[5][0x6c - 1] = "Tego",
-[5][0x6d - 1] = "Cswitch Corporation",
-[5][0x6e - 1] = "Haier (Beijing) IC Design Co.",
-[5][0x6f - 1] = "MetaRAM",
-[5][0x70 - 1] = "Axel Electronics Co. Ltd.",
-[5][0x71 - 1] = "Tilera Corporation",
-[5][0x72 - 1] = "Aquantia",
-[5][0x73 - 1] = "Vivace Semiconductor",
-[5][0x74 - 1] = "Redpine Signals",
-[5][0x75 - 1] = "Octalica",
-[5][0x76 - 1] = "InterDigital Communications",
-[5][0x77 - 1] = "Avant Technology",
-[5][0x78 - 1] = "Asrock, Inc.",
-[5][0x79 - 1] = "Availink",
-[5][0x7a - 1] = "Quartics, Inc.",
-[5][0x7b - 1] = "Element CXI",
-[5][0x7c - 1] = "Innovaciones Microelectronicas",
-[5][0x7d - 1] = "VeriSilicon Microelectronics",
-[5][0x7e - 1] = "W5 Networks",
-[6][0x01 - 1] = "MOVEKING",
-[6][0x02 - 1] = "Mavrix Technology, Inc.",
-[6][0x03 - 1] = "CellGuide Ltd.",
-[6][0x04 - 1] = "Faraday Technology",
-[6][0x05 - 1] = "Diablo Technologies, Inc.",
-[6][0x06 - 1] = "Jennic",
-[6][0x07 - 1] = "Octasic",
-[6][0x08 - 1] = "Molex Incorporated",
-[6][0x09 - 1] = "3Leaf Networks",
-[6][0x0a - 1] = "Bright Micron Technology",
-[6][0x0b - 1] = "Netxen",
-[6][0x0c - 1] = "NextWave Broadband Inc.",
-[6][0x0d - 1] = "DisplayLink",
-[6][0x0e - 1] = "ZMOS Technology",
-[6][0x0f - 1] = "Tec-Hill",
-[6][0x10 - 1] = "Multigig, Inc.",
-[6][0x11 - 1] = "Amimon",
-[6][0x12 - 1] = "Euphonic Technologies, Inc.",
-[6][0x13 - 1] = "BRN Phoenix",
-[6][0x14 - 1] = "InSilica",
-[6][0x15 - 1] = "Ember Corporation",
-[6][0x16 - 1] = "Avexir Technologies Corporation",
-[6][0x17 - 1] = "Echelon Corporation",
-[6][0x18 - 1] = "Edgewater Computer Systems",
-[6][0x19 - 1] = "XMOS Semiconductor Ltd.",
-[6][0x1a - 1] = "GENUSION, Inc.",
-[6][0x1b - 1] = "Memory Corp NV",
-[6][0x1c - 1] = "SiliconBlue Technologies",
-[6][0x1d - 1] = "Rambus Inc.",
-[6][0x1e - 1] = "Andes Technology Corporation",
-[6][0x1f - 1] = "Coronis Systems",
-[6][0x20 - 1] = "Achronix Semiconductor",
-[6][0x21 - 1] = "Siano Mobile Silicon Ltd.",
-[6][0x22 - 1] = "Semtech Corporation",
-[6][0x23 - 1] = "Pixelworks Inc.",
-[6][0x24 - 1] = "Gaisler Research AB",
-[6][0x25 - 1] = "Teranetics",
-[6][0x26 - 1] = "Toppan Printing Co. Ltd.",
-[6][0x27 - 1] = "Kingxcon",
-[6][0x28 - 1] = "Silicon Integrated Systems",
-[6][0x29 - 1] = "I-O Data Device, Inc.",
-[6][0x2a - 1] = "NDS Americas Inc.",
-[6][0x2b - 1] = "Solomon Systech Limited",
-[6][0x2c - 1] = "On Demand Microelectronics",
-[6][0x2d - 1] = "Amicus Wireless Inc.",
-[6][0x2e - 1] = "SMARDTV SNC",
-[6][0x2f - 1] = "Comsys Communication Ltd.",
-[6][0x30 - 1] = "Movidia Ltd.",
-[6][0x31 - 1] = "Javad GNSS, Inc.",
-[6][0x32 - 1] = "Montage Technology Group",
-[6][0x33 - 1] = "Trident Microsystems",
-[6][0x34 - 1] = "Super Talent",
-[6][0x35 - 1] = "Optichron, Inc.",
-[6][0x36 - 1] = "Future Waves UK Ltd.",
-[6][0x37 - 1] = "SiBEAM, Inc.",
-[6][0x38 - 1] = "Inicore,Inc.",
-[6][0x39 - 1] = "Virident Systems",
-[6][0x3a - 1] = "M2000, Inc.",
-[6][0x3b - 1] = "ZeroG Wireless, Inc.",
-[6][0x3c - 1] = "Gingle Technology Co. Ltd.",
-[6][0x3d - 1] = "Space Micro Inc.",
-[6][0x3e - 1] = "Wilocity",
-[6][0x3f - 1] = "Novafora, Inc.",
-[6][0x40 - 1] = "iKoa Corporation",
-[6][0x41 - 1] = "ASint Technology",
-[6][0x42 - 1] = "Ramtron",
-[6][0x43 - 1] = "Plato Networks Inc.",
-[6][0x44 - 1] = "IPtronics AS",
-[6][0x45 - 1] = "Infinite-Memories",
-[6][0x46 - 1] = "Parade Technologies Inc.",
-[6][0x47 - 1] = "Dune Networks",
-[6][0x48 - 1] = "GigaDevice Semiconductor",
-[6][0x49 - 1] = "Modu Ltd.",
-[6][0x4a - 1] = "CEITEC",
-[6][0x4b - 1] = "Northrop Grumman",
-[6][0x4c - 1] = "XRONET Corporation",
-[6][0x4d - 1] = "Sicon Semiconductor AB",
-[6][0x4e - 1] = "Atla Electronics Co. Ltd.",
-[6][0x4f - 1] = "TOPRAM Technology",
-[6][0x50 - 1] = "Silego Technology Inc.",
-[6][0x51 - 1] = "Kinglife",
-[6][0x52 - 1] = "Ability Industries Ltd.",
-[6][0x53 - 1] = "Silicon Power Computer &",
-[6][0x54 - 1] = "Augusta Technology, Inc.",
-[6][0x55 - 1] = "Nantronics Semiconductors",
-[6][0x56 - 1] = "Hilscher Gesellschaft",
-[6][0x57 - 1] = "Quixant Ltd.",
-[6][0x58 - 1] = "Percello Ltd.",
-[6][0x59 - 1] = "NextIO Inc.",
-[6][0x5a - 1] = "Scanimetrics Inc.",
-[6][0x5b - 1] = "FS-Semi Company Ltd.",
-[6][0x5c - 1] = "Infinera Corporation",
-[6][0x5d - 1] = "SandForce Inc.",
-[6][0x5e - 1] = "Lexar Media",
-[6][0x5f - 1] = "Teradyne Inc.",
-[6][0x60 - 1] = "Memory Exchange Corp.",
-[6][0x61 - 1] = "Suzhou Smartek Electronics",
-[6][0x62 - 1] = "Avantium Corporation",
-[6][0x63 - 1] = "ATP Electronics Inc.",
-[6][0x64 - 1] = "Valens Semiconductor Ltd",
-[6][0x65 - 1] = "Agate Logic, Inc.",
-[6][0x66 - 1] = "Netronome",
-[6][0x67 - 1] = "Zenverge, Inc.",
-[6][0x68 - 1] = "N-trig Ltd",
-[6][0x69 - 1] = "SanMax Technologies Inc.",
-[6][0x6a - 1] = "Contour Semiconductor Inc.",
-[6][0x6b - 1] = "TwinMOS",
-[6][0x6c - 1] = "Silicon Systems, Inc.",
-[6][0x6d - 1] = "V-Color Technology Inc.",
-[6][0x6e - 1] = "Certicom Corporation",
-[6][0x6f - 1] = "JSC ICC Milandr",
-[6][0x70 - 1] = "PhotoFast Global Inc.",
-[6][0x71 - 1] = "InnoDisk Corporation",
-[6][0x72 - 1] = "Muscle Power",
-[6][0x73 - 1] = "Energy Micro",
-[6][0x74 - 1] = "Innofidei",
-[6][0x75 - 1] = "CopperGate Communications",
-[6][0x76 - 1] = "Holtek Semiconductor Inc.",
-[6][0x77 - 1] = "Myson Century, Inc.",
-[6][0x78 - 1] = "FIDELIX",
-[6][0x79 - 1] = "Red Digital Cinema",
-[6][0x7a - 1] = "Densbits Technology",
-[6][0x7b - 1] = "Zempro",
-[6][0x7c - 1] = "MoSys",
-[6][0x7d - 1] = "Provigent",
-[6][0x7e - 1] = "Triad Semiconductor, Inc.",
-[7][0x01 - 1] = "Siklu Communication Ltd.",
-[7][0x02 - 1] = "A Force Manufacturing Ltd.",
-[7][0x03 - 1] = "Strontium",
-[7][0x04 - 1] = "Abilis Systems",
-[7][0x05 - 1] = "Siglead, Inc.",
-[7][0x06 - 1] = "Ubicom, Inc.",
-[7][0x07 - 1] = "Unifosa Corporation",
-[7][0x08 - 1] = "Stretch, Inc.",
-[7][0x09 - 1] = "Lantiq Deutschland GmbH",
-[7][0x0a - 1] = "Visipro.",
-[7][0x0b - 1] = "EKMemory",
-[7][0x0c - 1] = "Microelectronics Institute ZTE",
-[7][0x0d - 1] = "Cognovo Ltd.",
-[7][0x0e - 1] = "Carry Technology Co. Ltd.",
-[7][0x0f - 1] = "Nokia",
-[7][0x10 - 1] = "King Tiger Technology",
-[7][0x11 - 1] = "Sierra Wireless",
-[7][0x12 - 1] = "HT Micron",
-[7][0x13 - 1] = "Albatron Technology Co. Ltd.",
-[7][0x14 - 1] = "Leica Geosystems AG",
-[7][0x15 - 1] = "BroadLight",
-[7][0x16 - 1] = "AEXEA",
-[7][0x17 - 1] = "ClariPhy Communications, Inc.",
-[7][0x18 - 1] = "Green Plug",
-[7][0x19 - 1] = "Design Art Networks",
-[7][0x1a - 1] = "Mach Xtreme Technology Ltd.",
-[7][0x1b - 1] = "ATO Solutions Co. Ltd.",
-[7][0x1c - 1] = "Ramsta",
-[7][0x1d - 1] = "Greenliant Systems, Ltd.",
-[7][0x1e - 1] = "Teikon",
-[7][0x1f - 1] = "Antec Hadron",
-[7][0x20 - 1] = "NavCom Technology, Inc.",
-[7][0x21 - 1] = "Shanghai Fudan Microelectronics",
-[7][0x22 - 1] = "Calxeda, Inc.",
-[7][0x23 - 1] = "JSC EDC Electronics",
-[7][0x24 - 1] = "Kandit Technology Co. Ltd.",
-[7][0x25 - 1] = "Ramos Technology",
-[7][0x26 - 1] = "Goldenmars Technology",
-[7][0x27 - 1] = "XeL Technology Inc.",
-[7][0x28 - 1] = "Newzone Corporation",
-[7][0x29 - 1] = "ShenZhen MercyPower Tech",
-[7][0x2a - 1] = "Nanjing Yihuo Technology",
-[7][0x2b - 1] = "Nethra Imaging Inc.",
-[7][0x2c - 1] = "SiTel Semiconductor BV",
-[7][0x2d - 1] = "SolidGear Corporation",
-[7][0x2e - 1] = "Topower Computer Ind Co Ltd.",
-[7][0x2f - 1] = "Wilocity",
-[7][0x30 - 1] = "Profichip GmbH",
-[7][0x31 - 1] = "Gerad Technologies",
-[7][0x32 - 1] = "Ritek Corporation",
-[7][0x33 - 1] = "Gomos Technology Limited",
-[7][0x34 - 1] = "Memoright Corporation",
-[7][0x35 - 1] = "D-Broad, Inc.",
-[7][0x36 - 1] = "HiSilicon Technologies",
-[7][0x37 - 1] = "Syndiant Inc..",
-[7][0x38 - 1] = "Enverv Inc.",
-[7][0x39 - 1] = "Cognex",
-[7][0x3a - 1] = "Xinnova Technology Inc.",
-[7][0x3b - 1] = "Ultron AG",
-[7][0x3c - 1] = "Concord Idea Corporation",
-[7][0x3d - 1] = "AIM Corporation",
-[7][0x3e - 1] = "Lifetime Memory Products",
-[7][0x3f - 1] = "Ramsway",
-[7][0x40 - 1] = "Recore Systems B.V.",
-[7][0x41 - 1] = "Haotian Jinshibo Science Tech",
-[7][0x42 - 1] = "Being Advanced Memory",
-[7][0x43 - 1] = "Adesto Technologies",
-[7][0x44 - 1] = "Giantec Semiconductor, Inc.",
-[7][0x45 - 1] = "HMD Electronics AG",
-[7][0x46 - 1] = "Gloway International (HK)",
-[7][0x47 - 1] = "Kingcore",
-[7][0x48 - 1] = "Anucell Technology Holding",
-[7][0x49 - 1] = "Accord Software & Systems Pvt. Ltd.",
-[7][0x4a - 1] = "Active-Semi Inc.",
-[7][0x4b - 1] = "Denso Corporation",
-[7][0x4c - 1] = "TLSI Inc.",
-[7][0x4d - 1] = "Qidan",
-[7][0x4e - 1] = "Mustang",
-[7][0x4f - 1] = "Orca Systems",
-[7][0x50 - 1] = "Passif Semiconductor",
-[7][0x51 - 1] = "GigaDevice Semiconductor (Beijing)",
-[7][0x52 - 1] = "Memphis Electronic",
-[7][0x53 - 1] = "Beckhoff Automation GmbH",
-[7][0x54 - 1] = "Harmony Semiconductor Corp",
-[7][0x55 - 1] = "Air Computers SRL",
-[7][0x56 - 1] = "TMT Memory",
-[7][0x57 - 1] = "Eorex Corporation",
-[7][0x58 - 1] = "Xingtera",
-[7][0x59 - 1] = "Netsol",
-[7][0x5a - 1] = "Bestdon Technology Co. Ltd.",
-[7][0x5b - 1] = "Baysand Inc.",
-[7][0x5c - 1] = "Uroad Technology Co. Ltd.",
-[7][0x5d - 1] = "Wilk Elektronik S.A.",
-[7][0x5e - 1] = "AAI",
-[7][0x5f - 1] = "Harman",
-[7][0x60 - 1] = "Berg Microelectronics Inc.",
-[7][0x61 - 1] = "ASSIA, Inc.",
-[7][0x62 - 1] = "Visiontek Products LLC",
-[7][0x63 - 1] = "OCMEMORY",
-[7][0x64 - 1] = "Welink Solution Inc.",
-[7][0x65 - 1] = "Shark Gaming",
-[7][0x66 - 1] = "Avalanche Technology",
-[7][0x67 - 1] = "R&D Center ELVEES OJSC",
-[7][0x68 - 1] = "KingboMars Technology Co. Ltd.",
-[7][0x69 - 1] = "High Bridge Solutions Industria",
-[7][0x6a - 1] = "Transcend Technology Co. Ltd.",
-[7][0x6b - 1] = "Everspin Technologies",
-[7][0x6c - 1] = "Hon-Hai Precision",
-[7][0x6d - 1] = "Smart Storage Systems",
-[7][0x6e - 1] = "Toumaz Group",
-[7][0x6f - 1] = "Zentel Electronics Corporation",
-[7][0x70 - 1] = "Panram International Corporation",
-[7][0x71 - 1] = "Silicon Space Technology",
-[7][0x72 - 1] = "LITE-ON IT Corporation",
-[7][0x73 - 1] = "Inuitive",
-[7][0x74 - 1] = "HMicro",
-[7][0x75 - 1] = "BittWare, Inc.",
-[7][0x76 - 1] = "GLOBALFOUNDRIES",
-[7][0x77 - 1] = "ACPI Digital Co. Ltd.",
-[7][0x78 - 1] = "Annapurna Labs",
-[7][0x79 - 1] = "AcSiP Technology Corporation",
-[7][0x7a - 1] = "Idea! Electronic Systems",
-[7][0x7b - 1] = "Gowe Technology Co. Ltd.",
-[7][0x7c - 1] = "Hermes Testing Solutions, Inc.",
-[7][0x7d - 1] = "Positivo BGH",
-[7][0x7e - 1] = "Intelligence Silicon Technology",
-[8][0x01 - 1] = "3D PLUS",
-[8][0x02 - 1] = "Diehl Aerospace",
-[8][0x03 - 1] = "Fairchild",
-[8][0x04 - 1] = "Mercury Systems",
-[8][0x05 - 1] = "Sonics, Inc.",
-[8][0x06 - 1] = "GE Intelligent Platforms GmbH & Co.",
-[8][0x07 - 1] = "Shenzhen Jinge Information Co. Ltd.",
-[8][0x08 - 1] = "SCWW",
-[8][0x09 - 1] = "Silicon Motion Inc.",
-[8][0x0a - 1] = "Anurag",
-[8][0x0b - 1] = "King Kong",
-[8][0x0c - 1] = "FROM30 Co. Ltd.",
-[8][0x0d - 1] = "Gowin Semiconductor Corp",
-[8][0x0e - 1] = "Fremont Micro Devices Ltd.",
-[8][0x0f - 1] = "Ericsson Modems",
-[8][0x10 - 1] = "Exelis",
-[8][0x11 - 1] = "Satixfy Ltd.",
-[8][0x12 - 1] = "Galaxy Microsystems Ltd.",
-[8][0x13 - 1] = "Gloway International Co. Ltd.",
-[8][0x14 - 1] = "Lab",
-[8][0x15 - 1] = "Smart Energy Instruments",
-[8][0x16 - 1] = "Approved Memory Corporation",
-[8][0x17 - 1] = "Axell Corporation",
-[8][0x18 - 1] = "Essencore Limited",
-[8][0x19 - 1] = "Phytium",
-[8][0x1a - 1] = "Xi’an SinoChip Semiconductor",
-[8][0x1b - 1] = "Ambiq Micro",
-[8][0x1c - 1] = "eveRAM Technology, Inc.",
-[8][0x1d - 1] = "Infomax",
-[8][0x1e - 1] = "Butterfly Network, Inc.",
-[8][0x1f - 1] = "Shenzhen City Gcai Electronics",
-[8][0x20 - 1] = "Stack Devices Corporation",
-[8][0x21 - 1] = "ADK Media Group",
-[8][0x22 - 1] = "TSP Global Co., Ltd.",
-[8][0x23 - 1] = "HighX",
-[8][0x24 - 1] = "Shenzhen Elicks Technology",
-[8][0x25 - 1] = "ISSI/Chingis",
-[8][0x26 - 1] = "Google, Inc.",
-[8][0x27 - 1] = "Dasima International Development",
-[8][0x28 - 1] = "Leahkinn Technology Limited",
-[8][0x29 - 1] = "HIMA Paul Hildebrandt GmbH Co KG",
-[8][0x2a - 1] = "Keysight Technologies",
-[8][0x2b - 1] = "Techcomp International (Fastable)",
-[8][0x2c - 1] = "Ancore Technology Corporation",
-[8][0x2d - 1] = "Nuvoton",
-[8][0x2e - 1] = "Korea Uhbele International Group Ltd.",
-[8][0x2f - 1] = "Ikegami Tsushinki Co Ltd.",
-[8][0x30 - 1] = "RelChip, Inc.",
-[8][0x31 - 1] = "Baikal Electronics",
-[8][0x32 - 1] = "Nemostech Inc.",
-[8][0x33 - 1] = "Memorysolution GmbH",
-[8][0x34 - 1] = "Silicon Integrated Systems Corporation",
-[8][0x35 - 1] = "Xiede",
-[8][0x36 - 1] = "Multilaser Components",
-[8][0x37 - 1] = "Flash Chi",
-[8][0x38 - 1] = "Jone",
-[8][0x39 - 1] = "GCT Semiconductor Inc.",
-[8][0x3a - 1] = "Hong Kong Zetta Device Technology",
-[8][0x3b - 1] = "Unimemory Technology(s) Pte Ltd.",
-[8][0x3c - 1] = "Cuso",
-[8][0x3d - 1] = "Kuso",
-[8][0x3e - 1] = "Uniquify Inc.",
-[8][0x3f - 1] = "Skymedi Corporation",
-[8][0x40 - 1] = "Core Chance Co. Ltd.",
-[8][0x41 - 1] = "Tekism Co. Ltd.",
-[8][0x42 - 1] = "Seagate Technology PLC",
-[8][0x43 - 1] = "Hong Kong Gaia Group Co. Limited",
-[8][0x44 - 1] = "Gigacom Semiconductor LLC",
-[8][0x45 - 1] = "V2 Technologies",
-[8][0x46 - 1] = "TLi",
-[8][0x47 - 1] = "Neotion",
-[8][0x48 - 1] = "Lenovo",
-[8][0x49 - 1] = "Shenzhen Zhongteng Electronic Corp. Ltd.",
-[8][0x4a - 1] = "Compound Photonics",
-[8][0x4b - 1] = "in2H2 inc",
-[8][0x4c - 1] = "Shenzhen Pango Microsystems Co. Ltd",
-[8][0x4d - 1] = "Vasekey",
-[8][0x4e - 1] = "Cal-Comp Industria de Semicondutores",
-[8][0x4f - 1] = "Eyenix Co., Ltd.",
-[8][0x50 - 1] = "Heoriady",
-[8][0x51 - 1] = "Accelerated Memory Production Inc.",
-[8][0x52 - 1] = "INVECAS, Inc.",
-[8][0x53 - 1] = "AP Memory",
-[8][0x54 - 1] = "Douqi Technology",
-[8][0x55 - 1] = "Etron Technology, Inc.",
-[8][0x56 - 1] = "Indie Semiconductor",
-[8][0x57 - 1] = "Socionext Inc.",
-[8][0x58 - 1] = "HGST",
-[8][0x59 - 1] = "EVGA",
-[8][0x5a - 1] = "Audience Inc.",
-[8][0x5b - 1] = "EpicGear",
-[8][0x5c - 1] = "Vitesse Enterprise Co.",
-[8][0x5d - 1] = "Foxtronn International Corporation",
-[8][0x5e - 1] = "Bretelon Inc.",
-[8][0x5f - 1] = "Zbit Semiconductor, Inc.",
-[8][0x60 - 1] = "Eoplex Inc",
-[8][0x61 - 1] = "MaxLinear, Inc.",
-[8][0x62 - 1] = "ETA Devices",
-[8][0x63 - 1] = "LOKI",
-[8][0x64 - 1] = "IMS Semiconductor Co., Ltd",
-[8][0x65 - 1] = "Dosilicon Co., Ltd.",
-[8][0x66 - 1] = "Dolphin Integration",
-[8][0x67 - 1] = "Shenzhen Mic Electronics Technology",
-[8][0x68 - 1] = "Boya Microelectronics Inc.",
-[8][0x69 - 1] = "Geniachip (Roche)",
-[8][0x6a - 1] = "Axign",
-[8][0x6b - 1] = "Kingred Electronic Technology Ltd.",
-[8][0x6c - 1] = "Chao Yue Zhuo Computer Business Dept.",
-[8][0x6d - 1] = "Guangzhou Si Nuo Electronic Technology.",
-/* EOF */
diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c
deleted file mode 100644
index d13bdfb..0000000
--- a/src/helper/jim-nvp.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/* Jim - A small embeddable Tcl interpreter
- *
- * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
- * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
- * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
- * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
- * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
- * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
- * Copyright 2008 Steve Bennett <steveb@workware.net.au>
- * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
- * Copyright 2009 Zachary T Welch zw@superlucidity.net
- * Copyright 2009 David Brownell
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- */
-
-#include <string.h>
-#include <jim-nvp.h>
-
-int Jim_GetNvp(Jim_Interp *interp,
- Jim_Obj *objPtr, const Jim_Nvp *nvp_table, const Jim_Nvp **result)
-{
- Jim_Nvp *n;
- int e;
-
- e = Jim_Nvp_name2value_obj(interp, nvp_table, objPtr, &n);
- if (e == JIM_ERR)
- return e;
-
- /* Success? found? */
- if (n->name) {
- /* remove const */
- *result = (Jim_Nvp *) n;
- return JIM_OK;
- } else
- return JIM_ERR;
-}
-
-Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp *p, const char *name)
-{
- while (p->name) {
- if (0 == strcmp(name, p->name))
- break;
- p++;
- }
- return (Jim_Nvp *) (p);
-}
-
-Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp *p, const char *name)
-{
- while (p->name) {
- if (0 == strcasecmp(name, p->name))
- break;
- p++;
- }
- return (Jim_Nvp *) (p);
-}
-
-int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nvp **result)
-{
- return Jim_Nvp_name2value(interp, p, Jim_String(o), result);
-}
-
-int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp *_p, const char *name, Jim_Nvp **result)
-{
- const Jim_Nvp *p;
-
- p = Jim_Nvp_name2value_simple(_p, name);
-
- /* result */
- if (result)
- *result = (Jim_Nvp *) (p);
-
- /* found? */
- if (p->name)
- return JIM_OK;
- else
- return JIM_ERR;
-}
-
-int Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp,
- const Jim_Nvp *p,
- Jim_Obj *o,
- Jim_Nvp **puthere)
-{
- return Jim_Nvp_name2value_nocase(interp, p, Jim_String(o), puthere);
-}
-
-int Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp *_p, const char *name,
- Jim_Nvp **puthere)
-{
- const Jim_Nvp *p;
-
- p = Jim_Nvp_name2value_nocase_simple(_p, name);
-
- if (puthere)
- *puthere = (Jim_Nvp *) (p);
- /* found */
- if (p->name)
- return JIM_OK;
- else
- return JIM_ERR;
-}
-
-int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp *p, Jim_Obj *o, Jim_Nvp **result)
-{
- int e;
- jim_wide w;
-
- e = Jim_GetWide(interp, o, &w);
- if (e != JIM_OK)
- return e;
-
- return Jim_Nvp_value2name(interp, p, w, result);
-}
-
-Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp *p, int value)
-{
- while (p->name) {
- if (value == p->value)
- break;
- p++;
- }
- return (Jim_Nvp *) (p);
-}
-
-int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp *_p, int value, Jim_Nvp **result)
-{
- const Jim_Nvp *p;
-
- p = Jim_Nvp_value2name_simple(_p, value);
-
- if (result)
- *result = (Jim_Nvp *) (p);
-
- if (p->name)
- return JIM_OK;
- else
- return JIM_ERR;
-}
-
-int Jim_GetOpt_Setup(Jim_GetOptInfo *p, Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- memset(p, 0, sizeof(*p));
- p->interp = interp;
- p->argc = argc;
- p->argv = argv;
-
- return JIM_OK;
-}
-
-void Jim_GetOpt_Debug(Jim_GetOptInfo *p)
-{
- int x;
-
- fprintf(stderr, "---args---\n");
- for (x = 0; x < p->argc; x++)
- fprintf(stderr, "%2d) %s\n", x, Jim_String(p->argv[x]));
- fprintf(stderr, "-------\n");
-}
-
-int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere)
-{
- Jim_Obj *o;
-
- o = NULL; /* failure */
- if (goi->argc) {
- /* success */
- o = goi->argv[0];
- goi->argc -= 1;
- goi->argv += 1;
- }
- if (puthere)
- *puthere = o;
- if (o != NULL)
- return JIM_OK;
- else
- return JIM_ERR;
-}
-
-int Jim_GetOpt_String(Jim_GetOptInfo *goi, const char **puthere, int *len)
-{
- int r;
- Jim_Obj *o;
- const char *cp;
-
- r = Jim_GetOpt_Obj(goi, &o);
- if (r == JIM_OK) {
- cp = Jim_GetString(o, len);
- if (puthere) {
- *puthere = cp;
- }
- }
- return r;
-}
-
-int Jim_GetOpt_Double(Jim_GetOptInfo *goi, double *puthere)
-{
- int r;
- Jim_Obj *o;
- double _safe;
-
- if (puthere == NULL)
- puthere = &_safe;
-
- r = Jim_GetOpt_Obj(goi, &o);
- if (r == JIM_OK) {
- r = Jim_GetDouble(goi->interp, o, puthere);
- if (r != JIM_OK)
- Jim_SetResultFormatted(goi->interp, "not a number: %#s", o);
- }
- return r;
-}
-
-int Jim_GetOpt_Wide(Jim_GetOptInfo *goi, jim_wide *puthere)
-{
- int r;
- Jim_Obj *o;
- jim_wide _safe;
-
- if (puthere == NULL)
- puthere = &_safe;
-
- r = Jim_GetOpt_Obj(goi, &o);
- if (r == JIM_OK)
- r = Jim_GetWide(goi->interp, o, puthere);
- return r;
-}
-
-int Jim_GetOpt_Nvp(Jim_GetOptInfo *goi, const Jim_Nvp *nvp, Jim_Nvp **puthere)
-{
- Jim_Nvp *_safe;
- Jim_Obj *o;
- int e;
-
- if (puthere == NULL)
- puthere = &_safe;
-
- e = Jim_GetOpt_Obj(goi, &o);
- if (e == JIM_OK)
- e = Jim_Nvp_name2value_obj(goi->interp, nvp, o, puthere);
-
- return e;
-}
-
-void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *nvptable, int hadprefix)
-{
- if (hadprefix)
- Jim_SetResult_NvpUnknown(goi->interp, goi->argv[-2], goi->argv[-1], nvptable);
- else
- Jim_SetResult_NvpUnknown(goi->interp, NULL, goi->argv[-1], nvptable);
-}
-
-int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char *const *lookup, int *puthere)
-{
- int _safe;
- Jim_Obj *o;
- int e;
-
- if (puthere == NULL)
- puthere = &_safe;
- e = Jim_GetOpt_Obj(goi, &o);
- if (e == JIM_OK)
- e = Jim_GetEnum(goi->interp, o, lookup, puthere, "option", JIM_ERRMSG);
- return e;
-}
-
-void Jim_SetResult_NvpUnknown(Jim_Interp *interp,
- Jim_Obj *param_name, Jim_Obj *param_value, const Jim_Nvp *nvp)
-{
- if (param_name)
- Jim_SetResultFormatted(interp,
- "%#s: Unknown: %#s, try one of: ",
- param_name,
- param_value);
- else
- Jim_SetResultFormatted(interp, "Unknown param: %#s, try one of: ", param_value);
- while (nvp->name) {
- const char *a;
- const char *b;
-
- if ((nvp + 1)->name) {
- a = nvp->name;
- b = ", ";
- } else {
- a = "or ";
- b = nvp->name;
- }
- Jim_AppendStrings(interp, Jim_GetResult(interp), a, b, NULL);
- nvp++;
- }
-}
-
-const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- static Jim_Obj *debug_string_obj;
-
- int x;
-
- if (debug_string_obj)
- Jim_FreeObj(interp, debug_string_obj);
-
- debug_string_obj = Jim_NewEmptyStringObj(interp);
- for (x = 0; x < argc; x++)
- Jim_AppendStrings(interp, debug_string_obj, Jim_String(argv[x]), " ", NULL);
-
- return Jim_String(debug_string_obj);
-}
-
-int Jim_nvpInit(Jim_Interp *interp)
-{
- /* This is really a helper library, not an extension, but this is the easy way */
- return JIM_OK;
-}
diff --git a/src/helper/jim-nvp.h b/src/helper/jim-nvp.h
deleted file mode 100644
index 7b4a491..0000000
--- a/src/helper/jim-nvp.h
+++ /dev/null
@@ -1,329 +0,0 @@
-/* Jim - A small embeddable Tcl interpreter
- *
- * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
- * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
- * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
- * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
- * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
- * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
- * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
- * Copyright 2008 Steve Bennett <steveb@workware.net.au>
- * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
- * Copyright 2009 Zachary T Welch zw@superlucidity.net
- * Copyright 2009 David Brownell
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- */
-
-#ifndef OPENOCD_HELPER_JIM_NVP_H
-#define OPENOCD_HELPER_JIM_NVP_H
-
-#include <jim.h>
-
-/** Name Value Pairs, aka: NVP
- * - Given a string - return the associated int.
- * - Given a number - return the associated string.
- * .
- *
- * Very useful when the number is not a simple index into an array of
- * known string, or there may be multiple strings (aliases) that mean then same
- * thing.
- *
- * An NVP Table is terminated with ".name = NULL".
- *
- * During the 'name2value' operation, if no matching string is found
- * the pointer to the terminal element (with p->name == NULL) is returned.
- *
- * Example:
- * \code
- * const Jim_Nvp yn[] = {
- * { "yes", 1 },
- * { "no" , 0 },
- * { "yep", 1 },
- * { "nope", 0 },
- * { NULL, -1 },
- * };
- *
- * Jim_Nvp *result
- * e = Jim_Nvp_name2value(interp, yn, "y", &result);
- * returns &yn[0];
- * e = Jim_Nvp_name2value(interp, yn, "n", &result);
- * returns &yn[1];
- * e = Jim_Nvp_name2value(interp, yn, "Blah", &result);
- * returns &yn[4];
- * \endcode
- *
- * During the number2name operation, the first matching value is returned.
- */
-typedef struct {
- const char *name;
- int value;
-} Jim_Nvp;
-
-int Jim_GetNvp(Jim_Interp *interp,
- Jim_Obj *objPtr,
- const Jim_Nvp *nvp_table,
- const Jim_Nvp **result);
-
-/* Name Value Pairs Operations */
-Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp *nvp_table, const char *name);
-Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp *nvp_table, const char *name);
-Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp *nvp_table, int v);
-
-int Jim_Nvp_name2value(Jim_Interp *interp,
- const Jim_Nvp *nvp_table,
- const char *name,
- Jim_Nvp **result);
-int Jim_Nvp_name2value_nocase(Jim_Interp *interp,
- const Jim_Nvp *nvp_table,
- const char *name,
- Jim_Nvp **result);
-int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp *nvp_table, int value, Jim_Nvp **result);
-
-int Jim_Nvp_name2value_obj(Jim_Interp *interp,
- const Jim_Nvp *nvp_table,
- Jim_Obj *name_obj,
- Jim_Nvp **result);
-int Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp,
- const Jim_Nvp *nvp_table,
- Jim_Obj *name_obj,
- Jim_Nvp **result);
-int Jim_Nvp_value2name_obj(Jim_Interp *interp,
- const Jim_Nvp *nvp_table,
- Jim_Obj *value_obj,
- Jim_Nvp **result);
-
-/** prints a nice 'unknown' parameter error message to the 'result' */
-void Jim_SetResult_NvpUnknown(Jim_Interp *interp,
- Jim_Obj *param_name,
- Jim_Obj *param_value,
- const Jim_Nvp *nvp_table);
-
-/** Debug: convert argc/argv into a printable string for printf() debug
- *
- * \param interp - the interpeter
- * \param argc - arg count
- * \param argv - the objects
- *
- * \returns string pointer holding the text.
- *
- * Note, next call to this function will free the old (last) string.
- *
- * For example might want do this:
- * \code
- * fp = fopen("some.file.log", "a");
- * fprintf(fp, "PARAMS are: %s\n", Jim_DebugArgvString(interp, argc, argv));
- * fclose(fp);
- * \endcode
- */
-const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-
-
-/** A TCL -ish GetOpt like code.
- *
- * Some TCL objects have various "configuration" values.
- * For example - in Tcl/Tk the "buttons" have many options.
- *
- * Usefull when dealing with command options.
- * that may come in any order...
- *
- * Does not support "-foo = 123" type options.
- * Only supports tcl type options, like "-foo 123"
- */
-
-typedef struct jim_getopt {
- Jim_Interp *interp;
- int argc;
- Jim_Obj *const *argv;
- int isconfigure; /* non-zero if configure */
-} Jim_GetOptInfo;
-
-/** GetOpt - how to.
- *
- * Example (short and incomplete):
- * \code
- * Jim_GetOptInfo goi;
- *
- * Jim_GetOpt_Setup(&goi, interp, argc, argv);
- *
- * while (goi.argc) {
- * e = Jim_GetOpt_Nvp(&goi, nvp_options, &n);
- * if (e != JIM_OK) {
- * Jim_GetOpt_NvpUnknown(&goi, nvp_options, 0);
- * return e;
- * }
- *
- * switch (n->value) {
- * case ALIVE:
- * printf("Option ALIVE specified\n");
- * break;
- * case FIRST:
- * if (goi.argc < 1) {
- * .. not enough args error ..
- * }
- * Jim_GetOpt_String(&goi, &cp, NULL);
- * printf("FIRSTNAME: %s\n", cp);
- * case AGE:
- * Jim_GetOpt_Wide(&goi, &w);
- * printf("AGE: %d\n", (int)(w));
- * break;
- * case POLITICS:
- * e = Jim_GetOpt_Nvp(&goi, nvp_politics, &n);
- * if (e != JIM_OK) {
- * Jim_GetOpt_NvpUnknown(&goi, nvp_politics, 1);
- * return e;
- * }
- * }
- * }
- *
- * \endcode
- *
- */
-
-/** Setup GETOPT
- *
- * \param goi - get opt info to be initialized
- * \param interp - jim interp
- * \param argc - argc count.
- * \param argv - argv (will be copied)
- *
- * \code
- * Jim_GetOptInfo goi;
- *
- * Jim_GetOptSetup(&goi, interp, argc, argv);
- * \endcode
- */
-
-int Jim_GetOpt_Setup(Jim_GetOptInfo *goi,
- Jim_Interp *interp,
- int argc,
- Jim_Obj *const *argv);
-
-
-/** Debug - Dump parameters to stderr
- * \param goi - current parameters
- */
-void Jim_GetOpt_Debug(Jim_GetOptInfo *goi);
-
-/** Remove argv[0] from the list.
- *
- * \param goi - get opt info
- * \param puthere - where param is put
- *
- */
-int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere);
-
-/** Remove argv[0] as string.
- *
- * \param goi - get opt info
- * \param puthere - where param is put
- * \param len - return its length
- */
-int Jim_GetOpt_String(Jim_GetOptInfo *goi, const char **puthere, int *len);
-
-/** Remove argv[0] as double.
- *
- * \param goi - get opt info
- * \param puthere - where param is put.
- *
- */
-int Jim_GetOpt_Double(Jim_GetOptInfo *goi, double *puthere);
-
-/** Remove argv[0] as wide.
- *
- * \param goi - get opt info
- * \param puthere - where param is put.
- */
-int Jim_GetOpt_Wide(Jim_GetOptInfo *goi, jim_wide *puthere);
-
-/** Remove argv[0] as NVP.
- *
- * \param goi - get opt info
- * \param lookup - nvp lookup table
- * \param puthere - where param is put.
- *
- */
-int Jim_GetOpt_Nvp(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, Jim_Nvp **puthere);
-
-/** Create an appropriate error message for an NVP.
- *
- * \param goi - options info
- * \param lookup - the NVP table that was used.
- * \param hadprefix - 0 or 1 if the option had a prefix.
- *
- * This function will set the "interp->result" to a human readable
- * error message listing the available options.
- *
- * This function assumes the previous option argv[-1] is the unknown string.
- *
- * If this option had some prefix, then pass "hadprefix = 1" else pass "hadprefix = 0"
- *
- * Example:
- * \code
- *
- * while (goi.argc) {
- * // Get the next option
- * e = Jim_GetOpt_Nvp(&goi, cmd_options, &n);
- * if (e != JIM_OK) {
- * // option was not recognized
- * // pass 'hadprefix = 0' because there is no prefix
- * Jim_GetOpt_NvpUnknown(&goi, cmd_options, 0);
- * return e;
- * }
- *
- * switch (n->value) {
- * case OPT_SEX:
- * // handle: --sex male | female | lots | needmore
- * e = Jim_GetOpt_Nvp(&goi, &nvp_sex, &n);
- * if (e != JIM_OK) {
- * Jim_GetOpt_NvpUnknown(&ogi, nvp_sex, 1);
- * return e;
- * }
- * printf("Code: (%d) is %s\n", n->value, n->name);
- * break;
- * case ...:
- * [snip]
- * }
- * }
- * \endcode
- *
- */
-void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, int hadprefix);
-
-
-/** Remove argv[0] as Enum
- *
- * \param goi - get opt info
- * \param lookup - lookup table.
- * \param puthere - where param is put.
- *
- */
-int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char *const *lookup, int *puthere);
-
-#endif /* OPENOCD_HELPER_JIM_NVP_H */
diff --git a/src/helper/list.h b/src/helper/list.h
deleted file mode 100644
index 6fd0e7c..0000000
--- a/src/helper/list.h
+++ /dev/null
@@ -1,737 +0,0 @@
-#ifndef OPENOCD_HELPER_LIST_H
-#define OPENOCD_HELPER_LIST_H
-
-/* begin local changes */
-#include <helper/types.h>
-
-#define prefetch(x) ((void)x)
-#define LIST_POISON1 NULL
-#define LIST_POISON2 NULL
-
-struct list_head {
- struct list_head *next, *prev;
-};
-struct hlist_head {
- struct hlist_node *first;
-};
-struct hlist_node {
- struct hlist_node *next, **pprev;
-};
-/* end local changes */
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
- list->next = list;
- list->prev = list;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-#ifndef CONFIG_DEBUG_LIST
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-#else
-extern void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next);
-#endif
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-#ifndef CONFIG_DEBUG_LIST
-static inline void __list_del_entry(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
-}
-
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-#else
-extern void __list_del_entry(struct list_head *entry);
-extern void list_del(struct list_head *entry);
-#endif
-
-/**
- * list_replace - replace old entry by new one
- * @old : the element to be replaced
- * @new : the new element to insert
- *
- * If @old was empty, it will be overwritten.
- */
-static inline void list_replace(struct list_head *old,
- struct list_head *new)
-{
- new->next = old->next;
- new->next->prev = new;
- new->prev = old->prev;
- new->prev->next = new;
-}
-
-static inline void list_replace_init(struct list_head *old,
- struct list_head *new)
-{
- list_replace(old, new);
- INIT_LIST_HEAD(old);
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
- __list_del_entry(entry);
- INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
- __list_del_entry(list);
- list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
-{
- __list_del_entry(list);
- list_add_tail(list, head);
-}
-
-/**
- * list_is_last - tests whether @list is the last entry in list @head
- * @list: the entry to test
- * @head: the head of the list
- */
-static inline int list_is_last(const struct list_head *list,
- const struct list_head *head)
-{
- return list->next == head;
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
- return head->next == head;
-}
-
-/**
- * list_empty_careful - tests whether a list is empty and not being modified
- * @head: the list to test
- *
- * Description:
- * tests whether a list is empty _and_ checks that no other CPU might be
- * in the process of modifying either member (next or prev)
- *
- * NOTE: using list_empty_careful() without synchronization
- * can only be safe if the only activity that can happen
- * to the list entry is list_del_init(). Eg. it cannot be used
- * if another CPU could re-list_add() it.
- */
-static inline int list_empty_careful(const struct list_head *head)
-{
- struct list_head *next = head->next;
- return (next == head) && (next == head->prev);
-}
-
-/**
- * list_rotate_left - rotate the list to the left
- * @head: the head of the list
- */
-static inline void list_rotate_left(struct list_head *head)
-{
- struct list_head *first;
-
- if (!list_empty(head)) {
- first = head->next;
- list_move_tail(first, head);
- }
-}
-
-/**
- * list_is_singular - tests whether a list has just one entry.
- * @head: the list to test.
- */
-static inline int list_is_singular(const struct list_head *head)
-{
- return !list_empty(head) && (head->next == head->prev);
-}
-
-static inline void __list_cut_position(struct list_head *list,
- struct list_head *head, struct list_head *entry)
-{
- struct list_head *new_first = entry->next;
- list->next = head->next;
- list->next->prev = list;
- list->prev = entry;
- entry->next = list;
- head->next = new_first;
- new_first->prev = head;
-}
-
-/**
- * list_cut_position - cut a list into two
- * @list: a new list to add all removed entries
- * @head: a list with entries
- * @entry: an entry within head, could be the head itself
- * and if so we won't cut the list
- *
- * This helper moves the initial part of @head, up to and
- * including @entry, from @head to @list. You should
- * pass on @entry an element you know is on @head. @list
- * should be an empty list or a list you do not care about
- * losing its data.
- *
- */
-static inline void list_cut_position(struct list_head *list,
- struct list_head *head, struct list_head *entry)
-{
- if (list_empty(head))
- return;
- if (list_is_singular(head) &&
- (head->next != entry && head != entry))
- return;
- if (entry == head)
- INIT_LIST_HEAD(list);
- else
- __list_cut_position(list, head, entry);
-}
-
-static inline void __list_splice(const struct list_head *list,
- struct list_head *prev,
- struct list_head *next)
-{
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
-
- first->prev = prev;
- prev->next = first;
-
- last->next = next;
- next->prev = last;
-}
-
-/**
- * list_splice - join two lists, this is designed for stacks
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(const struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list))
- __list_splice(list, head, head->next);
-}
-
-/**
- * list_splice_tail - join two lists, each list being a queue
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice_tail(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list))
- __list_splice(list, head->prev, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head, head->next);
- INIT_LIST_HEAD(list);
- }
-}
-
-/**
- * list_splice_tail_init - join two lists and reinitialise the emptied list
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * Each of the lists is a queue.
- * The list at @list is reinitialised
- */
-static inline void list_splice_tail_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head->prev, head);
- INIT_LIST_HEAD(list);
- }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_first_entry - get the first element from a list
- * @ptr: the list head to take the element from.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-/**
- * list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; prefetch(pos->next), pos != (head); \
- pos = pos->next)
-
-/**
- * __list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- *
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
- */
-#define __list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_prev - iterate over a list backwards
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- */
-#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
- pos = pos->prev)
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos: the &struct list_head to use as a loop cursor.
- * @n: another &struct list_head to use as temporary storage
- * @head: the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-/**
- * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
- * @pos: the &struct list_head to use as a loop cursor.
- * @n: another &struct list_head to use as temporary storage
- * @head: the head for your list.
- */
-#define list_for_each_prev_safe(pos, n, head) \
- for (pos = (head)->prev, n = pos->prev; \
- prefetch(pos->prev), pos != (head); \
- pos = n, n = pos->prev)
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member); \
- prefetch(pos->member.prev), &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
- * @pos: the type * to use as a start point
- * @head: the head of the list
- * @member: the name of the list_struct within the struct.
- *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
- */
-#define list_prepare_entry(pos, head, member) \
- ((pos) ? : list_entry(head, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue - continue iteration over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Continue to iterate over list of given type, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue_reverse - iterate backwards from the given point
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Start to iterate over list of given type backwards, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue_reverse(pos, head, member) \
- for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
- prefetch(pos->member.prev), &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_for_each_entry_from - iterate over list of given type from the current point
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from(pos, head, member) \
- for (; prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_continue - continue list iteration safe against removal
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing after current point,
- * safe against removal of list entry.
- */
-#define list_for_each_entry_safe_continue(pos, n, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_from - iterate over list from current point safe against removal
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Iterate over list of given type from current point, safe against
- * removal of list entry.
- */
-#define list_for_each_entry_safe_from(pos, n, head, member) \
- for (n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Iterate backwards over list of given type, safe against removal
- * of list entry.
- */
-#define list_for_each_entry_safe_reverse(pos, n, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member), \
- n = list_entry(pos->member.prev, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.prev, typeof(*n), member))
-
-/**
- * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
- * @pos: the loop cursor used in the list_for_each_entry_safe loop
- * @n: temporary storage used in list_for_each_entry_safe
- * @member: the name of the list_struct within the struct.
- *
- * list_safe_reset_next is not safe to use in general if the list may be
- * modified concurrently (eg. the lock is dropped in the loop body). An
- * exception to this is if the cursor element (pos) is pinned in the list,
- * and list_safe_reset_next is called after re-taking the lock and before
- * completing the current iteration of the loop body.
- */
-#define list_safe_reset_next(pos, n, member) \
- n = list_entry(pos->member.next, typeof(*pos), member)
-
-/*
- * Double linked lists with a single pointer list head.
- * Mostly useful for hash tables where the two pointer list head is
- * too wasteful.
- * You lose the ability to access the tail in O(1).
- */
-
-#define HLIST_HEAD_INIT { .first = NULL }
-#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
-#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
-static inline void INIT_HLIST_NODE(struct hlist_node *h)
-{
- h->next = NULL;
- h->pprev = NULL;
-}
-
-static inline int hlist_unhashed(const struct hlist_node *h)
-{
- return !h->pprev;
-}
-
-static inline int hlist_empty(const struct hlist_head *h)
-{
- return !h->first;
-}
-
-static inline void __hlist_del(struct hlist_node *n)
-{
- struct hlist_node *next = n->next;
- struct hlist_node **pprev = n->pprev;
- *pprev = next;
- if (next)
- next->pprev = pprev;
-}
-
-static inline void hlist_del(struct hlist_node *n)
-{
- __hlist_del(n);
- n->next = LIST_POISON1;
- n->pprev = LIST_POISON2;
-}
-
-static inline void hlist_del_init(struct hlist_node *n)
-{
- if (!hlist_unhashed(n)) {
- __hlist_del(n);
- INIT_HLIST_NODE(n);
- }
-}
-
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
- struct hlist_node *first = h->first;
- n->next = first;
- if (first)
- first->pprev = &n->next;
- h->first = n;
- n->pprev = &h->first;
-}
-
-/* next must be != NULL */
-static inline void hlist_add_before(struct hlist_node *n,
- struct hlist_node *next)
-{
- n->pprev = next->pprev;
- n->next = next;
- next->pprev = &n->next;
- *(n->pprev) = n;
-}
-
-static inline void hlist_add_after(struct hlist_node *n,
- struct hlist_node *next)
-{
- next->next = n->next;
- n->next = next;
- next->pprev = &n->next;
-
- if (next->next)
- next->next->pprev = &next->next;
-}
-
-/* after that we'll appear to be on some hlist and hlist_del will work */
-static inline void hlist_add_fake(struct hlist_node *n)
-{
- n->pprev = &n->next;
-}
-
-/*
- * Move a list from one list head to another. Fixup the pprev
- * reference of the first entry if it exists.
- */
-static inline void hlist_move_list(struct hlist_head *old,
- struct hlist_head *new)
-{
- new->first = old->first;
- if (new->first)
- new->first->pprev = &new->first;
- old->first = NULL;
-}
-
-#define hlist_entry(ptr, type, member) container_of(ptr, type, member)
-
-#define hlist_for_each(pos, head) \
- for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
- pos = pos->next)
-
-#define hlist_for_each_safe(pos, n, head) \
- for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
- pos = n)
-
-/**
- * hlist_for_each_entry - iterate over list of given type
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry(tpos, pos, head, member) \
- for (pos = (head)->first; \
- pos && ({ prefetch(pos->next); 1; }) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
- pos = pos->next)
-
-/**
- * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @member: the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_continue(tpos, pos, member) \
- for (pos = (pos)->next; \
- pos && ({ prefetch(pos->next); 1; }) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
- pos = pos->next)
-
-/**
- * hlist_for_each_entry_from - iterate over a hlist continuing from current point
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @member: the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_from(tpos, pos, member) \
- for (; pos && ({ prefetch(pos->next); 1; }) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
- pos = pos->next)
-
-/**
- * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @n: another &struct hlist_node to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
- for (pos = (head)->first; \
- pos && ({ n = pos->next; 1; }) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
- pos = n)
-
-#endif /* OPENOCD_HELPER_LIST_H */
diff --git a/src/helper/log.c b/src/helper/log.c
deleted file mode 100644
index e33f869..0000000
--- a/src/helper/log.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "log.h"
-#include "command.h"
-#include "time_support.h"
-
-#include <stdarg.h>
-
-#ifdef _DEBUG_FREE_SPACE_
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#else
-#error "malloc.h is required to use --enable-malloc-logging"
-#endif
-#endif
-
-int debug_level = -1;
-
-static FILE *log_output;
-static struct log_callback *log_callbacks;
-
-static int64_t last_time;
-static int64_t current_time;
-
-static int64_t start;
-
-static const char * const log_strings[5] = {
- "User : ",
- "Error: ",
- "Warn : ", /* want a space after each colon, all same width, colons aligned */
- "Info : ",
- "Debug: "
-};
-
-static int count;
-
-static struct store_log_forward *log_head;
-static int log_forward_count;
-
-struct store_log_forward {
- struct store_log_forward *next;
- const char *file;
- int line;
- const char *function;
- const char *string;
-};
-
-/* either forward the log to the listeners or store it for possible forwarding later */
-static void log_forward(const char *file, unsigned line, const char *function, const char *string)
-{
- if (log_forward_count == 0) {
- struct log_callback *cb, *next;
- cb = log_callbacks;
- /* DANGER!!!! the log callback can remove itself!!!! */
- while (cb) {
- next = cb->next;
- cb->fn(cb->priv, file, line, function, string);
- cb = next;
- }
- } else {
- struct store_log_forward *log = malloc(sizeof(struct store_log_forward));
- log->file = strdup(file);
- log->line = line;
- log->function = strdup(function);
- log->string = strdup(string);
- log->next = NULL;
- if (log_head == NULL)
- log_head = log;
- else {
- /* append to tail */
- struct store_log_forward *t;
- t = log_head;
- while (t->next != NULL)
- t = t->next;
- t->next = log;
- }
- }
-}
-
-/* The log_puts() serves two somewhat different goals:
- *
- * - logging
- * - feeding low-level info to the user in GDB or Telnet
- *
- * The latter dictates that strings without newline are not logged, lest there
- * will be *MANY log lines when sending one char at the time(e.g.
- * target_request.c).
- *
- */
-static void log_puts(enum log_levels level,
- const char *file,
- int line,
- const char *function,
- const char *string)
-{
- char *f;
- if (level == LOG_LVL_OUTPUT) {
- /* do not prepend any headers, just print out what we were given and return */
- fputs(string, log_output);
- fflush(log_output);
- return;
- }
-
- f = strrchr(file, '/');
- if (f != NULL)
- file = f + 1;
-
- if (strlen(string) > 0) {
- if (debug_level >= LOG_LVL_DEBUG) {
- /* print with count and time information */
- int64_t t = timeval_ms() - start;
-#ifdef _DEBUG_FREE_SPACE_
- struct mallinfo info;
- info = mallinfo();
-#endif
- fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()"
-#ifdef _DEBUG_FREE_SPACE_
- " %d"
-#endif
- ": %s", log_strings[level + 1], count, t, file, line, function,
-#ifdef _DEBUG_FREE_SPACE_
- info.fordblks,
-#endif
- string);
- } else {
- /* if we are using gdb through pipes then we do not want any output
- * to the pipe otherwise we get repeated strings */
- fprintf(log_output, "%s%s",
- (level > LOG_LVL_USER) ? log_strings[level + 1] : "", string);
- }
- } else {
- /* Empty strings are sent to log callbacks to keep e.g. gdbserver alive, here we do
- *nothing. */
- }
-
- fflush(log_output);
-
- /* Never forward LOG_LVL_DEBUG, too verbose and they can be found in the log if need be */
- if (level <= LOG_LVL_INFO)
- log_forward(file, line, function, string);
-}
-
-void log_printf(enum log_levels level,
- const char *file,
- unsigned line,
- const char *function,
- const char *format,
- ...)
-{
- char *string;
- va_list ap;
-
- count++;
- if (level > debug_level)
- return;
-
- va_start(ap, format);
-
- string = alloc_vprintf(format, ap);
- if (string != NULL) {
- log_puts(level, file, line, function, string);
- free(string);
- }
-
- va_end(ap);
-}
-
-void log_printf_lf(enum log_levels level,
- const char *file,
- unsigned line,
- const char *function,
- const char *format,
- ...)
-{
- char *string;
- va_list ap;
-
- count++;
- if (level > debug_level)
- return;
-
- va_start(ap, format);
-
- string = alloc_vprintf(format, ap);
- if (string != NULL) {
- strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one
- *char longer */
- log_puts(level, file, line, function, string);
- free(string);
- }
-
- va_end(ap);
-}
-
-COMMAND_HANDLER(handle_debug_level_command)
-{
- if (CMD_ARGC == 1) {
- int new_level;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], new_level);
- if ((new_level > LOG_LVL_DEBUG) || (new_level < LOG_LVL_SILENT)) {
- LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- debug_level = new_level;
- } else if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- command_print(CMD_CTX, "debug_level: %i", debug_level);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_log_output_command)
-{
- if (CMD_ARGC == 1) {
- FILE *file = fopen(CMD_ARGV[0], "w");
-
- if (file)
- log_output = file;
- }
-
- return ERROR_OK;
-}
-
-static struct command_registration log_command_handlers[] = {
- {
- .name = "log_output",
- .handler = handle_log_output_command,
- .mode = COMMAND_ANY,
- .help = "redirect logging to a file (default: stderr)",
- .usage = "file_name",
- },
- {
- .name = "debug_level",
- .handler = handle_debug_level_command,
- .mode = COMMAND_ANY,
- .help = "Sets the verbosity level of debugging output. "
- "0 shows errors only; 1 adds warnings; "
- "2 (default) adds other info; 3 adds debugging.",
- .usage = "number",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int log_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, log_command_handlers);
-}
-
-void log_init(void)
-{
- /* set defaults for daemon configuration,
- * if not set by cmdline or cfgfile */
- if (debug_level == -1)
- debug_level = LOG_LVL_INFO;
-
- char *debug_env = getenv("OPENOCD_DEBUG_LEVEL");
- if (NULL != debug_env) {
- int value;
- int retval = parse_int(debug_env, &value);
- if (ERROR_OK == retval &&
- debug_level >= LOG_LVL_SILENT &&
- debug_level <= LOG_LVL_DEBUG)
- debug_level = value;
- }
-
- if (log_output == NULL)
- log_output = stderr;
-
- start = last_time = timeval_ms();
-}
-
-int set_log_output(struct command_context *cmd_ctx, FILE *output)
-{
- log_output = output;
- return ERROR_OK;
-}
-
-/* add/remove log callback handler */
-int log_add_callback(log_callback_fn fn, void *priv)
-{
- struct log_callback *cb;
-
- /* prevent the same callback to be registered more than once, just for sure */
- for (cb = log_callbacks; cb; cb = cb->next) {
- if (cb->fn == fn && cb->priv == priv)
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* alloc memory, it is safe just to return in case of an error, no need for the caller to
- *check this */
- cb = malloc(sizeof(struct log_callback));
- if (cb == NULL)
- return ERROR_BUF_TOO_SMALL;
-
- /* add item to the beginning of the linked list */
- cb->fn = fn;
- cb->priv = priv;
- cb->next = log_callbacks;
- log_callbacks = cb;
-
- return ERROR_OK;
-}
-
-int log_remove_callback(log_callback_fn fn, void *priv)
-{
- struct log_callback *cb, **p;
-
- for (p = &log_callbacks; (cb = *p); p = &(*p)->next) {
- if (cb->fn == fn && cb->priv == priv) {
- *p = cb->next;
- free(cb);
- return ERROR_OK;
- }
- }
-
- /* no such item */
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-/* return allocated string w/printf() result */
-char *alloc_vprintf(const char *fmt, va_list ap)
-{
- va_list ap_copy;
- int len;
- char *string;
-
- /* determine the length of the buffer needed */
- va_copy(ap_copy, ap);
- len = vsnprintf(NULL, 0, fmt, ap_copy);
- va_end(ap_copy);
-
- /* allocate and make room for terminating zero. */
- /* FIXME: The old version always allocated at least one byte extra and
- * other code depend on that. They should be probably be fixed, but for
- * now reserve the extra byte. */
- string = malloc(len + 2);
- if (string == NULL)
- return NULL;
-
- /* do the real work */
- vsnprintf(string, len + 1, fmt, ap);
-
- return string;
-}
-
-char *alloc_printf(const char *format, ...)
-{
- char *string;
- va_list ap;
- va_start(ap, format);
- string = alloc_vprintf(format, ap);
- va_end(ap);
- return string;
-}
-
-/* Code must return to the server loop before 1000ms has returned or invoke
- * this function.
- *
- * The GDB connection will time out if it spends >2000ms and you'll get nasty
- * error messages from GDB:
- *
- * Ignoring packet error, continuing...
- * Reply contains invalid hex digit 116
- *
- * While it is possible use "set remotetimeout" to more than the default 2000ms
- * in GDB, OpenOCD guarantees that it sends keep-alive packages on the
- * GDB protocol and it is a bug in OpenOCD not to either return to the server
- * loop or invoke keep_alive() every 1000ms.
- *
- * This function will send a keep alive packet if >500ms has passed since last time
- * it was invoked.
- *
- * Note that this function can be invoked often, so it needs to be relatively
- * fast when invoked more often than every 500ms.
- *
- */
-void keep_alive()
-{
- current_time = timeval_ms();
- if (current_time-last_time > 1000) {
- extern int gdb_actual_connections;
-
- if (gdb_actual_connections)
- LOG_WARNING("keep_alive() was not invoked in the "
- "1000ms timelimit. GDB alive packet not "
- "sent! (%" PRId64 "). Workaround: increase "
- "\"set remotetimeout\" in GDB",
- current_time-last_time);
- else
- LOG_DEBUG("keep_alive() was not invoked in the "
- "1000ms timelimit (%" PRId64 "). This may cause "
- "trouble with GDB connections.",
- current_time-last_time);
- }
- if (current_time-last_time > 500) {
- /* this will keep the GDB connection alive */
- LOG_USER_N("%s", "");
-
- /* DANGER!!!! do not add code to invoke e.g. target event processing,
- * jim timer processing, etc. it can cause infinite recursion +
- * jim event callbacks need to happen at a well defined time,
- * not anywhere keep_alive() is invoked.
- *
- * These functions should be invoked at a well defined spot in server.c
- */
-
- last_time = current_time;
- }
-}
-
-/* reset keep alive timer without sending message */
-void kept_alive()
-{
- current_time = timeval_ms();
- last_time = current_time;
-}
-
-/* if we sleep for extended periods of time, we must invoke keep_alive() intermittantly */
-void alive_sleep(uint64_t ms)
-{
- uint64_t napTime = 10;
- for (uint64_t i = 0; i < ms; i += napTime) {
- uint64_t sleep_a_bit = ms - i;
- if (sleep_a_bit > napTime)
- sleep_a_bit = napTime;
-
- usleep(sleep_a_bit * 1000);
- keep_alive();
- }
-}
-
-void busy_sleep(uint64_t ms)
-{
- uint64_t then = timeval_ms();
- while (timeval_ms() - then < ms) {
- /*
- * busy wait
- */
- }
-}
diff --git a/src/helper/log.h b/src/helper/log.h
deleted file mode 100644
index eb222cb..0000000
--- a/src/helper/log.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_LOG_H
-#define OPENOCD_HELPER_LOG_H
-
-#include <helper/command.h>
-
-/* To achieve C99 printf compatibility in MinGW, gnu_printf should be
- * used for __attribute__((format( ... ))), with GCC v4.4 or later
- */
-#if (defined(IS_MINGW) && (((__GNUC__ << 16) + __GNUC_MINOR__) >= 0x00040004))
-#define PRINTF_ATTRIBUTE_FORMAT gnu_printf
-#else
-#define PRINTF_ATTRIBUTE_FORMAT printf
-#endif
-
-/* logging priorities
- * LOG_LVL_SILENT - turn off all output. In lieu of try + catch this can be used as a
- * feeble ersatz.
- * LOG_LVL_USER - user messages. Could be anything from information
- * to progress messags. These messages do not represent
- * incorrect or unexpected behaviour, just normal execution.
- * LOG_LVL_ERROR - fatal errors, that are likely to cause program abort
- * LOG_LVL_WARNING - non-fatal errors, that may be resolved later
- * LOG_LVL_INFO - state information, etc.
- * LOG_LVL_DEBUG - debug statements, execution trace
- */
-enum log_levels {
- LOG_LVL_SILENT = -3,
- LOG_LVL_OUTPUT = -2,
- LOG_LVL_USER = -1,
- LOG_LVL_ERROR = 0,
- LOG_LVL_WARNING = 1,
- LOG_LVL_INFO = 2,
- LOG_LVL_DEBUG = 3
-};
-
-void log_printf(enum log_levels level, const char *file, unsigned line,
- const char *function, const char *format, ...)
-__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
-void log_printf_lf(enum log_levels level, const char *file, unsigned line,
- const char *function, const char *format, ...)
-__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
-
-/**
- * Initialize logging module. Call during program startup.
- */
-void log_init(void);
-int set_log_output(struct command_context *cmd_ctx, FILE *output);
-
-int log_register_commands(struct command_context *cmd_ctx);
-
-void keep_alive(void);
-void kept_alive(void);
-
-void alive_sleep(uint64_t ms);
-void busy_sleep(uint64_t ms);
-
-typedef void (*log_callback_fn)(void *priv, const char *file, unsigned line,
- const char *function, const char *string);
-
-struct log_callback {
- log_callback_fn fn;
- void *priv;
- struct log_callback *next;
-};
-
-int log_add_callback(log_callback_fn fn, void *priv);
-int log_remove_callback(log_callback_fn fn, void *priv);
-
-char *alloc_vprintf(const char *fmt, va_list ap);
-char *alloc_printf(const char *fmt, ...);
-
-extern int debug_level;
-
-/* Avoid fn call and building parameter list if we're not outputting the information.
- * Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */
-
-#define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO))
-
-#define LOG_DEBUG(expr ...) \
- do { \
- if (debug_level >= LOG_LVL_DEBUG) \
- log_printf_lf(LOG_LVL_DEBUG, \
- __FILE__, __LINE__, __func__, \
- expr); \
- } while (0)
-
-#define LOG_INFO(expr ...) \
- log_printf_lf(LOG_LVL_INFO, __FILE__, __LINE__, __func__, expr)
-
-#define LOG_WARNING(expr ...) \
- log_printf_lf(LOG_LVL_WARNING, __FILE__, __LINE__, __func__, expr)
-
-#define LOG_ERROR(expr ...) \
- log_printf_lf(LOG_LVL_ERROR, __FILE__, __LINE__, __func__, expr)
-
-#define LOG_USER(expr ...) \
- log_printf_lf(LOG_LVL_USER, __FILE__, __LINE__, __func__, expr)
-
-#define LOG_USER_N(expr ...) \
- log_printf(LOG_LVL_USER, __FILE__, __LINE__, __func__, expr)
-
-#define LOG_OUTPUT(expr ...) \
- log_printf(LOG_LVL_OUTPUT, __FILE__, __LINE__, __func__, expr)
-
-/* general failures
- * error codes < 100
- */
-#define ERROR_OK (0)
-#define ERROR_NO_CONFIG_FILE (-2)
-#define ERROR_BUF_TOO_SMALL (-3)
-/* see "Error:" log entry for meaningful message to the user. The caller should
- * make no assumptions about what went wrong and try to handle the problem.
- */
-#define ERROR_FAIL (-4)
-#define ERROR_WAIT (-5)
-
-
-#endif /* OPENOCD_HELPER_LOG_H */
diff --git a/src/helper/options.c b/src/helper/options.c
deleted file mode 100644
index b7db10f..0000000
--- a/src/helper/options.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "configuration.h"
-#include "log.h"
-#include "command.h"
-
-#include <getopt.h>
-
-static int help_flag, version_flag;
-
-static const struct option long_options[] = {
- {"help", no_argument, &help_flag, 1},
- {"version", no_argument, &version_flag, 1},
- {"debug", optional_argument, 0, 'd'},
- {"file", required_argument, 0, 'f'},
- {"search", required_argument, 0, 's'},
- {"log_output", required_argument, 0, 'l'},
- {"command", required_argument, 0, 'c'},
- {"pipe", no_argument, 0, 'p'},
- {0, 0, 0, 0}
-};
-
-int configuration_output_handler(struct command_context *context, const char *line)
-{
- LOG_USER_N("%s", line);
-
- return ERROR_OK;
-}
-
-#ifdef _WIN32
-static char *find_suffix(const char *text, const char *suffix)
-{
- size_t text_len = strlen(text);
- size_t suffix_len = strlen(suffix);
-
- if (suffix_len == 0)
- return (char *)text + text_len;
-
- if (suffix_len > text_len || strncmp(text + text_len - suffix_len, suffix, suffix_len) != 0)
- return NULL; /* Not a suffix of text */
-
- return (char *)text + text_len - suffix_len;
-}
-#endif
-
-static void add_default_dirs(void)
-{
- const char *run_prefix;
- char *path;
-
-#ifdef _WIN32
- char strExePath[MAX_PATH];
- GetModuleFileName(NULL, strExePath, MAX_PATH);
-
- /* Strip executable file name, leaving path */
- *strrchr(strExePath, '\\') = '\0';
-
- /* Convert path separators to UNIX style, should work on Windows also. */
- for (char *p = strExePath; *p; p++) {
- if (*p == '\\')
- *p = '/';
- }
-
- char *end_of_prefix = find_suffix(strExePath, BINDIR);
- if (end_of_prefix != NULL)
- *end_of_prefix = '\0';
-
- run_prefix = strExePath;
-#else
- run_prefix = "";
-#endif
-
- LOG_DEBUG("bindir=%s", BINDIR);
- LOG_DEBUG("pkgdatadir=%s", PKGDATADIR);
- LOG_DEBUG("run_prefix=%s", run_prefix);
-
- /*
- * The directory containing OpenOCD-supplied scripts should be
- * listed last in the built-in search order, so the user can
- * override these scripts with site-specific customizations.
- */
- const char *home = getenv("HOME");
-
- if (home) {
- path = alloc_printf("%s/.openocd", home);
- if (path) {
- add_script_search_dir(path);
- free(path);
- }
- }
-
- path = getenv("OPENOCD_SCRIPTS");
-
- if (path)
- add_script_search_dir(path);
-
-#ifdef _WIN32
- const char *appdata = getenv("APPDATA");
-
- if (appdata) {
- path = alloc_printf("%s/OpenOCD", appdata);
- if (path) {
- add_script_search_dir(path);
- free(path);
- }
- }
-#endif
-
- path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/site");
- if (path) {
- add_script_search_dir(path);
- free(path);
- }
-
- path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/scripts");
- if (path) {
- add_script_search_dir(path);
- free(path);
- }
-}
-
-int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
-{
- int c;
-
- while (1) {
- /* getopt_long stores the option index here. */
- int option_index = 0;
-
- c = getopt_long(argc, argv, "hvd::l:f:s:c:p", long_options, &option_index);
-
- /* Detect the end of the options. */
- if (c == -1)
- break;
-
- switch (c) {
- case 0:
- break;
- case 'h': /* --help | -h */
- help_flag = 1;
- break;
- case 'v': /* --version | -v */
- version_flag = 1;
- break;
- case 'f': /* --file | -f */
- {
- char *command = alloc_printf("script {%s}", optarg);
- add_config_command(command);
- free(command);
- break;
- }
- case 's': /* --search | -s */
- add_script_search_dir(optarg);
- break;
- case 'd': /* --debug | -d */
- {
- char *command = alloc_printf("debug_level %s", optarg ? optarg : "3");
- command_run_line(cmd_ctx, command);
- free(command);
- break;
- }
- case 'l': /* --log_output | -l */
- if (optarg) {
- char *command = alloc_printf("log_output %s", optarg);
- command_run_line(cmd_ctx, command);
- free(command);
- }
- break;
- case 'c': /* --command | -c */
- if (optarg)
- add_config_command(optarg);
- break;
- case 'p':
- /* to replicate the old syntax this needs to be synchronous
- * otherwise the gdb stdin will overflow with the warning message */
- command_run_line(cmd_ctx, "gdb_port pipe; log_output openocd.log");
- LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; "
- "log_output openocd.log\"' instead.");
- break;
- }
- }
-
- if (help_flag) {
- LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n");
- LOG_OUTPUT("--help | -h\tdisplay this help\n");
- LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n");
- LOG_OUTPUT("--file | -f\tuse configuration file <name>\n");
- LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n");
- LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n");
- LOG_OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
- LOG_OUTPUT("--command | -c\trun <command>\n");
- exit(-1);
- }
-
- if (version_flag) {
- /* Nothing to do, version gets printed automatically. */
- /* It is not an error to request the VERSION number. */
- exit(0);
- }
-
- /* paths specified on the command line take precedence over these
- * built-in paths
- */
- add_default_dirs();
-
- return ERROR_OK;
-}
diff --git a/src/helper/replacements.c b/src/helper/replacements.c
deleted file mode 100644
index b4bb94f..0000000
--- a/src/helper/replacements.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-/* DANGER!!!! These must be defined *BEFORE* replacements.h and the malloc() macro!!!! */
-
-#include <stdlib.h>
-#include <string.h>
-/*
- * clear_malloc
- *
- * will alloc memory and clear it
- */
-void *clear_malloc(size_t size)
-{
- void *t = malloc(size);
- if (t != NULL)
- memset(t, 0x00, size);
- return t;
-}
-
-void *fill_malloc(size_t size)
-{
- void *t = malloc(size);
- if (t != NULL) {
- /* We want to initialize memory to some known bad state.
- * 0 and 0xff yields 0 and -1 as integers, which often
- * have meaningful values. 0x5555... is not often a valid
- * integer and is quite easily spotted in the debugger
- * also it is almost certainly an invalid address */
- memset(t, 0x55, size);
- }
- return t;
-}
-
-#define IN_REPLACEMENTS_C
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#ifdef _WIN32
-#include <io.h>
-#endif
-
-/* replacements for gettimeofday */
-#ifndef HAVE_GETTIMEOFDAY
-
-/* Windows */
-#ifdef _WIN32
-
-#ifndef __GNUC__
-#define EPOCHFILETIME (116444736000000000i64)
-#else
-#define EPOCHFILETIME (116444736000000000LL)
-#endif
-
-int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- FILETIME ft;
- LARGE_INTEGER li;
- __int64 t;
- static int tzflag;
-
- if (tv) {
- GetSystemTimeAsFileTime(&ft);
- li.LowPart = ft.dwLowDateTime;
- li.HighPart = ft.dwHighDateTime;
- t = li.QuadPart; /* In 100-nanosecond intervals */
- t -= EPOCHFILETIME; /* Offset to the Epoch time */
- t /= 10; /* In microseconds */
- tv->tv_sec = (long)(t / 1000000);
- tv->tv_usec = (long)(t % 1000000);
- }
-
- if (tz) {
- if (!tzflag) {
- _tzset();
- tzflag++;
- }
- tz->tz_minuteswest = _timezone / 60;
- tz->tz_dsttime = _daylight;
- }
-
- return 0;
-}
-#endif /* _WIN32 */
-
-#endif /* HAVE_GETTIMEOFDAY */
-
-#ifndef HAVE_STRNLEN
-size_t strnlen(const char *s, size_t maxlen)
-{
- const char *end = (const char *)memchr(s, '\0', maxlen);
- return end ? (size_t) (end - s) : maxlen;
-}
-#endif
-
-#ifndef HAVE_STRNDUP
-char *strndup(const char *s, size_t n)
-{
- size_t len = strnlen(s, n);
- char *new = malloc(len + 1);
-
- if (new == NULL)
- return NULL;
-
- new[len] = '\0';
- return (char *) memcpy(new, s, len);
-}
-#endif
-
-#ifdef _WIN32
-int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
-{
- DWORD ms_total, limit;
- HANDLE handles[MAXIMUM_WAIT_OBJECTS];
- int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
- int n_handles = 0, i;
- fd_set sock_read, sock_write, sock_except;
- fd_set aread, awrite, aexcept;
- int sock_max_fd = -1;
- struct timeval tvslice;
- int retcode;
-
-#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
-
- /* calculate how long we need to wait in milliseconds */
- if (tv == NULL)
- ms_total = INFINITE;
- else {
- ms_total = tv->tv_sec * 1000;
- ms_total += tv->tv_usec / 1000;
- }
-
- FD_ZERO(&sock_read);
- FD_ZERO(&sock_write);
- FD_ZERO(&sock_except);
-
- /* build an array of handles for non-sockets */
- for (i = 0; i < max_fd; i++) {
- if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) {
- intptr_t handle = (intptr_t) _get_osfhandle(i);
- handles[n_handles] = (HANDLE)handle;
- if (handles[n_handles] == INVALID_HANDLE_VALUE) {
- /* socket */
- if (SAFE_FD_ISSET(i, rfds))
- FD_SET(i, &sock_read);
- if (SAFE_FD_ISSET(i, wfds))
- FD_SET(i, &sock_write);
- if (SAFE_FD_ISSET(i, efds))
- FD_SET(i, &sock_except);
- if (i > sock_max_fd)
- sock_max_fd = i;
- } else {
- handle_slot_to_fd[n_handles] = i;
- n_handles++;
- }
- }
- }
-
- if (n_handles == 0) {
- /* plain sockets only - let winsock handle the whole thing */
- return select(max_fd, rfds, wfds, efds, tv);
- }
-
- /* mixture of handles and sockets; lets multiplex between
- * winsock and waiting on the handles */
-
- FD_ZERO(&aread);
- FD_ZERO(&awrite);
- FD_ZERO(&aexcept);
-
- limit = GetTickCount() + ms_total;
- do {
- retcode = 0;
-
- if (sock_max_fd >= 0) {
- /* overwrite the zero'd sets here; the select call
- * will clear those that are not active */
- aread = sock_read;
- awrite = sock_write;
- aexcept = sock_except;
-
- tvslice.tv_sec = 0;
- tvslice.tv_usec = 1000;
-
- retcode = select(sock_max_fd + 1, &aread, &awrite, &aexcept, &tvslice);
- }
-
- if (n_handles > 0) {
- /* check handles */
- DWORD wret;
-
- wret = MsgWaitForMultipleObjects(n_handles,
- handles,
- FALSE,
- retcode > 0 ? 0 : 1,
- QS_ALLEVENTS);
-
- if (wret == WAIT_TIMEOUT) {
- /* set retcode to 0; this is the default.
- * select() may have set it to something else,
- * in which case we leave it alone, so this branch
- * does nothing */
- ;
- } else if (wret == WAIT_FAILED) {
- if (retcode == 0)
- retcode = -1;
- } else {
- if (retcode < 0)
- retcode = 0;
- for (i = 0; i < n_handles; i++) {
- if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
- if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) {
- DWORD dwBytes;
- intptr_t handle = (intptr_t) _get_osfhandle(
- handle_slot_to_fd[i]);
-
- if (PeekNamedPipe((HANDLE)handle, NULL, 0,
- NULL, &dwBytes, NULL)) {
- /* check to see if gdb pipe has data available */
- if (dwBytes) {
- FD_SET(handle_slot_to_fd[i], &aread);
- retcode++;
- }
- } else {
- FD_SET(handle_slot_to_fd[i], &aread);
- retcode++;
- }
- }
- if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) {
- FD_SET(handle_slot_to_fd[i], &awrite);
- retcode++;
- }
- if (SAFE_FD_ISSET(handle_slot_to_fd[i], efds)) {
- FD_SET(handle_slot_to_fd[i], &aexcept);
- retcode++;
- }
- }
- }
- }
- }
- } while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));
-
- if (rfds)
- *rfds = aread;
- if (wfds)
- *wfds = awrite;
- if (efds)
- *efds = aexcept;
-
- return retcode;
-}
-#endif
-
-#if defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME
-#include <libusb.h>
-/* Verbatim from git://git.libusb.org/libusb.git tag 1.0.9
- * The libusb_error enum is compatible down to v0.9.1
- */
-const char *libusb_error_name(int error_code)
-{
- enum libusb_error error = error_code;
- switch (error) {
- case LIBUSB_SUCCESS:
- return "LIBUSB_SUCCESS";
- case LIBUSB_ERROR_IO:
- return "LIBUSB_ERROR_IO";
- case LIBUSB_ERROR_INVALID_PARAM:
- return "LIBUSB_ERROR_INVALID_PARAM";
- case LIBUSB_ERROR_ACCESS:
- return "LIBUSB_ERROR_ACCESS";
- case LIBUSB_ERROR_NO_DEVICE:
- return "LIBUSB_ERROR_NO_DEVICE";
- case LIBUSB_ERROR_NOT_FOUND:
- return "LIBUSB_ERROR_NOT_FOUND";
- case LIBUSB_ERROR_BUSY:
- return "LIBUSB_ERROR_BUSY";
- case LIBUSB_ERROR_TIMEOUT:
- return "LIBUSB_ERROR_TIMEOUT";
- case LIBUSB_ERROR_OVERFLOW:
- return "LIBUSB_ERROR_OVERFLOW";
- case LIBUSB_ERROR_PIPE:
- return "LIBUSB_ERROR_PIPE";
- case LIBUSB_ERROR_INTERRUPTED:
- return "LIBUSB_ERROR_INTERRUPTED";
- case LIBUSB_ERROR_NO_MEM:
- return "LIBUSB_ERROR_NO_MEM";
- case LIBUSB_ERROR_NOT_SUPPORTED:
- return "LIBUSB_ERROR_NOT_SUPPORTED";
- case LIBUSB_ERROR_OTHER:
- return "LIBUSB_ERROR_OTHER";
- }
- return "**UNKNOWN**";
-}
-#endif
diff --git a/src/helper/replacements.h b/src/helper/replacements.h
deleted file mode 100644
index 1e2fbf2..0000000
--- a/src/helper/replacements.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_REPLACEMENTS_H
-#define OPENOCD_HELPER_REPLACEMENTS_H
-
-/* MIN,MAX macros */
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#endif
-
-/* for systems that do not support ENOTSUP
- * win32 being one of them */
-#ifndef ENOTSUP
-#define ENOTSUP 134 /* Not supported */
-#endif
-
-/* for systems that do not support O_BINARY
- * linux being one of them */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#ifndef HAVE_SYS_TIME_H
-
-#ifndef _TIMEVAL_DEFINED
-#define _TIMEVAL_DEFINED
-
-struct timeval {
- long tv_sec;
- long tv_usec;
-};
-
-#endif /* _TIMEVAL_DEFINED */
-
-#endif
-
-/* gettimeofday() */
-#ifndef HAVE_GETTIMEOFDAY
-
-#ifdef _WIN32
-struct timezone {
- int tz_minuteswest;
- int tz_dsttime;
-};
-#endif
-struct timezone;
-
-int gettimeofday(struct timeval *tv, struct timezone *tz);
-
-#endif
-
-#ifndef IN_REPLACEMENTS_C
-/**** clear_malloc & fill_malloc ****/
-void *clear_malloc(size_t size);
-void *fill_malloc(size_t size);
-#endif
-
-/*
- * Now you have 3 ways for the malloc function:
- *
- * 1. Do not change anything, use the original malloc
- *
- * 2. Use the clear_malloc function instead of the original malloc.
- * In this case you must use the following define:
- * #define malloc((_a)) clear_malloc((_a))
- *
- * 3. Use the fill_malloc function instead of the original malloc.
- * In this case you must use the following define:
- * #define malloc((_a)) fill_malloc((_a))
- *
- * We have figured out that there could exist some malloc problems
- * where variables are using without to be initialise. To find this
- * places, use the fill_malloc function. With this function we want
- * to initialize memory to some known bad state. This is quite easily
- * spotted in the debugger and will trap to an invalid address.
- *
- * clear_malloc can be used if you want to set not initialise
- * variable to 0.
- *
- * If you do not want to change the malloc function, to not use one of
- * the following macros. Which is the default way.
- */
-
-/* #define malloc(_a) clear_malloc(_a)
- * #define malloc(_a) fill_malloc(_a) */
-
-/* GNU extensions to the C library that may be missing on some systems */
-#ifndef HAVE_STRNDUP
-char *strndup(const char *s, size_t n);
-#endif /* HAVE_STRNDUP */
-
-#ifndef HAVE_STRNLEN
-size_t strnlen(const char *s, size_t maxlen);
-#endif /* HAVE_STRNLEN */
-
-#ifndef HAVE_USLEEP
-#ifdef _WIN32
-static inline unsigned usleep(unsigned int usecs)
-{
- Sleep((usecs/1000));
- return 0;
-}
-#else
-#error no usleep defined for your platform
-#endif
-#endif /* HAVE_USLEEP */
-
-/* Windows specific */
-#ifdef _WIN32
-
-#include <windows.h>
-#include <time.h>
-
-/* Windows does not declare sockaddr_un */
-#define UNIX_PATH_LEN 108
-struct sockaddr_un {
- uint16_t sun_family;
- char sun_path[UNIX_PATH_LEN];
-};
-
-/* win32 systems do not support ETIMEDOUT */
-
-#ifndef ETIMEDOUT
-#define ETIMEDOUT WSAETIMEDOUT
-#endif
-
-#if IS_MINGW == 1
-static inline unsigned char inb(unsigned short int port)
-{
- unsigned char _v;
- __asm__ __volatile__ ("inb %w1,%0" : "=a" (_v) : "Nd" (port));
- return _v;
-}
-
-static inline void outb(unsigned char value, unsigned short int port)
-{
- __asm__ __volatile__ ("outb %b0,%w1" : : "a" (value), "Nd" (port));
-}
-
-/* mingw does not have ffs, so use gcc builtin types */
-#define ffs __builtin_ffs
-
-#endif /* IS_MINGW */
-
-int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv);
-
-#endif /* _WIN32 */
-
-/* generic socket functions for Windows and Posix */
-static inline int write_socket(int handle, const void *buffer, unsigned int count)
-{
-#ifdef _WIN32
- return send(handle, buffer, count, 0);
-#else
- return write(handle, buffer, count);
-#endif
-}
-
-static inline int read_socket(int handle, void *buffer, unsigned int count)
-{
-#ifdef _WIN32
- return recv(handle, buffer, count, 0);
-#else
- return read(handle, buffer, count);
-#endif
-}
-
-static inline int close_socket(int sock)
-{
-#ifdef _WIN32
- return closesocket(sock);
-#else
- return close(sock);
-#endif
-}
-
-static inline void socket_nonblock(int fd)
-{
-#ifdef _WIN32
- unsigned long nonblock = 1;
- ioctlsocket(fd, FIONBIO, &nonblock);
-#else
- int oldopts = fcntl(fd, F_GETFL, 0);
- fcntl(fd, F_SETFL, oldopts | O_NONBLOCK);
-#endif
-}
-
-static inline int socket_select(int max_fd,
- fd_set *rfds,
- fd_set *wfds,
- fd_set *efds,
- struct timeval *tv)
-{
-#ifdef _WIN32
- return win_select(max_fd, rfds, wfds, efds, tv);
-#else
- return select(max_fd, rfds, wfds, efds, tv);
-#endif
-}
-
-#ifndef HAVE_ELF_H
-
-typedef uint32_t Elf32_Addr;
-typedef uint16_t Elf32_Half;
-typedef uint32_t Elf32_Off;
-typedef int32_t Elf32_Sword;
-typedef uint32_t Elf32_Word;
-typedef uint32_t Elf32_Size;
-typedef Elf32_Off Elf32_Hashelt;
-
-typedef struct {
- unsigned char e_ident[16]; /* Magic number and other info */
- Elf32_Half e_type; /* Object file type */
- Elf32_Half e_machine; /* Architecture */
- Elf32_Word e_version; /* Object file version */
- Elf32_Addr e_entry; /* Entry point virtual address */
- Elf32_Off e_phoff; /* Program header table file offset */
- Elf32_Off e_shoff; /* Section header table file offset */
- Elf32_Word e_flags; /* Processor-specific flags */
- Elf32_Half e_ehsize; /* ELF header size in bytes */
- Elf32_Half e_phentsize; /* Program header table entry size */
- Elf32_Half e_phnum; /* Program header table entry count */
- Elf32_Half e_shentsize; /* Section header table entry size */
- Elf32_Half e_shnum; /* Section header table entry count */
- Elf32_Half e_shstrndx; /* Section header string table index */
-} Elf32_Ehdr;
-
-#define ELFMAG "\177ELF"
-#define SELFMAG 4
-
-#define EI_CLASS 4 /* File class byte index */
-#define ELFCLASS32 1 /* 32-bit objects */
-#define ELFCLASS64 2 /* 64-bit objects */
-
-#define EI_DATA 5 /* Data encoding byte index */
-#define ELFDATA2LSB 1 /* 2's complement, little endian */
-#define ELFDATA2MSB 2 /* 2's complement, big endian */
-
-typedef struct {
- Elf32_Word p_type; /* Segment type */
- Elf32_Off p_offset; /* Segment file offset */
- Elf32_Addr p_vaddr; /* Segment virtual address */
- Elf32_Addr p_paddr; /* Segment physical address */
- Elf32_Size p_filesz; /* Segment size in file */
- Elf32_Size p_memsz; /* Segment size in memory */
- Elf32_Word p_flags; /* Segment flags */
- Elf32_Size p_align; /* Segment alignment */
-} Elf32_Phdr;
-
-#define PT_LOAD 1 /* Loadable program segment */
-
-#endif /* HAVE_ELF_H */
-
-#if defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME
-const char *libusb_error_name(int error_code);
-#endif /* defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME */
-
-#endif /* OPENOCD_HELPER_REPLACEMENTS_H */
diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl
deleted file mode 100644
index 4ca2cab..0000000
--- a/src/helper/startup.tcl
+++ /dev/null
@@ -1,66 +0,0 @@
-# Defines basic Tcl procs that must exist for OpenOCD scripts to work.
-#
-# Embedded into OpenOCD executable
-#
-
-
-# We need to explicitly redirect this to the OpenOCD command
-# as Tcl defines the exit proc
-proc exit {} {
- ocd_throw exit
-}
-
-# All commands are registered with an 'ocd_' prefix, while the "real"
-# command is a wrapper that calls this function. Its primary purpose is
-# to discard 'handler' command output,
-proc ocd_bouncer {name args} {
- set cmd [format "ocd_%s" $name]
- set type [eval ocd_command type $cmd $args]
- set errcode error
- if {$type == "native"} {
- return [eval $cmd $args]
- } else {if {$type == "simple"} {
- set errcode [catch {eval $cmd $args}]
- if {$errcode == 0} {
- return ""
- } else {
- # 'classic' commands output error message as part of progress output
- set errmsg ""
- }
- } else {if {$type == "group"} {
- catch {eval ocd_usage $name $args}
- set errmsg [format "%s: command requires more arguments" \
- [concat $name " " $args]]
- } else {
- set errmsg [format "invalid subcommand \"%s\"" $args]
- }}}
- return -code $errcode $errmsg
-}
-
-# Try flipping / and \ to find file if the filename does not
-# match the precise spelling
-proc find {filename} {
- if {[catch {ocd_find $filename} t]==0} {
- return $t
- }
- if {[catch {ocd_find [string map {\ /} $filename} t]==0} {
- return $t
- }
- if {[catch {ocd_find [string map {/ \\} $filename} t]==0} {
- return $t
- }
- # make sure error message matches original input string
- return -code error "Can't find $filename"
-}
-add_usage_text find "<file>"
-add_help_text find "print full path to file according to OpenOCD search rules"
-
-# Find and run a script
-proc script {filename} {
- uplevel #0 [list source [find $filename]]
-}
-add_help_text script "filename of OpenOCD script (tcl) to run"
-add_usage_text script "<file>"
-
-#########
-
diff --git a/src/helper/system.h b/src/helper/system.h
deleted file mode 100644
index 97b3443..0000000
--- a/src/helper/system.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007-2008 by Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_SYSTEM_H
-#define OPENOCD_HELPER_SYSTEM_H
-
-/* standard C library header files */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-
-/* +++ AC_HEADER_TIME +++ */
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-/* --- AC_HEADER_TIME --- */
-
-/* +++ platform specific headers +++ */
-#ifdef _WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
-/* --- platform specific headers --- */
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
-
-#ifdef __ECOS
-/* missing from eCos */
-#ifndef EFAULT
-#define EFAULT 14 /* Bad address */
-#endif
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h> /* select, FD_SET and friends (POSIX.1-2001) */
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h> /* for MIN/MAX macros */
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifndef true
-#define true 1
-#define false 0
-#endif
-
-#endif /* OPENOCD_HELPER_SYSTEM_H */
diff --git a/src/helper/time_support.c b/src/helper/time_support.c
deleted file mode 100644
index 8337e73..0000000
--- a/src/helper/time_support.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "time_support.h"
-
-/* calculate difference between two struct timeval values */
-int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
-{
- if (x->tv_usec < y->tv_usec) {
- int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
- y->tv_usec -= 1000000 * nsec;
- y->tv_sec += nsec;
- }
- if (x->tv_usec - y->tv_usec > 1000000) {
- int nsec = (x->tv_usec - y->tv_usec) / 1000000;
- y->tv_usec += 1000000 * nsec;
- y->tv_sec -= nsec;
- }
-
- result->tv_sec = x->tv_sec - y->tv_sec;
- result->tv_usec = x->tv_usec - y->tv_usec;
-
- /* Return 1 if result is negative. */
- return x->tv_sec < y->tv_sec;
-}
-
-int timeval_add_time(struct timeval *result, long sec, long usec)
-{
- result->tv_sec += sec;
- result->tv_usec += usec;
-
- while (result->tv_usec > 1000000) {
- result->tv_usec -= 1000000;
- result->tv_sec++;
- }
-
- return 0;
-}
-
-int duration_start(struct duration *duration)
-{
- return gettimeofday(&duration->start, NULL);
-}
-
-int duration_measure(struct duration *duration)
-{
- struct timeval end;
- int retval = gettimeofday(&end, NULL);
- if (0 == retval)
- timeval_subtract(&duration->elapsed, &end, &duration->start);
- return retval;
-}
-
-float duration_elapsed(const struct duration *duration)
-{
- float t = duration->elapsed.tv_sec;
- t += (float)duration->elapsed.tv_usec / 1000000.0;
- return t;
-}
-
-float duration_kbps(const struct duration *duration, size_t count)
-{
- return count / (1024.0 * duration_elapsed(duration));
-}
diff --git a/src/helper/time_support.h b/src/helper/time_support.h
deleted file mode 100644
index 58c8c48..0000000
--- a/src/helper/time_support.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_TIME_SUPPORT_H
-#define OPENOCD_HELPER_TIME_SUPPORT_H
-
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
-int timeval_add_time(struct timeval *result, long sec, long usec);
-
-/** @returns gettimeofday() timeval as 64-bit in ms */
-int64_t timeval_ms(void);
-
-struct duration {
- struct timeval start;
- struct timeval elapsed;
-};
-
-/** Update the duration->start field to start the @a duration measurement. */
-int duration_start(struct duration *duration);
-/** Update the duration->elapsed field to finish the @a duration measurment. */
-int duration_measure(struct duration *duration);
-
-/** @returns Elapsed time in seconds. */
-float duration_elapsed(const struct duration *duration);
-/** @returns KB/sec for the elapsed @a duration and @a count bytes. */
-float duration_kbps(const struct duration *duration, size_t count);
-
-#endif /* OPENOCD_HELPER_TIME_SUPPORT_H */
diff --git a/src/helper/time_support_common.c b/src/helper/time_support_common.c
deleted file mode 100644
index b733c27..0000000
--- a/src/helper/time_support_common.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "time_support.h"
-
-/* simple and low overhead fetching of ms counter. Use only
- * the difference between ms counters returned from this fn.
- */
-int64_t timeval_ms(void)
-{
- struct timeval now;
- int retval = gettimeofday(&now, NULL);
- if (retval < 0)
- return retval;
- return (int64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
-}
diff --git a/src/helper/types.h b/src/helper/types.h
deleted file mode 100644
index 1854ba8..0000000
--- a/src/helper/types.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_TYPES_H
-#define OPENOCD_HELPER_TYPES_H
-
-#include <stddef.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#ifdef HAVE_STDBOOL_H
-#include <stdbool.h>
-#else /* HAVE_STDBOOL_H */
-#define __bool_true_false_are_defined 1
-
-#ifndef HAVE__BOOL
-#ifndef __cplusplus
-
-#define false 0
-#define true 1
-
-typedef int _Bool;
-#else
-typedef bool _Bool;
-#endif /* __cplusplus */
-#endif /* HAVE__BOOL */
-
-#define bool _Bool
-
-#endif /* HAVE_STDBOOL_H */
-
-/// turns a macro argument into a string constant
-#define stringify(s) __stringify(s)
-#define __stringify(s) #s
-
-
-/**
- * Compute the number of elements of a variable length array.
- * <code>
- * const char *strs[] = { "a", "b", "c" };
- * unsigned num_strs = ARRAY_SIZE(strs);
- * </code>
- */
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
-
-
-/**
- * Cast a member of a structure out to the containing structure.
- * @param ptr The pointer to the member.
- * @param type The type of the container struct this is embedded in.
- * @param member The name of the member within the struct.
- *
- * This is a mechanism which is used throughout the Linux kernel.
- */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (void *) ( (char *)__mptr - offsetof(type,member) ) );})
-
-
-/**
- * Rounds @c m up to the nearest multiple of @c n using division.
- * @param m The value to round up to @c n.
- * @param n Round @c m up to a multiple of this number.
- * @returns The rounded integer value.
- */
-#define DIV_ROUND_UP(m, n) (((m) + (n) - 1) / (n))
-
-
-/* DANGER!!!! here be dragons!
- *
- * Leave these fn's as byte accesses because it is safe
- * across architectures. Clever usage of 32 bit access
- * will create problems on some hosts.
- *
- * Note that the "buf" pointer in memory is probably unaligned.
- *
- * Were these functions to be re-written to take a 32 bit wide or 16 bit wide
- * memory access shortcut, then on some CPU's, i.e. ARM7, the 2 lsbytes of the address are
- * ignored for 32 bit access, whereas on other CPU's a 32 bit wide unaligned memory access
- * will cause an exception, and lastly on x86, an unaligned "greater than bytewide"
- * memory access works as if aligned. So what follows below will work for all
- * platforms and gives the compiler leeway to do its own platform specific optimizations.
- *
- * Again, note that the "buf" pointer in memory is probably unaligned.
- */
-
-static inline uint64_t le_to_h_u64(const uint8_t *buf)
-{
- return (uint64_t)((uint64_t)buf[0] |
- (uint64_t)buf[1] << 8 |
- (uint64_t)buf[2] << 16 |
- (uint64_t)buf[3] << 24 |
- (uint64_t)buf[4] << 32 |
- (uint64_t)buf[5] << 40 |
- (uint64_t)buf[6] << 48 |
- (uint64_t)buf[7] << 56);
-}
-
-static inline uint32_t le_to_h_u32(const uint8_t* buf)
-{
- return (uint32_t)(buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24);
-}
-
-static inline uint32_t le_to_h_u24(const uint8_t* buf)
-{
- return (uint32_t)(buf[0] | buf[1] << 8 | buf[2] << 16);
-}
-
-static inline uint16_t le_to_h_u16(const uint8_t* buf)
-{
- return (uint16_t)(buf[0] | buf[1] << 8);
-}
-
-static inline uint64_t be_to_h_u64(const uint8_t *buf)
-{
- return (uint64_t)((uint64_t)buf[7] |
- (uint64_t)buf[6] << 8 |
- (uint64_t)buf[5] << 16 |
- (uint64_t)buf[4] << 24 |
- (uint64_t)buf[3] << 32 |
- (uint64_t)buf[2] << 40 |
- (uint64_t)buf[1] << 48 |
- (uint64_t)buf[0] << 56);
-}
-
-static inline uint32_t be_to_h_u32(const uint8_t* buf)
-{
- return (uint32_t)(buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24);
-}
-
-static inline uint32_t be_to_h_u24(const uint8_t* buf)
-{
- return (uint32_t)(buf[2] | buf[1] << 8 | buf[0] << 16);
-}
-
-static inline uint16_t be_to_h_u16(const uint8_t* buf)
-{
- return (uint16_t)(buf[1] | buf[0] << 8);
-}
-
-static inline void h_u64_to_le(uint8_t *buf, int64_t val)
-{
- buf[7] = (uint8_t) (val >> 56);
- buf[6] = (uint8_t) (val >> 48);
- buf[5] = (uint8_t) (val >> 40);
- buf[4] = (uint8_t) (val >> 32);
- buf[3] = (uint8_t) (val >> 24);
- buf[2] = (uint8_t) (val >> 16);
- buf[1] = (uint8_t) (val >> 8);
- buf[0] = (uint8_t) (val >> 0);
-}
-
-static inline void h_u64_to_be(uint8_t *buf, int64_t val)
-{
- buf[0] = (uint8_t) (val >> 56);
- buf[1] = (uint8_t) (val >> 48);
- buf[2] = (uint8_t) (val >> 40);
- buf[3] = (uint8_t) (val >> 32);
- buf[4] = (uint8_t) (val >> 24);
- buf[5] = (uint8_t) (val >> 16);
- buf[6] = (uint8_t) (val >> 8);
- buf[7] = (uint8_t) (val >> 0);
-}
-
-static inline void h_u32_to_le(uint8_t* buf, int val)
-{
- buf[3] = (uint8_t) (val >> 24);
- buf[2] = (uint8_t) (val >> 16);
- buf[1] = (uint8_t) (val >> 8);
- buf[0] = (uint8_t) (val >> 0);
-}
-
-static inline void h_u32_to_be(uint8_t* buf, int val)
-{
- buf[0] = (uint8_t) (val >> 24);
- buf[1] = (uint8_t) (val >> 16);
- buf[2] = (uint8_t) (val >> 8);
- buf[3] = (uint8_t) (val >> 0);
-}
-
-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_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_t* buf, int val)
-{
- buf[1] = (uint8_t) (val >> 8);
- buf[0] = (uint8_t) (val >> 0);
-}
-
-static inline void h_u16_to_be(uint8_t* buf, int val)
-{
- buf[0] = (uint8_t) (val >> 8);
- buf[1] = (uint8_t) (val >> 0);
-}
-
-/**
- * Byte-swap buffer 16-bit.
- *
- * Len must be even, dst and src must be either the same or non-overlapping.
- *
- * @param dst Destination buffer.
- * @param src Source buffer.
- * @param len Length of source (and destination) buffer, in bytes.
- */
-static inline void buf_bswap16(uint8_t *dst, const uint8_t *src, size_t len)
-{
- assert(len % 2 == 0);
- assert(dst == src || dst + len <= src || src + len <= dst);
-
- for (size_t n = 0; n < len; n += 2) {
- uint16_t x = be_to_h_u16(src + n);
- h_u16_to_le(dst + n, x);
- }
-}
-
-/**
- * Byte-swap buffer 32-bit.
- *
- * Len must be divisible by four, dst and src must be either the same or non-overlapping.
- *
- * @param dst Destination buffer.
- * @param src Source buffer.
- * @param len Length of source (and destination) buffer, in bytes.
- */
-static inline void buf_bswap32(uint8_t *dst, const uint8_t *src, size_t len)
-{
- assert(len % 4 == 0);
- assert(dst == src || dst + len <= src || src + len <= dst);
-
- for (size_t n = 0; n < len; n += 4) {
- uint32_t x = be_to_h_u32(src + n);
- h_u32_to_le(dst + n, x);
- }
-}
-
-/**
- * Calculate the (even) parity of a 32-bit datum.
- * @param x The datum.
- * @return 1 if the number of set bits in x is odd, 0 if it is even.
- */
-static inline int parity_u32(uint32_t x)
-{
-#ifdef __GNUC__
- return __builtin_parityl(x);
-#else
- x ^= x >> 16;
- x ^= x >> 8;
- x ^= x >> 4;
- x ^= x >> 2;
- x ^= x >> 1;
- return x & 1;
-#endif
-}
-
-#if defined(__ECOS)
-
-/* eCos plain lacks these definition... A series of upstream patches
- * could probably repair it, but it seems like too much work to be
- * worth it.
- */
-
-#if !defined(_STDINT_H)
-#define PRIx32 "x"
-#define PRId32 "d"
-#define SCNx32 "x"
-#define PRIi32 "i"
-#define PRIu32 "u"
-#define PRId8 PRId32
-#define SCNx64 "llx"
-#define PRIx64 "llx"
-
-typedef CYG_ADDRWORD intptr_t;
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-#define INT8_MAX 0x7f
-#define INT8_MIN (-INT8_MAX - 1)
-# define UINT8_MAX (255)
-#define INT16_MAX 0x7fff
-#define INT16_MIN (-INT16_MAX - 1)
-# define UINT16_MAX (65535)
-#define INT32_MAX 0x7fffffffL
-#define INT32_MIN (-INT32_MAX - 1L)
-# define UINT32_MAX (4294967295U)
-#define INT64_MAX 0x7fffffffffffffffLL
-#define INT64_MIN (-INT64_MAX - 1LL)
-#define UINT64_MAX (__CONCAT(INT64_MAX, U) * 2ULL + 1ULL)
-#endif
-
- #ifndef LLONG_MAX
- #define ULLONG_MAX UINT64_C(0xFFFFFFFFFFFFFFFF)
- #define LLONG_MAX INT64_C(0x7FFFFFFFFFFFFFFF)
- #define LLONG_MIN ULLONG_MAX
- #endif
-
-
-#define ULLONG_MAX 18446744073709551615
-
-/* C99, eCos is C90 compliant (with bits of C99) */
-#define isblank(c) ((c) == ' ' || (c) == '\t')
-
-
-#endif
-
-#endif /* OPENOCD_HELPER_TYPES_H */
diff --git a/src/helper/update_jep106.pl b/src/helper/update_jep106.pl
deleted file mode 100755
index caec066..0000000
--- a/src/helper/update_jep106.pl
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use File::Basename;
-
-if (@ARGV != 1) {
- die "Usage: $0 <JEP106 PDF document>\n\n"
- . "Convert the JEDEC document containing manufacturer identification codes\n"
- . "to an array initializer suitable for incusion into jep106.c. The latest\n"
- . "version of the document can be found here:\n"
- . "http://www.jedec.org/standards-documents/results/jep106\n";
-};
-
-my $outfile = dirname($0) . "/jep106.inc";
-
-open(my $out, ">", $outfile) || die "Cannot open $outfile: $!\n";
-open(my $pdftotext, "pdftotext -layout $ARGV[0] - |") || die "Cannot fork: $!\n";
-
-print $out "/* Autogenerated with " . basename($0) . "*/\n";
-
-my $bank = -1;
-
-while (<$pdftotext>) {
- if (/^[0-9]+[[:space:]]+(.*?)[[:space:]]+([01][[:space:]]+){8}([0-9A-F]{2})$/) {
- if ($3 eq "01") {
- $bank++
- }
- my $id=sprintf("0x%02x",hex($3)&0x7f);
- print $out "[$bank][$id - 1] = \"$1\",\n";
- }
-}
-
-close $pdftotext || die "Error: $! $?\n";
-
-print $out "/* EOF */\n";
diff --git a/src/helper/util.c b/src/helper/util.c
deleted file mode 100644
index 56baf95..0000000
--- a/src/helper/util.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Øyvind Harboe *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* this file contains various functionality useful to standalone systems */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "log.h"
-#include "time_support.h"
-
-static int util_Jim_Command_ms(Jim_Interp *interp,
- int argc,
- Jim_Obj * const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
- return JIM_ERR;
- }
-
- /* Cast from 64 to 32 bit int works for 2's-compliment
- * when calculating differences*/
- Jim_SetResult(interp, Jim_NewIntObj(interp, (int)timeval_ms()));
-
- return JIM_OK;
-}
-
-static const struct command_registration util_command_handlers[] = {
- /* jim handlers */
- {
- .name = "ms",
- .mode = COMMAND_ANY,
- .jim_handler = util_Jim_Command_ms,
- .help =
- "Returns ever increasing milliseconds. Used to calculuate differences in time.",
- .usage = "",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int util_init(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, util_command_handlers);
-}
diff --git a/src/helper/util.h b/src/helper/util.h
deleted file mode 100644
index c9a11dd..0000000
--- a/src/helper/util.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Øyvind Harboe *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_HELPER_UTIL_H
-#define OPENOCD_HELPER_UTIL_H
-
-struct command_context;
-
-int util_init(struct command_context *cmd_ctx);
-
-#endif /* OPENOCD_HELPER_UTIL_H */
diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am
deleted file mode 100644
index db3e6ff..0000000
--- a/src/jtag/Makefile.am
+++ /dev/null
@@ -1,86 +0,0 @@
-include $(top_srcdir)/common.mk
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libjtag.la
-
-SUBDIRS =
-DRIVERFILES =
-libjtag_la_LIBADD =
-
-CLEANFILES =
-
-BUILT_SOURCES =
-
-BUILT_SOURCES += minidriver_imp.h
-CLEANFILES += minidriver_imp.h
-
-if MINIDRIVER
-
-if ZY1000
-DRIVERFILES += zy1000/zy1000.c
-JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000
-endif
-if MINIDRIVER_DUMMY
-DRIVERFILES += minidummy/minidummy.c commands.c
-JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy
-endif
-
-MINIDRIVER_IMP_DIR = $(srcdir)/minidriver
-
-jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h
- cp $< $@
-
-BUILT_SOURCES += jtag_minidriver.h
-
-CLEANFILES += jtag_minidriver.h
-
-else
-
-MINIDRIVER_IMP_DIR = $(srcdir)/drivers
-DRIVERFILES += commands.c
-
-if HLADAPTER
-SUBDIRS += hla
-libjtag_la_LIBADD += $(top_builddir)/src/jtag/hla/libocdhla.la
-endif
-
-if AICE
-SUBDIRS += aice
-libjtag_la_LIBADD += $(top_builddir)/src/jtag/aice/libocdaice.la
-endif
-
-SUBDIRS += drivers
-libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la
-
-
-endif
-
-# endif // MINIDRIVER
-
-minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h
- cp $< $@
-
-
-libjtag_la_SOURCES = \
- adapter.c \
- core.c \
- interface.c \
- interfaces.c \
- tcl.c \
- $(DRIVERFILES)
-
-noinst_HEADERS = \
- commands.h \
- driver.h \
- interface.h \
- interfaces.h \
- minidriver.h \
- jtag.h \
- minidriver/minidriver_imp.h \
- minidummy/jtag_minidriver.h \
- swd.h \
- tcl.h
-
-EXTRA_DIST = startup.tcl
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
deleted file mode 100644
index 5953de7..0000000
--- a/src/jtag/adapter.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag.h"
-#include "minidriver.h"
-#include "interface.h"
-#include "interfaces.h"
-#include <transport/transport.h>
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-/**
- * @file
- * Holds support for configuring debug adapters from TCl scripts.
- */
-
-extern struct jtag_interface *jtag_interface;
-const char * const jtag_only[] = { "jtag", NULL };
-
-static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
-
- /* return the name of the interface */
- /* TCL code might need to know the exact type... */
- /* FUTURE: we allow this as a means to "set" the interface. */
- if (goi.argc != 0) {
- Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
- return JIM_ERR;
- }
- const char *name = jtag_interface ? jtag_interface->name : NULL;
- Jim_SetResultString(goi.interp, name ? : "undefined", -1);
- return JIM_OK;
-}
-
-static int default_khz(int khz, int *jtag_speed)
-{
- LOG_ERROR("Translation from khz to jtag_speed not implemented");
- return ERROR_FAIL;
-}
-
-static int default_speed_div(int speed, int *khz)
-{
- LOG_ERROR("Translation from jtag_speed to khz not implemented");
- return ERROR_FAIL;
-}
-
-static int default_power_dropout(int *dropout)
-{
- *dropout = 0; /* by default we can't detect power dropout */
- return ERROR_OK;
-}
-
-static int default_srst_asserted(int *srst_asserted)
-{
- *srst_asserted = 0; /* by default we can't detect srst asserted */
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(interface_transport_command)
-{
- char **transports;
- int retval;
-
- retval = CALL_COMMAND_HANDLER(transport_list_parse, &transports);
- if (retval != ERROR_OK)
- return retval;
-
- retval = allow_transports(CMD_CTX, (const char **)transports);
-
- if (retval != ERROR_OK) {
- for (unsigned i = 0; transports[i]; i++)
- free(transports[i]);
- free(transports);
- }
- return retval;
-}
-
-COMMAND_HANDLER(handle_interface_list_command)
-{
- if (strcmp(CMD_NAME, "interface_list") == 0 && CMD_ARGC > 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- command_print(CMD_CTX, "The following debug interfaces are available:");
- for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) {
- const char *name = jtag_interfaces[i]->name;
- command_print(CMD_CTX, "%u: %s", i + 1, name);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_interface_command)
-{
- int retval;
-
- /* check whether the interface is already configured */
- if (jtag_interface) {
- LOG_WARNING("Interface already configured, ignoring");
- return ERROR_OK;
- }
-
- /* interface name is a mandatory argument */
- if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0')
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) {
- if (strcmp(CMD_ARGV[0], jtag_interfaces[i]->name) != 0)
- continue;
-
- if (NULL != jtag_interfaces[i]->commands) {
- retval = register_commands(CMD_CTX, NULL,
- jtag_interfaces[i]->commands);
- if (ERROR_OK != retval)
- return retval;
- }
-
- jtag_interface = jtag_interfaces[i];
-
- /* LEGACY SUPPORT ... adapter drivers must declare what
- * transports they allow. Until they all do so, assume
- * the legacy drivers are JTAG-only
- */
- if (!jtag_interface->transports)
- LOG_WARNING("Adapter driver '%s' did not declare "
- "which transports it allows; assuming "
- "legacy JTAG-only", jtag_interface->name);
- retval = allow_transports(CMD_CTX, jtag_interface->transports
- ? jtag_interface->transports : jtag_only);
- if (ERROR_OK != retval)
- return retval;
-
- if (jtag_interface->khz == NULL)
- jtag_interface->khz = default_khz;
- if (jtag_interface->speed_div == NULL)
- jtag_interface->speed_div = default_speed_div;
- if (jtag_interface->power_dropout == NULL)
- jtag_interface->power_dropout = default_power_dropout;
- if (jtag_interface->srst_asserted == NULL)
- jtag_interface->srst_asserted = default_srst_asserted;
-
- return ERROR_OK;
- }
-
- /* no valid interface was found (i.e. the configuration option,
- * didn't match one of the compiled-in interfaces
- */
- LOG_ERROR("The specified debug interface was not found (%s)",
- CMD_ARGV[0]);
- CALL_COMMAND_HANDLER(handle_interface_list_command);
- return ERROR_JTAG_INVALID_INTERFACE;
-}
-
-COMMAND_HANDLER(handle_reset_config_command)
-{
- int new_cfg = 0;
- int mask = 0;
-
- /* Original versions cared about the order of these tokens:
- * reset_config signals [combination [trst_type [srst_type]]]
- * They also clobbered the previous configuration even on error.
- *
- * Here we don't care about the order, and only change values
- * which have been explicitly specified.
- */
- for (; CMD_ARGC; CMD_ARGC--, CMD_ARGV++) {
- int tmp = 0;
- int m;
-
- /* gating */
- m = RESET_SRST_NO_GATING;
- if (strcmp(*CMD_ARGV, "srst_gates_jtag") == 0)
- /* default: don't use JTAG while SRST asserted */;
- else if (strcmp(*CMD_ARGV, "srst_nogate") == 0)
- tmp = RESET_SRST_NO_GATING;
- else
- m = 0;
- if (mask & m) {
- LOG_ERROR("extra reset_config %s spec (%s)",
- "gating", *CMD_ARGV);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- if (m)
- goto next;
-
- /* signals */
- m = RESET_HAS_TRST | RESET_HAS_SRST;
- if (strcmp(*CMD_ARGV, "none") == 0)
- tmp = RESET_NONE;
- else if (strcmp(*CMD_ARGV, "trst_only") == 0)
- tmp = RESET_HAS_TRST;
- else if (strcmp(*CMD_ARGV, "srst_only") == 0)
- tmp = RESET_HAS_SRST;
- else if (strcmp(*CMD_ARGV, "trst_and_srst") == 0)
- tmp = RESET_HAS_TRST | RESET_HAS_SRST;
- else
- m = 0;
- if (mask & m) {
- LOG_ERROR("extra reset_config %s spec (%s)",
- "signal", *CMD_ARGV);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- if (m)
- goto next;
-
- /* combination (options for broken wiring) */
- m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
- if (strcmp(*CMD_ARGV, "separate") == 0)
- /* separate reset lines - default */;
- else if (strcmp(*CMD_ARGV, "srst_pulls_trst") == 0)
- tmp |= RESET_SRST_PULLS_TRST;
- else if (strcmp(*CMD_ARGV, "trst_pulls_srst") == 0)
- tmp |= RESET_TRST_PULLS_SRST;
- else if (strcmp(*CMD_ARGV, "combined") == 0)
- tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
- else
- m = 0;
- if (mask & m) {
- LOG_ERROR("extra reset_config %s spec (%s)",
- "combination", *CMD_ARGV);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- if (m)
- goto next;
-
- /* trst_type (NOP without HAS_TRST) */
- m = RESET_TRST_OPEN_DRAIN;
- if (strcmp(*CMD_ARGV, "trst_open_drain") == 0)
- tmp |= RESET_TRST_OPEN_DRAIN;
- else if (strcmp(*CMD_ARGV, "trst_push_pull") == 0)
- /* push/pull from adapter - default */;
- else
- m = 0;
- if (mask & m) {
- LOG_ERROR("extra reset_config %s spec (%s)",
- "trst_type", *CMD_ARGV);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- if (m)
- goto next;
-
- /* srst_type (NOP without HAS_SRST) */
- m = RESET_SRST_PUSH_PULL;
- if (strcmp(*CMD_ARGV, "srst_push_pull") == 0)
- tmp |= RESET_SRST_PUSH_PULL;
- else if (strcmp(*CMD_ARGV, "srst_open_drain") == 0)
- /* open drain from adapter - default */;
- else
- m = 0;
- if (mask & m) {
- LOG_ERROR("extra reset_config %s spec (%s)",
- "srst_type", *CMD_ARGV);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- if (m)
- goto next;
-
- /* connect_type - only valid when srst_nogate */
- m = RESET_CNCT_UNDER_SRST;
- if (strcmp(*CMD_ARGV, "connect_assert_srst") == 0)
- tmp |= RESET_CNCT_UNDER_SRST;
- else if (strcmp(*CMD_ARGV, "connect_deassert_srst") == 0)
- /* connect normally - default */;
- else
- m = 0;
- if (mask & m) {
- LOG_ERROR("extra reset_config %s spec (%s)",
- "connect_type", *CMD_ARGV);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- if (m)
- goto next;
-
- /* caller provided nonsense; fail */
- LOG_ERROR("unknown reset_config flag (%s)", *CMD_ARGV);
- return ERROR_COMMAND_SYNTAX_ERROR;
-
-next:
- /* Remember the bits which were specified (mask)
- * and their new values (new_cfg).
- */
- mask |= m;
- new_cfg |= tmp;
- }
-
- /* clear previous values of those bits, save new values */
- if (mask) {
- int old_cfg = jtag_get_reset_config();
-
- old_cfg &= ~mask;
- new_cfg |= old_cfg;
- jtag_set_reset_config(new_cfg);
- } else
- new_cfg = jtag_get_reset_config();
-
- /*
- * Display the (now-)current reset mode
- */
- char *modes[6];
-
- /* minimal JTAG has neither SRST nor TRST (so that's the default) */
- switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
- case RESET_HAS_SRST:
- modes[0] = "srst_only";
- break;
- case RESET_HAS_TRST:
- modes[0] = "trst_only";
- break;
- case RESET_TRST_AND_SRST:
- modes[0] = "trst_and_srst";
- break;
- default:
- modes[0] = "none";
- break;
- }
-
- /* normally SRST and TRST are decoupled; but bugs happen ... */
- switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) {
- case RESET_SRST_PULLS_TRST:
- modes[1] = "srst_pulls_trst";
- break;
- case RESET_TRST_PULLS_SRST:
- modes[1] = "trst_pulls_srst";
- break;
- case RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST:
- modes[1] = "combined";
- break;
- default:
- modes[1] = "separate";
- break;
- }
-
- /* TRST-less connectors include Altera, Xilinx, and minimal JTAG */
- if (new_cfg & RESET_HAS_TRST) {
- if (new_cfg & RESET_TRST_OPEN_DRAIN)
- modes[3] = " trst_open_drain";
- else
- modes[3] = " trst_push_pull";
- } else
- modes[3] = "";
-
- /* SRST-less connectors include TI-14, Xilinx, and minimal JTAG */
- if (new_cfg & RESET_HAS_SRST) {
- if (new_cfg & RESET_SRST_NO_GATING)
- modes[2] = " srst_nogate";
- else
- modes[2] = " srst_gates_jtag";
-
- if (new_cfg & RESET_SRST_PUSH_PULL)
- modes[4] = " srst_push_pull";
- else
- modes[4] = " srst_open_drain";
-
- if (new_cfg & RESET_CNCT_UNDER_SRST)
- modes[5] = " connect_assert_srst";
- else
- modes[5] = " connect_deassert_srst";
- } else {
- modes[2] = "";
- modes[4] = "";
- modes[5] = "";
- }
-
- command_print(CMD_CTX, "%s %s%s%s%s%s",
- modes[0], modes[1],
- modes[2], modes[3], modes[4], modes[5]);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (CMD_ARGC == 1) {
- unsigned delay;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
-
- jtag_set_nsrst_delay(delay);
- }
- command_print(CMD_CTX, "adapter_nsrst_delay: %u", jtag_get_nsrst_delay());
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (CMD_ARGC == 1) {
- unsigned width;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], width);
-
- jtag_set_nsrst_assert_width(width);
- }
- command_print(CMD_CTX, "adapter_nsrst_assert_width: %u", jtag_get_nsrst_assert_width());
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_adapter_khz_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int retval = ERROR_OK;
- if (CMD_ARGC == 1) {
- unsigned khz = 0;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz);
-
- retval = jtag_config_khz(khz);
- if (ERROR_OK != retval)
- return retval;
- }
-
- int cur_speed = jtag_get_speed_khz();
- retval = jtag_get_speed_readable(&cur_speed);
- if (ERROR_OK != retval)
- return retval;
-
- if (cur_speed)
- command_print(CMD_CTX, "adapter speed: %d kHz", cur_speed);
- else
- command_print(CMD_CTX, "adapter speed: RCLK - adaptive");
-
- return retval;
-}
-
-static const struct command_registration interface_command_handlers[] = {
- {
- .name = "adapter_khz",
- .handler = handle_adapter_khz_command,
- .mode = COMMAND_ANY,
- .help = "With an argument, change to the specified maximum "
- "jtag speed. For JTAG, 0 KHz signifies adaptive "
- " clocking. "
- "With or without argument, display current setting.",
- .usage = "[khz]",
- },
- {
- .name = "adapter_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,
- .mode = COMMAND_ANY,
- .help = "delay after deasserting SRST in ms",
- .usage = "[milliseconds]",
- },
- {
- .name = "adapter_nsrst_assert_width",
- .handler = handle_adapter_nsrst_assert_width_command,
- .mode = COMMAND_ANY,
- .help = "delay after asserting SRST in ms",
- .usage = "[milliseconds]",
- },
- {
- .name = "interface",
- .handler = handle_interface_command,
- .mode = COMMAND_CONFIG,
- .help = "Select a debug adapter interface (driver)",
- .usage = "driver_name",
- },
- {
- .name = "interface_transports",
- .handler = interface_transport_command,
- .mode = COMMAND_CONFIG,
- .help = "Declare transports the interface supports.",
- .usage = "transport ... ",
- },
- {
- .name = "interface_list",
- .handler = handle_interface_list_command,
- .mode = COMMAND_ANY,
- .help = "List all built-in debug adapter interfaces (drivers)",
- },
- {
- .name = "reset_config",
- .handler = handle_reset_config_command,
- .mode = COMMAND_ANY,
- .help = "configure adapter reset behavior",
- .usage = "[none|trst_only|srst_only|trst_and_srst] "
- "[srst_pulls_trst|trst_pulls_srst|combined|separate] "
- "[srst_gates_jtag|srst_nogate] "
- "[trst_push_pull|trst_open_drain] "
- "[srst_push_pull|srst_open_drain] "
- "[connect_deassert_srst|connect_assert_srst]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/**
- * Register the commands which deal with arbitrary debug adapter drivers.
- *
- * @todo Remove internal assumptions that all debug adapters use JTAG for
- * transport. Various types and data structures are not named generically.
- */
-int interface_register_commands(struct command_context *ctx)
-{
- return register_commands(ctx, NULL, interface_command_handlers);
-}
diff --git a/src/jtag/aice/Makefile.am b/src/jtag/aice/Makefile.am
deleted file mode 100644
index 7b9469d..0000000
--- a/src/jtag/aice/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-include $(top_srcdir)/common.mk
-
-AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS)
-
-noinst_LTLIBRARIES = libocdaice.la
-
-libocdaice_la_SOURCES = \
- $(AICEFILES)
-
-AICEFILES =
-
-if AICE
-AICEFILES += aice_transport.c
-AICEFILES += aice_interface.c
-AICEFILES += aice_port.c
-AICEFILES += aice_usb.c
-AICEFILES += aice_pipe.c
-endif
-
-noinst_HEADERS = \
- aice_transport.h \
- aice_interface.h \
- aice_port.h \
- aice_usb.h \
- aice_pipe.h
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/jtag/aice/aice_interface.c b/src/jtag/aice/aice_interface.c
deleted file mode 100644
index 20f1f07..0000000
--- a/src/jtag/aice/aice_interface.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <transport/transport.h>
-#include <target/target.h>
-#include <jtag/aice/aice_transport.h>
-#include <jtag/drivers/libusb_common.h>
-#include "aice_usb.h"
-
-#define AICE_KHZ_TO_SPEED_MAP_SIZE 16
-static const int aice_khz_to_speed_map[AICE_KHZ_TO_SPEED_MAP_SIZE] = {
- 30000,
- 15000,
- 7500,
- 3750,
- 1875,
- 937,
- 468,
- 234,
- 48000,
- 24000,
- 12000,
- 6000,
- 3000,
- 1500,
- 750,
- 375,
-};
-
-static const struct aice_port *aice_port;
-static struct aice_port_param_s param;
-static uint32_t retry_times;
-static uint32_t count_to_check_dbger;
-
-/***************************************************************************/
-/* External interface implementation */
-static uint32_t aice_target_id_codes[AICE_MAX_NUM_CORE];
-static uint8_t aice_num_of_target_id_codes;
-
-/***************************************************************************/
-/* AICE operations */
-int aice_init_targets(void)
-{
- int res;
- struct target *target;
- struct aice_port_s *aice;
-
- LOG_DEBUG("aice_init_targets");
-
- if (aice_num_of_target_id_codes == 0) {
- res = aice_port->api->idcode(aice_target_id_codes, &aice_num_of_target_id_codes);
- if (res != ERROR_OK) {
- LOG_ERROR("<-- TARGET ERROR! Failed to identify AndesCore "
- "JTAG Manufacture ID in the JTAG scan chain. "
- "Failed to access EDM registers. -->");
- return res;
- }
- }
-
- for (target = all_targets; target; target = target->next) {
- target->tap->idcode = aice_target_id_codes[target->tap->abs_chain_position];
-
- unsigned ii, limit = target->tap->expected_ids_cnt;
- int found = 0;
-
- for (ii = 0; ii < limit; ii++) {
- uint32_t expected = target->tap->expected_ids[ii];
-
- /* treat "-expected-id 0" as a "don't-warn" wildcard */
- if (!expected || (target->tap->idcode == expected)) {
- found = 1;
- break;
- }
- }
-
- if (found == 0) {
- LOG_ERROR
- ("aice_init_targets: target not found: idcode: %" PRIx32,
- target->tap->idcode);
- return ERROR_FAIL;
- }
-
- aice = calloc(1, sizeof(struct aice_port_s));
- aice->port = aice_port;
- aice->coreid = target->tap->abs_chain_position;
-
- target->tap->priv = aice;
- target->tap->hasidcode = 1;
- }
-
- return ERROR_OK;
-}
-
-/***************************************************************************/
-/* End of External interface implementation */
-
-/* initial aice
- * 1. open usb
- * 2. get/show version number
- * 3. reset
- */
-static int aice_init(void)
-{
- if (ERROR_OK != aice_port->api->open(&param)) {
- LOG_ERROR("Cannot find AICE Interface! Please check "
- "connection and permissions.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- aice_port->api->set_retry_times(retry_times);
- aice_port->api->set_count_to_check_dbger(count_to_check_dbger);
-
- LOG_INFO("AICE JTAG Interface ready");
-
- return ERROR_OK;
-}
-
-/* cleanup aice resource
- * close usb
- */
-static int aice_quit(void)
-{
- aice_port->api->close();
- return ERROR_OK;
-}
-
-static int aice_execute_reset(struct jtag_command *cmd)
-{
- static int last_trst;
- int retval = ERROR_OK;
-
- DEBUG_JTAG_IO("reset trst: %d", cmd->cmd.reset->trst);
-
- if (cmd->cmd.reset->trst != last_trst) {
- if (cmd->cmd.reset->trst)
- retval = aice_port->api->reset();
-
- last_trst = cmd->cmd.reset->trst;
- }
-
- return retval;
-}
-
-static int aice_execute_command(struct jtag_command *cmd)
-{
- int retval;
-
- switch (cmd->type) {
- case JTAG_RESET:
- retval = aice_execute_reset(cmd);
- break;
- default:
- retval = ERROR_OK;
- break;
- }
- return retval;
-}
-
-/* aice has no need to implement jtag execution model
-*/
-static int aice_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
- int retval;
-
- retval = ERROR_OK;
-
- while (cmd) {
- if (aice_execute_command(cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
-
- cmd = cmd->next;
- }
-
- return retval;
-}
-
-/* set jtag frequency(base frequency/frequency divider) to your jtag adapter */
-static int aice_speed(int speed)
-{
- return aice_port->api->set_jtag_clock(speed);
-}
-
-/* convert jtag adapter frequency(base frequency/frequency divider) to
- * human readable KHz value */
-static int aice_speed_div(int speed, int *khz)
-{
- *khz = aice_khz_to_speed_map[speed];
-
- return ERROR_OK;
-}
-
-/* convert human readable KHz value to jtag adapter frequency
- * (base frequency/frequency divider) */
-static int aice_khz(int khz, int *jtag_speed)
-{
- int i;
- for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++) {
- if (khz == aice_khz_to_speed_map[i]) {
- if (8 <= i)
- *jtag_speed = i | AICE_TCK_CONTROL_TCK3048;
- else
- *jtag_speed = i;
- break;
- }
- }
-
- if (i == AICE_KHZ_TO_SPEED_MAP_SIZE) {
- LOG_INFO("No support the jtag clock: %d", khz);
- LOG_INFO("Supported jtag clocks are:");
-
- for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++)
- LOG_INFO("* %d", aice_khz_to_speed_map[i]);
-
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-/***************************************************************************/
-/* Command handlers */
-COMMAND_HANDLER(aice_handle_aice_info_command)
-{
- LOG_DEBUG("aice_handle_aice_info_command");
-
- command_print(CMD_CTX, "Description: %s", param.device_desc);
- command_print(CMD_CTX, "Serial number: %s", param.serial);
- if (strncmp(aice_port->name, "aice_pipe", 9) == 0)
- command_print(CMD_CTX, "Adapter: %s", param.adapter_name);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(aice_handle_aice_port_command)
-{
- LOG_DEBUG("aice_handle_aice_port_command");
-
- if (CMD_ARGC != 1) {
- LOG_ERROR("Need exactly one argument to 'aice port'");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- for (const struct aice_port *l = aice_port_get_list(); l->name; l++) {
- if (strcmp(l->name, CMD_ARGV[0]) == 0) {
- aice_port = l;
- return ERROR_OK;
- }
- }
-
- LOG_ERROR("No AICE port '%s' found", CMD_ARGV[0]);
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(aice_handle_aice_desc_command)
-{
- LOG_DEBUG("aice_handle_aice_desc_command");
-
- if (CMD_ARGC == 1)
- param.device_desc = strdup(CMD_ARGV[0]);
- else
- LOG_ERROR("expected exactly one argument to aice desc <description>");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(aice_handle_aice_serial_command)
-{
- LOG_DEBUG("aice_handle_aice_serial_command");
-
- if (CMD_ARGC == 1)
- param.serial = strdup(CMD_ARGV[0]);
- else
- LOG_ERROR("expected exactly one argument to aice serial <serial-number>");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(aice_handle_aice_vid_pid_command)
-{
- LOG_DEBUG("aice_handle_aice_vid_pid_command");
-
- if (CMD_ARGC != 2) {
- LOG_WARNING("ignoring extra IDs in aice vid_pid (maximum is 1 pair)");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], param.vid);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], param.pid);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(aice_handle_aice_adapter_command)
-{
- LOG_DEBUG("aice_handle_aice_adapter_command");
-
- if (CMD_ARGC == 1)
- param.adapter_name = strdup(CMD_ARGV[0]);
- else
- LOG_ERROR("expected exactly one argument to aice adapter <adapter-name>");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(aice_handle_aice_retry_times_command)
-{
- LOG_DEBUG("aice_handle_aice_retry_times_command");
-
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], retry_times);
- else
- LOG_ERROR("expected exactly one argument to aice retry_times <num_of_retry>");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(aice_handle_aice_count_to_check_dbger_command)
-{
- LOG_DEBUG("aice_handle_aice_count_to_check_dbger_command");
-
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], count_to_check_dbger);
- else
- LOG_ERROR("expected exactly one argument to aice count_to_check_dbger "
- "<count_of_checking>");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(aice_handle_aice_custom_srst_script_command)
-{
- LOG_DEBUG("aice_handle_aice_custom_srst_script_command");
-
- if (CMD_ARGC > 0) {
- aice_port->api->set_custom_srst_script(CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(aice_handle_aice_custom_trst_script_command)
-{
- LOG_DEBUG("aice_handle_aice_custom_trst_script_command");
-
- if (CMD_ARGC > 0) {
- aice_port->api->set_custom_trst_script(CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(aice_handle_aice_custom_restart_script_command)
-{
- LOG_DEBUG("aice_handle_aice_custom_restart_script_command");
-
- if (CMD_ARGC > 0) {
- aice_port->api->set_custom_restart_script(CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(aice_handle_aice_reset_command)
-{
- LOG_DEBUG("aice_handle_aice_reset_command");
-
- return aice_port->api->reset();
-}
-
-
-static const struct command_registration aice_subcommand_handlers[] = {
- {
- .name = "info",
- .handler = &aice_handle_aice_info_command,
- .mode = COMMAND_EXEC,
- .help = "show aice info",
- .usage = "aice info",
- },
- {
- .name = "port",
- .handler = &aice_handle_aice_port_command,
- .mode = COMMAND_CONFIG,
- .help = "set the port of the AICE",
- .usage = "aice port ['aice_pipe'|'aice_usb']",
- },
- {
- .name = "desc",
- .handler = &aice_handle_aice_desc_command,
- .mode = COMMAND_CONFIG,
- .help = "set the aice device description",
- .usage = "aice desc [desciption string]",
- },
- {
- .name = "serial",
- .handler = &aice_handle_aice_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the AICE device",
- .usage = "aice serial [serial string]",
- },
- {
- .name = "vid_pid",
- .handler = &aice_handle_aice_vid_pid_command,
- .mode = COMMAND_CONFIG,
- .help = "the vendor and product ID of the AICE device",
- .usage = "aice vid_pid (vid pid)*",
- },
- {
- .name = "adapter",
- .handler = &aice_handle_aice_adapter_command,
- .mode = COMMAND_CONFIG,
- .help = "set the file name of adapter",
- .usage = "aice adapter [adapter name]",
- },
- {
- .name = "retry_times",
- .handler = &aice_handle_aice_retry_times_command,
- .mode = COMMAND_CONFIG,
- .help = "set retry times as AICE timeout",
- .usage = "aice retry_times num_of_retry",
- },
- {
- .name = "count_to_check_dbger",
- .handler = &aice_handle_aice_count_to_check_dbger_command,
- .mode = COMMAND_CONFIG,
- .help = "set retry times as checking $DBGER status",
- .usage = "aice count_to_check_dbger count_of_checking",
- },
- {
- .name = "custom_srst_script",
- .handler = &aice_handle_aice_custom_srst_script_command,
- .mode = COMMAND_CONFIG,
- .usage = "custom_srst_script script_file_name",
- .help = "set custom srst script",
- },
- {
- .name = "custom_trst_script",
- .handler = &aice_handle_aice_custom_trst_script_command,
- .mode = COMMAND_CONFIG,
- .usage = "custom_trst_script script_file_name",
- .help = "set custom trst script",
- },
- {
- .name = "custom_restart_script",
- .handler = &aice_handle_aice_custom_restart_script_command,
- .mode = COMMAND_CONFIG,
- .usage = "custom_restart_script script_file_name",
- .help = "set custom restart script",
- },
- {
- .name = "reset",
- .handler = &aice_handle_aice_reset_command,
- .mode = COMMAND_EXEC,
- .usage = "aice reset",
- .help = "reset AICE",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration aice_command_handlers[] = {
- {
- .name = "aice",
- .mode = COMMAND_ANY,
- .help = "perform aice management",
- .usage = "aice [subcommand]",
- .chain = aice_subcommand_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-/***************************************************************************/
-/* End of Command handlers */
-
-struct jtag_interface aice_interface = {
- .name = "aice",
- .commands = aice_command_handlers,
- .transports = aice_transports,
- .init = aice_init,
- .quit = aice_quit,
- .execute_queue = aice_execute_queue,
- .speed = aice_speed, /* set interface speed */
- .speed_div = aice_speed_div, /* return readable value */
- .khz = aice_khz, /* convert khz to interface speed value */
-};
diff --git a/src/jtag/aice/aice_interface.h b/src/jtag/aice/aice_interface.h
deleted file mode 100644
index 0e3f108..0000000
--- a/src/jtag/aice/aice_interface.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_AICE_AICE_INTERFACE_H
-#define OPENOCD_JTAG_AICE_AICE_INTERFACE_H
-
-struct aice_interface_param_s {
- /** */
- const char *device_desc;
- /** */
- const char *serial;
- /** */
- uint16_t vid;
- /** */
- uint16_t pid;
-};
-
-int aice_init_targets(void);
-
-#endif /* OPENOCD_JTAG_AICE_AICE_INTERFACE_H */
diff --git a/src/jtag/aice/aice_pipe.c b/src/jtag/aice/aice_pipe.c
deleted file mode 100644
index 18ad40e..0000000
--- a/src/jtag/aice/aice_pipe.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <signal.h>
-#endif
-
-#include <helper/log.h>
-#include <helper/time_support.h>
-#include "aice_port.h"
-#include "aice_pipe.h"
-
-#define AICE_PIPE_MAXLINE 8192
-
-#ifdef _WIN32
-PROCESS_INFORMATION proc_info;
-
-HANDLE aice_pipe_output[2];
-HANDLE aice_pipe_input[2];
-
-static int aice_pipe_write(const void *buffer, int count)
-{
- BOOL success;
- DWORD written;
-
- success = WriteFile(aice_pipe_output[1], buffer, count, &written, NULL);
- if (!success) {
- LOG_ERROR("(WIN32) write to pipe failed, error code: 0x%08l" PRIx32, GetLastError());
- return -1;
- }
-
- return written;
-}
-
-static int aice_pipe_read(void *buffer, int count)
-{
- BOOL success;
- DWORD has_read;
-
- success = ReadFile(aice_pipe_input[0], buffer, count, &has_read, NULL);
- if (!success || (has_read == 0)) {
- LOG_ERROR("(WIN32) read from pipe failed, error code: 0x%08l" PRIx32, GetLastError());
- return -1;
- }
-
- return has_read;
-}
-
-static int aice_pipe_child_init(struct aice_port_param_s *param)
-{
- STARTUPINFO start_info;
- BOOL success;
-
- ZeroMemory(&proc_info, sizeof(PROCESS_INFORMATION));
- ZeroMemory(&start_info, sizeof(STARTUPINFO));
- start_info.cb = sizeof(STARTUPINFO);
- start_info.hStdError = aice_pipe_input[1];
- start_info.hStdOutput = aice_pipe_input[1];
- start_info.hStdInput = aice_pipe_output[0];
- start_info.dwFlags |= STARTF_USESTDHANDLES;
-
- success = CreateProcess(NULL,
- param->adapter_name,
- NULL,
- NULL,
- TRUE,
- 0,
- NULL,
- NULL,
- &start_info,
- &proc_info);
-
- if (!success) {
- LOG_ERROR("Create new process failed");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_pipe_parent_init(struct aice_port_param_s *param)
-{
- /* send open to adapter */
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_OPEN;
- set_u16(command + 1, param->vid);
- set_u16(command + 3, param->pid);
-
- if (aice_pipe_write(command, 5) != 5) {
- LOG_ERROR("write failed\n");
- return ERROR_FAIL;
- }
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) {
- LOG_ERROR("read failed\n");
- return ERROR_FAIL;
- }
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_open(struct aice_port_param_s *param)
-{
- SECURITY_ATTRIBUTES attribute;
-
- attribute.nLength = sizeof(SECURITY_ATTRIBUTES);
- attribute.bInheritHandle = TRUE;
- attribute.lpSecurityDescriptor = NULL;
-
- if (!CreatePipe(&aice_pipe_output[0], &aice_pipe_output[1],
- &attribute, AICE_PIPE_MAXLINE)) {
- LOG_ERROR("Create pipes failed");
- return ERROR_FAIL;
- }
- if (!CreatePipe(&aice_pipe_input[0], &aice_pipe_input[1],
- &attribute, AICE_PIPE_MAXLINE)) {
- LOG_ERROR("Create pipes failed");
- return ERROR_FAIL;
- }
-
- /* do not inherit aice_pipe_output[1] & aice_pipe_input[0] to child process */
- if (!SetHandleInformation(aice_pipe_output[1], HANDLE_FLAG_INHERIT, 0))
- return ERROR_FAIL;
- if (!SetHandleInformation(aice_pipe_input[0], HANDLE_FLAG_INHERIT, 0))
- return ERROR_FAIL;
-
- aice_pipe_child_init(param);
-
- aice_pipe_parent_init(param);
-
- return ERROR_OK;
-}
-
-#else
-
-int aice_pipe_output[2];
-int aice_pipe_input[2];
-
-static int aice_pipe_write(const void *buffer, int count)
-{
- if (write(aice_pipe_output[1], buffer, count) != count) {
- LOG_ERROR("write to pipe failed");
- return -1;
- }
-
- return count;
-}
-
-static int aice_pipe_read(void *buffer, int count)
-{
- int n;
- int64_t then, cur;
-
- then = timeval_ms();
-
- while (1) {
- n = read(aice_pipe_input[0], buffer, count);
-
- if ((n == -1) && (errno == EAGAIN)) {
- cur = timeval_ms();
- if (cur - then > 500)
- keep_alive();
- continue;
- } else if (n > 0)
- break;
- else {
- LOG_ERROR("read from pipe failed");
- break;
- }
- }
-
- return n;
-}
-
-static int aice_pipe_child_init(struct aice_port_param_s *param)
-{
- close(aice_pipe_output[1]);
- close(aice_pipe_input[0]);
-
- if (aice_pipe_output[0] != STDIN_FILENO) {
- if (dup2(aice_pipe_output[0], STDIN_FILENO) != STDIN_FILENO) {
- LOG_ERROR("Map aice_pipe to STDIN failed");
- return ERROR_FAIL;
- }
- close(aice_pipe_output[0]);
- }
-
- if (aice_pipe_input[1] != STDOUT_FILENO) {
- if (dup2(aice_pipe_input[1], STDOUT_FILENO) != STDOUT_FILENO) {
- LOG_ERROR("Map aice_pipe to STDOUT failed");
- return ERROR_FAIL;
- }
- close(aice_pipe_input[1]);
- }
-
- if (execl(param->adapter_name, param->adapter_name, (char *)0) < 0) {
- LOG_ERROR("Execute aice_pipe failed");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_pipe_parent_init(struct aice_port_param_s *param)
-{
- close(aice_pipe_output[0]);
- close(aice_pipe_input[1]);
-
- /* set read end of pipe as non-blocking */
- if (fcntl(aice_pipe_input[0], F_SETFL, O_NONBLOCK))
- return ERROR_FAIL;
-
- /* send open to adapter */
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_OPEN;
- set_u16(command + 1, param->vid);
- set_u16(command + 3, param->pid);
-
- if (aice_pipe_write(command, 5) != 5) {
- LOG_ERROR("write failed\n");
- return ERROR_FAIL;
- }
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) {
- LOG_ERROR("read failed\n");
- return ERROR_FAIL;
- }
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static void sig_pipe(int signo)
-{
- exit(1);
-}
-
-static int aice_pipe_open(struct aice_port_param_s *param)
-{
- pid_t pid;
-
- if (signal(SIGPIPE, sig_pipe) == SIG_ERR) {
- LOG_ERROR("Register SIGPIPE handler failed");
- return ERROR_FAIL;
- }
-
- if (pipe(aice_pipe_output) < 0 || pipe(aice_pipe_input) < 0) {
- LOG_ERROR("Create pipes failed");
- return ERROR_FAIL;
- }
-
- pid = fork();
- if (pid < 0) {
- LOG_ERROR("Fork new process failed");
- return ERROR_FAIL;
- } else if (pid == 0) {
- if (aice_pipe_child_init(param) != ERROR_OK) {
- LOG_ERROR("AICE_PIPE child process initial error");
- return ERROR_FAIL;
- } else {
- if (aice_pipe_parent_init(param) != ERROR_OK) {
- LOG_ERROR("AICE_PIPE parent process initial error");
- return ERROR_FAIL;
- }
- }
- }
-
- return ERROR_OK;
-}
-#endif
-
-static int aice_pipe_close(void)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_CLOSE;
-
- if (aice_pipe_write(command, 1) != 1)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK) {
-#ifdef _WIN32
- WaitForSingleObject(proc_info.hProcess, INFINITE);
- CloseHandle(proc_info.hProcess);
- CloseHandle(proc_info.hThread);
-#endif
- return ERROR_OK;
- } else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_idcode(uint32_t *idcode, uint8_t *num_of_idcode)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_IDCODE;
-
- if (aice_pipe_write(command, 1) != 1)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- *num_of_idcode = line[0];
-
- if ((*num_of_idcode == 0) || (*num_of_idcode >= 16))
- return ERROR_FAIL;
-
- for (int i = 0 ; i < *num_of_idcode ; i++)
- idcode[i] = get_u32(line + i * 4 + 1);
-
- return ERROR_OK;
-}
-
-static int aice_pipe_state(uint32_t coreid, enum aice_target_state_s *state)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_STATE;
-
- if (aice_pipe_write(command, 1) != 1)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- *state = (enum aice_target_state_s)line[0];
-
- return ERROR_OK;
-}
-
-static int aice_pipe_reset(void)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_RESET;
-
- if (aice_pipe_write(command, 1) != 1)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_assert_srst(uint32_t coreid, enum aice_srst_type_s srst)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_ASSERT_SRST;
- command[1] = srst;
-
- if (aice_pipe_write(command, 2) != 2)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_run(uint32_t coreid)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_RUN;
-
- if (aice_pipe_write(command, 1) != 1)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_halt(uint32_t coreid)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_HALT;
-
- if (aice_pipe_write(command, 1) != 1)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_READ_REG;
- set_u32(command + 1, num);
-
- if (aice_pipe_write(command, 5) != 5)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- *val = get_u32(line);
-
- return ERROR_OK;
-}
-
-static int aice_pipe_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_WRITE_REG;
- set_u32(command + 1, num);
- set_u32(command + 5, val);
-
- if (aice_pipe_write(command, 9) != 9)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_READ_REG_64;
- set_u32(command + 1, num);
-
- if (aice_pipe_write(command, 5) != 5)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- *val = (((uint64_t)get_u32(line + 4)) << 32) | get_u32(line);
-
- return ERROR_OK;
-}
-
-static int aice_pipe_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_WRITE_REG_64;
- set_u32(command + 1, num);
- set_u32(command + 5, val & 0xFFFFFFFF);
- set_u32(command + 9, (val >> 32) & 0xFFFFFFFF);
-
- if (aice_pipe_write(command, 13) != 9)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_step(uint32_t coreid)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_STEP;
-
- if (aice_pipe_write(command, 1) != 1)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_read_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_READ_MEM_UNIT;
- set_u32(command + 1, addr);
- set_u32(command + 5, size);
- set_u32(command + 9, count);
-
- if (aice_pipe_write(command, 13) != 13)
- return ERROR_FAIL;
-
- if (aice_pipe_read(buffer, size * count) < 0)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int aice_pipe_write_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_WRITE_MEM_UNIT;
- set_u32(command + 1, addr);
- set_u32(command + 5, size);
- set_u32(command + 9, count);
-
- /* WRITE_MEM_UNIT|addr|size|count|data */
- memcpy(command + 13, buffer, size * count);
-
- if (aice_pipe_write(command, 13 + size * count) < 0)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int aice_pipe_read_mem_bulk(uint32_t coreid, uint32_t addr,
- uint32_t length, uint8_t *buffer)
-{
- char line[AICE_PIPE_MAXLINE + 1];
- char command[AICE_PIPE_MAXLINE];
- uint32_t remain_len = length;
- uint32_t prepare_len;
- char *received_line;
- uint32_t received_len;
- int read_len;
-
- command[0] = AICE_READ_MEM_BULK;
- set_u32(command + 1, addr);
- set_u32(command + 5, length);
-
- if (aice_pipe_write(command, 9) < 0)
- return ERROR_FAIL;
-
- while (remain_len > 0) {
- if (remain_len > AICE_PIPE_MAXLINE)
- prepare_len = AICE_PIPE_MAXLINE;
- else
- prepare_len = remain_len;
-
- prepare_len++;
- received_len = 0;
- received_line = line;
- do {
- read_len = aice_pipe_read(received_line, prepare_len - received_len);
- if (read_len < 0)
- return ERROR_FAIL;
- received_line += read_len;
- received_len += read_len;
- } while (received_len < prepare_len);
-
- if (line[0] != AICE_OK)
- return ERROR_FAIL;
-
- prepare_len--;
- memcpy(buffer, line + 1, prepare_len);
- remain_len -= prepare_len;
- buffer += prepare_len;
- }
-
- return ERROR_OK;
-}
-
-static int aice_pipe_write_mem_bulk(uint32_t coreid, uint32_t addr,
- uint32_t length, const uint8_t *buffer)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE + 4];
- uint32_t remain_len = length;
- uint32_t written_len = 0;
- uint32_t write_len;
-
- command[0] = AICE_WRITE_MEM_BULK;
- set_u32(command + 1, addr);
- set_u32(command + 5, length);
-
- /* Send command first */
- if (aice_pipe_write(command, 9) < 0)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_ERROR)
- return ERROR_FAIL;
-
- while (remain_len > 0) {
- if (remain_len > AICE_PIPE_MAXLINE)
- write_len = AICE_PIPE_MAXLINE;
- else
- write_len = remain_len;
-
- set_u32(command, write_len);
- memcpy(command + 4, buffer + written_len, write_len); /* data only */
-
- if (aice_pipe_write(command, write_len + 4) < 0)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_ERROR)
- return ERROR_FAIL;
-
- remain_len -= write_len;
- written_len += write_len;
- }
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_READ_DEBUG_REG;
- set_u32(command + 1, addr);
-
- if (aice_pipe_write(command, 5) != 5)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- *val = get_u32(line);
-
- return ERROR_OK;
-}
-
-static int aice_pipe_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_WRITE_DEBUG_REG;
- set_u32(command + 1, addr);
- set_u32(command + 5, val);
-
- if (aice_pipe_write(command, 9) != 9)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_set_jtag_clock(uint32_t a_clock)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_SET_JTAG_CLOCK;
- set_u32(command + 1, a_clock);
-
- if (aice_pipe_write(command, 5) != 5)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_memory_access(uint32_t coreid, enum nds_memory_access access_channel)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_MEMORY_ACCESS;
- set_u32(command + 1, access_channel);
-
- if (aice_pipe_write(command, 5) != 5)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_select)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_MEMORY_MODE;
- set_u32(command + 1, mem_select);
-
- if (aice_pipe_write(command, 5) != 5)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address,
- uint32_t *physical_address)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_READ_TLB;
- set_u32(command + 1, virtual_address);
-
- if (aice_pipe_write(command, 5) != 5)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK) {
- *physical_address = get_u32(line + 1);
- return ERROR_OK;
- } else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address)
-{
- char line[AICE_PIPE_MAXLINE];
- char command[AICE_PIPE_MAXLINE];
-
- command[0] = AICE_CACHE_CTL;
- set_u32(command + 1, subtype);
- set_u32(command + 5, address);
-
- if (aice_pipe_write(command, 9) != 9)
- return ERROR_FAIL;
-
- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
- return ERROR_FAIL;
-
- if (line[0] == AICE_OK)
- return ERROR_OK;
- else
- return ERROR_FAIL;
-}
-
-static int aice_pipe_set_retry_times(uint32_t a_retry_times)
-{
- return ERROR_OK;
-}
-
-/** */
-struct aice_port_api_s aice_pipe = {
- /** */
- .open = aice_pipe_open,
- /** */
- .close = aice_pipe_close,
- /** */
- .idcode = aice_pipe_idcode,
- /** */
- .set_jtag_clock = aice_pipe_set_jtag_clock,
- /** */
- .state = aice_pipe_state,
- /** */
- .reset = aice_pipe_reset,
- /** */
- .assert_srst = aice_pipe_assert_srst,
- /** */
- .run = aice_pipe_run,
- /** */
- .halt = aice_pipe_halt,
- /** */
- .step = aice_pipe_step,
- /** */
- .read_reg = aice_pipe_read_reg,
- /** */
- .write_reg = aice_pipe_write_reg,
- /** */
- .read_reg_64 = aice_pipe_read_reg_64,
- /** */
- .write_reg_64 = aice_pipe_write_reg_64,
- /** */
- .read_mem_unit = aice_pipe_read_mem_unit,
- /** */
- .write_mem_unit = aice_pipe_write_mem_unit,
- /** */
- .read_mem_bulk = aice_pipe_read_mem_bulk,
- /** */
- .write_mem_bulk = aice_pipe_write_mem_bulk,
- /** */
- .read_debug_reg = aice_pipe_read_debug_reg,
- /** */
- .write_debug_reg = aice_pipe_write_debug_reg,
-
- /** */
- .memory_access = aice_pipe_memory_access,
- /** */
- .memory_mode = aice_pipe_memory_mode,
-
- /** */
- .read_tlb = aice_pipe_read_tlb,
-
- /** */
- .cache_ctl = aice_pipe_cache_ctl,
-
- /** */
- .set_retry_times = aice_pipe_set_retry_times,
-};
diff --git a/src/jtag/aice/aice_pipe.h b/src/jtag/aice/aice_pipe.h
deleted file mode 100644
index 467ad0a..0000000
--- a/src/jtag/aice/aice_pipe.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_AICE_AICE_PIPE_H
-#define OPENOCD_JTAG_AICE_AICE_PIPE_H
-
-#include <helper/types.h>
-
-#define set_u32(buffer, value) h_u32_to_le((uint8_t *)buffer, value)
-#define set_u16(buffer, value) h_u16_to_le((uint8_t *)buffer, value)
-#define get_u32(buffer) le_to_h_u32((const uint8_t *)buffer)
-#define get_u16(buffer) le_to_h_u16((const uint8_t *)buffer)
-
-extern struct aice_port_api_s aice_pipe;
-
-#endif /* OPENOCD_JTAG_AICE_AICE_PIPE_H */
diff --git a/src/jtag/aice/aice_port.c b/src/jtag/aice/aice_port.c
deleted file mode 100644
index 2fa346c..0000000
--- a/src/jtag/aice/aice_port.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include "aice_usb.h"
-#include "aice_pipe.h"
-#include "aice_port.h"
-
-static const struct aice_port aice_ports[] = {
- {
- .name = "aice_usb",
- .type = AICE_PORT_AICE_USB,
- .api = &aice_usb_api,
- },
- {
- .name = "aice_pipe",
- .type = AICE_PORT_AICE_PIPE,
- .api = &aice_pipe,
- },
- {.name = NULL, /* END OF TABLE */ },
-};
-
-/** */
-const struct aice_port *aice_port_get_list(void)
-{
- return aice_ports;
-}
diff --git a/src/jtag/aice/aice_port.h b/src/jtag/aice/aice_port.h
deleted file mode 100644
index 4568ce1..0000000
--- a/src/jtag/aice/aice_port.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_AICE_AICE_PORT_H
-#define OPENOCD_JTAG_AICE_AICE_PORT_H
-
-#include <target/nds32_edm.h>
-
-#define AICE_MAX_NUM_CORE (0x10)
-
-#define ERROR_AICE_DISCONNECT (-200)
-#define ERROR_AICE_TIMEOUT (-201)
-
-enum aice_target_state_s {
- AICE_DISCONNECT = 0,
- AICE_TARGET_DETACH,
- AICE_TARGET_UNKNOWN,
- AICE_TARGET_RUNNING,
- AICE_TARGET_HALTED,
- AICE_TARGET_RESET,
- AICE_TARGET_DEBUG_RUNNING,
-};
-
-enum aice_srst_type_s {
- AICE_SRST = 0x1,
- AICE_RESET_HOLD = 0x8,
-};
-
-enum aice_target_endian {
- AICE_LITTLE_ENDIAN = 0,
- AICE_BIG_ENDIAN,
-};
-
-enum aice_api_s {
- AICE_OPEN = 0x0,
- AICE_CLOSE,
- AICE_RESET,
- AICE_IDCODE,
- AICE_SET_JTAG_CLOCK,
- AICE_ASSERT_SRST,
- AICE_RUN,
- AICE_HALT,
- AICE_STEP,
- AICE_READ_REG,
- AICE_WRITE_REG,
- AICE_READ_REG_64,
- AICE_WRITE_REG_64,
- AICE_READ_MEM_UNIT,
- AICE_WRITE_MEM_UNIT,
- AICE_READ_MEM_BULK,
- AICE_WRITE_MEM_BULK,
- AICE_READ_DEBUG_REG,
- AICE_WRITE_DEBUG_REG,
- AICE_STATE,
- AICE_MEMORY_ACCESS,
- AICE_MEMORY_MODE,
- AICE_READ_TLB,
- AICE_CACHE_CTL,
- AICE_SET_RETRY_TIMES,
- AICE_PROGRAM_EDM,
- AICE_SET_COMMAND_MODE,
- AICE_EXECUTE,
- AICE_SET_CUSTOM_SRST_SCRIPT,
- AICE_SET_CUSTOM_TRST_SCRIPT,
- AICE_SET_CUSTOM_RESTART_SCRIPT,
- AICE_SET_COUNT_TO_CHECK_DBGER,
- AICE_SET_DATA_ENDIAN,
-};
-
-enum aice_error_s {
- AICE_OK,
- AICE_ACK,
- AICE_ERROR,
-};
-
-enum aice_cache_ctl_type {
- AICE_CACHE_CTL_L1D_INVALALL = 0,
- AICE_CACHE_CTL_L1D_VA_INVAL,
- AICE_CACHE_CTL_L1D_WBALL,
- AICE_CACHE_CTL_L1D_VA_WB,
- AICE_CACHE_CTL_L1I_INVALALL,
- AICE_CACHE_CTL_L1I_VA_INVAL,
-};
-
-enum aice_command_mode {
- AICE_COMMAND_MODE_NORMAL,
- AICE_COMMAND_MODE_PACK,
- AICE_COMMAND_MODE_BATCH,
-};
-
-struct aice_port_param_s {
- /** */
- const char *device_desc;
- /** */
- const char *serial;
- /** */
- uint16_t vid;
- /** */
- uint16_t pid;
- /** */
- char *adapter_name;
-};
-
-struct aice_port_s {
- /** */
- uint32_t coreid;
- /** */
- const struct aice_port *port;
-};
-
-/** */
-extern struct aice_port_api_s aice_usb_layout_api;
-
-/** */
-struct aice_port_api_s {
- /** */
- int (*open)(struct aice_port_param_s *param);
- /** */
- int (*close)(void);
- /** */
- int (*reset)(void);
- /** */
- int (*idcode)(uint32_t *idcode, uint8_t *num_of_idcode);
- /** */
- int (*set_jtag_clock)(uint32_t a_clock);
- /** */
- int (*assert_srst)(uint32_t coreid, enum aice_srst_type_s srst);
- /** */
- int (*run)(uint32_t coreid);
- /** */
- int (*halt)(uint32_t coreid);
- /** */
- int (*step)(uint32_t coreid);
- /** */
- int (*read_reg)(uint32_t coreid, uint32_t num, uint32_t *val);
- /** */
- int (*write_reg)(uint32_t coreid, uint32_t num, uint32_t val);
- /** */
- int (*read_reg_64)(uint32_t coreid, uint32_t num, uint64_t *val);
- /** */
- int (*write_reg_64)(uint32_t coreid, uint32_t num, uint64_t val);
- /** */
- int (*read_mem_unit)(uint32_t coreid, uint32_t addr, uint32_t size,
- uint32_t count, uint8_t *buffer);
- /** */
- int (*write_mem_unit)(uint32_t coreid, uint32_t addr, uint32_t size,
- uint32_t count, const uint8_t *buffer);
- /** */
- int (*read_mem_bulk)(uint32_t coreid, uint32_t addr, uint32_t length,
- uint8_t *buffer);
- /** */
- int (*write_mem_bulk)(uint32_t coreid, uint32_t addr, uint32_t length,
- const uint8_t *buffer);
- /** */
- int (*read_debug_reg)(uint32_t coreid, uint32_t addr, uint32_t *val);
- /** */
- int (*write_debug_reg)(uint32_t coreid, uint32_t addr, const uint32_t val);
-
- /** */
- int (*state)(uint32_t coreid, enum aice_target_state_s *state);
-
- /** */
- int (*memory_access)(uint32_t coreid, enum nds_memory_access a_access);
- /** */
- int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select);
-
- /** */
- int (*read_tlb)(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address);
-
- /** */
- int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address);
-
- /** */
- int (*set_retry_times)(uint32_t a_retry_times);
-
- /** */
- int (*program_edm)(uint32_t coreid, char *command_sequence);
-
- /** */
- int (*set_command_mode)(enum aice_command_mode command_mode);
-
- /** */
- int (*execute)(uint32_t coreid, uint32_t *instructions, uint32_t instruction_num);
-
- /** */
- int (*set_custom_srst_script)(const char *script);
-
- /** */
- int (*set_custom_trst_script)(const char *script);
-
- /** */
- int (*set_custom_restart_script)(const char *script);
-
- /** */
- int (*set_count_to_check_dbger)(uint32_t count_to_check);
-
- /** */
- int (*set_data_endian)(uint32_t coreid, enum aice_target_endian target_data_endian);
-
- /** */
- int (*profiling)(uint32_t coreid, uint32_t interval, uint32_t iteration,
- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples);
-};
-
-#define AICE_PORT_UNKNOWN 0
-#define AICE_PORT_AICE_USB 1
-#define AICE_PORT_AICE_PIPE 2
-
-/** */
-struct aice_port {
- /** */
- const char *name;
- /** */
- int type;
- /** */
- struct aice_port_api_s *const api;
-};
-
-/** */
-const struct aice_port *aice_port_get_list(void);
-
-#endif /* OPENOCD_JTAG_AICE_AICE_PORT_H */
diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c
deleted file mode 100644
index 9f07946..0000000
--- a/src/jtag/aice/aice_transport.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <jtag/tcl.h>
-#include <transport/transport.h>
-#include <target/target.h>
-#include <jtag/aice/aice_interface.h>
-#include <jtag/aice/aice_transport.h>
-
-/* */
-static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
- struct jtag_tap *pTap)
-{
- jim_wide w;
- int e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK) {
- Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
- n->name);
- return e;
- }
-
- unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt;
- uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
- if (new_expected_ids == NULL) {
- Jim_SetResultFormatted(goi->interp, "no memory");
- return JIM_ERR;
- }
-
- memcpy(new_expected_ids, pTap->expected_ids, expected_len);
-
- new_expected_ids[pTap->expected_ids_cnt] = w;
-
- free(pTap->expected_ids);
- pTap->expected_ids = new_expected_ids;
- pTap->expected_ids_cnt++;
-
- return JIM_OK;
-}
-
-#define NTAP_OPT_EXPECTED_ID 0
-
-/* */
-static int jim_aice_newtap_cmd(Jim_GetOptInfo *goi)
-{
- struct jtag_tap *pTap;
- int x;
- int e;
- Jim_Nvp *n;
- char *cp;
- const Jim_Nvp opts[] = {
- {.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID},
- {.name = NULL, .value = -1},
- };
-
- pTap = calloc(1, sizeof(struct jtag_tap));
- if (!pTap) {
- Jim_SetResultFormatted(goi->interp, "no memory");
- return JIM_ERR;
- }
-
- /*
- * we expect CHIP + TAP + OPTIONS
- * */
- if (goi->argc < 3) {
- Jim_SetResultFormatted(goi->interp,
- "Missing CHIP TAP OPTIONS ....");
- free(pTap);
- return JIM_ERR;
- }
-
- const char *tmp;
- Jim_GetOpt_String(goi, &tmp, NULL);
- pTap->chip = strdup(tmp);
-
- Jim_GetOpt_String(goi, &tmp, NULL);
- pTap->tapname = strdup(tmp);
-
- /* name + dot + name + null */
- x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
- cp = malloc(x);
- sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
- pTap->dotted_name = cp;
-
- LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
- pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);
-
- while (goi->argc) {
- e = Jim_GetOpt_Nvp(goi, opts, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, opts, 0);
- free(cp);
- free(pTap);
- return e;
- }
- LOG_DEBUG("Processing option: %s", n->name);
- switch (n->value) {
- case NTAP_OPT_EXPECTED_ID:
- e = jim_newtap_expected_id(n, goi, pTap);
- if (JIM_OK != e) {
- free(cp);
- free(pTap);
- return e;
- }
- break;
- } /* switch (n->value) */
- } /* while (goi->argc) */
-
- /* default is enabled-after-reset */
- pTap->enabled = !pTap->disabled_after_reset;
-
- jtag_tap_init(pTap);
- return JIM_OK;
-}
-
-/* */
-static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
- return jim_aice_newtap_cmd(&goi);
-}
-
-/* */
-COMMAND_HANDLER(handle_aice_init_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- static bool jtag_initialized;
- if (jtag_initialized) {
- LOG_INFO("'jtag init' has already been called");
- return ERROR_OK;
- }
- jtag_initialized = true;
-
- LOG_DEBUG("Initializing jtag devices...");
- return jtag_init(CMD_CTX);
-}
-
-static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- LOG_DEBUG("No implement: jim_aice_arp_init");
-
- return JIM_OK;
-}
-
-/* */
-static int aice_init_reset(struct command_context *cmd_ctx)
-{
- LOG_DEBUG("Initializing with hard TRST+SRST reset");
-
- int retval;
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- jtag_add_reset(1, 0); /* TAP_RESET */
- if (jtag_reset_config & RESET_HAS_SRST) {
- jtag_add_reset(1, 1);
- if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
- jtag_add_reset(0, 1);
- }
- jtag_add_reset(0, 0);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-/* */
-static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- int e = ERROR_OK;
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
- if (goi.argc != 0) {
- Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
- return JIM_ERR;
- }
- struct command_context *context = current_command_context(interp);
- e = aice_init_reset(context);
-
- if (e != ERROR_OK) {
- Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e);
- Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
- Jim_FreeNewObj(goi.interp, eObj);
- return JIM_ERR;
- }
- return JIM_OK;
-}
-
-static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
- if (goi.argc != 0) {
- Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
- return JIM_ERR;
- }
- Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
- struct jtag_tap *tap;
-
- for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
- Jim_ListAppendElement(goi.interp,
- Jim_GetResult(goi.interp),
- Jim_NewStringObj(goi.interp,
- tap->dotted_name, -1));
-
- return JIM_OK;
-}
-
-/* */
-static const struct command_registration
-aice_transport_jtag_subcommand_handlers[] = {
- {
- .name = "init",
- .mode = COMMAND_ANY,
- .handler = handle_aice_init_command,
- .help = "initialize jtag scan chain",
- .usage = ""
- },
- {
- .name = "arp_init",
- .mode = COMMAND_ANY,
- .jim_handler = jim_aice_arp_init,
- .help = "Validates JTAG scan chain against the list of "
- "declared TAPs.",
- },
- {
- .name = "arp_init-reset",
- .mode = COMMAND_ANY,
- .jim_handler = jim_aice_arp_init_reset,
- .help = "Uses TRST and SRST to try resetting everything on "
- "the JTAG scan chain, then performs 'jtag arp_init'."
- },
- {
- .name = "newtap",
- .mode = COMMAND_CONFIG,
- .jim_handler = jim_aice_newtap,
- .help = "Create a new TAP instance named basename.tap_type, "
- "and appends it to the scan chain.",
- .usage = "basename tap_type ['-expected_id' number]"
- },
- {
- .name = "tapisenabled",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- .help = "Returns a Tcl boolean (0/1) indicating whether "
- "the TAP is enabled (1) or not (0).",
- .usage = "tap_name",
- },
- {
- .name = "tapenable",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- .help = "Try to enable the specified TAP using the "
- "'tap-enable' TAP event.",
- .usage = "tap_name",
- },
- {
- .name = "tapdisable",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- .help = "Try to disable the specified TAP using the "
- "'tap-disable' TAP event.",
- .usage = "tap_name",
- },
- {
- .name = "configure",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_configure,
- .help = "Provide a Tcl handler for the specified "
- "TAP event.",
- .usage = "tap_name '-event' event_name handler",
- },
- {
- .name = "cget",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_configure,
- .help = "Return any Tcl handler for the specified "
- "TAP event.",
- .usage = "tap_name '-event' event_name",
- },
- {
- .name = "names",
- .mode = COMMAND_ANY,
- .jim_handler = jim_aice_names,
- .help = "Returns list of all JTAG tap names.",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-/* */
-static const struct command_registration aice_transport_command_handlers[] = {
- {
- .name = "jtag",
- .mode = COMMAND_ANY,
- .usage = "",
- .chain = aice_transport_jtag_subcommand_handlers,
- },
- COMMAND_REGISTRATION_DONE
-
-};
-
-/* */
-static int aice_transport_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL,
- aice_transport_command_handlers);
-}
-
-/* */
-static int aice_transport_init(struct command_context *cmd_ctx)
-{
- LOG_DEBUG("aice_transport_init");
- struct target *t = get_current_target(cmd_ctx);
- struct transport *transport;
-
- if (!t) {
- LOG_ERROR("no current target");
- return ERROR_FAIL;
- }
-
- transport = get_current_transport();
-
- if (!transport) {
- LOG_ERROR("no transport selected");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("current transport %s", transport->name);
-
- return aice_init_targets();
-}
-
-/* */
-static int aice_transport_select(struct command_context *ctx)
-{
- LOG_DEBUG("aice_transport_select");
-
- int retval;
-
- retval = aice_transport_register_commands(ctx);
-
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static struct transport aice_jtag_transport = {
- .name = "aice_jtag",
- .select = aice_transport_select,
- .init = aice_transport_init,
-};
-
-const char *aice_transports[] = { "aice_jtag", NULL };
-
-static void aice_constructor(void) __attribute__((constructor));
-static void aice_constructor(void)
-{
- transport_register(&aice_jtag_transport);
-}
-
diff --git a/src/jtag/aice/aice_transport.h b/src/jtag/aice/aice_transport.h
deleted file mode 100644
index 3af8bc2..0000000
--- a/src/jtag/aice/aice_transport.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_AICE_AICE_TRANSPORT_H
-#define OPENOCD_JTAG_AICE_AICE_TRANSPORT_H
-
-extern const char *aice_transports[];
-
-#endif /* OPENOCD_JTAG_AICE_AICE_TRANSPORT_H */
diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c
deleted file mode 100644
index b27f720..0000000
--- a/src/jtag/aice/aice_usb.c
+++ /dev/null
@@ -1,4123 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/drivers/libusb_common.h>
-#include <helper/log.h>
-#include <helper/time_support.h>
-#include <target/target.h>
-#include <jtag/jtag.h>
-#include <target/nds32_insn.h>
-#include <target/nds32_reg.h>
-#include "aice_usb.h"
-
-
-/* Global USB buffers */
-static uint8_t usb_in_buffer[AICE_IN_BUFFER_SIZE];
-static uint8_t usb_out_buffer[AICE_OUT_BUFFER_SIZE];
-static uint32_t jtag_clock;
-static struct aice_usb_handler_s aice_handler;
-/* AICE max retry times. If AICE command timeout, retry it. */
-static int aice_max_retry_times = 50;
-/* Default endian is little endian. */
-static enum aice_target_endian data_endian;
-
-/* Constants for AICE command format length */
-static const int32_t AICE_FORMAT_HTDA = 3;
-static const int32_t AICE_FORMAT_HTDC = 7;
-static const int32_t AICE_FORMAT_HTDMA = 4;
-static const int32_t AICE_FORMAT_HTDMB = 8;
-static const int32_t AICE_FORMAT_HTDMC = 8;
-static const int32_t AICE_FORMAT_HTDMD = 12;
-static const int32_t AICE_FORMAT_DTHA = 6;
-static const int32_t AICE_FORMAT_DTHB = 2;
-static const int32_t AICE_FORMAT_DTHMA = 8;
-static const int32_t AICE_FORMAT_DTHMB = 4;
-
-/* Constants for AICE command */
-static const uint8_t AICE_CMD_SCAN_CHAIN = 0x00;
-static const uint8_t AICE_CMD_T_READ_MISC = 0x20;
-static const uint8_t AICE_CMD_T_READ_EDMSR = 0x21;
-static const uint8_t AICE_CMD_T_READ_DTR = 0x22;
-static const uint8_t AICE_CMD_T_READ_MEM_B = 0x24;
-static const uint8_t AICE_CMD_T_READ_MEM_H = 0x25;
-static const uint8_t AICE_CMD_T_READ_MEM = 0x26;
-static const uint8_t AICE_CMD_T_FASTREAD_MEM = 0x27;
-static const uint8_t AICE_CMD_T_WRITE_MISC = 0x28;
-static const uint8_t AICE_CMD_T_WRITE_EDMSR = 0x29;
-static const uint8_t AICE_CMD_T_WRITE_DTR = 0x2A;
-static const uint8_t AICE_CMD_T_WRITE_DIM = 0x2B;
-static const uint8_t AICE_CMD_T_WRITE_MEM_B = 0x2C;
-static const uint8_t AICE_CMD_T_WRITE_MEM_H = 0x2D;
-static const uint8_t AICE_CMD_T_WRITE_MEM = 0x2E;
-static const uint8_t AICE_CMD_T_FASTWRITE_MEM = 0x2F;
-static const uint8_t AICE_CMD_T_EXECUTE = 0x3E;
-static const uint8_t AICE_CMD_READ_CTRL = 0x50;
-static const uint8_t AICE_CMD_WRITE_CTRL = 0x51;
-static const uint8_t AICE_CMD_BATCH_BUFFER_READ = 0x60;
-static const uint8_t AICE_CMD_READ_DTR_TO_BUFFER = 0x61;
-static const uint8_t AICE_CMD_BATCH_BUFFER_WRITE = 0x68;
-static const uint8_t AICE_CMD_WRITE_DTR_FROM_BUFFER = 0x69;
-
-/***************************************************************************/
-/* AICE commands' pack/unpack functions */
-static void aice_pack_htda(uint8_t cmd_code, uint8_t extra_word_length,
- uint32_t address)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = extra_word_length;
- usb_out_buffer[2] = (uint8_t)(address & 0xFF);
-}
-
-static void aice_pack_htdc(uint8_t cmd_code, uint8_t extra_word_length,
- uint32_t address, uint32_t word, enum aice_target_endian access_endian)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = extra_word_length;
- usb_out_buffer[2] = (uint8_t)(address & 0xFF);
- if (access_endian == AICE_BIG_ENDIAN) {
- usb_out_buffer[6] = (uint8_t)((word >> 24) & 0xFF);
- usb_out_buffer[5] = (uint8_t)((word >> 16) & 0xFF);
- usb_out_buffer[4] = (uint8_t)((word >> 8) & 0xFF);
- usb_out_buffer[3] = (uint8_t)(word & 0xFF);
- } else {
- usb_out_buffer[3] = (uint8_t)((word >> 24) & 0xFF);
- usb_out_buffer[4] = (uint8_t)((word >> 16) & 0xFF);
- usb_out_buffer[5] = (uint8_t)((word >> 8) & 0xFF);
- usb_out_buffer[6] = (uint8_t)(word & 0xFF);
- }
-}
-
-static void aice_pack_htdma(uint8_t cmd_code, uint8_t target_id,
- uint8_t extra_word_length, uint32_t address)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = target_id;
- usb_out_buffer[2] = extra_word_length;
- usb_out_buffer[3] = (uint8_t)(address & 0xFF);
-}
-
-static void aice_pack_htdmb(uint8_t cmd_code, uint8_t target_id,
- uint8_t extra_word_length, uint32_t address)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = target_id;
- usb_out_buffer[2] = extra_word_length;
- usb_out_buffer[3] = 0;
- usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF);
- usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF);
- usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF);
- usb_out_buffer[7] = (uint8_t)(address & 0xFF);
-}
-
-static void aice_pack_htdmc(uint8_t cmd_code, uint8_t target_id,
- uint8_t extra_word_length, uint32_t address, uint32_t word,
- enum aice_target_endian access_endian)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = target_id;
- usb_out_buffer[2] = extra_word_length;
- usb_out_buffer[3] = (uint8_t)(address & 0xFF);
- if (access_endian == AICE_BIG_ENDIAN) {
- usb_out_buffer[7] = (uint8_t)((word >> 24) & 0xFF);
- usb_out_buffer[6] = (uint8_t)((word >> 16) & 0xFF);
- usb_out_buffer[5] = (uint8_t)((word >> 8) & 0xFF);
- usb_out_buffer[4] = (uint8_t)(word & 0xFF);
- } else {
- usb_out_buffer[4] = (uint8_t)((word >> 24) & 0xFF);
- usb_out_buffer[5] = (uint8_t)((word >> 16) & 0xFF);
- usb_out_buffer[6] = (uint8_t)((word >> 8) & 0xFF);
- usb_out_buffer[7] = (uint8_t)(word & 0xFF);
- }
-}
-
-static void aice_pack_htdmc_multiple_data(uint8_t cmd_code, uint8_t target_id,
- uint8_t extra_word_length, uint32_t address, uint32_t *word,
- uint8_t num_of_words, enum aice_target_endian access_endian)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = target_id;
- usb_out_buffer[2] = extra_word_length;
- usb_out_buffer[3] = (uint8_t)(address & 0xFF);
-
- uint8_t i;
- for (i = 0 ; i < num_of_words ; i++, word++) {
- if (access_endian == AICE_BIG_ENDIAN) {
- usb_out_buffer[7 + i * 4] = (uint8_t)((*word >> 24) & 0xFF);
- usb_out_buffer[6 + i * 4] = (uint8_t)((*word >> 16) & 0xFF);
- usb_out_buffer[5 + i * 4] = (uint8_t)((*word >> 8) & 0xFF);
- usb_out_buffer[4 + i * 4] = (uint8_t)(*word & 0xFF);
- } else {
- usb_out_buffer[4 + i * 4] = (uint8_t)((*word >> 24) & 0xFF);
- usb_out_buffer[5 + i * 4] = (uint8_t)((*word >> 16) & 0xFF);
- usb_out_buffer[6 + i * 4] = (uint8_t)((*word >> 8) & 0xFF);
- usb_out_buffer[7 + i * 4] = (uint8_t)(*word & 0xFF);
- }
- }
-}
-
-static void aice_pack_htdmd(uint8_t cmd_code, uint8_t target_id,
- uint8_t extra_word_length, uint32_t address, uint32_t word,
- enum aice_target_endian access_endian)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = target_id;
- usb_out_buffer[2] = extra_word_length;
- usb_out_buffer[3] = 0;
- usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF);
- usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF);
- usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF);
- usb_out_buffer[7] = (uint8_t)(address & 0xFF);
- if (access_endian == AICE_BIG_ENDIAN) {
- usb_out_buffer[11] = (uint8_t)((word >> 24) & 0xFF);
- usb_out_buffer[10] = (uint8_t)((word >> 16) & 0xFF);
- usb_out_buffer[9] = (uint8_t)((word >> 8) & 0xFF);
- usb_out_buffer[8] = (uint8_t)(word & 0xFF);
- } else {
- usb_out_buffer[8] = (uint8_t)((word >> 24) & 0xFF);
- usb_out_buffer[9] = (uint8_t)((word >> 16) & 0xFF);
- usb_out_buffer[10] = (uint8_t)((word >> 8) & 0xFF);
- usb_out_buffer[11] = (uint8_t)(word & 0xFF);
- }
-}
-
-static void aice_pack_htdmd_multiple_data(uint8_t cmd_code, uint8_t target_id,
- uint8_t extra_word_length, uint32_t address, const uint8_t *word,
- enum aice_target_endian access_endian)
-{
- usb_out_buffer[0] = cmd_code;
- usb_out_buffer[1] = target_id;
- usb_out_buffer[2] = extra_word_length;
- usb_out_buffer[3] = 0;
- usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF);
- usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF);
- usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF);
- usb_out_buffer[7] = (uint8_t)(address & 0xFF);
-
- uint32_t i;
- /* num_of_words may be over 0xFF, so use uint32_t */
- uint32_t num_of_words = extra_word_length + 1;
-
- for (i = 0 ; i < num_of_words ; i++, word += 4) {
- if (access_endian == AICE_BIG_ENDIAN) {
- usb_out_buffer[11 + i * 4] = word[3];
- usb_out_buffer[10 + i * 4] = word[2];
- usb_out_buffer[9 + i * 4] = word[1];
- usb_out_buffer[8 + i * 4] = word[0];
- } else {
- usb_out_buffer[8 + i * 4] = word[3];
- usb_out_buffer[9 + i * 4] = word[2];
- usb_out_buffer[10 + i * 4] = word[1];
- usb_out_buffer[11 + i * 4] = word[0];
- }
- }
-}
-
-static void aice_unpack_dtha(uint8_t *cmd_ack_code, uint8_t *extra_word_length,
- uint32_t *word, enum aice_target_endian access_endian)
-{
- *cmd_ack_code = usb_in_buffer[0];
- *extra_word_length = usb_in_buffer[1];
-
- if (access_endian == AICE_BIG_ENDIAN) {
- *word = (usb_in_buffer[5] << 24) |
- (usb_in_buffer[4] << 16) |
- (usb_in_buffer[3] << 8) |
- (usb_in_buffer[2]);
- } else {
- *word = (usb_in_buffer[2] << 24) |
- (usb_in_buffer[3] << 16) |
- (usb_in_buffer[4] << 8) |
- (usb_in_buffer[5]);
- }
-}
-
-static void aice_unpack_dtha_multiple_data(uint8_t *cmd_ack_code,
- uint8_t *extra_word_length, uint32_t *word, uint8_t num_of_words,
- enum aice_target_endian access_endian)
-{
- *cmd_ack_code = usb_in_buffer[0];
- *extra_word_length = usb_in_buffer[1];
-
- uint8_t i;
- for (i = 0 ; i < num_of_words ; i++, word++) {
- if (access_endian == AICE_BIG_ENDIAN) {
- *word = (usb_in_buffer[5 + i * 4] << 24) |
- (usb_in_buffer[4 + i * 4] << 16) |
- (usb_in_buffer[3 + i * 4] << 8) |
- (usb_in_buffer[2 + i * 4]);
- } else {
- *word = (usb_in_buffer[2 + i * 4] << 24) |
- (usb_in_buffer[3 + i * 4] << 16) |
- (usb_in_buffer[4 + i * 4] << 8) |
- (usb_in_buffer[5 + i * 4]);
- }
- }
-}
-
-static void aice_unpack_dthb(uint8_t *cmd_ack_code, uint8_t *extra_word_length)
-{
- *cmd_ack_code = usb_in_buffer[0];
- *extra_word_length = usb_in_buffer[1];
-}
-
-static void aice_unpack_dthma(uint8_t *cmd_ack_code, uint8_t *target_id,
- uint8_t *extra_word_length, uint32_t *word,
- enum aice_target_endian access_endian)
-{
- *cmd_ack_code = usb_in_buffer[0];
- *target_id = usb_in_buffer[1];
- *extra_word_length = usb_in_buffer[2];
- if (access_endian == AICE_BIG_ENDIAN) {
- *word = (usb_in_buffer[7] << 24) |
- (usb_in_buffer[6] << 16) |
- (usb_in_buffer[5] << 8) |
- (usb_in_buffer[4]);
- } else {
- *word = (usb_in_buffer[4] << 24) |
- (usb_in_buffer[5] << 16) |
- (usb_in_buffer[6] << 8) |
- (usb_in_buffer[7]);
- }
-}
-
-static void aice_unpack_dthma_multiple_data(uint8_t *cmd_ack_code,
- uint8_t *target_id, uint8_t *extra_word_length, uint8_t *word,
- enum aice_target_endian access_endian)
-{
- *cmd_ack_code = usb_in_buffer[0];
- *target_id = usb_in_buffer[1];
- *extra_word_length = usb_in_buffer[2];
- if (access_endian == AICE_BIG_ENDIAN) {
- word[0] = usb_in_buffer[4];
- word[1] = usb_in_buffer[5];
- word[2] = usb_in_buffer[6];
- word[3] = usb_in_buffer[7];
- } else {
- word[0] = usb_in_buffer[7];
- word[1] = usb_in_buffer[6];
- word[2] = usb_in_buffer[5];
- word[3] = usb_in_buffer[4];
- }
- word += 4;
-
- uint8_t i;
- for (i = 0; i < *extra_word_length; i++) {
- if (access_endian == AICE_BIG_ENDIAN) {
- word[0] = usb_in_buffer[8 + i * 4];
- word[1] = usb_in_buffer[9 + i * 4];
- word[2] = usb_in_buffer[10 + i * 4];
- word[3] = usb_in_buffer[11 + i * 4];
- } else {
- word[0] = usb_in_buffer[11 + i * 4];
- word[1] = usb_in_buffer[10 + i * 4];
- word[2] = usb_in_buffer[9 + i * 4];
- word[3] = usb_in_buffer[8 + i * 4];
- }
- word += 4;
- }
-}
-
-static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id,
- uint8_t *extra_word_length)
-{
- *cmd_ack_code = usb_in_buffer[0];
- *target_id = usb_in_buffer[1];
- *extra_word_length = usb_in_buffer[2];
-}
-
-/***************************************************************************/
-/* End of AICE commands' pack/unpack functions */
-
-/* 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),
- jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout)
-{
- int tries = 3, count = 0;
-
- while (tries && (count < size)) {
- int result = f(dev, ep, bytes + count, size - count, timeout);
- if (result > 0)
- count += result;
- else if ((-ETIMEDOUT != result) || !--tries)
- return result;
- }
- return count;
-}
-
-static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep,
- char *buff, int size, int timeout)
-{
- /* usb_bulk_write() takes const char *buff */
- return jtag_libusb_bulk_write(dev, ep, buff, size, timeout);
-}
-
-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);
-}
-
-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);
-}
-
-/* Write data from out_buffer to USB. */
-static int aice_usb_write(uint8_t *out_buffer, int out_length)
-{
- int result;
-
- if (out_length > AICE_OUT_BUFFER_SIZE) {
- LOG_ERROR("aice_write illegal out_length=%i (max=%i)",
- out_length, AICE_OUT_BUFFER_SIZE);
- return -1;
- }
-
- result = usb_bulk_write_ex(aice_handler.usb_handle, aice_handler.usb_write_ep,
- (char *)out_buffer, out_length, AICE_USB_TIMEOUT);
-
- DEBUG_JTAG_IO("aice_usb_write, out_length = %i, result = %i",
- out_length, result);
-
- return result;
-}
-
-/* Read data from USB into in_buffer. */
-static int aice_usb_read(uint8_t *in_buffer, int expected_size)
-{
- int32_t result = usb_bulk_read_ex(aice_handler.usb_handle, aice_handler.usb_read_ep,
- (char *)in_buffer, expected_size, AICE_USB_TIMEOUT);
-
- DEBUG_JTAG_IO("aice_usb_read, result = %" PRId32, result);
-
- return result;
-}
-
-static uint8_t usb_out_packets_buffer[AICE_OUT_PACKETS_BUFFER_SIZE];
-static uint8_t usb_in_packets_buffer[AICE_IN_PACKETS_BUFFER_SIZE];
-static uint32_t usb_out_packets_buffer_length;
-static uint32_t usb_in_packets_buffer_length;
-static enum aice_command_mode aice_command_mode;
-
-static int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word,
- uint32_t num_of_words);
-
-static int aice_usb_packet_flush(void)
-{
- if (usb_out_packets_buffer_length == 0)
- return 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_PACK)");
-
- if (aice_usb_write(usb_out_packets_buffer,
- usb_out_packets_buffer_length) < 0)
- return ERROR_FAIL;
-
- if (aice_usb_read(usb_in_packets_buffer,
- usb_in_packets_buffer_length) < 0)
- return ERROR_FAIL;
-
- usb_out_packets_buffer_length = 0;
- usb_in_packets_buffer_length = 0;
-
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_BATCH)");
-
- /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */
- if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0,
- usb_out_packets_buffer,
- (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK)
- return ERROR_FAIL;
-
- usb_out_packets_buffer_length = 0;
- usb_in_packets_buffer_length = 0;
-
- /* enable BATCH command */
- aice_command_mode = AICE_COMMAND_MODE_NORMAL;
- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL, 0x80000000) != ERROR_OK)
- return ERROR_FAIL;
- aice_command_mode = AICE_COMMAND_MODE_BATCH;
-
- /* wait 1 second (AICE bug, workaround) */
- alive_sleep(1000);
-
- /* check status */
- uint32_t i;
- uint32_t batch_status;
-
- i = 0;
- while (1) {
- aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
-
- if (batch_status & 0x1)
- return ERROR_OK;
- else if (batch_status & 0xE)
- return ERROR_FAIL;
-
- if ((i % 30) == 0)
- keep_alive();
-
- i++;
- }
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_packet_append(uint8_t *out_buffer, int out_length, int in_length)
-{
- uint32_t max_packet_size = AICE_OUT_PACKETS_BUFFER_SIZE;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- max_packet_size = AICE_OUT_PACK_COMMAND_SIZE;
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- max_packet_size = AICE_OUT_BATCH_COMMAND_SIZE;
- } else {
- /* AICE_COMMAND_MODE_NORMAL */
- if (aice_usb_packet_flush() != ERROR_OK)
- return ERROR_FAIL;
- }
-
- if (usb_out_packets_buffer_length + out_length > max_packet_size)
- if (aice_usb_packet_flush() != ERROR_OK) {
- LOG_DEBUG("Flush usb packets failed");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("Append usb packets 0x%02x", out_buffer[0]);
-
- memcpy(usb_out_packets_buffer + usb_out_packets_buffer_length, out_buffer, out_length);
- usb_out_packets_buffer_length += out_length;
- usb_in_packets_buffer_length += in_length;
-
- return ERROR_OK;
-}
-
-/***************************************************************************/
-/* AICE commands */
-static int aice_reset_box(void)
-{
- if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
- return ERROR_FAIL;
-
- /* turn off FASTMODE */
- uint32_t pin_status;
- if (aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status)
- != ERROR_OK)
- return ERROR_FAIL;
-
- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x2))
- != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int aice_scan_chain(uint32_t *id_codes, uint8_t *num_of_ids)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htda(AICE_CMD_SCAN_CHAIN, 0x0F, 0x0);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDA);
-
- LOG_DEBUG("SCAN_CHAIN, length: 0x0F");
-
- /** TODO: modify receive length */
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA);
- if (AICE_FORMAT_DTHA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHA, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- aice_unpack_dtha_multiple_data(&cmd_ack_code, num_of_ids, id_codes,
- 0x10, AICE_LITTLE_ENDIAN);
-
- if (cmd_ack_code != AICE_CMD_SCAN_CHAIN) {
-
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_SCAN_CHAIN, cmd_ack_code);
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- continue;
- }
-
- LOG_DEBUG("SCAN_CHAIN response, # of IDs: %" PRIu8, *num_of_ids);
-
- if (*num_of_ids == 0xFF) {
- LOG_ERROR("No target connected");
- return ERROR_FAIL;
- } else if (*num_of_ids == AICE_MAX_NUM_CORE) {
- LOG_INFO("The ice chain over 16 targets");
- } else {
- (*num_of_ids)++;
- }
- break;
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_read_ctrl(uint32_t address, uint32_t *data)
-{
- int32_t result;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- aice_pack_htda(AICE_CMD_READ_CTRL, 0, address);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDA);
-
- LOG_DEBUG("READ_CTRL, address: 0x%" PRIx32, address);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA);
- if (AICE_FORMAT_DTHA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHA, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- aice_unpack_dtha(&cmd_ack_code, &extra_length, data, AICE_LITTLE_ENDIAN);
-
- LOG_DEBUG("READ_CTRL response, data: 0x%" PRIx32, *data);
-
- if (cmd_ack_code != AICE_CMD_READ_CTRL) {
- LOG_ERROR("aice command error (command=0x%" PRIx32 ", response=0x%" PRIx8 ")",
- (uint32_t)AICE_CMD_READ_CTRL, cmd_ack_code);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-int aice_write_ctrl(uint32_t address, uint32_t data)
-{
- int32_t result;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDC,
- AICE_FORMAT_DTHB);
- }
-
- aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDC);
-
- LOG_DEBUG("WRITE_CTRL, address: 0x%" PRIx32 ", data: 0x%" PRIx32, address, data);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHB);
- if (AICE_FORMAT_DTHB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- aice_unpack_dthb(&cmd_ack_code, &extra_length);
-
- LOG_DEBUG("WRITE_CTRL response");
-
- if (cmd_ack_code != AICE_CMD_WRITE_CTRL) {
- LOG_ERROR("aice command error (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_WRITE_CTRL, cmd_ack_code);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-int aice_read_dtr(uint8_t target_id, uint32_t *data)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htdma(AICE_CMD_T_READ_DTR, target_id, 0, 0);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
-
- LOG_DEBUG("READ_DTR, COREID: %" PRIu8, target_id);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
- if (AICE_FORMAT_DTHMA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
- data, AICE_LITTLE_ENDIAN);
-
- if (cmd_ack_code == AICE_CMD_T_READ_DTR) {
- LOG_DEBUG("READ_DTR response, data: 0x%" PRIx32, *data);
- break;
- } else {
-
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_READ_DTR, cmd_ack_code);
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_read_dtr_to_buffer(uint8_t target_id, uint32_t buffer_idx)
-{
- int32_t result;
- int retry_times = 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
-
- LOG_DEBUG("READ_DTR_TO_BUFFER, COREID: %" PRIu8, target_id);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_READ_DTR_TO_BUFFER) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_READ_DTR_TO_BUFFER, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_write_dtr(uint8_t target_id, uint32_t data)
-{
- int32_t result;
- int retry_times = 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
-
- LOG_DEBUG("WRITE_DTR, COREID: %" PRIu8 ", data: 0x%" PRIx32, target_id, data);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_WRITE_DTR) {
- LOG_DEBUG("WRITE_DTR response");
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_WRITE_DTR, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_write_dtr_from_buffer(uint8_t target_id, uint32_t buffer_idx)
-{
- int32_t result;
- int retry_times = 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
-
- LOG_DEBUG("WRITE_DTR_FROM_BUFFER, COREID: %" PRIu8 "", target_id);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_WRITE_DTR_FROM_BUFFER) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_WRITE_DTR_FROM_BUFFER, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_read_misc(uint8_t target_id, uint32_t address, uint32_t *data)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htdma(AICE_CMD_T_READ_MISC, target_id, 0, address);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
-
- LOG_DEBUG("READ_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
- if (AICE_FORMAT_DTHMA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA, result);
- return ERROR_AICE_DISCONNECT;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
- data, AICE_LITTLE_ENDIAN);
-
- if (cmd_ack_code == AICE_CMD_T_READ_MISC) {
- LOG_DEBUG("READ_MISC response, data: 0x%" PRIx32, *data);
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_READ_MISC, cmd_ack_code);
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_write_misc(uint8_t target_id, uint32_t address, uint32_t data)
-{
- int32_t result;
- int retry_times = 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address, data,
- AICE_LITTLE_ENDIAN);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address,
- data, AICE_LITTLE_ENDIAN);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
-
- LOG_DEBUG("WRITE_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32,
- target_id, address, data);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_WRITE_MISC) {
- LOG_DEBUG("WRITE_MISC response");
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_WRITE_MISC, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_read_edmsr(uint8_t target_id, uint32_t address, uint32_t *data)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htdma(AICE_CMD_T_READ_EDMSR, target_id, 0, address);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
-
- LOG_DEBUG("READ_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
- if (AICE_FORMAT_DTHMA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
- data, AICE_LITTLE_ENDIAN);
-
- if (cmd_ack_code == AICE_CMD_T_READ_EDMSR) {
- LOG_DEBUG("READ_EDMSR response, data: 0x%" PRIx32, *data);
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_READ_EDMSR, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_write_edmsr(uint8_t target_id, uint32_t address, uint32_t data)
-{
- int32_t result;
- int retry_times = 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address, data,
- AICE_LITTLE_ENDIAN);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address,
- data, AICE_LITTLE_ENDIAN);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
-
- LOG_DEBUG("WRITE_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32,
- target_id, address, data);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_WRITE_EDMSR) {
- LOG_DEBUG("WRITE_EDMSR response");
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_WRITE_EDMSR, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-static int aice_switch_to_big_endian(uint32_t *word, uint8_t num_of_words)
-{
- uint32_t tmp;
-
- for (uint8_t i = 0 ; i < num_of_words ; i++) {
- tmp = ((word[i] >> 24) & 0x000000FF) |
- ((word[i] >> 8) & 0x0000FF00) |
- ((word[i] << 8) & 0x00FF0000) |
- ((word[i] << 24) & 0xFF000000);
- word[i] = tmp;
- }
-
- return ERROR_OK;
-}
-
-static int aice_write_dim(uint8_t target_id, uint32_t *word, uint8_t num_of_words)
-{
- int32_t result;
- uint32_t big_endian_word[4];
- int retry_times = 0;
-
- /** instruction is big-endian */
- memcpy(big_endian_word, word, sizeof(big_endian_word));
- aice_switch_to_big_endian(big_endian_word, num_of_words);
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id,
- num_of_words - 1, 0, big_endian_word, num_of_words,
- AICE_LITTLE_ENDIAN);
- return aice_usb_packet_append(usb_out_buffer,
- AICE_FORMAT_HTDMC + (num_of_words - 1) * 4,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id, num_of_words - 1, 0,
- big_endian_word, num_of_words, AICE_LITTLE_ENDIAN);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4);
-
- LOG_DEBUG("WRITE_DIM, COREID: %" PRIu8
- ", data: 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32,
- target_id,
- big_endian_word[0],
- big_endian_word[1],
- big_endian_word[2],
- big_endian_word[3]);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
-
- if (cmd_ack_code == AICE_CMD_T_WRITE_DIM) {
- LOG_DEBUG("WRITE_DIM response");
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8
- ", response=0x%" PRIx8 ")",
- AICE_CMD_T_WRITE_DIM, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-static int aice_do_execute(uint8_t target_id)
-{
- int32_t result;
- int retry_times = 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN);
- return aice_usb_packet_append(usb_out_buffer,
- AICE_FORMAT_HTDMC,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
-
- LOG_DEBUG("EXECUTE, COREID: %" PRIu8 "", target_id);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_EXECUTE) {
- LOG_DEBUG("EXECUTE response");
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_EXECUTE, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_write_mem_b(uint8_t target_id, uint32_t address, uint32_t data)
-{
- int32_t result;
- int retry_times = 0;
-
- LOG_DEBUG("WRITE_MEM_B, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32,
- target_id,
- address,
- data);
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode)) {
- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0, address,
- data & 0x000000FF, data_endian);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
- AICE_FORMAT_DTHMB);
- } else {
- do {
- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0,
- address, data & 0x000000FF, data_endian);
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32
- ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_B) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_WRITE_MEM_B, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
- }
-
- return ERROR_OK;
-}
-
-int aice_write_mem_h(uint8_t target_id, uint32_t address, uint32_t data)
-{
- int32_t result;
- int retry_times = 0;
-
- LOG_DEBUG("WRITE_MEM_H, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32,
- target_id,
- address,
- data);
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode)) {
- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0,
- (address >> 1) & 0x7FFFFFFF, data & 0x0000FFFF, data_endian);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
- AICE_FORMAT_DTHMB);
- } else {
- do {
- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0,
- (address >> 1) & 0x7FFFFFFF, data & 0x0000FFFF, data_endian);
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_H) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_WRITE_MEM_H, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
- }
-
- return ERROR_OK;
-}
-
-int aice_write_mem(uint8_t target_id, uint32_t address, uint32_t data)
-{
- int32_t result;
- int retry_times = 0;
-
- LOG_DEBUG("WRITE_MEM, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32,
- target_id,
- address,
- data);
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode)) {
- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0,
- (address >> 2) & 0x3FFFFFFF, data, data_endian);
- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
- AICE_FORMAT_DTHMB);
- } else {
- do {
- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0,
- (address >> 2) & 0x3FFFFFFF, data, data_endian);
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_WRITE_MEM) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_WRITE_MEM, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
- }
-
- return ERROR_OK;
-}
-
-int aice_fastread_mem(uint8_t target_id, uint8_t *word, uint32_t num_of_words)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htdmb(AICE_CMD_T_FASTREAD_MEM, target_id, num_of_words - 1, 0);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
-
- LOG_DEBUG("FASTREAD_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32,
- target_id, num_of_words);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4);
- if (result < 0) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma_multiple_data(&cmd_ack_code, &res_target_id,
- &extra_length, word, data_endian);
-
- if (cmd_ack_code == AICE_CMD_T_FASTREAD_MEM) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_FASTREAD_MEM, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_fastwrite_mem(uint8_t target_id, const uint8_t *word, uint32_t num_of_words)
-{
- int32_t result;
- int retry_times = 0;
-
- if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
- aice_usb_packet_flush();
- } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
- aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id,
- num_of_words - 1, 0, word, data_endian);
- return aice_usb_packet_append(usb_out_buffer,
- AICE_FORMAT_HTDMD + (num_of_words - 1) * 4,
- AICE_FORMAT_DTHMB);
- }
-
- do {
- aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id,
- num_of_words - 1, 0, word, data_endian);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD + (num_of_words - 1) * 4);
-
- LOG_DEBUG("FASTWRITE_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32,
- target_id, num_of_words);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_T_FASTWRITE_MEM) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_FASTWRITE_MEM, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_read_mem_b(uint8_t target_id, uint32_t address, uint32_t *data)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htdmb(AICE_CMD_T_READ_MEM_B, target_id, 0, address);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
-
- LOG_DEBUG("READ_MEM_B, COREID: %" PRIu8 "", target_id);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
- if (AICE_FORMAT_DTHMA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
- data, data_endian);
-
- if (cmd_ack_code == AICE_CMD_T_READ_MEM_B) {
- LOG_DEBUG("READ_MEM_B response, data: 0x%02" PRIx32, *data);
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_READ_MEM_B, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_read_mem_h(uint8_t target_id, uint32_t address, uint32_t *data)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htdmb(AICE_CMD_T_READ_MEM_H, target_id, 0, (address >> 1) & 0x7FFFFFFF);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
-
- LOG_DEBUG("READ_MEM_H, CORE_ID: %" PRIu8 "", target_id);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
- if (AICE_FORMAT_DTHMA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
- data, data_endian);
-
- if (cmd_ack_code == AICE_CMD_T_READ_MEM_H) {
- LOG_DEBUG("READ_MEM_H response, data: 0x%" PRIx32, *data);
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_READ_MEM_H, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_read_mem(uint8_t target_id, uint32_t address, uint32_t *data)
-{
- int32_t result;
- int retry_times = 0;
-
- if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
- (AICE_COMMAND_MODE_BATCH == aice_command_mode))
- aice_usb_packet_flush();
-
- do {
- aice_pack_htdmb(AICE_CMD_T_READ_MEM, target_id, 0,
- (address >> 2) & 0x3FFFFFFF);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
-
- LOG_DEBUG("READ_MEM, COREID: %" PRIu8 "", target_id);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
- if (AICE_FORMAT_DTHMA != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
- data, data_endian);
-
- if (cmd_ack_code == AICE_CMD_T_READ_MEM) {
- LOG_DEBUG("READ_MEM response, data: 0x%" PRIx32, *data);
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_T_READ_MEM, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_batch_buffer_read(uint8_t buf_index, uint32_t *word, uint32_t num_of_words)
-{
- int32_t result;
- int retry_times = 0;
-
- do {
- aice_pack_htdma(AICE_CMD_BATCH_BUFFER_READ, 0, num_of_words - 1, buf_index);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
-
- LOG_DEBUG("BATCH_BUFFER_READ, # of DATA %08" PRIx32, num_of_words);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4);
- if (result < 0) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthma_multiple_data(&cmd_ack_code, &res_target_id,
- &extra_length, (uint8_t *)word, data_endian);
-
- if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_READ) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_BATCH_BUFFER_READ, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word, uint32_t num_of_words)
-{
- int32_t result;
- int retry_times = 0;
-
- if (num_of_words == 0)
- return ERROR_OK;
-
- do {
- /* only pack AICE_CMD_BATCH_BUFFER_WRITE command header */
- aice_pack_htdmc(AICE_CMD_BATCH_BUFFER_WRITE, 0, num_of_words - 1, buf_index,
- 0, data_endian);
-
- /* use append instead of pack */
- memcpy(usb_out_buffer + 4, word, num_of_words * 4);
-
- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4);
-
- LOG_DEBUG("BATCH_BUFFER_WRITE, # of DATA %08" PRIx32, num_of_words);
-
- result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
- if (AICE_FORMAT_DTHMB != result) {
- LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
- AICE_FORMAT_DTHMB, result);
- return ERROR_FAIL;
- }
-
- uint8_t cmd_ack_code;
- uint8_t extra_length;
- uint8_t res_target_id;
- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
-
- if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_WRITE) {
- break;
- } else {
- if (retry_times > aice_max_retry_times) {
- LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
- AICE_CMD_BATCH_BUFFER_WRITE, cmd_ack_code);
-
- return ERROR_FAIL;
- }
-
- /* clear timeout and retry */
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- retry_times++;
- }
- } while (1);
-
- return ERROR_OK;
-}
-
-/***************************************************************************/
-/* End of AICE commands */
-
-typedef int (*read_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t *data);
-typedef int (*write_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t data);
-
-struct aice_nds32_info core_info[AICE_MAX_NUM_CORE];
-static uint8_t total_num_of_core;
-
-static char *custom_srst_script;
-static char *custom_trst_script;
-static char *custom_restart_script;
-static uint32_t aice_count_to_check_dbger = 30;
-
-static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val);
-static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val);
-
-static int check_suppressed_exception(uint32_t coreid, uint32_t dbger_value)
-{
- uint32_t ir4_value;
- uint32_t ir6_value;
- /* the default value of handling_suppressed_exception is false */
- static bool handling_suppressed_exception;
-
- if (handling_suppressed_exception)
- return ERROR_OK;
-
- if ((dbger_value & NDS_DBGER_ALL_SUPRS_EX) == NDS_DBGER_ALL_SUPRS_EX) {
- LOG_ERROR("<-- TARGET WARNING! Exception is detected and suppressed. -->");
- handling_suppressed_exception = true;
-
- aice_read_reg(coreid, IR4, &ir4_value);
- /* Clear IR6.SUPRS_EXC, IR6.IMP_EXC */
- aice_read_reg(coreid, IR6, &ir6_value);
- /*
- * For MCU version(MSC_CFG.MCU == 1) like V3m
- * | SWID[30:16] | Reserved[15:10] | SUPRS_EXC[9] | IMP_EXC[8]
- * |VECTOR[7:5] | INST[4] | Exc Type[3:0] |
- *
- * For non-MCU version(MSC_CFG.MCU == 0) like V3
- * | SWID[30:16] | Reserved[15:14] | SUPRS_EXC[13] | IMP_EXC[12]
- * | VECTOR[11:5] | INST[4] | Exc Type[3:0] |
- */
- LOG_INFO("EVA: 0x%08" PRIx32, ir4_value);
- LOG_INFO("ITYPE: 0x%08" PRIx32, ir6_value);
-
- ir6_value = ir6_value & (~0x300); /* for MCU */
- ir6_value = ir6_value & (~0x3000); /* for non-MCU */
- aice_write_reg(coreid, IR6, ir6_value);
-
- handling_suppressed_exception = false;
- }
-
- return ERROR_OK;
-}
-
-static int check_privilege(uint32_t coreid, uint32_t dbger_value)
-{
- if ((dbger_value & NDS_DBGER_ILL_SEC_ACC) == NDS_DBGER_ILL_SEC_ACC) {
- LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege "
- "to execute the debug operations. -->");
-
- /* Clear DBGER.ILL_SEC_ACC */
- if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
- NDS_DBGER_ILL_SEC_ACC) != ERROR_OK)
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_check_dbger(uint32_t coreid, uint32_t expect_status)
-{
- uint32_t i = 0;
- uint32_t value_dbger;
-
- while (1) {
- aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &value_dbger);
-
- if ((value_dbger & expect_status) == expect_status) {
- if (ERROR_OK != check_suppressed_exception(coreid, value_dbger))
- return ERROR_FAIL;
- if (ERROR_OK != check_privilege(coreid, value_dbger))
- return ERROR_FAIL;
- return ERROR_OK;
- }
-
- if ((i % 30) == 0)
- keep_alive();
-
- int64_t then = 0;
- if (i == aice_count_to_check_dbger)
- then = timeval_ms();
- if (i >= aice_count_to_check_dbger) {
- if ((timeval_ms() - then) > 1000) {
- LOG_ERROR("Timeout (1000ms) waiting for $DBGER status "
- "being 0x%08" PRIx32, expect_status);
- return ERROR_FAIL;
- }
- }
- i++;
- }
-
- return ERROR_FAIL;
-}
-
-static int aice_execute_dim(uint32_t coreid, uint32_t *insts, uint8_t n_inst)
-{
- /** fill DIM */
- if (aice_write_dim(coreid, insts, n_inst) != ERROR_OK)
- return ERROR_FAIL;
-
- /** clear DBGER.DPED */
- if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK)
- return ERROR_FAIL;
-
- /** execute DIM */
- if (aice_do_execute(coreid) != ERROR_OK)
- return ERROR_FAIL;
-
- /** read DBGER.DPED */
- if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) {
- LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly: "
- "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 ". -->",
- insts[0],
- insts[1],
- insts[2],
- insts[3]);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
-{
- LOG_DEBUG("aice_read_reg, reg_no: 0x%08" PRIx32, num);
-
- uint32_t instructions[4]; /** execute instructions in DIM */
-
- if (NDS32_REG_TYPE_GPR == nds32_reg_type(num)) { /* general registers */
- instructions[0] = MTSR_DTR(num);
- instructions[1] = DSB;
- instructions[2] = NOP;
- instructions[3] = BEQ_MINUS_12;
- } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(num)) { /* user special registers */
- instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(num));
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else if (NDS32_REG_TYPE_AUMR == nds32_reg_type(num)) { /* audio registers */
- if ((CB_CTL <= num) && (num <= CBE3)) {
- instructions[0] = AMFAR2(0, nds32_reg_sr_index(num));
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else {
- instructions[0] = AMFAR(0, nds32_reg_sr_index(num));
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- }
- } else if (NDS32_REG_TYPE_FPU == nds32_reg_type(num)) { /* fpu registers */
- if (FPCSR == num) {
- instructions[0] = FMFCSR;
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else if (FPCFG == num) {
- instructions[0] = FMFCFG;
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else {
- if (FS0 <= num && num <= FS31) { /* single precision */
- instructions[0] = FMFSR(0, nds32_reg_sr_index(num));
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else if (FD0 <= num && num <= FD31) { /* double precision */
- instructions[0] = FMFDR(0, nds32_reg_sr_index(num));
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- }
- }
- } else { /* system registers */
- instructions[0] = MFSR(0, nds32_reg_sr_index(num));
- instructions[1] = MTSR_DTR(0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- }
-
- aice_execute_dim(coreid, instructions, 4);
-
- uint32_t value_edmsw;
- aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
- if (value_edmsw & NDS_EDMSW_WDV)
- aice_read_dtr(coreid, val);
- else {
- LOG_ERROR("<-- TARGET ERROR! The debug target failed to update "
- "the DTR register. -->");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
-{
- LOG_DEBUG("aice_usb_read_reg");
-
- if (num == R0) {
- *val = core_info[coreid].r0_backup;
- } else if (num == R1) {
- *val = core_info[coreid].r1_backup;
- } else if (num == DR41) {
- /* As target is halted, OpenOCD will backup DR41/DR42/DR43.
- * As user wants to read these registers, OpenOCD should return
- * the backup values, instead of reading the real values.
- * As user wants to write these registers, OpenOCD should write
- * to the backup values, instead of writing to real registers. */
- *val = core_info[coreid].edmsw_backup;
- } else if (num == DR42) {
- *val = core_info[coreid].edm_ctl_backup;
- } else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43)) {
- *val = core_info[coreid].target_dtr_backup;
- } else {
- if (ERROR_OK != aice_read_reg(coreid, num, val))
- *val = 0xBBADBEEF;
- }
-
- return ERROR_OK;
-}
-
-static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
-{
- LOG_DEBUG("aice_write_reg, reg_no: 0x%08" PRIx32 ", value: 0x%08" PRIx32, num, val);
-
- uint32_t instructions[4]; /** execute instructions in DIM */
- uint32_t value_edmsw;
-
- aice_write_dtr(coreid, val);
- aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
- if (0 == (value_edmsw & NDS_EDMSW_RDV)) {
- LOG_ERROR("<-- TARGET ERROR! AICE failed to write to the DTR register. -->");
- return ERROR_FAIL;
- }
-
- if (NDS32_REG_TYPE_GPR == nds32_reg_type(num)) { /* general registers */
- instructions[0] = MFSR_DTR(num);
- instructions[1] = DSB;
- instructions[2] = NOP;
- instructions[3] = BEQ_MINUS_12;
- } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(num)) { /* user special registers */
- instructions[0] = MFSR_DTR(0);
- instructions[1] = MTUSR_G0(0, nds32_reg_sr_index(num));
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else if (NDS32_REG_TYPE_AUMR == nds32_reg_type(num)) { /* audio registers */
- if ((CB_CTL <= num) && (num <= CBE3)) {
- instructions[0] = MFSR_DTR(0);
- instructions[1] = AMTAR2(0, nds32_reg_sr_index(num));
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else {
- instructions[0] = MFSR_DTR(0);
- instructions[1] = AMTAR(0, nds32_reg_sr_index(num));
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- }
- } else if (NDS32_REG_TYPE_FPU == nds32_reg_type(num)) { /* fpu registers */
- if (FPCSR == num) {
- instructions[0] = MFSR_DTR(0);
- instructions[1] = FMTCSR;
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else if (FPCFG == num) {
- /* FPCFG is readonly */
- } else {
- if (FS0 <= num && num <= FS31) { /* single precision */
- instructions[0] = MFSR_DTR(0);
- instructions[1] = FMTSR(0, nds32_reg_sr_index(num));
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- } else if (FD0 <= num && num <= FD31) { /* double precision */
- instructions[0] = MFSR_DTR(0);
- instructions[1] = FMTDR(0, nds32_reg_sr_index(num));
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- }
- }
- } else {
- instructions[0] = MFSR_DTR(0);
- instructions[1] = MTSR(0, nds32_reg_sr_index(num));
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- }
-
- return aice_execute_dim(coreid, instructions, 4);
-}
-
-static int aice_usb_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
-{
- LOG_DEBUG("aice_usb_write_reg");
-
- if (num == R0)
- core_info[coreid].r0_backup = val;
- else if (num == R1)
- core_info[coreid].r1_backup = val;
- else if (num == DR42)
- /* As target is halted, OpenOCD will backup DR41/DR42/DR43.
- * As user wants to read these registers, OpenOCD should return
- * the backup values, instead of reading the real values.
- * As user wants to write these registers, OpenOCD should write
- * to the backup values, instead of writing to real registers. */
- core_info[coreid].edm_ctl_backup = val;
- else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43))
- core_info[coreid].target_dtr_backup = val;
- else
- return aice_write_reg(coreid, num, val);
-
- return ERROR_OK;
-}
-
-static int aice_usb_open(struct aice_port_param_s *param)
-{
- const uint16_t vids[] = { param->vid, 0 };
- const uint16_t pids[] = { param->pid, 0 };
- struct jtag_libusb_device_handle *devh;
-
- if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
- return ERROR_FAIL;
-
- /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
- * AREA!!!!!!!!!!! The behavior of libusb is not completely
- * consistent across Windows, Linux, and Mac OS X platforms.
- * The actions taken in the following compiler conditionals may
- * not agree with published documentation for libusb, but were
- * found to be necessary through trials and tribulations. Even
- * little tweaks can break one or more platforms, so if you do
- * make changes test them carefully on all platforms before
- * committing them!
- */
-
-#if IS_WIN32 == 0
-
- jtag_libusb_reset_device(devh);
-
-#if IS_DARWIN == 0
-
- int timeout = 5;
- /* reopen jlink after usb_reset
- * on win32 this may take a second or two to re-enumerate */
- int retval;
- while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
- usleep(1000);
- timeout--;
- if (!timeout)
- break;
- }
- if (ERROR_OK != retval)
- return ERROR_FAIL;
-#endif
-
-#endif
-
- /* usb_set_configuration required under win32 */
- jtag_libusb_set_configuration(devh, 0);
-
- unsigned int aice_read_ep;
- unsigned int aice_write_ep;
- jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1);
-
- aice_handler.usb_read_ep = aice_read_ep;
- aice_handler.usb_write_ep = aice_write_ep;
- aice_handler.usb_handle = devh;
-
- return ERROR_OK;
-}
-
-static int aice_usb_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val)
-{
- LOG_DEBUG("aice_usb_read_reg_64, %s", nds32_reg_simple_name(num));
-
- uint32_t value;
- uint32_t high_value;
-
- if (ERROR_OK != aice_read_reg(coreid, num, &value))
- value = 0xBBADBEEF;
-
- aice_read_reg(coreid, R1, &high_value);
-
- LOG_DEBUG("low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n", value, high_value);
-
- if (data_endian == AICE_BIG_ENDIAN)
- *val = (((uint64_t)high_value) << 32) | value;
- else
- *val = (((uint64_t)value) << 32) | high_value;
-
- return ERROR_OK;
-}
-
-static int aice_usb_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val)
-{
- uint32_t value;
- uint32_t high_value;
-
- if (data_endian == AICE_BIG_ENDIAN) {
- value = val & 0xFFFFFFFF;
- high_value = (val >> 32) & 0xFFFFFFFF;
- } else {
- high_value = val & 0xFFFFFFFF;
- value = (val >> 32) & 0xFFFFFFFF;
- }
-
- LOG_DEBUG("aice_usb_write_reg_64, %s, low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n",
- nds32_reg_simple_name(num), value, high_value);
-
- aice_write_reg(coreid, R1, high_value);
- return aice_write_reg(coreid, num, value);
-}
-
-static int aice_get_version_info(void)
-{
- uint32_t hardware_version;
- uint32_t firmware_version;
- uint32_t fpga_version;
-
- if (aice_read_ctrl(AICE_READ_CTRL_GET_HARDWARE_VERSION, &hardware_version) != ERROR_OK)
- return ERROR_FAIL;
-
- if (aice_read_ctrl(AICE_READ_CTRL_GET_FIRMWARE_VERSION, &firmware_version) != ERROR_OK)
- return ERROR_FAIL;
-
- if (aice_read_ctrl(AICE_READ_CTRL_GET_FPGA_VERSION, &fpga_version) != ERROR_OK)
- return ERROR_FAIL;
-
- LOG_INFO("AICE version: hw_ver = 0x%" PRIx32 ", fw_ver = 0x%" PRIx32 ", fpga_ver = 0x%" PRIx32,
- hardware_version, firmware_version, fpga_version);
-
- return ERROR_OK;
-}
-
-#define LINE_BUFFER_SIZE 1024
-
-static int aice_execute_custom_script(const char *script)
-{
- FILE *script_fd;
- char line_buffer[LINE_BUFFER_SIZE];
- char *op_str;
- char *reset_str;
- uint32_t delay;
- uint32_t write_ctrl_value;
- bool set_op;
-
- script_fd = fopen(script, "r");
- if (script_fd == NULL) {
- return ERROR_FAIL;
- } else {
- while (fgets(line_buffer, LINE_BUFFER_SIZE, script_fd) != NULL) {
- /* execute operations */
- set_op = false;
- op_str = strstr(line_buffer, "set");
- if (op_str != NULL) {
- set_op = true;
- goto get_reset_type;
- }
-
- op_str = strstr(line_buffer, "clear");
- if (op_str == NULL)
- continue;
-get_reset_type:
- reset_str = strstr(op_str, "srst");
- if (reset_str != NULL) {
- if (set_op)
- write_ctrl_value = AICE_CUSTOM_DELAY_SET_SRST;
- else
- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_SRST;
- goto get_delay;
- }
- reset_str = strstr(op_str, "dbgi");
- if (reset_str != NULL) {
- if (set_op)
- write_ctrl_value = AICE_CUSTOM_DELAY_SET_DBGI;
- else
- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_DBGI;
- goto get_delay;
- }
- reset_str = strstr(op_str, "trst");
- if (reset_str != NULL) {
- if (set_op)
- write_ctrl_value = AICE_CUSTOM_DELAY_SET_TRST;
- else
- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_TRST;
- goto get_delay;
- }
- continue;
-get_delay:
- /* get delay */
- delay = strtoul(reset_str + 4, NULL, 0);
- write_ctrl_value |= (delay << 16);
-
- if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
- write_ctrl_value) != ERROR_OK) {
- fclose(script_fd);
- return ERROR_FAIL;
- }
- }
- fclose(script_fd);
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_clock(int set_clock)
-{
- if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL,
- AICE_TCK_CONTROL_TCK_SCAN) != ERROR_OK)
- return ERROR_FAIL;
-
- /* Read out TCK_SCAN clock value */
- uint32_t scan_clock;
- if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &scan_clock) != ERROR_OK)
- return ERROR_FAIL;
-
- scan_clock &= 0x0F;
-
- uint32_t scan_base_freq;
- if (scan_clock & 0x8)
- scan_base_freq = 48000; /* 48 MHz */
- else
- scan_base_freq = 30000; /* 30 MHz */
-
- uint32_t set_base_freq;
- if (set_clock & 0x8)
- set_base_freq = 48000;
- else
- set_base_freq = 30000;
-
- uint32_t set_freq;
- uint32_t scan_freq;
- set_freq = set_base_freq >> (set_clock & 0x7);
- scan_freq = scan_base_freq >> (scan_clock & 0x7);
-
- if (scan_freq < set_freq) {
- LOG_ERROR("User specifies higher jtag clock than TCK_SCAN clock");
- return ERROR_FAIL;
- }
-
- if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, set_clock) != ERROR_OK)
- return ERROR_FAIL;
-
- uint32_t check_speed;
- if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &check_speed) != ERROR_OK)
- return ERROR_FAIL;
-
- if (((int)check_speed & 0x0F) != set_clock) {
- LOG_ERROR("Set jtag clock failed");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_edm_init(uint32_t coreid)
-{
- aice_write_edmsr(coreid, NDS_EDM_SR_DIMBR, 0xFFFF0000);
- aice_write_misc(coreid, NDS_EDM_MISC_DIMIR, 0);
-
- /* unconditionally try to turn on V3_EDM_MODE */
- uint32_t edm_ctl_value;
- aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
- aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value | 0x00000040);
-
- /* clear DBGER */
- aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
- NDS_DBGER_DPED | NDS_DBGER_CRST | NDS_DBGER_AT_MAX);
-
- /* get EDM version */
- uint32_t value_edmcfg;
- aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CFG, &value_edmcfg);
- core_info[coreid].edm_version = (value_edmcfg >> 16) & 0xFFFF;
-
- return ERROR_OK;
-}
-
-static bool is_v2_edm(uint32_t coreid)
-{
- if ((core_info[coreid].edm_version & 0x1000) == 0)
- return true;
- else
- return false;
-}
-
-static int aice_init_edm_registers(uint32_t coreid, bool clear_dex_use_psw)
-{
- /* enable DEH_SEL & MAX_STOP & V3_EDM_MODE & DBGI_MASK */
- uint32_t host_edm_ctl = core_info[coreid].edm_ctl_backup | 0xA000004F;
- if (clear_dex_use_psw)
- /* After entering debug mode, OpenOCD may set
- * DEX_USE_PSW accidentally through backup value
- * of target EDM_CTL.
- * So, clear DEX_USE_PSW by force. */
- host_edm_ctl &= ~(0x40000000);
-
- LOG_DEBUG("aice_init_edm_registers - EDM_CTL: 0x%08" PRIx32, host_edm_ctl);
-
- int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, host_edm_ctl);
-
- return result;
-}
-
-/**
- * EDM_CTL will be modified by OpenOCD as debugging. OpenOCD has the
- * responsibility to keep EDM_CTL untouched after debugging.
- *
- * There are two scenarios to consider:
- * 1. single step/running as debugging (running under debug session)
- * 2. detached from gdb (exit debug session)
- *
- * So, we need to bakcup EDM_CTL before halted and restore it after
- * running. The difference of these two scenarios is EDM_CTL.DEH_SEL
- * is on for scenario 1, and off for scenario 2.
- */
-static int aice_backup_edm_registers(uint32_t coreid)
-{
- int result = aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL,
- &core_info[coreid].edm_ctl_backup);
-
- /* To call aice_backup_edm_registers() after DEX on, DEX_USE_PSW
- * may be not correct. (For example, hit breakpoint, then backup
- * EDM_CTL. EDM_CTL.DEX_USE_PSW will be cleared.) Because debug
- * interrupt will clear DEX_USE_PSW, DEX_USE_PSW is always off after
- * DEX is on. It only backups correct value before OpenOCD issues DBGI.
- * (Backup EDM_CTL, then issue DBGI actively (refer aice_usb_halt())) */
- if (core_info[coreid].edm_ctl_backup & 0x40000000)
- core_info[coreid].dex_use_psw_on = true;
- else
- core_info[coreid].dex_use_psw_on = false;
-
- LOG_DEBUG("aice_backup_edm_registers - EDM_CTL: 0x%08" PRIx32 ", DEX_USE_PSW: %s",
- core_info[coreid].edm_ctl_backup,
- core_info[coreid].dex_use_psw_on ? "on" : "off");
-
- return result;
-}
-
-static int aice_restore_edm_registers(uint32_t coreid)
-{
- LOG_DEBUG("aice_restore_edm_registers -");
-
- /* set DEH_SEL, because target still under EDM control */
- int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL,
- core_info[coreid].edm_ctl_backup | 0x80000000);
-
- return result;
-}
-
-static int aice_backup_tmp_registers(uint32_t coreid)
-{
- LOG_DEBUG("backup_tmp_registers -");
-
- /* backup target DTR first(if the target DTR is valid) */
- uint32_t value_edmsw;
- aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
- core_info[coreid].edmsw_backup = value_edmsw;
- if (value_edmsw & 0x1) { /* EDMSW.WDV == 1 */
- aice_read_dtr(coreid, &core_info[coreid].target_dtr_backup);
- core_info[coreid].target_dtr_valid = true;
-
- LOG_DEBUG("Backup target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup);
- } else {
- core_info[coreid].target_dtr_valid = false;
- }
-
- /* Target DTR has been backup, then backup $R0 and $R1 */
- aice_read_reg(coreid, R0, &core_info[coreid].r0_backup);
- aice_read_reg(coreid, R1, &core_info[coreid].r1_backup);
-
- /* backup host DTR(if the host DTR is valid) */
- if (value_edmsw & 0x2) { /* EDMSW.RDV == 1*/
- /* read out host DTR and write into target DTR, then use aice_read_edmsr to
- * read out */
- uint32_t instructions[4] = {
- MFSR_DTR(R0), /* R0 has already been backup */
- DSB,
- MTSR_DTR(R0),
- BEQ_MINUS_12
- };
- aice_execute_dim(coreid, instructions, 4);
-
- aice_read_dtr(coreid, &core_info[coreid].host_dtr_backup);
- core_info[coreid].host_dtr_valid = true;
-
- LOG_DEBUG("Backup host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup);
- } else {
- core_info[coreid].host_dtr_valid = false;
- }
-
- LOG_DEBUG("r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32,
- core_info[coreid].r0_backup, core_info[coreid].r1_backup);
-
- return ERROR_OK;
-}
-
-static int aice_restore_tmp_registers(uint32_t coreid)
-{
- LOG_DEBUG("restore_tmp_registers - r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32,
- core_info[coreid].r0_backup, core_info[coreid].r1_backup);
-
- if (core_info[coreid].target_dtr_valid) {
- uint32_t instructions[4] = {
- SETHI(R0, core_info[coreid].target_dtr_backup >> 12),
- ORI(R0, R0, core_info[coreid].target_dtr_backup & 0x00000FFF),
- NOP,
- BEQ_MINUS_12
- };
- aice_execute_dim(coreid, instructions, 4);
-
- instructions[0] = MTSR_DTR(R0);
- instructions[1] = DSB;
- instructions[2] = NOP;
- instructions[3] = BEQ_MINUS_12;
- aice_execute_dim(coreid, instructions, 4);
-
- LOG_DEBUG("Restore target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup);
- }
-
- aice_write_reg(coreid, R0, core_info[coreid].r0_backup);
- aice_write_reg(coreid, R1, core_info[coreid].r1_backup);
-
- if (core_info[coreid].host_dtr_valid) {
- aice_write_dtr(coreid, core_info[coreid].host_dtr_backup);
-
- LOG_DEBUG("Restore host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup);
- }
-
- return ERROR_OK;
-}
-
-static int aice_open_device(struct aice_port_param_s *param)
-{
- if (ERROR_OK != aice_usb_open(param))
- return ERROR_FAIL;
-
- if (ERROR_FAIL == aice_get_version_info()) {
- LOG_ERROR("Cannot get AICE version!");
- return ERROR_FAIL;
- }
-
- LOG_INFO("AICE initialization started");
-
- /* attempt to reset Andes EDM */
- if (ERROR_FAIL == aice_reset_box()) {
- LOG_ERROR("Cannot initial AICE box!");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_jtag_clock(uint32_t a_clock)
-{
- jtag_clock = a_clock;
-
- if (ERROR_OK != aice_usb_set_clock(a_clock)) {
- LOG_ERROR("Cannot set AICE JTAG clock!");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_close(void)
-{
- jtag_libusb_close(aice_handler.usb_handle);
-
- if (custom_srst_script)
- free(custom_srst_script);
-
- if (custom_trst_script)
- free(custom_trst_script);
-
- if (custom_restart_script)
- free(custom_restart_script);
-
- return ERROR_OK;
-}
-
-static int aice_core_init(uint32_t coreid)
-{
- core_info[coreid].access_channel = NDS_MEMORY_ACC_CPU;
- core_info[coreid].memory_select = NDS_MEMORY_SELECT_AUTO;
- core_info[coreid].core_state = AICE_TARGET_UNKNOWN;
-
- return ERROR_OK;
-}
-
-static int aice_usb_idcode(uint32_t *idcode, uint8_t *num_of_idcode)
-{
- int retval;
-
- retval = aice_scan_chain(idcode, num_of_idcode);
- if (ERROR_OK == retval) {
- for (int i = 0; i < *num_of_idcode; i++) {
- aice_core_init(i);
- aice_edm_init(i);
- }
- total_num_of_core = *num_of_idcode;
- }
-
- return retval;
-}
-
-static int aice_usb_halt(uint32_t coreid)
-{
- if (core_info[coreid].core_state == AICE_TARGET_HALTED) {
- LOG_DEBUG("aice_usb_halt check halted");
- return ERROR_OK;
- }
-
- LOG_DEBUG("aice_usb_halt");
-
- /** backup EDM registers */
- aice_backup_edm_registers(coreid);
- /** init EDM for host debugging */
- /** no need to clear dex_use_psw, because dbgi will clear it */
- aice_init_edm_registers(coreid, false);
-
- /** Clear EDM_CTL.DBGIM & EDM_CTL.DBGACKM */
- uint32_t edm_ctl_value;
- aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
- if (edm_ctl_value & 0x3)
- aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value & ~(0x3));
-
- uint32_t dbger;
- uint32_t acc_ctl_value;
-
- core_info[coreid].debug_under_dex_on = false;
- aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger);
-
- if (dbger & NDS_DBGER_AT_MAX)
- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level. -->");
-
- if (dbger & NDS_DBGER_DEX) {
- if (is_v2_edm(coreid) == false) {
- /** debug 'debug mode'. use force_debug to issue dbgi */
- aice_read_misc(coreid, NDS_EDM_MISC_ACC_CTL, &acc_ctl_value);
- acc_ctl_value |= 0x8;
- aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL, acc_ctl_value);
- core_info[coreid].debug_under_dex_on = true;
-
- aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0);
- /* If CPU stalled due to AT_MAX, clear AT_MAX status. */
- if (dbger & NDS_DBGER_AT_MAX)
- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
- }
- } else {
- /** Issue DBGI normally */
- aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0);
- /* If CPU stalled due to AT_MAX, clear AT_MAX status. */
- if (dbger & NDS_DBGER_AT_MAX)
- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
- }
-
- if (aice_check_dbger(coreid, NDS_DBGER_DEX) != ERROR_OK) {
- LOG_ERROR("<-- TARGET ERROR! Unable to stop the debug target through DBGI. -->");
- return ERROR_FAIL;
- }
-
- if (core_info[coreid].debug_under_dex_on) {
- if (core_info[coreid].dex_use_psw_on == false) {
- /* under debug 'debug mode', force $psw to 'debug mode' bahavior */
- /* !!!NOTICE!!! this is workaround for debug 'debug mode'.
- * it is only for debugging 'debug exception handler' purpose.
- * after openocd detaches from target, target behavior is
- * undefined. */
- uint32_t ir0_value;
- uint32_t debug_mode_ir0_value;
- aice_read_reg(coreid, IR0, &ir0_value);
- debug_mode_ir0_value = ir0_value | 0x408; /* turn on DEX, set POM = 1 */
- debug_mode_ir0_value &= ~(0x000000C1); /* turn off DT/IT/GIE */
- aice_write_reg(coreid, IR0, debug_mode_ir0_value);
- }
- }
-
- /** set EDM_CTL.DBGIM & EDM_CTL.DBGACKM after halt */
- if (edm_ctl_value & 0x3)
- aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value);
-
- /* backup r0 & r1 */
- aice_backup_tmp_registers(coreid);
- core_info[coreid].core_state = AICE_TARGET_HALTED;
-
- return ERROR_OK;
-}
-
-static int aice_usb_state(uint32_t coreid, enum aice_target_state_s *state)
-{
- uint32_t dbger_value;
- uint32_t ice_state;
-
- int result = aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger_value);
-
- if (ERROR_AICE_TIMEOUT == result) {
- if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &ice_state) != ERROR_OK) {
- LOG_ERROR("<-- AICE ERROR! AICE is unplugged. -->");
- return ERROR_FAIL;
- }
-
- if ((ice_state & 0x20) == 0) {
- LOG_ERROR("<-- TARGET ERROR! Target is disconnected with AICE. -->");
- return ERROR_FAIL;
- } else {
- return ERROR_FAIL;
- }
- } else if (ERROR_AICE_DISCONNECT == result) {
- LOG_ERROR("<-- AICE ERROR! AICE is unplugged. -->");
- return ERROR_FAIL;
- }
-
- if ((dbger_value & NDS_DBGER_ILL_SEC_ACC) == NDS_DBGER_ILL_SEC_ACC) {
- LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege. -->");
-
- /* Clear ILL_SEC_ACC */
- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_ILL_SEC_ACC);
-
- *state = AICE_TARGET_RUNNING;
- core_info[coreid].core_state = AICE_TARGET_RUNNING;
- } else if ((dbger_value & NDS_DBGER_AT_MAX) == NDS_DBGER_AT_MAX) {
- /* Issue DBGI to exit cpu stall */
- aice_usb_halt(coreid);
-
- /* Read OIPC to find out the trigger point */
- uint32_t ir11_value;
- aice_read_reg(coreid, IR11, &ir11_value);
-
- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level; "
- "CPU is stalled at 0x%08" PRIx32 " for debugging. -->", ir11_value);
-
- *state = AICE_TARGET_HALTED;
- } else if ((dbger_value & NDS_DBGER_CRST) == NDS_DBGER_CRST) {
- LOG_DEBUG("DBGER.CRST is on.");
-
- *state = AICE_TARGET_RESET;
- core_info[coreid].core_state = AICE_TARGET_RUNNING;
-
- /* Clear CRST */
- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_CRST);
- } else if ((dbger_value & NDS_DBGER_DEX) == NDS_DBGER_DEX) {
- if (AICE_TARGET_RUNNING == core_info[coreid].core_state) {
- /* enter debug mode, init EDM registers */
- /* backup EDM registers */
- aice_backup_edm_registers(coreid);
- /* init EDM for host debugging */
- aice_init_edm_registers(coreid, true);
- aice_backup_tmp_registers(coreid);
- core_info[coreid].core_state = AICE_TARGET_HALTED;
- } else if (AICE_TARGET_UNKNOWN == core_info[coreid].core_state) {
- /* debug 'debug mode', use force debug to halt core */
- aice_usb_halt(coreid);
- }
- *state = AICE_TARGET_HALTED;
- } else {
- *state = AICE_TARGET_RUNNING;
- core_info[coreid].core_state = AICE_TARGET_RUNNING;
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_reset(void)
-{
- if (aice_reset_box() != ERROR_OK)
- return ERROR_FAIL;
-
- /* issue TRST */
- if (custom_trst_script == NULL) {
- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
- AICE_JTAG_PIN_CONTROL_TRST) != ERROR_OK)
- return ERROR_FAIL;
- } else {
- /* custom trst operations */
- if (aice_execute_custom_script(custom_trst_script) != ERROR_OK)
- return ERROR_FAIL;
- }
-
- if (aice_usb_set_clock(jtag_clock) != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int aice_issue_srst(uint32_t coreid)
-{
- LOG_DEBUG("aice_issue_srst");
-
- /* After issuing srst, target will be running. So we need to restore EDM_CTL. */
- aice_restore_edm_registers(coreid);
-
- if (custom_srst_script == NULL) {
- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
- AICE_JTAG_PIN_CONTROL_SRST) != ERROR_OK)
- return ERROR_FAIL;
- } else {
- /* custom srst operations */
- if (aice_execute_custom_script(custom_srst_script) != ERROR_OK)
- return ERROR_FAIL;
- }
-
- /* wait CRST infinitely */
- uint32_t dbger_value;
- int i = 0;
- while (1) {
- if (aice_read_misc(coreid,
- NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK)
- return ERROR_FAIL;
-
- if (dbger_value & NDS_DBGER_CRST)
- break;
-
- if ((i % 30) == 0)
- keep_alive();
- i++;
- }
-
- core_info[coreid].host_dtr_valid = false;
- core_info[coreid].target_dtr_valid = false;
-
- core_info[coreid].core_state = AICE_TARGET_RUNNING;
- return ERROR_OK;
-}
-
-static int aice_issue_reset_hold(uint32_t coreid)
-{
- LOG_DEBUG("aice_issue_reset_hold");
-
- /* set no_dbgi_pin to 0 */
- uint32_t pin_status;
- aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status);
- if (pin_status | 0x4)
- aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x4));
-
- /* issue restart */
- if (custom_restart_script == NULL) {
- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
- AICE_JTAG_PIN_CONTROL_RESTART) != ERROR_OK)
- return ERROR_FAIL;
- } else {
- /* custom restart operations */
- if (aice_execute_custom_script(custom_restart_script) != ERROR_OK)
- return ERROR_FAIL;
- }
-
- if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
- aice_backup_tmp_registers(coreid);
- core_info[coreid].core_state = AICE_TARGET_HALTED;
-
- return ERROR_OK;
- } else {
- /* set no_dbgi_pin to 1 */
- aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status | 0x4);
-
- /* issue restart again */
- if (custom_restart_script == NULL) {
- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
- AICE_JTAG_PIN_CONTROL_RESTART) != ERROR_OK)
- return ERROR_FAIL;
- } else {
- /* custom restart operations */
- if (aice_execute_custom_script(custom_restart_script) != ERROR_OK)
- return ERROR_FAIL;
- }
-
- if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
- aice_backup_tmp_registers(coreid);
- core_info[coreid].core_state = AICE_TARGET_HALTED;
-
- return ERROR_OK;
- }
-
- /* do software reset-and-hold */
- aice_issue_srst(coreid);
- aice_usb_halt(coreid);
-
- uint32_t value_ir3;
- aice_read_reg(coreid, IR3, &value_ir3);
- aice_write_reg(coreid, PC, value_ir3 & 0xFFFF0000);
- }
-
- return ERROR_FAIL;
-}
-
-static int aice_issue_reset_hold_multi(void)
-{
- uint32_t write_ctrl_value = 0;
-
- /* set SRST */
- write_ctrl_value = AICE_CUSTOM_DELAY_SET_SRST;
- write_ctrl_value |= (0x200 << 16);
- if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
- write_ctrl_value) != ERROR_OK)
- return ERROR_FAIL;
-
- for (uint8_t i = 0 ; i < total_num_of_core ; i++)
- aice_write_misc(i, NDS_EDM_MISC_EDM_CMDR, 0);
-
- /* clear SRST */
- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_SRST;
- write_ctrl_value |= (0x200 << 16);
- if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
- write_ctrl_value) != ERROR_OK)
- return ERROR_FAIL;
-
- for (uint8_t i = 0; i < total_num_of_core; i++)
- aice_edm_init(i);
-
- return ERROR_FAIL;
-}
-
-static int aice_usb_assert_srst(uint32_t coreid, enum aice_srst_type_s srst)
-{
- if ((AICE_SRST != srst) && (AICE_RESET_HOLD != srst))
- return ERROR_FAIL;
-
- /* clear DBGER */
- if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
- NDS_DBGER_CLEAR_ALL) != ERROR_OK)
- return ERROR_FAIL;
-
- int result = ERROR_OK;
- if (AICE_SRST == srst)
- result = aice_issue_srst(coreid);
- else {
- if (1 == total_num_of_core)
- result = aice_issue_reset_hold(coreid);
- else
- result = aice_issue_reset_hold_multi();
- }
-
- /* Clear DBGER.CRST after reset to avoid 'core-reset checking' errors.
- * assert_srst is user-intentional reset behavior, so we could
- * clear DBGER.CRST safely.
- */
- if (aice_write_misc(coreid,
- NDS_EDM_MISC_DBGER, NDS_DBGER_CRST) != ERROR_OK)
- return ERROR_FAIL;
-
- return result;
-}
-
-static int aice_usb_run(uint32_t coreid)
-{
- LOG_DEBUG("aice_usb_run");
-
- uint32_t dbger_value;
- if (aice_read_misc(coreid,
- NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK)
- return ERROR_FAIL;
-
- if ((dbger_value & NDS_DBGER_DEX) != NDS_DBGER_DEX) {
- LOG_WARNING("<-- TARGET WARNING! The debug target exited "
- "the debug mode unexpectedly. -->");
- return ERROR_FAIL;
- }
-
- /* restore r0 & r1 before free run */
- aice_restore_tmp_registers(coreid);
- core_info[coreid].core_state = AICE_TARGET_RUNNING;
-
- /* clear DBGER */
- aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
- NDS_DBGER_CLEAR_ALL);
-
- /** restore EDM registers */
- /** OpenOCD should restore EDM_CTL **before** to exit debug state.
- * Otherwise, following instruction will read wrong EDM_CTL value.
- *
- * pc -> mfsr $p0, EDM_CTL (single step)
- * slli $p0, $p0, 1
- * slri $p0, $p0, 31
- */
- aice_restore_edm_registers(coreid);
-
- /** execute instructions in DIM */
- uint32_t instructions[4] = {
- NOP,
- NOP,
- NOP,
- IRET
- };
- int result = aice_execute_dim(coreid, instructions, 4);
-
- return result;
-}
-
-static int aice_usb_step(uint32_t coreid)
-{
- LOG_DEBUG("aice_usb_step");
-
- uint32_t ir0_value;
- uint32_t ir0_reg_num;
-
- if (is_v2_edm(coreid) == true)
- /* V2 EDM will push interrupt stack as debug exception */
- ir0_reg_num = IR1;
- else
- ir0_reg_num = IR0;
-
- /** enable HSS */
- aice_read_reg(coreid, ir0_reg_num, &ir0_value);
- if ((ir0_value & 0x800) == 0) {
- /** set PSW.HSS */
- ir0_value |= (0x01 << 11);
- aice_write_reg(coreid, ir0_reg_num, ir0_value);
- }
-
- if (ERROR_FAIL == aice_usb_run(coreid))
- return ERROR_FAIL;
-
- int i = 0;
- enum aice_target_state_s state;
- while (1) {
- /* read DBGER */
- if (aice_usb_state(coreid, &state) != ERROR_OK)
- return ERROR_FAIL;
-
- if (AICE_TARGET_HALTED == state)
- break;
-
- int64_t then = 0;
- if (i == 30)
- then = timeval_ms();
-
- if (i >= 30) {
- if ((timeval_ms() - then) > 1000)
- LOG_WARNING("Timeout (1000ms) waiting for halt to complete");
-
- return ERROR_FAIL;
- }
- i++;
- }
-
- /** disable HSS */
- aice_read_reg(coreid, ir0_reg_num, &ir0_value);
- ir0_value &= ~(0x01 << 11);
- aice_write_reg(coreid, ir0_reg_num, ir0_value);
-
- return ERROR_OK;
-}
-
-static int aice_usb_read_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t *data)
-{
- return aice_read_mem_b(coreid, address, data);
-}
-
-static int aice_usb_read_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t *data)
-{
- return aice_read_mem_h(coreid, address, data);
-}
-
-static int aice_usb_read_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t *data)
-{
- return aice_read_mem(coreid, address, data);
-}
-
-static int aice_usb_read_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t *data)
-{
- uint32_t value;
- uint32_t instructions[4] = {
- LBI_BI(R1, R0),
- MTSR_DTR(R1),
- DSB,
- BEQ_MINUS_12
- };
-
- aice_execute_dim(coreid, instructions, 4);
-
- aice_read_dtr(coreid, &value);
- *data = value & 0xFF;
-
- return ERROR_OK;
-}
-
-static int aice_usb_read_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t *data)
-{
- uint32_t value;
- uint32_t instructions[4] = {
- LHI_BI(R1, R0),
- MTSR_DTR(R1),
- DSB,
- BEQ_MINUS_12
- };
-
- aice_execute_dim(coreid, instructions, 4);
-
- aice_read_dtr(coreid, &value);
- *data = value & 0xFFFF;
-
- return ERROR_OK;
-}
-
-static int aice_usb_read_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t *data)
-{
- uint32_t instructions[4] = {
- LWI_BI(R1, R0),
- MTSR_DTR(R1),
- DSB,
- BEQ_MINUS_12
- };
-
- aice_execute_dim(coreid, instructions, 4);
-
- aice_read_dtr(coreid, data);
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_address_dim(uint32_t coreid, uint32_t address)
-{
- uint32_t instructions[4] = {
- SETHI(R0, address >> 12),
- ORI(R0, R0, address & 0x00000FFF),
- NOP,
- BEQ_MINUS_12
- };
-
- return aice_execute_dim(coreid, instructions, 4);
-}
-
-static int aice_usb_read_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- LOG_DEBUG("aice_usb_read_memory_unit, addr: 0x%08" PRIx32
- ", size: %" PRIu32 ", count: %" PRIu32 "",
- addr, size, count);
-
- if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
- aice_usb_set_address_dim(coreid, addr);
-
- uint32_t value;
- size_t i;
- read_mem_func_t read_mem_func;
-
- switch (size) {
- case 1:
- if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
- read_mem_func = aice_usb_read_mem_b_bus;
- else
- read_mem_func = aice_usb_read_mem_b_dim;
-
- for (i = 0; i < count; i++) {
- read_mem_func(coreid, addr, &value);
- *buffer++ = (uint8_t)value;
- addr++;
- }
- break;
- case 2:
- if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
- read_mem_func = aice_usb_read_mem_h_bus;
- else
- read_mem_func = aice_usb_read_mem_h_dim;
-
- for (i = 0; i < count; i++) {
- read_mem_func(coreid, addr, &value);
- uint16_t svalue = value;
- memcpy(buffer, &svalue, sizeof(uint16_t));
- buffer += 2;
- addr += 2;
- }
- break;
- case 4:
- if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
- read_mem_func = aice_usb_read_mem_w_bus;
- else
- read_mem_func = aice_usb_read_mem_w_dim;
-
- for (i = 0; i < count; i++) {
- read_mem_func(coreid, addr, &value);
- memcpy(buffer, &value, sizeof(uint32_t));
- buffer += 4;
- addr += 4;
- }
- break;
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_write_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t data)
-{
- return aice_write_mem_b(coreid, address, data);
-}
-
-static int aice_usb_write_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t data)
-{
- return aice_write_mem_h(coreid, address, data);
-}
-
-static int aice_usb_write_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t data)
-{
- return aice_write_mem(coreid, address, data);
-}
-
-static int aice_usb_write_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t data)
-{
- uint32_t instructions[4] = {
- MFSR_DTR(R1),
- SBI_BI(R1, R0),
- DSB,
- BEQ_MINUS_12
- };
-
- aice_write_dtr(coreid, data & 0xFF);
- aice_execute_dim(coreid, instructions, 4);
-
- return ERROR_OK;
-}
-
-static int aice_usb_write_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t data)
-{
- uint32_t instructions[4] = {
- MFSR_DTR(R1),
- SHI_BI(R1, R0),
- DSB,
- BEQ_MINUS_12
- };
-
- aice_write_dtr(coreid, data & 0xFFFF);
- aice_execute_dim(coreid, instructions, 4);
-
- return ERROR_OK;
-}
-
-static int aice_usb_write_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t data)
-{
- uint32_t instructions[4] = {
- MFSR_DTR(R1),
- SWI_BI(R1, R0),
- DSB,
- BEQ_MINUS_12
- };
-
- aice_write_dtr(coreid, data);
- aice_execute_dim(coreid, instructions, 4);
-
- return ERROR_OK;
-}
-
-static int aice_usb_write_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- LOG_DEBUG("aice_usb_write_memory_unit, addr: 0x%08" PRIx32
- ", size: %" PRIu32 ", count: %" PRIu32 "",
- addr, size, count);
-
- if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
- aice_usb_set_address_dim(coreid, addr);
-
- size_t i;
- write_mem_func_t write_mem_func;
-
- switch (size) {
- case 1:
- if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
- write_mem_func = aice_usb_write_mem_b_bus;
- else
- write_mem_func = aice_usb_write_mem_b_dim;
-
- for (i = 0; i < count; i++) {
- write_mem_func(coreid, addr, *buffer);
- buffer++;
- addr++;
- }
- break;
- case 2:
- if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
- write_mem_func = aice_usb_write_mem_h_bus;
- else
- write_mem_func = aice_usb_write_mem_h_dim;
-
- for (i = 0; i < count; i++) {
- uint16_t value;
- memcpy(&value, buffer, sizeof(uint16_t));
-
- write_mem_func(coreid, addr, value);
- buffer += 2;
- addr += 2;
- }
- break;
- case 4:
- if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
- write_mem_func = aice_usb_write_mem_w_bus;
- else
- write_mem_func = aice_usb_write_mem_w_dim;
-
- for (i = 0; i < count; i++) {
- uint32_t value;
- memcpy(&value, buffer, sizeof(uint32_t));
-
- write_mem_func(coreid, addr, value);
- buffer += 4;
- addr += 4;
- }
- break;
- }
-
- return ERROR_OK;
-}
-
-static int aice_bulk_read_mem(uint32_t coreid, uint32_t addr, uint32_t count,
- uint8_t *buffer)
-{
- uint32_t packet_size;
-
- while (count > 0) {
- packet_size = (count >= 0x100) ? 0x100 : count;
-
- /** set address */
- addr &= 0xFFFFFFFC;
- if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr) != ERROR_OK)
- return ERROR_FAIL;
-
- if (aice_fastread_mem(coreid, buffer,
- packet_size) != ERROR_OK)
- return ERROR_FAIL;
-
- buffer += (packet_size * 4);
- addr += (packet_size * 4);
- count -= packet_size;
- }
-
- return ERROR_OK;
-}
-
-static int aice_bulk_write_mem(uint32_t coreid, uint32_t addr, uint32_t count,
- const uint8_t *buffer)
-{
- uint32_t packet_size;
-
- while (count > 0) {
- packet_size = (count >= 0x100) ? 0x100 : count;
-
- /** set address */
- addr &= 0xFFFFFFFC;
- if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr | 1) != ERROR_OK)
- return ERROR_FAIL;
-
- if (aice_fastwrite_mem(coreid, buffer,
- packet_size) != ERROR_OK)
- return ERROR_FAIL;
-
- buffer += (packet_size * 4);
- addr += (packet_size * 4);
- count -= packet_size;
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_bulk_read_mem(uint32_t coreid, uint32_t addr,
- uint32_t length, uint8_t *buffer)
-{
- LOG_DEBUG("aice_usb_bulk_read_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length);
-
- int retval;
-
- if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
- aice_usb_set_address_dim(coreid, addr);
-
- if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
- retval = aice_usb_read_memory_unit(coreid, addr, 4, length / 4, buffer);
- else
- retval = aice_bulk_read_mem(coreid, addr, length / 4, buffer);
-
- return retval;
-}
-
-static int aice_usb_bulk_write_mem(uint32_t coreid, uint32_t addr,
- uint32_t length, const uint8_t *buffer)
-{
- LOG_DEBUG("aice_usb_bulk_write_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length);
-
- int retval;
-
- if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
- aice_usb_set_address_dim(coreid, addr);
-
- if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
- retval = aice_usb_write_memory_unit(coreid, addr, 4, length / 4, buffer);
- else
- retval = aice_bulk_write_mem(coreid, addr, length / 4, buffer);
-
- return retval;
-}
-
-static int aice_usb_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val)
-{
- if (AICE_TARGET_HALTED == core_info[coreid].core_state) {
- if (NDS_EDM_SR_EDMSW == addr) {
- *val = core_info[coreid].edmsw_backup;
- } else if (NDS_EDM_SR_EDM_DTR == addr) {
- if (core_info[coreid].target_dtr_valid) {
- /* if EDM_DTR has read out, clear it. */
- *val = core_info[coreid].target_dtr_backup;
- core_info[coreid].edmsw_backup &= (~0x1);
- core_info[coreid].target_dtr_valid = false;
- } else {
- *val = 0;
- }
- }
- }
-
- return aice_read_edmsr(coreid, addr, val);
-}
-
-static int aice_usb_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val)
-{
- if (AICE_TARGET_HALTED == core_info[coreid].core_state) {
- if (NDS_EDM_SR_EDM_DTR == addr) {
- core_info[coreid].host_dtr_backup = val;
- core_info[coreid].edmsw_backup |= 0x2;
- core_info[coreid].host_dtr_valid = true;
- }
- }
-
- return aice_write_edmsr(coreid, addr, val);
-}
-
-static int aice_usb_memory_access(uint32_t coreid, enum nds_memory_access channel)
-{
- LOG_DEBUG("aice_usb_memory_access, access channel: %u", channel);
-
- core_info[coreid].access_channel = channel;
-
- return ERROR_OK;
-}
-
-static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_select)
-{
- if (core_info[coreid].memory_select == mem_select)
- return ERROR_OK;
-
- LOG_DEBUG("aice_usb_memory_mode, memory select: %u", mem_select);
-
- core_info[coreid].memory_select = mem_select;
-
- if (NDS_MEMORY_SELECT_AUTO != core_info[coreid].memory_select)
- aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL,
- core_info[coreid].memory_select - 1);
- else
- aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL,
- NDS_MEMORY_SELECT_MEM - 1);
-
- return ERROR_OK;
-}
-
-static int aice_usb_read_tlb(uint32_t coreid, uint32_t virtual_address,
- uint32_t *physical_address)
-{
- LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" PRIx32, virtual_address);
-
- uint32_t instructions[4];
- uint32_t probe_result;
- uint32_t value_mr3;
- uint32_t value_mr4;
- uint32_t access_page_size;
- uint32_t virtual_offset;
- uint32_t physical_page_number;
-
- aice_write_dtr(coreid, virtual_address);
-
- /* probe TLB first */
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = TLBOP_TARGET_PROBE(R1, R0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- aice_execute_dim(coreid, instructions, 4);
-
- aice_read_reg(coreid, R1, &probe_result);
-
- if (probe_result & 0x80000000)
- return ERROR_FAIL;
-
- /* read TLB entry */
- aice_write_dtr(coreid, probe_result & 0x7FF);
-
- /* probe TLB first */
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = TLBOP_TARGET_READ(R0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
- aice_execute_dim(coreid, instructions, 4);
-
- /* TODO: it should backup mr3, mr4 */
- aice_read_reg(coreid, MR3, &value_mr3);
- aice_read_reg(coreid, MR4, &value_mr4);
-
- access_page_size = value_mr4 & 0xF;
- if (0 == access_page_size) { /* 4K page */
- virtual_offset = virtual_address & 0x00000FFF;
- physical_page_number = value_mr3 & 0xFFFFF000;
- } else if (1 == access_page_size) { /* 8K page */
- virtual_offset = virtual_address & 0x00001FFF;
- physical_page_number = value_mr3 & 0xFFFFE000;
- } else if (5 == access_page_size) { /* 1M page */
- virtual_offset = virtual_address & 0x000FFFFF;
- physical_page_number = value_mr3 & 0xFFF00000;
- } else {
- return ERROR_FAIL;
- }
-
- *physical_address = physical_page_number | virtual_offset;
-
- return ERROR_OK;
-}
-
-static int aice_usb_init_cache(uint32_t coreid)
-{
- LOG_DEBUG("aice_usb_init_cache");
-
- uint32_t value_cr1;
- uint32_t value_cr2;
-
- aice_read_reg(coreid, CR1, &value_cr1);
- aice_read_reg(coreid, CR2, &value_cr2);
-
- struct cache_info *icache = &core_info[coreid].icache;
-
- icache->set = value_cr1 & 0x7;
- icache->log2_set = icache->set + 6;
- icache->set = 64 << icache->set;
- icache->way = ((value_cr1 >> 3) & 0x7) + 1;
- icache->line_size = (value_cr1 >> 6) & 0x7;
- if (icache->line_size != 0) {
- icache->log2_line_size = icache->line_size + 2;
- icache->line_size = 8 << (icache->line_size - 1);
- } else {
- icache->log2_line_size = 0;
- }
-
- LOG_DEBUG("\ticache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", "
- "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "",
- icache->set, icache->way, icache->line_size,
- icache->log2_set, icache->log2_line_size);
-
- struct cache_info *dcache = &core_info[coreid].dcache;
-
- dcache->set = value_cr2 & 0x7;
- dcache->log2_set = dcache->set + 6;
- dcache->set = 64 << dcache->set;
- dcache->way = ((value_cr2 >> 3) & 0x7) + 1;
- dcache->line_size = (value_cr2 >> 6) & 0x7;
- if (dcache->line_size != 0) {
- dcache->log2_line_size = dcache->line_size + 2;
- dcache->line_size = 8 << (dcache->line_size - 1);
- } else {
- dcache->log2_line_size = 0;
- }
-
- LOG_DEBUG("\tdcache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", "
- "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "",
- dcache->set, dcache->way, dcache->line_size,
- dcache->log2_set, dcache->log2_line_size);
-
- core_info[coreid].cache_init = true;
-
- return ERROR_OK;
-}
-
-static int aice_usb_dcache_inval_all(uint32_t coreid)
-{
- LOG_DEBUG("aice_usb_dcache_inval_all");
-
- uint32_t set_index;
- uint32_t way_index;
- uint32_t cache_index;
- uint32_t instructions[4];
-
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = L1D_IX_INVAL(R0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
-
- struct cache_info *dcache = &core_info[coreid].dcache;
-
- for (set_index = 0; set_index < dcache->set; set_index++) {
- for (way_index = 0; way_index < dcache->way; way_index++) {
- cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) |
- (set_index << dcache->log2_line_size);
-
- if (ERROR_OK != aice_write_dtr(coreid, cache_index))
- return ERROR_FAIL;
-
- if (ERROR_OK != aice_execute_dim(coreid, instructions, 4))
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_dcache_va_inval(uint32_t coreid, uint32_t address)
-{
- LOG_DEBUG("aice_usb_dcache_va_inval");
-
- uint32_t instructions[4];
-
- aice_write_dtr(coreid, address);
-
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = L1D_VA_INVAL(R0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
-
- return aice_execute_dim(coreid, instructions, 4);
-}
-
-static int aice_usb_dcache_wb_all(uint32_t coreid)
-{
- LOG_DEBUG("aice_usb_dcache_wb_all");
-
- uint32_t set_index;
- uint32_t way_index;
- uint32_t cache_index;
- uint32_t instructions[4];
-
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = L1D_IX_WB(R0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
-
- struct cache_info *dcache = &core_info[coreid].dcache;
-
- for (set_index = 0; set_index < dcache->set; set_index++) {
- for (way_index = 0; way_index < dcache->way; way_index++) {
- cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) |
- (set_index << dcache->log2_line_size);
-
- if (ERROR_OK != aice_write_dtr(coreid, cache_index))
- return ERROR_FAIL;
-
- if (ERROR_OK != aice_execute_dim(coreid, instructions, 4))
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_dcache_va_wb(uint32_t coreid, uint32_t address)
-{
- LOG_DEBUG("aice_usb_dcache_va_wb");
-
- uint32_t instructions[4];
-
- aice_write_dtr(coreid, address);
-
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = L1D_VA_WB(R0);
- instructions[2] = DSB;
- instructions[3] = BEQ_MINUS_12;
-
- return aice_execute_dim(coreid, instructions, 4);
-}
-
-static int aice_usb_icache_inval_all(uint32_t coreid)
-{
- LOG_DEBUG("aice_usb_icache_inval_all");
-
- uint32_t set_index;
- uint32_t way_index;
- uint32_t cache_index;
- uint32_t instructions[4];
-
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = L1I_IX_INVAL(R0);
- instructions[2] = ISB;
- instructions[3] = BEQ_MINUS_12;
-
- struct cache_info *icache = &core_info[coreid].icache;
-
- for (set_index = 0; set_index < icache->set; set_index++) {
- for (way_index = 0; way_index < icache->way; way_index++) {
- cache_index = (way_index << (icache->log2_set + icache->log2_line_size)) |
- (set_index << icache->log2_line_size);
-
- if (ERROR_OK != aice_write_dtr(coreid, cache_index))
- return ERROR_FAIL;
-
- if (ERROR_OK != aice_execute_dim(coreid, instructions, 4))
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_icache_va_inval(uint32_t coreid, uint32_t address)
-{
- LOG_DEBUG("aice_usb_icache_va_inval");
-
- uint32_t instructions[4];
-
- aice_write_dtr(coreid, address);
-
- instructions[0] = MFSR_DTR(R0);
- instructions[1] = L1I_VA_INVAL(R0);
- instructions[2] = ISB;
- instructions[3] = BEQ_MINUS_12;
-
- return aice_execute_dim(coreid, instructions, 4);
-}
-
-static int aice_usb_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address)
-{
- LOG_DEBUG("aice_usb_cache_ctl");
-
- int result;
-
- if (core_info[coreid].cache_init == false)
- aice_usb_init_cache(coreid);
-
- switch (subtype) {
- case AICE_CACHE_CTL_L1D_INVALALL:
- result = aice_usb_dcache_inval_all(coreid);
- break;
- case AICE_CACHE_CTL_L1D_VA_INVAL:
- result = aice_usb_dcache_va_inval(coreid, address);
- break;
- case AICE_CACHE_CTL_L1D_WBALL:
- result = aice_usb_dcache_wb_all(coreid);
- break;
- case AICE_CACHE_CTL_L1D_VA_WB:
- result = aice_usb_dcache_va_wb(coreid, address);
- break;
- case AICE_CACHE_CTL_L1I_INVALALL:
- result = aice_usb_icache_inval_all(coreid);
- break;
- case AICE_CACHE_CTL_L1I_VA_INVAL:
- result = aice_usb_icache_va_inval(coreid, address);
- break;
- default:
- result = ERROR_FAIL;
- break;
- }
-
- return result;
-}
-
-static int aice_usb_set_retry_times(uint32_t a_retry_times)
-{
- aice_max_retry_times = a_retry_times;
- return ERROR_OK;
-}
-
-static int aice_usb_program_edm(uint32_t coreid, char *command_sequence)
-{
- char *command_str;
- char *reg_name_0;
- char *reg_name_1;
- uint32_t data_value;
- int i;
-
- /* init strtok() */
- command_str = strtok(command_sequence, ";");
- if (command_str == NULL)
- return ERROR_OK;
-
- do {
- i = 0;
- /* process one command */
- while (command_str[i] == ' ' ||
- command_str[i] == '\n' ||
- command_str[i] == '\r' ||
- command_str[i] == '\t')
- i++;
-
- /* skip ' ', '\r', '\n', '\t' */
- command_str = command_str + i;
-
- if (strncmp(command_str, "write_misc", 10) == 0) {
- reg_name_0 = strstr(command_str, "gen_port0");
- reg_name_1 = strstr(command_str, "gen_port1");
-
- if (reg_name_0 != NULL) {
- data_value = strtoul(reg_name_0 + 9, NULL, 0);
-
- if (aice_write_misc(coreid,
- NDS_EDM_MISC_GEN_PORT0, data_value) != ERROR_OK)
- return ERROR_FAIL;
-
- } else if (reg_name_1 != NULL) {
- data_value = strtoul(reg_name_1 + 9, NULL, 0);
-
- if (aice_write_misc(coreid,
- NDS_EDM_MISC_GEN_PORT1, data_value) != ERROR_OK)
- return ERROR_FAIL;
- } else {
- LOG_ERROR("program EDM, unsupported misc register: %s", command_str);
- }
- } else {
- LOG_ERROR("program EDM, unsupported command: %s", command_str);
- }
-
- /* update command_str */
- command_str = strtok(NULL, ";");
-
- } while (command_str != NULL);
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_command_mode(enum aice_command_mode command_mode)
-{
- int retval = ERROR_OK;
-
- /* flush usb_packets_buffer as users change mode */
- retval = aice_usb_packet_flush();
-
- if (AICE_COMMAND_MODE_BATCH == command_mode) {
- /* reset batch buffer */
- aice_command_mode = AICE_COMMAND_MODE_NORMAL;
- retval = aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CMD_BUF0_CTRL, 0x40000);
- }
-
- aice_command_mode = command_mode;
-
- return retval;
-}
-
-static int aice_usb_execute(uint32_t coreid, uint32_t *instructions,
- uint32_t instruction_num)
-{
- uint32_t i, j;
- uint8_t current_instruction_num;
- uint32_t dim_instructions[4] = {NOP, NOP, NOP, BEQ_MINUS_12};
-
- /* To execute 4 instructions as a special case */
- if (instruction_num == 4)
- return aice_execute_dim(coreid, instructions, 4);
-
- for (i = 0 ; i < instruction_num ; i += 3) {
- if (instruction_num - i < 3) {
- current_instruction_num = instruction_num - i;
- for (j = current_instruction_num ; j < 3 ; j++)
- dim_instructions[j] = NOP;
- } else {
- current_instruction_num = 3;
- }
-
- memcpy(dim_instructions, instructions + i,
- current_instruction_num * sizeof(uint32_t));
-
- /** fill DIM */
- if (aice_write_dim(coreid,
- dim_instructions,
- 4) != ERROR_OK)
- return ERROR_FAIL;
-
- /** clear DBGER.DPED */
- if (aice_write_misc(coreid,
- NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK)
- return ERROR_FAIL;
-
- /** execute DIM */
- if (aice_do_execute(coreid) != ERROR_OK)
- return ERROR_FAIL;
-
- /** check DBGER.DPED */
- if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) {
-
- LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly:"
- "0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 ". -->",
- dim_instructions[0],
- dim_instructions[1],
- dim_instructions[2],
- dim_instructions[3]);
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_custom_srst_script(const char *script)
-{
- custom_srst_script = strdup(script);
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_custom_trst_script(const char *script)
-{
- custom_trst_script = strdup(script);
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_custom_restart_script(const char *script)
-{
- custom_restart_script = strdup(script);
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_count_to_check_dbger(uint32_t count_to_check)
-{
- aice_count_to_check_dbger = count_to_check;
-
- return ERROR_OK;
-}
-
-static int aice_usb_set_data_endian(uint32_t coreid,
- enum aice_target_endian target_data_endian)
-{
- data_endian = target_data_endian;
-
- return ERROR_OK;
-}
-
-static int fill_profiling_batch_commands(uint32_t coreid, uint32_t reg_no)
-{
- uint32_t dim_instructions[4];
-
- aice_usb_set_command_mode(AICE_COMMAND_MODE_BATCH);
-
- /* halt */
- if (aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0) != ERROR_OK)
- return ERROR_FAIL;
-
- /* backup $r0 */
- dim_instructions[0] = MTSR_DTR(0);
- dim_instructions[1] = DSB;
- dim_instructions[2] = NOP;
- dim_instructions[3] = BEQ_MINUS_12;
- if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
- return ERROR_FAIL;
- aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_0);
-
- /* get samples */
- if (NDS32_REG_TYPE_GPR == nds32_reg_type(reg_no)) {
- /* general registers */
- dim_instructions[0] = MTSR_DTR(reg_no);
- dim_instructions[1] = DSB;
- dim_instructions[2] = NOP;
- dim_instructions[3] = BEQ_MINUS_12;
- } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(reg_no)) {
- /* user special registers */
- dim_instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(reg_no));
- dim_instructions[1] = MTSR_DTR(0);
- dim_instructions[2] = DSB;
- dim_instructions[3] = BEQ_MINUS_12;
- } else { /* system registers */
- dim_instructions[0] = MFSR(0, nds32_reg_sr_index(reg_no));
- dim_instructions[1] = MTSR_DTR(0);
- dim_instructions[2] = DSB;
- dim_instructions[3] = BEQ_MINUS_12;
- }
- if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
- return ERROR_FAIL;
- aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_1);
-
- /* restore $r0 */
- aice_write_dtr_from_buffer(coreid, AICE_BATCH_DATA_BUFFER_0);
- dim_instructions[0] = MFSR_DTR(0);
- dim_instructions[1] = DSB;
- dim_instructions[2] = NOP;
- dim_instructions[3] = IRET; /* free run */
- if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
- return ERROR_FAIL;
-
- aice_command_mode = AICE_COMMAND_MODE_NORMAL;
-
- /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */
- if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0,
- usb_out_packets_buffer,
- (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK)
- return ERROR_FAIL;
-
- usb_out_packets_buffer_length = 0;
- usb_in_packets_buffer_length = 0;
-
- return ERROR_OK;
-}
-
-static int aice_usb_profiling(uint32_t coreid, uint32_t interval, uint32_t iteration,
- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples)
-{
- uint32_t iteration_count;
- uint32_t this_iteration;
- int retval = ERROR_OK;
- const uint32_t MAX_ITERATION = 250;
-
- *num_samples = 0;
-
- /* init DIM size */
- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DIM_SIZE, 4) != ERROR_OK)
- return ERROR_FAIL;
-
- /* Use AICE_BATCH_DATA_BUFFER_0 to read/write $DTR.
- * Set it to circular buffer */
- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL, 0xC0000) != ERROR_OK)
- return ERROR_FAIL;
-
- fill_profiling_batch_commands(coreid, reg_no);
-
- iteration_count = 0;
- while (iteration_count < iteration) {
- if (iteration - iteration_count < MAX_ITERATION)
- this_iteration = iteration - iteration_count;
- else
- this_iteration = MAX_ITERATION;
-
- /* set number of iterations */
- uint32_t val_iteration;
- val_iteration = interval << 16 | this_iteration;
- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_ITERATION,
- val_iteration) != ERROR_OK) {
- retval = ERROR_FAIL;
- goto end_profiling;
- }
-
- /* init AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL to store $PC */
- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL,
- 0x40000) != ERROR_OK) {
- retval = ERROR_FAIL;
- goto end_profiling;
- }
-
- aice_usb_run(coreid);
-
- /* enable BATCH command */
- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL,
- 0x80000000) != ERROR_OK) {
- aice_usb_halt(coreid);
- retval = ERROR_FAIL;
- goto end_profiling;
- }
-
- /* wait a while (AICE bug, workaround) */
- alive_sleep(this_iteration);
-
- /* check status */
- uint32_t i;
- uint32_t batch_status;
-
- i = 0;
- while (1) {
- aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
-
- if (batch_status & 0x1) {
- break;
- } else if (batch_status & 0xE) {
- aice_usb_halt(coreid);
- retval = ERROR_FAIL;
- goto end_profiling;
- }
-
- if ((i % 30) == 0)
- keep_alive();
-
- i++;
- }
-
- aice_usb_halt(coreid);
-
- /* get samples from batch data buffer */
- if (aice_batch_buffer_read(AICE_BATCH_DATA_BUFFER_1,
- samples + iteration_count, this_iteration) != ERROR_OK) {
- retval = ERROR_FAIL;
- goto end_profiling;
- }
-
- iteration_count += this_iteration;
- }
-
-end_profiling:
- *num_samples = iteration_count;
-
- return retval;
-}
-
-/** */
-struct aice_port_api_s aice_usb_api = {
- /** */
- .open = aice_open_device,
- /** */
- .close = aice_usb_close,
- /** */
- .idcode = aice_usb_idcode,
- /** */
- .state = aice_usb_state,
- /** */
- .reset = aice_usb_reset,
- /** */
- .assert_srst = aice_usb_assert_srst,
- /** */
- .run = aice_usb_run,
- /** */
- .halt = aice_usb_halt,
- /** */
- .step = aice_usb_step,
- /** */
- .read_reg = aice_usb_read_reg,
- /** */
- .write_reg = aice_usb_write_reg,
- /** */
- .read_reg_64 = aice_usb_read_reg_64,
- /** */
- .write_reg_64 = aice_usb_write_reg_64,
- /** */
- .read_mem_unit = aice_usb_read_memory_unit,
- /** */
- .write_mem_unit = aice_usb_write_memory_unit,
- /** */
- .read_mem_bulk = aice_usb_bulk_read_mem,
- /** */
- .write_mem_bulk = aice_usb_bulk_write_mem,
- /** */
- .read_debug_reg = aice_usb_read_debug_reg,
- /** */
- .write_debug_reg = aice_usb_write_debug_reg,
- /** */
- .set_jtag_clock = aice_usb_set_jtag_clock,
- /** */
- .memory_access = aice_usb_memory_access,
- /** */
- .memory_mode = aice_usb_memory_mode,
- /** */
- .read_tlb = aice_usb_read_tlb,
- /** */
- .cache_ctl = aice_usb_cache_ctl,
- /** */
- .set_retry_times = aice_usb_set_retry_times,
- /** */
- .program_edm = aice_usb_program_edm,
- /** */
- .set_command_mode = aice_usb_set_command_mode,
- /** */
- .execute = aice_usb_execute,
- /** */
- .set_custom_srst_script = aice_usb_set_custom_srst_script,
- /** */
- .set_custom_trst_script = aice_usb_set_custom_trst_script,
- /** */
- .set_custom_restart_script = aice_usb_set_custom_restart_script,
- /** */
- .set_count_to_check_dbger = aice_usb_set_count_to_check_dbger,
- /** */
- .set_data_endian = aice_usb_set_data_endian,
- /** */
- .profiling = aice_usb_profiling,
-};
diff --git a/src/jtag/aice/aice_usb.h b/src/jtag/aice/aice_usb.h
deleted file mode 100644
index 2911ae5..0000000
--- a/src/jtag/aice/aice_usb.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_AICE_AICE_USB_H
-#define OPENOCD_JTAG_AICE_AICE_USB_H
-
-#include "aice_port.h"
-
-/* AICE USB timeout value */
-#define AICE_USB_TIMEOUT 5000
-
-/* AICE USB buffer size */
-#define AICE_IN_BUFFER_SIZE 2048
-#define AICE_OUT_BUFFER_SIZE 2048
-#define AICE_IN_PACKETS_BUFFER_SIZE 2048
-#define AICE_OUT_PACKETS_BUFFER_SIZE 2048
-#define AICE_IN_BATCH_COMMAND_SIZE 512
-#define AICE_OUT_BATCH_COMMAND_SIZE 512
-#define AICE_IN_PACK_COMMAND_SIZE 2048
-#define AICE_OUT_PACK_COMMAND_SIZE 2048
-
-/* Constants for AICE command READ_CTRL */
-#define AICE_READ_CTRL_GET_ICE_STATE 0x00
-#define AICE_READ_CTRL_GET_HARDWARE_VERSION 0x01
-#define AICE_READ_CTRL_GET_FPGA_VERSION 0x02
-#define AICE_READ_CTRL_GET_FIRMWARE_VERSION 0x03
-#define AICE_READ_CTRL_GET_JTAG_PIN_STATUS 0x04
-#define AICE_READ_CTRL_BATCH_BUF_INFO 0x22
-#define AICE_READ_CTRL_BATCH_STATUS 0x23
-#define AICE_READ_CTRL_BATCH_BUF0_STATE 0x31
-#define AICE_READ_CTRL_BATCH_BUF4_STATE 0x39
-#define AICE_READ_CTRL_BATCH_BUF5_STATE 0x3b
-
-/* Constants for AICE command WRITE_CTRL */
-#define AICE_WRITE_CTRL_TCK_CONTROL 0x00
-#define AICE_WRITE_CTRL_JTAG_PIN_CONTROL 0x01
-#define AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS 0x02
-#define AICE_WRITE_CTRL_RESERVED 0x03
-#define AICE_WRITE_CTRL_JTAG_PIN_STATUS 0x04
-#define AICE_WRITE_CTRL_CUSTOM_DELAY 0x0d
-#define AICE_WRITE_CTRL_BATCH_CTRL 0x20
-#define AICE_WRITE_CTRL_BATCH_ITERATION 0x21
-#define AICE_WRITE_CTRL_BATCH_DIM_SIZE 0x22
-#define AICE_WRITE_CTRL_BATCH_CMD_BUF0_CTRL 0x30
-#define AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL 0x38
-#define AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL 0x3a
-
-#define AICE_BATCH_COMMAND_BUFFER_0 0x0
-#define AICE_BATCH_COMMAND_BUFFER_1 0x1
-#define AICE_BATCH_COMMAND_BUFFER_2 0x2
-#define AICE_BATCH_COMMAND_BUFFER_3 0x3
-#define AICE_BATCH_DATA_BUFFER_0 0x4
-#define AICE_BATCH_DATA_BUFFER_1 0x5
-#define AICE_BATCH_DATA_BUFFER_2 0x6
-#define AICE_BATCH_DATA_BUFFER_3 0x7
-
-/* Constants for AICE command WRITE_CTRL:TCK_CONTROL */
-#define AICE_TCK_CONTROL_TCK3048 0x08
-
-/* Constants for AICE command WRITE_CTRL:JTAG_PIN_CONTROL */
-#define AICE_JTAG_PIN_CONTROL_SRST 0x01
-#define AICE_JTAG_PIN_CONTROL_TRST 0x02
-#define AICE_JTAG_PIN_CONTROL_STOP 0x04
-#define AICE_JTAG_PIN_CONTROL_RESTART 0x08
-
-/* Constants for AICE command WRITE_CTRL:TCK_CONTROL */
-#define AICE_TCK_CONTROL_TCK_SCAN 0x10
-
-/* Custom SRST/DBGI/TRST */
-#define AICE_CUSTOM_DELAY_SET_SRST 0x01
-#define AICE_CUSTOM_DELAY_CLEAN_SRST 0x02
-#define AICE_CUSTOM_DELAY_SET_DBGI 0x04
-#define AICE_CUSTOM_DELAY_CLEAN_DBGI 0x08
-#define AICE_CUSTOM_DELAY_SET_TRST 0x10
-#define AICE_CUSTOM_DELAY_CLEAN_TRST 0x20
-
-struct aice_usb_handler_s {
- unsigned int usb_read_ep;
- unsigned int usb_write_ep;
- struct jtag_libusb_device_handle *usb_handle;
-};
-
-struct cache_info {
- uint32_t set;
- uint32_t way;
- uint32_t line_size;
-
- uint32_t log2_set;
- uint32_t log2_line_size;
-};
-
-struct aice_nds32_info {
- uint32_t edm_version;
- uint32_t r0_backup;
- uint32_t r1_backup;
- uint32_t host_dtr_backup;
- uint32_t target_dtr_backup;
- uint32_t edmsw_backup;
- uint32_t edm_ctl_backup;
- bool debug_under_dex_on;
- bool dex_use_psw_on;
- bool host_dtr_valid;
- bool target_dtr_valid;
- enum nds_memory_access access_channel;
- enum nds_memory_select memory_select;
- enum aice_target_state_s core_state;
- bool cache_init;
- struct cache_info icache;
- struct cache_info dcache;
-};
-
-extern struct aice_port_api_s aice_usb_api;
-
-int aice_read_ctrl(uint32_t address, uint32_t *data);
-int aice_write_ctrl(uint32_t address, uint32_t data);
-
-#endif /* OPENOCD_JTAG_AICE_AICE_USB_H */
diff --git a/src/jtag/commands.c b/src/jtag/commands.c
deleted file mode 100644
index ed40755..0000000
--- a/src/jtag/commands.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/jtag.h>
-#include "commands.h"
-
-struct cmd_queue_page {
- struct cmd_queue_page *next;
- void *address;
- size_t used;
-};
-
-#define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
-static struct cmd_queue_page *cmd_queue_pages;
-static struct cmd_queue_page *cmd_queue_pages_tail;
-
-struct jtag_command *jtag_command_queue;
-static struct jtag_command **next_command_pointer = &jtag_command_queue;
-
-void jtag_queue_command(struct jtag_command *cmd)
-{
- /* this command goes on the end, so ensure the queue terminates */
- cmd->next = NULL;
-
- struct jtag_command **last_cmd = next_command_pointer;
- assert(NULL != last_cmd);
- assert(NULL == *last_cmd);
- *last_cmd = cmd;
-
- /* store location where the next command pointer will be stored */
- next_command_pointer = &cmd->next;
-}
-
-void *cmd_queue_alloc(size_t size)
-{
- struct cmd_queue_page **p_page = &cmd_queue_pages;
- int offset;
- uint8_t *t;
-
- /*
- * WARNING:
- * We align/round the *SIZE* per below
- * so that all pointers returned by
- * this function are reasonably well
- * aligned.
- *
- * If we did not, then an "odd-length" request would cause the
- * *next* allocation to be at an *odd* address, and because
- * this function has the same type of api as malloc() - we
- * must also return pointers that have the same type of
- * alignment.
- *
- * What I do not/have is a reasonable portable means
- * to align by...
- *
- * The solution here, is based on these suggestions.
- * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html
- *
- */
- union worse_case_align {
- int i;
- long l;
- float f;
- void *v;
- };
-#define ALIGN_SIZE (sizeof(union worse_case_align))
-
- /* The alignment process. */
- size = (size + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1));
- /* Done... */
-
- if (*p_page) {
- p_page = &cmd_queue_pages_tail;
- if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
- p_page = &((*p_page)->next);
- }
-
- if (!*p_page) {
- *p_page = malloc(sizeof(struct cmd_queue_page));
- (*p_page)->used = 0;
- size_t alloc_size = (size < CMD_QUEUE_PAGE_SIZE) ?
- CMD_QUEUE_PAGE_SIZE : size;
- (*p_page)->address = malloc(alloc_size);
- (*p_page)->next = NULL;
- cmd_queue_pages_tail = *p_page;
- }
-
- offset = (*p_page)->used;
- (*p_page)->used += size;
-
- t = (*p_page)->address;
- return t + offset;
-}
-
-static void cmd_queue_free(void)
-{
- struct cmd_queue_page *page = cmd_queue_pages;
-
- while (page) {
- struct cmd_queue_page *last = page;
- free(page->address);
- page = page->next;
- free(last);
- }
-
- cmd_queue_pages = NULL;
- cmd_queue_pages_tail = NULL;
-}
-
-void jtag_command_queue_reset(void)
-{
- cmd_queue_free();
-
- jtag_command_queue = NULL;
- next_command_pointer = &jtag_command_queue;
-}
-
-enum scan_type jtag_scan_type(const struct scan_command *cmd)
-{
- int i;
- int type = 0;
-
- for (i = 0; i < cmd->num_fields; i++) {
- if (cmd->fields[i].in_value)
- type |= SCAN_IN;
- if (cmd->fields[i].out_value)
- type |= SCAN_OUT;
- }
-
- return type;
-}
-
-int jtag_scan_size(const struct scan_command *cmd)
-{
- int bit_count = 0;
- int i;
-
- /* count bits in scan command */
- for (i = 0; i < cmd->num_fields; i++)
- bit_count += cmd->fields[i].num_bits;
-
- return bit_count;
-}
-
-int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
-{
- int bit_count = 0;
- int i;
-
- bit_count = jtag_scan_size(cmd);
- *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8));
-
- bit_count = 0;
-
- DEBUG_JTAG_IO("%s num_fields: %i",
- cmd->ir_scan ? "IRSCAN" : "DRSCAN",
- cmd->num_fields);
-
- for (i = 0; i < cmd->num_fields; i++) {
- if (cmd->fields[i].out_value) {
-#ifdef _DEBUG_JTAG_IO_
- char *char_buf = buf_to_str(cmd->fields[i].out_value,
- (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ)
- ? DEBUG_JTAG_IOZ
- : cmd->fields[i].num_bits, 16);
-
- LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i,
- cmd->fields[i].num_bits, char_buf);
- free(char_buf);
-#endif
- buf_set_buf(cmd->fields[i].out_value, 0, *buffer,
- bit_count, cmd->fields[i].num_bits);
- } else {
- DEBUG_JTAG_IO("fields[%i].out_value[%i]: NULL",
- i, cmd->fields[i].num_bits);
- }
-
- bit_count += cmd->fields[i].num_bits;
- }
-
- /*DEBUG_JTAG_IO("bit_count totalling: %i", bit_count); */
-
- return bit_count;
-}
-
-int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
-{
- int i;
- int bit_count = 0;
- int retval;
-
- /* we return ERROR_OK, unless a check fails, or a handler reports a problem */
- retval = ERROR_OK;
-
- for (i = 0; i < cmd->num_fields; i++) {
- /* if neither in_value nor in_handler
- * are specified we don't have to examine this field
- */
- if (cmd->fields[i].in_value) {
- int num_bits = cmd->fields[i].num_bits;
- uint8_t *captured = buf_set_buf(buffer, bit_count,
- malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits);
-
-#ifdef _DEBUG_JTAG_IO_
- char *char_buf = buf_to_str(captured,
- (num_bits > DEBUG_JTAG_IOZ)
- ? DEBUG_JTAG_IOZ
- : num_bits, 16);
-
- LOG_DEBUG("fields[%i].in_value[%i]: 0x%s",
- i, num_bits, char_buf);
- free(char_buf);
-#endif
-
- if (cmd->fields[i].in_value)
- buf_cpy(captured, cmd->fields[i].in_value, num_bits);
-
- free(captured);
- }
- bit_count += cmd->fields[i].num_bits;
- }
-
- return retval;
-}
diff --git a/src/jtag/commands.h b/src/jtag/commands.h
deleted file mode 100644
index 947c947..0000000
--- a/src/jtag/commands.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_COMMANDS_H
-#define OPENOCD_JTAG_COMMANDS_H
-
-/**
- * The inferred type of a scan_command_s structure, indicating whether
- * the command has the host scan in from the device, the host scan out
- * to the device, or both.
- */
-enum scan_type {
- /** From device to host, */
- SCAN_IN = 1,
- /** From host to device, */
- SCAN_OUT = 2,
- /** Full-duplex scan. */
- SCAN_IO = 3
-};
-
-/**
- * The scan_command provide a means of encapsulating a set of scan_field_s
- * structures that should be scanned in/out to the device.
- */
-struct scan_command {
- /** instruction/not data scan */
- bool ir_scan;
- /** number of fields in *fields array */
- int num_fields;
- /** pointer to an array of data scan fields */
- struct scan_field *fields;
- /** state in which JTAG commands should finish */
- tap_state_t end_state;
-};
-
-struct statemove_command {
- /** state in which JTAG commands should finish */
- tap_state_t end_state;
-};
-
-struct pathmove_command {
- /** number of states in *path */
- int num_states;
- /** states that have to be passed */
- tap_state_t *path;
-};
-
-struct runtest_command {
- /** number of cycles to spend in Run-Test/Idle state */
- int num_cycles;
- /** state in which JTAG commands should finish */
- tap_state_t end_state;
-};
-
-
-struct stableclocks_command {
- /** number of clock cycles that should be sent */
- int num_cycles;
-};
-
-
-struct reset_command {
- /** Set TRST output: 0 = deassert, 1 = assert, -1 = no change */
- int trst;
- /** Set SRST output: 0 = deassert, 1 = assert, -1 = no change */
- int srst;
-};
-
-struct end_state_command {
- /** state in which JTAG commands should finish */
- tap_state_t end_state;
-};
-
-struct sleep_command {
- /** number of microseconds to sleep */
- uint32_t us;
-};
-
-/**
- * Encapsulates a series of bits to be clocked out, affecting state
- * and mode of the interface.
- *
- * In JTAG mode these are clocked out on TMS, using TCK. They may be
- * used for link resets, transitioning between JTAG and SWD modes, or
- * to implement JTAG state machine transitions (implementing pathmove
- * or statemove operations).
- *
- * In SWD mode these are clocked out on SWDIO, using SWCLK, and are
- * used for link resets and transitioning between SWD and JTAG modes.
- */
-struct tms_command {
- /** How many bits should be clocked out. */
- unsigned num_bits;
- /** The bits to clock out; the LSB is bit 0 of bits[0]. */
- const uint8_t *bits;
-};
-
-/**
- * Defines a container type that hold a pointer to a JTAG command
- * structure of any defined type.
- */
-union jtag_command_container {
- struct scan_command *scan;
- struct statemove_command *statemove;
- struct pathmove_command *pathmove;
- struct runtest_command *runtest;
- struct stableclocks_command *stableclocks;
- struct reset_command *reset;
- struct end_state_command *end_state;
- struct sleep_command *sleep;
- struct tms_command *tms;
-};
-
-/**
- * The type of the @c jtag_command_container contained by a
- * @c jtag_command_s structure.
- */
-enum jtag_command_type {
- JTAG_SCAN = 1,
- /* JTAG_TLR_RESET's non-minidriver implementation is a
- * vestige from a statemove cmd. The statemove command
- * is obsolete and replaced by pathmove.
- *
- * pathmove does not support reset as one of it's states,
- * hence the need for an explicit statemove command.
- */
- JTAG_TLR_RESET = 2,
- JTAG_RUNTEST = 3,
- JTAG_RESET = 4,
- JTAG_PATHMOVE = 6,
- JTAG_SLEEP = 7,
- JTAG_STABLECLOCKS = 8,
- JTAG_TMS = 9,
-};
-
-struct jtag_command {
- union jtag_command_container cmd;
- enum jtag_command_type type;
- struct jtag_command *next;
-};
-
-/** The current queue of jtag_command_s structures. */
-extern struct jtag_command *jtag_command_queue;
-
-void *cmd_queue_alloc(size_t size);
-
-void jtag_queue_command(struct jtag_command *cmd);
-void jtag_command_queue_reset(void);
-
-enum scan_type jtag_scan_type(const struct scan_command *cmd);
-int jtag_scan_size(const struct scan_command *cmd);
-int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd);
-int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer);
-
-#endif /* OPENOCD_JTAG_COMMANDS_H */
diff --git a/src/jtag/core.c b/src/jtag/core.c
deleted file mode 100644
index 3da69ff..0000000
--- a/src/jtag/core.c
+++ /dev/null
@@ -1,1966 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * Copyright (C) 2007,2008,2009 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag.h"
-#include "swd.h"
-#include "interface.h"
-#include <transport/transport.h>
-#include <helper/jep106.h>
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-/* SVF and XSVF are higher level JTAG command sets (for boundary scan) */
-#include "svf/svf.h"
-#include "xsvf/xsvf.h"
-
-/** The number of JTAG queue flushes (for profiling and debugging purposes). */
-static int jtag_flush_queue_count;
-
-/* Sleep this # of ms after flushing the queue */
-static int jtag_flush_queue_sleep;
-
-static void jtag_add_scan_check(struct jtag_tap *active,
- void (*jtag_add_scan)(struct jtag_tap *active,
- int in_num_fields,
- const struct scan_field *in_fields,
- tap_state_t state),
- int in_num_fields, struct scan_field *in_fields, tap_state_t state);
-
-/**
- * The jtag_error variable is set when an error occurs while executing
- * the queue. Application code may set this using jtag_set_error(),
- * when an error occurs during processing that should be reported during
- * jtag_execute_queue().
- *
- * The value is set and cleared, but never read by normal application code.
- *
- * This value is returned (and cleared) by jtag_execute_queue().
- */
-static int jtag_error = ERROR_OK;
-
-static const char *jtag_event_strings[] = {
- [JTAG_TRST_ASSERTED] = "TAP reset",
- [JTAG_TAP_EVENT_SETUP] = "TAP setup",
- [JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
- [JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
-};
-
-/*
- * JTAG adapters must initialize with TRST and SRST de-asserted
- * (they're negative logic, so that means *high*). But some
- * hardware doesn't necessarily work that way ... so set things
- * up so that jtag_init() always forces that state.
- */
-static int jtag_trst = -1;
-static int jtag_srst = -1;
-
-/**
- * List all TAPs that have been created.
- */
-static struct jtag_tap *__jtag_all_taps;
-
-static enum reset_types jtag_reset_config = RESET_NONE;
-tap_state_t cmd_queue_cur_state = TAP_RESET;
-
-static bool jtag_verify_capture_ir = true;
-static int jtag_verify = 1;
-
-/* how long the OpenOCD should wait before attempting JTAG communication after reset lines
- *deasserted (in ms) */
-static int adapter_nsrst_delay; /* default to no nSRST delay */
-static int jtag_ntrst_delay;/* default to no nTRST delay */
-static int adapter_nsrst_assert_width; /* width of assertion */
-static int jtag_ntrst_assert_width; /* width of assertion */
-
-/**
- * Contains a single callback along with a pointer that will be passed
- * when an event occurs.
- */
-struct jtag_event_callback {
- /** a event callback */
- jtag_event_handler_t callback;
- /** the private data to pass to the callback */
- void *priv;
- /** the next callback */
- struct jtag_event_callback *next;
-};
-
-/* callbacks to inform high-level handlers about JTAG state changes */
-static struct jtag_event_callback *jtag_event_callbacks;
-
-/* speed in kHz*/
-static int speed_khz;
-/* speed to fallback to when RCLK is requested but not supported */
-static int rclk_fallback_speed_khz;
-static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode;
-static int jtag_speed;
-
-static struct jtag_interface *jtag;
-
-/* configuration */
-struct jtag_interface *jtag_interface;
-
-void jtag_set_flush_queue_sleep(int ms)
-{
- jtag_flush_queue_sleep = ms;
-}
-
-void jtag_set_error(int error)
-{
- if ((error == ERROR_OK) || (jtag_error != ERROR_OK))
- return;
- jtag_error = error;
-}
-
-int jtag_error_clear(void)
-{
- int temp = jtag_error;
- jtag_error = ERROR_OK;
- return temp;
-}
-
-/************/
-
-static bool jtag_poll = 1;
-
-bool is_jtag_poll_safe(void)
-{
- /* Polling can be disabled explicitly with set_enabled(false).
- * It is also implicitly disabled while TRST is active and
- * while SRST is gating the JTAG clock.
- */
- if (!transport_is_jtag())
- return jtag_poll;
-
- if (!jtag_poll || jtag_trst != 0)
- return false;
- return jtag_srst == 0 || (jtag_reset_config & RESET_SRST_NO_GATING);
-}
-
-bool jtag_poll_get_enabled(void)
-{
- return jtag_poll;
-}
-
-void jtag_poll_set_enabled(bool value)
-{
- jtag_poll = value;
-}
-
-/************/
-
-struct jtag_tap *jtag_all_taps(void)
-{
- return __jtag_all_taps;
-};
-
-unsigned jtag_tap_count(void)
-{
- struct jtag_tap *t = jtag_all_taps();
- unsigned n = 0;
- while (t) {
- n++;
- t = t->next_tap;
- }
- return n;
-}
-
-unsigned jtag_tap_count_enabled(void)
-{
- struct jtag_tap *t = jtag_all_taps();
- unsigned n = 0;
- while (t) {
- if (t->enabled)
- n++;
- t = t->next_tap;
- }
- return n;
-}
-
-/** Append a new TAP to the chain of all taps. */
-void jtag_tap_add(struct jtag_tap *t)
-{
- unsigned jtag_num_taps = 0;
-
- struct jtag_tap **tap = &__jtag_all_taps;
- while (*tap != NULL) {
- jtag_num_taps++;
- tap = &(*tap)->next_tap;
- }
- *tap = t;
- t->abs_chain_position = jtag_num_taps;
-}
-
-/* returns a pointer to the n-th device in the scan chain */
-struct jtag_tap *jtag_tap_by_position(unsigned n)
-{
- struct jtag_tap *t = jtag_all_taps();
-
- while (t && n-- > 0)
- t = t->next_tap;
-
- return t;
-}
-
-struct jtag_tap *jtag_tap_by_string(const char *s)
-{
- /* try by name first */
- struct jtag_tap *t = jtag_all_taps();
-
- while (t) {
- if (0 == strcmp(t->dotted_name, s))
- return t;
- t = t->next_tap;
- }
-
- /* no tap found by name, so try to parse the name as a number */
- unsigned n;
- if (parse_uint(s, &n) != ERROR_OK)
- return NULL;
-
- /* FIXME remove this numeric fallback code late June 2010, along
- * with all info in the User's Guide that TAPs have numeric IDs.
- * Also update "scan_chain" output to not display the numbers.
- */
- t = jtag_tap_by_position(n);
- if (t)
- LOG_WARNING("Specify TAP '%s' by name, not number %u",
- t->dotted_name, n);
-
- return t;
-}
-
-struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p)
-{
- p = p ? p->next_tap : jtag_all_taps();
- while (p) {
- if (p->enabled)
- return p;
- p = p->next_tap;
- }
- return NULL;
-}
-
-const char *jtag_tap_name(const struct jtag_tap *tap)
-{
- return (tap == NULL) ? "(unknown)" : tap->dotted_name;
-}
-
-
-int jtag_register_event_callback(jtag_event_handler_t callback, void *priv)
-{
- struct jtag_event_callback **callbacks_p = &jtag_event_callbacks;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (*callbacks_p) {
- while ((*callbacks_p)->next)
- callbacks_p = &((*callbacks_p)->next);
- callbacks_p = &((*callbacks_p)->next);
- }
-
- (*callbacks_p) = malloc(sizeof(struct jtag_event_callback));
- (*callbacks_p)->callback = callback;
- (*callbacks_p)->priv = priv;
- (*callbacks_p)->next = NULL;
-
- return ERROR_OK;
-}
-
-int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv)
-{
- struct jtag_event_callback **p = &jtag_event_callbacks, *temp;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- while (*p) {
- if (((*p)->priv != priv) || ((*p)->callback != callback)) {
- p = &(*p)->next;
- continue;
- }
-
- temp = *p;
- *p = (*p)->next;
- free(temp);
- }
-
- return ERROR_OK;
-}
-
-int jtag_call_event_callbacks(enum jtag_event event)
-{
- struct jtag_event_callback *callback = jtag_event_callbacks;
-
- LOG_DEBUG("jtag event: %s", jtag_event_strings[event]);
-
- while (callback) {
- struct jtag_event_callback *next;
-
- /* callback may remove itself */
- next = callback->next;
- callback->callback(event, callback->priv);
- callback = next;
- }
-
- return ERROR_OK;
-}
-
-static void jtag_checks(void)
-{
- assert(jtag_trst == 0);
-}
-
-static void jtag_prelude(tap_state_t state)
-{
- jtag_checks();
-
- assert(state != TAP_INVALID);
-
- cmd_queue_cur_state = state;
-}
-
-void jtag_add_ir_scan_noverify(struct jtag_tap *active, const struct scan_field *in_fields,
- tap_state_t state)
-{
- jtag_prelude(state);
-
- int retval = interface_jtag_add_ir_scan(active, in_fields, state);
- jtag_set_error(retval);
-}
-
-static void jtag_add_ir_scan_noverify_callback(struct jtag_tap *active,
- int dummy,
- const struct scan_field *in_fields,
- tap_state_t state)
-{
- jtag_add_ir_scan_noverify(active, in_fields, state);
-}
-
-/* If fields->in_value is filled out, then the captured IR value will be checked */
-void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap_state_t state)
-{
- assert(state != TAP_RESET);
-
- if (jtag_verify && jtag_verify_capture_ir) {
- /* 8 x 32 bit id's is enough for all invocations */
-
- /* if we are to run a verification of the ir scan, we need to get the input back.
- * We may have to allocate space if the caller didn't ask for the input back.
- */
- in_fields->check_value = active->expected;
- in_fields->check_mask = active->expected_mask;
- jtag_add_scan_check(active, jtag_add_ir_scan_noverify_callback, 1, in_fields,
- state);
- } else
- jtag_add_ir_scan_noverify(active, in_fields, state);
-}
-
-void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
- tap_state_t state)
-{
- assert(out_bits != NULL);
- assert(state != TAP_RESET);
-
- jtag_prelude(state);
-
- int retval = interface_jtag_add_plain_ir_scan(
- num_bits, out_bits, in_bits, state);
- jtag_set_error(retval);
-}
-
-static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
- uint8_t *in_check_mask, int num_bits);
-
-static int jtag_check_value_mask_callback(jtag_callback_data_t data0,
- jtag_callback_data_t data1,
- jtag_callback_data_t data2,
- jtag_callback_data_t data3)
-{
- return jtag_check_value_inner((uint8_t *)data0,
- (uint8_t *)data1,
- (uint8_t *)data2,
- (int)data3);
-}
-
-static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)(
- struct jtag_tap *active,
- int in_num_fields,
- const struct scan_field *in_fields,
- tap_state_t state),
- int in_num_fields, struct scan_field *in_fields, tap_state_t state)
-{
- jtag_add_scan(active, in_num_fields, in_fields, state);
-
- for (int i = 0; i < in_num_fields; i++) {
- if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) {
- /* this is synchronous for a minidriver */
- jtag_add_callback4(jtag_check_value_mask_callback,
- (jtag_callback_data_t)in_fields[i].in_value,
- (jtag_callback_data_t)in_fields[i].check_value,
- (jtag_callback_data_t)in_fields[i].check_mask,
- (jtag_callback_data_t)in_fields[i].num_bits);
- }
- }
-}
-
-void jtag_add_dr_scan_check(struct jtag_tap *active,
- int in_num_fields,
- struct scan_field *in_fields,
- tap_state_t state)
-{
- if (jtag_verify)
- jtag_add_scan_check(active, jtag_add_dr_scan, in_num_fields, in_fields, state);
- else
- jtag_add_dr_scan(active, in_num_fields, in_fields, state);
-}
-
-
-void jtag_add_dr_scan(struct jtag_tap *active,
- int in_num_fields,
- const struct scan_field *in_fields,
- tap_state_t state)
-{
- assert(state != TAP_RESET);
-
- jtag_prelude(state);
-
- int retval;
- retval = interface_jtag_add_dr_scan(active, in_num_fields, in_fields, state);
- jtag_set_error(retval);
-}
-
-void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
- tap_state_t state)
-{
- assert(out_bits != NULL);
- assert(state != TAP_RESET);
-
- jtag_prelude(state);
-
- int retval;
- retval = interface_jtag_add_plain_dr_scan(num_bits, out_bits, in_bits, state);
- jtag_set_error(retval);
-}
-
-void jtag_add_tlr(void)
-{
- jtag_prelude(TAP_RESET);
- jtag_set_error(interface_jtag_add_tlr());
-
- /* NOTE: order here matches TRST path in jtag_add_reset() */
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
- jtag_notify_event(JTAG_TRST_ASSERTED);
-}
-
-/**
- * If supported by the underlying adapter, this clocks a raw bit sequence
- * onto TMS for switching betwen JTAG and SWD modes.
- *
- * DO NOT use this to bypass the integrity checks and logging provided
- * by the jtag_add_pathmove() and jtag_add_statemove() calls.
- *
- * @param nbits How many bits to clock out.
- * @param seq The bit sequence. The LSB is bit 0 of seq[0].
- * @param state The JTAG tap state to record on completion. Use
- * TAP_INVALID to represent being in in SWD mode.
- *
- * @todo Update naming conventions to stop assuming everything is JTAG.
- */
-int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state)
-{
- int retval;
-
- if (!(jtag->supported & DEBUG_CAP_TMS_SEQ))
- return ERROR_JTAG_NOT_IMPLEMENTED;
-
- jtag_checks();
- cmd_queue_cur_state = state;
-
- retval = interface_add_tms_seq(nbits, seq, state);
- jtag_set_error(retval);
- return retval;
-}
-
-void jtag_add_pathmove(int num_states, const tap_state_t *path)
-{
- tap_state_t cur_state = cmd_queue_cur_state;
-
- /* the last state has to be a stable state */
- if (!tap_is_state_stable(path[num_states - 1])) {
- LOG_ERROR("BUG: TAP path doesn't finish in a stable state");
- jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE);
- return;
- }
-
- for (int i = 0; i < num_states; i++) {
- if (path[i] == TAP_RESET) {
- LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences");
- jtag_set_error(ERROR_JTAG_STATE_INVALID);
- return;
- }
-
- if (tap_state_transition(cur_state, true) != path[i] &&
- tap_state_transition(cur_state, false) != path[i]) {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(cur_state), tap_state_name(path[i]));
- jtag_set_error(ERROR_JTAG_TRANSITION_INVALID);
- return;
- }
- cur_state = path[i];
- }
-
- jtag_checks();
-
- jtag_set_error(interface_jtag_add_pathmove(num_states, path));
- cmd_queue_cur_state = path[num_states - 1];
-}
-
-int jtag_add_statemove(tap_state_t goal_state)
-{
- tap_state_t cur_state = cmd_queue_cur_state;
-
- if (goal_state != cur_state) {
- LOG_DEBUG("cur_state=%s goal_state=%s",
- tap_state_name(cur_state),
- tap_state_name(goal_state));
- }
-
- /* If goal is RESET, be paranoid and force that that transition
- * (e.g. five TCK cycles, TMS high). Else trust "cur_state".
- */
- if (goal_state == TAP_RESET)
- jtag_add_tlr();
- else if (goal_state == cur_state)
- /* nothing to do */;
-
- else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state)) {
- unsigned tms_bits = tap_get_tms_path(cur_state, goal_state);
- unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state);
- tap_state_t moves[8];
- assert(tms_count < ARRAY_SIZE(moves));
-
- for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1) {
- bool bit = tms_bits & 1;
-
- cur_state = tap_state_transition(cur_state, bit);
- moves[i] = cur_state;
- }
-
- jtag_add_pathmove(tms_count, moves);
- } else if (tap_state_transition(cur_state, true) == goal_state
- || tap_state_transition(cur_state, false) == goal_state)
- jtag_add_pathmove(1, &goal_state);
- else
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-void jtag_add_runtest(int num_cycles, tap_state_t state)
-{
- jtag_prelude(state);
- jtag_set_error(interface_jtag_add_runtest(num_cycles, state));
-}
-
-
-void jtag_add_clocks(int num_cycles)
-{
- if (!tap_is_state_stable(cmd_queue_cur_state)) {
- LOG_ERROR("jtag_add_clocks() called with TAP in unstable state \"%s\"",
- tap_state_name(cmd_queue_cur_state));
- jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE);
- return;
- }
-
- if (num_cycles > 0) {
- jtag_checks();
- jtag_set_error(interface_jtag_add_clocks(num_cycles));
- }
-}
-
-void swd_add_reset(int req_srst)
-{
- if (req_srst) {
- if (!(jtag_reset_config & RESET_HAS_SRST)) {
- LOG_ERROR("BUG: can't assert SRST");
- jtag_set_error(ERROR_FAIL);
- return;
- }
- req_srst = 1;
- }
-
- /* Maybe change SRST signal state */
- if (jtag_srst != req_srst) {
- int retval;
-
- retval = interface_jtag_add_reset(0, req_srst);
- if (retval != ERROR_OK)
- jtag_set_error(retval);
- else
- retval = jtag_execute_queue();
-
- if (retval != ERROR_OK) {
- LOG_ERROR("TRST/SRST error");
- return;
- }
-
- /* SRST resets everything hooked up to that signal */
- jtag_srst = req_srst;
- if (jtag_srst) {
- LOG_DEBUG("SRST line asserted");
- if (adapter_nsrst_assert_width)
- jtag_add_sleep(adapter_nsrst_assert_width * 1000);
- } else {
- LOG_DEBUG("SRST line released");
- if (adapter_nsrst_delay)
- jtag_add_sleep(adapter_nsrst_delay * 1000);
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("SRST timings error");
- return;
- }
- }
-}
-
-void jtag_add_reset(int req_tlr_or_trst, int req_srst)
-{
- int trst_with_tlr = 0;
- int new_srst = 0;
- int new_trst = 0;
-
- /* Without SRST, we must use target-specific JTAG operations
- * on each target; callers should not be requesting SRST when
- * that signal doesn't exist.
- *
- * RESET_SRST_PULLS_TRST is a board or chip level quirk, which
- * can kick in even if the JTAG adapter can't drive TRST.
- */
- if (req_srst) {
- if (!(jtag_reset_config & RESET_HAS_SRST)) {
- LOG_ERROR("BUG: can't assert SRST");
- jtag_set_error(ERROR_FAIL);
- return;
- }
- if ((jtag_reset_config & RESET_SRST_PULLS_TRST) != 0
- && !req_tlr_or_trst) {
- LOG_ERROR("BUG: can't assert only SRST");
- jtag_set_error(ERROR_FAIL);
- return;
- }
- new_srst = 1;
- }
-
- /* JTAG reset (entry to TAP_RESET state) can always be achieved
- * using TCK and TMS; that may go through a TAP_{IR,DR}UPDATE
- * state first. TRST accelerates it, and bypasses those states.
- *
- * RESET_TRST_PULLS_SRST is a board or chip level quirk, which
- * can kick in even if the JTAG adapter can't drive SRST.
- */
- if (req_tlr_or_trst) {
- if (!(jtag_reset_config & RESET_HAS_TRST))
- trst_with_tlr = 1;
- else if ((jtag_reset_config & RESET_TRST_PULLS_SRST) != 0
- && !req_srst)
- trst_with_tlr = 1;
- else
- new_trst = 1;
- }
-
- /* Maybe change TRST and/or SRST signal state */
- if (jtag_srst != new_srst || jtag_trst != new_trst) {
- int retval;
-
- retval = interface_jtag_add_reset(new_trst, new_srst);
- if (retval != ERROR_OK)
- jtag_set_error(retval);
- else
- retval = jtag_execute_queue();
-
- if (retval != ERROR_OK) {
- LOG_ERROR("TRST/SRST error");
- return;
- }
- }
-
- /* SRST resets everything hooked up to that signal */
- if (jtag_srst != new_srst) {
- jtag_srst = new_srst;
- if (jtag_srst) {
- LOG_DEBUG("SRST line asserted");
- if (adapter_nsrst_assert_width)
- jtag_add_sleep(adapter_nsrst_assert_width * 1000);
- } else {
- LOG_DEBUG("SRST line released");
- if (adapter_nsrst_delay)
- jtag_add_sleep(adapter_nsrst_delay * 1000);
- }
- }
-
- /* Maybe enter the JTAG TAP_RESET state ...
- * - using only TMS, TCK, and the JTAG state machine
- * - or else more directly, using TRST
- *
- * TAP_RESET should be invisible to non-debug parts of the system.
- */
- if (trst_with_tlr) {
- LOG_DEBUG("JTAG reset with TLR instead of TRST");
- jtag_add_tlr();
-
- } else if (jtag_trst != new_trst) {
- jtag_trst = new_trst;
- if (jtag_trst) {
- LOG_DEBUG("TRST line asserted");
- tap_set_state(TAP_RESET);
- if (jtag_ntrst_assert_width)
- jtag_add_sleep(jtag_ntrst_assert_width * 1000);
- } else {
- LOG_DEBUG("TRST line released");
- if (jtag_ntrst_delay)
- jtag_add_sleep(jtag_ntrst_delay * 1000);
-
- /* We just asserted nTRST, so we're now in TAP_RESET.
- * Inform possible listeners about this, now that
- * JTAG instructions and data can be shifted. This
- * sequence must match jtag_add_tlr().
- */
- jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
- jtag_notify_event(JTAG_TRST_ASSERTED);
- }
- }
-}
-
-void jtag_add_sleep(uint32_t us)
-{
- /** @todo Here, keep_alive() appears to be a layering violation!!! */
- keep_alive();
- jtag_set_error(interface_jtag_add_sleep(us));
-}
-
-static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
- uint8_t *in_check_mask, int num_bits)
-{
- int retval = ERROR_OK;
- int compare_failed;
-
- if (in_check_mask)
- compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits);
- else
- compare_failed = buf_cmp(captured, in_check_value, num_bits);
-
- if (compare_failed) {
- char *captured_str, *in_check_value_str;
- int bits = (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits;
-
- /* NOTE: we've lost diagnostic context here -- 'which tap' */
-
- captured_str = buf_to_str(captured, bits, 16);
- in_check_value_str = buf_to_str(in_check_value, bits, 16);
-
- LOG_WARNING("Bad value '%s' captured during DR or IR scan:",
- captured_str);
- LOG_WARNING(" check_value: 0x%s", in_check_value_str);
-
- free(captured_str);
- free(in_check_value_str);
-
- if (in_check_mask) {
- char *in_check_mask_str;
-
- in_check_mask_str = buf_to_str(in_check_mask, bits, 16);
- LOG_WARNING(" check_mask: 0x%s", in_check_mask_str);
- free(in_check_mask_str);
- }
-
- retval = ERROR_JTAG_QUEUE_FAILED;
- }
- return retval;
-}
-
-void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask)
-{
- assert(field->in_value != NULL);
-
- if (value == NULL) {
- /* no checking to do */
- return;
- }
-
- jtag_execute_queue_noclear();
-
- int retval = jtag_check_value_inner(field->in_value, value, mask, field->num_bits);
- jtag_set_error(retval);
-}
-
-int default_interface_jtag_execute_queue(void)
-{
- if (NULL == jtag) {
- LOG_ERROR("No JTAG interface configured yet. "
- "Issue 'init' command in startup scripts "
- "before communicating with targets.");
- return ERROR_FAIL;
- }
-
- int result = jtag->execute_queue();
-
-#if 0
- // TODO: I like these better than some of the other JTAG debug statements,
- // but having both is silly.
- struct jtag_command *cmd = jtag_command_queue;
- while (debug_level >= LOG_LVL_DEBUG && cmd) {
- switch (cmd->type) {
- case JTAG_SCAN:
-#if 0
- LOG_DEBUG("JTAG %s SCAN to %s",
- cmd->cmd.scan->ir_scan ? "IR" : "DR",
- tap_state_name(cmd->cmd.scan->end_state));
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++) {
- struct scan_field *field = cmd->cmd.scan->fields + i;
- if (field->out_value) {
- char *str = buf_to_str(field->out_value, field->num_bits, 16);
- LOG_DEBUG(" %db out: %s", field->num_bits, str);
- free(str);
- }
- if (field->in_value) {
- char *str = buf_to_str(field->in_value, field->num_bits, 16);
- LOG_DEBUG(" %db in: %s", field->num_bits, str);
- free(str);
- }
- if (field->check_value) {
- char *str = buf_to_str(field->check_value, field->num_bits, 16);
- LOG_DEBUG(" %db check: %s", field->num_bits, str);
- free(str);
- }
- if (field->check_mask) {
- char *str = buf_to_str(field->check_mask, field->num_bits, 16);
- LOG_DEBUG(" %db mask: %s", field->num_bits, str);
- free(str);
- }
- }
-#endif
- {
- uint8_t *buf = NULL;
- int scan_bits = jtag_build_buffer(cmd->cmd.scan, &buf);
- char *str_out = buf_to_str(buf, scan_bits, 16);
- free(buf);
- LOG_DEBUG("vvv jtag_scan(%d, %d, %d'h%s, %d); // %s",
- cmd->cmd.scan->ir_scan,
- scan_bits,
- scan_bits, str_out,
- cmd->cmd.scan->end_state, tap_state_name(cmd->cmd.scan->end_state));
- free(str_out);
-
- struct scan_field *last_field = cmd->cmd.scan->fields + cmd->cmd.scan->num_fields - 1;
- if (last_field->in_value) {
- char *str_in = buf_to_str(last_field->in_value, last_field->num_bits, 16);
- LOG_DEBUG("vvv jtag_check_tdo(%d, %d'h%s);",
- last_field->num_bits,
- last_field->num_bits, str_in);
- free(str_in);
- }
- }
- break;
- case JTAG_TLR_RESET:
-#if 0
- LOG_DEBUG("JTAG TLR RESET to %s",
- tap_state_name(cmd->cmd.statemove->end_state));
-#endif
- LOG_DEBUG("vvv jtag_tlr_reset(%d); // %s",
- cmd->cmd.statemove->end_state,
- tap_state_name(cmd->cmd.statemove->end_state));
- break;
- case JTAG_RUNTEST:
-#if 0
- LOG_DEBUG("JTAG RUNTEST %d cycles to %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
-#endif
- LOG_DEBUG("vvv jtag_runtest(%d, %d); // %s",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state,
- tap_state_name(cmd->cmd.runtest->end_state));
- break;
- case JTAG_RESET:
- {
-#if 0
- const char *reset_str[3] = {
- "leave", "deassert", "assert"
- };
- LOG_DEBUG("JTAG RESET %s TRST, %s SRST",
- reset_str[cmd->cmd.reset->trst + 1],
- reset_str[cmd->cmd.reset->srst + 1]);
-#endif
- LOG_DEBUG("vvv jtag_reset(%d, %d);",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- }
- break;
- case JTAG_PATHMOVE:
- LOG_DEBUG("JTAG PATHMOVE (TODO)");
- break;
- case JTAG_SLEEP:
- LOG_DEBUG("JTAG SLEEP (TODO)");
- break;
- case JTAG_STABLECLOCKS:
- LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
- break;
- case JTAG_TMS:
- LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
- break;
- default:
- LOG_ERROR("Unknown JTAG command: %d", cmd->type);
- break;
- }
- cmd = cmd->next;
- }
-#endif
-
- return result;
-}
-
-void jtag_execute_queue_noclear(void)
-{
- jtag_flush_queue_count++;
- jtag_set_error(interface_jtag_execute_queue());
-
- if (jtag_flush_queue_sleep > 0) {
- /* For debug purposes it can be useful to test performance
- * or behavior when delaying after flushing the queue,
- * e.g. to simulate long roundtrip times.
- */
- usleep(jtag_flush_queue_sleep * 1000);
- }
-}
-
-int jtag_get_flush_queue_count(void)
-{
- return jtag_flush_queue_count;
-}
-
-int jtag_execute_queue(void)
-{
- jtag_execute_queue_noclear();
- return jtag_error_clear();
-}
-
-static int jtag_reset_callback(enum jtag_event event, void *priv)
-{
- struct jtag_tap *tap = priv;
-
- if (event == JTAG_TRST_ASSERTED) {
- tap->enabled = !tap->disabled_after_reset;
-
- /* current instruction is either BYPASS or IDCODE */
- buf_set_ones(tap->cur_instr, tap->ir_length);
- tap->bypass = 1;
- }
-
- return ERROR_OK;
-}
-
-/* sleep at least us microseconds. When we sleep more than 1000ms we
- * do an alive sleep, i.e. keep GDB alive. Note that we could starve
- * GDB if we slept for <1000ms many times.
- */
-void jtag_sleep(uint32_t us)
-{
- if (us < 1000)
- usleep(us);
- else
- alive_sleep((us+999)/1000);
-}
-
-#define JTAG_MAX_AUTO_TAPS 20
-
-#define EXTRACT_JEP106_BANK(X) (((X) & 0xf00) >> 8)
-#define EXTRACT_JEP106_ID(X) (((X) & 0xfe) >> 1)
-#define EXTRACT_MFG(X) (((X) & 0xffe) >> 1)
-#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
-#define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28)
-
-/* A reserved manufacturer ID is used in END_OF_CHAIN_FLAG, so we
- * know that no valid TAP will have it as an IDCODE value.
- */
-#define END_OF_CHAIN_FLAG 0xffffffff
-
-/* a larger IR length than we ever expect to autoprobe */
-#define JTAG_IRLEN_MAX 60
-
-static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
-{
- struct scan_field field = {
- .num_bits = num_idcode * 32,
- .out_value = idcode_buffer,
- .in_value = idcode_buffer,
- };
-
- /* initialize to the end of chain ID value */
- for (unsigned i = 0; i < num_idcode; i++)
- buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG);
-
- jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE);
- jtag_add_tlr();
- return jtag_execute_queue();
-}
-
-static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count)
-{
- uint8_t zero_check = 0x0;
- uint8_t one_check = 0xff;
-
- for (unsigned i = 0; i < count * 4; i++) {
- zero_check |= idcodes[i];
- one_check &= idcodes[i];
- }
-
- /* if there wasn't a single non-zero bit or if all bits were one,
- * the scan is not valid. We wrote a mix of both values; either
- *
- * - There's a hardware issue (almost certainly):
- * + all-zeroes can mean a target stuck in JTAG reset
- * + all-ones tends to mean no target
- * - The scan chain is WAY longer than we can handle, *AND* either
- * + there are several hundreds of TAPs in bypass, or
- * + at least a few dozen TAPs all have an all-ones IDCODE
- */
- if (zero_check == 0x00 || one_check == 0xff) {
- LOG_ERROR("JTAG scan chain interrogation failed: all %s",
- (zero_check == 0x00) ? "zeroes" : "ones");
- LOG_ERROR("Check JTAG interface, timings, target power, etc.");
- return false;
- }
- return true;
-}
-
-static void jtag_examine_chain_display(enum log_levels level, const char *msg,
- const char *name, uint32_t idcode)
-{
- log_printf_lf(level, __FILE__, __LINE__, __func__,
- "JTAG tap: %s %16.16s: 0x%08x "
- "(mfg: 0x%3.3x (%s), part: 0x%4.4x, ver: 0x%1.1x)",
- name, msg,
- (unsigned int)idcode,
- (unsigned int)EXTRACT_MFG(idcode),
- jep106_manufacturer(EXTRACT_JEP106_BANK(idcode), EXTRACT_JEP106_ID(idcode)),
- (unsigned int)EXTRACT_PART(idcode),
- (unsigned int)EXTRACT_VER(idcode));
-}
-
-static bool jtag_idcode_is_final(uint32_t idcode)
-{
- /*
- * Some devices, such as AVR8, will output all 1's instead
- * of TDI input value at end of chain. Allow those values
- * instead of failing.
- */
- return idcode == END_OF_CHAIN_FLAG;
-}
-
-/**
- * This helper checks that remaining bits in the examined chain data are
- * all as expected, but a single JTAG device requires only 64 bits to be
- * read back correctly. This can help identify and diagnose problems
- * with the JTAG chain earlier, gives more helpful/explicit error messages.
- * Returns TRUE iff garbage was found.
- */
-static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max)
-{
- bool triggered = false;
- for (; count < max - 31; count += 32) {
- uint32_t idcode = buf_get_u32(idcodes, count, 32);
-
- /* do not trigger the warning if the data looks good */
- if (jtag_idcode_is_final(idcode))
- continue;
- LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
- count, (unsigned int)idcode);
- triggered = true;
- }
- return triggered;
-}
-
-static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
-{
-
- if (tap->expected_ids_cnt == 0 || !tap->hasidcode)
- return true;
-
- /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */
- uint32_t mask = tap->ignore_version ? ~(0xf << 28) : ~0;
- uint32_t idcode = tap->idcode & mask;
-
- /* Loop over the expected identification codes and test for a match */
- for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
- uint32_t expected = tap->expected_ids[ii] & mask;
-
- if (idcode == expected)
- return true;
-
- /* treat "-expected-id 0" as a "don't-warn" wildcard */
- if (0 == tap->expected_ids[ii])
- return true;
- }
-
- /* If none of the expected ids matched, warn */
- jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED",
- tap->dotted_name, tap->idcode);
- for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
- char msg[32];
-
- snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, tap->expected_ids_cnt);
- jtag_examine_chain_display(LOG_LVL_ERROR, msg,
- tap->dotted_name, tap->expected_ids[ii]);
- }
- return false;
-}
-
-/* Try to examine chain layout according to IEEE 1149.1 §12
- * This is called a "blind interrogation" of the scan chain.
- */
-static int jtag_examine_chain(void)
-{
- int retval;
- unsigned max_taps = jtag_tap_count();
-
- /* Autoprobe up to this many. */
- if (max_taps < JTAG_MAX_AUTO_TAPS)
- max_taps = JTAG_MAX_AUTO_TAPS;
-
- /* Add room for end-of-chain marker. */
- max_taps++;
-
- uint8_t *idcode_buffer = malloc(max_taps * 4);
- if (idcode_buffer == NULL)
- return ERROR_JTAG_INIT_FAILED;
-
- /* DR scan to collect BYPASS or IDCODE register contents.
- * Then make sure the scan data has both ones and zeroes.
- */
- LOG_DEBUG("DR scan interrogation for IDCODE/BYPASS");
- retval = jtag_examine_chain_execute(idcode_buffer, max_taps);
- if (retval != ERROR_OK)
- goto out;
- if (!jtag_examine_chain_check(idcode_buffer, max_taps)) {
- retval = ERROR_JTAG_INIT_FAILED;
- goto out;
- }
-
- /* Point at the 1st predefined tap, if any */
- struct jtag_tap *tap = jtag_tap_next_enabled(NULL);
-
- unsigned bit_count = 0;
- unsigned autocount = 0;
- for (unsigned i = 0; i < max_taps; i++) {
- assert(bit_count < max_taps * 32);
- uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32);
-
- /* No predefined TAP? Auto-probe. */
- if (tap == NULL) {
- /* Is there another TAP? */
- if (jtag_idcode_is_final(idcode))
- break;
-
- /* Default everything in this TAP except IR length.
- *
- * REVISIT create a jtag_alloc(chip, tap) routine, and
- * share it with jim_newtap_cmd().
- */
- tap = calloc(1, sizeof *tap);
- if (!tap) {
- retval = ERROR_FAIL;
- goto out;
- }
-
- tap->chip = alloc_printf("auto%u", autocount++);
- tap->tapname = strdup("tap");
- tap->dotted_name = alloc_printf("%s.%s", tap->chip, tap->tapname);
-
- tap->ir_length = 0; /* ... signifying irlen autoprobe */
- tap->ir_capture_mask = 0x03;
- tap->ir_capture_value = 0x01;
-
- tap->enabled = true;
-
- jtag_tap_init(tap);
- }
-
- if ((idcode & 1) == 0) {
- /* Zero for LSB indicates a device in bypass */
- LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%x)",
- tap->dotted_name, idcode);
- tap->hasidcode = false;
- tap->idcode = 0;
-
- bit_count += 1;
- } else {
- /* Friendly devices support IDCODE */
- tap->hasidcode = true;
- tap->idcode = idcode;
- jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", tap->dotted_name, idcode);
-
- bit_count += 32;
- }
-
- /* ensure the TAP ID matches what was expected */
- if (!jtag_examine_chain_match_tap(tap))
- retval = ERROR_JTAG_INIT_SOFT_FAIL;
-
- tap = jtag_tap_next_enabled(tap);
- }
-
- /* After those IDCODE or BYPASS register values should be
- * only the data we fed into the scan chain.
- */
- if (jtag_examine_chain_end(idcode_buffer, bit_count, max_taps * 32)) {
- LOG_ERROR("double-check your JTAG setup (interface, speed, ...)");
- retval = ERROR_JTAG_INIT_FAILED;
- goto out;
- }
-
- /* Return success or, for backwards compatibility if only
- * some IDCODE values mismatched, a soft/continuable fault.
- */
-out:
- free(idcode_buffer);
- return retval;
-}
-
-/*
- * Validate the date loaded by entry to the Capture-IR state, to help
- * find errors related to scan chain configuration (wrong IR lengths)
- * or communication.
- *
- * Entry state can be anything. On non-error exit, all TAPs are in
- * bypass mode. On error exits, the scan chain is reset.
- */
-static int jtag_validate_ircapture(void)
-{
- struct jtag_tap *tap;
- int total_ir_length = 0;
- uint8_t *ir_test = NULL;
- struct scan_field field;
- uint64_t val;
- int chain_pos = 0;
- int retval;
-
- /* when autoprobing, accomodate huge IR lengths */
- for (tap = NULL, total_ir_length = 0;
- (tap = jtag_tap_next_enabled(tap)) != NULL;
- total_ir_length += tap->ir_length) {
- if (tap->ir_length == 0)
- total_ir_length += JTAG_IRLEN_MAX;
- }
-
- /* increase length to add 2 bit sentinel after scan */
- total_ir_length += 2;
-
- ir_test = malloc(DIV_ROUND_UP(total_ir_length, 8));
- if (ir_test == NULL)
- return ERROR_FAIL;
-
- /* after this scan, all TAPs will capture BYPASS instructions */
- buf_set_ones(ir_test, total_ir_length);
-
- field.num_bits = total_ir_length;
- field.out_value = ir_test;
- field.in_value = ir_test;
-
- jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value, TAP_IDLE);
-
- LOG_DEBUG("IR capture validation scan");
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- goto done;
-
- tap = NULL;
- chain_pos = 0;
-
- for (;; ) {
- tap = jtag_tap_next_enabled(tap);
- if (tap == NULL)
- break;
-
- /* If we're autoprobing, guess IR lengths. They must be at
- * least two bits. Guessing will fail if (a) any TAP does
- * not conform to the JTAG spec; or (b) when the upper bits
- * captured from some conforming TAP are nonzero. Or if
- * (c) an IR length is longer than JTAG_IRLEN_MAX bits,
- * an implementation limit, which could someday be raised.
- *
- * REVISIT optimization: if there's a *single* TAP we can
- * lift restrictions (a) and (b) by scanning a recognizable
- * pattern before the all-ones BYPASS. Check for where the
- * pattern starts in the result, instead of an 0...01 value.
- *
- * REVISIT alternative approach: escape to some tcl code
- * which could provide more knowledge, based on IDCODE; and
- * only guess when that has no success.
- */
- if (tap->ir_length == 0) {
- tap->ir_length = 2;
- while ((val = buf_get_u64(ir_test, chain_pos, tap->ir_length + 1)) == 1
- && tap->ir_length < JTAG_IRLEN_MAX) {
- tap->ir_length++;
- }
- LOG_WARNING("AUTO %s - use \"jtag newtap " "%s %s -irlen %d "
- "-expected-id 0x%08" PRIx32 "\"",
- tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode);
- }
-
- /* Validate the two LSBs, which must be 01 per JTAG spec.
- *
- * Or ... more bits could be provided by TAP declaration.
- * Plus, some taps (notably in i.MX series chips) violate
- * this part of the JTAG spec, so their capture mask/value
- * attributes might disable this test.
- */
- val = buf_get_u64(ir_test, chain_pos, tap->ir_length);
- if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
- LOG_ERROR("%s: IR capture error; saw 0x%0*" PRIx64 " not 0x%0*" PRIx32,
- jtag_tap_name(tap),
- (tap->ir_length + 7) / tap->ir_length, val,
- (tap->ir_length + 7) / tap->ir_length, tap->ir_capture_value);
-
- retval = ERROR_JTAG_INIT_FAILED;
- goto done;
- }
- LOG_DEBUG("%s: IR capture 0x%0*" PRIx64, jtag_tap_name(tap),
- (tap->ir_length + 7) / tap->ir_length, val);
- chain_pos += tap->ir_length;
- }
-
- /* verify the '11' sentinel we wrote is returned at the end */
- val = buf_get_u64(ir_test, chain_pos, 2);
- if (val != 0x3) {
- char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
-
- LOG_ERROR("IR capture error at bit %d, saw 0x%s not 0x...3",
- chain_pos, cbuf);
- free(cbuf);
- retval = ERROR_JTAG_INIT_FAILED;
- }
-
-done:
- free(ir_test);
- if (retval != ERROR_OK) {
- jtag_add_tlr();
- jtag_execute_queue();
- }
- return retval;
-}
-
-void jtag_tap_init(struct jtag_tap *tap)
-{
- unsigned ir_len_bits;
- unsigned ir_len_bytes;
-
- /* if we're autoprobing, cope with potentially huge ir_length */
- ir_len_bits = tap->ir_length ? : JTAG_IRLEN_MAX;
- ir_len_bytes = DIV_ROUND_UP(ir_len_bits, 8);
-
- tap->expected = calloc(1, ir_len_bytes);
- tap->expected_mask = calloc(1, ir_len_bytes);
- tap->cur_instr = malloc(ir_len_bytes);
-
- /** @todo cope better with ir_length bigger than 32 bits */
- if (ir_len_bits > 32)
- ir_len_bits = 32;
-
- buf_set_u32(tap->expected, 0, ir_len_bits, tap->ir_capture_value);
- buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask);
-
- /* TAP will be in bypass mode after jtag_validate_ircapture() */
- tap->bypass = 1;
- buf_set_ones(tap->cur_instr, tap->ir_length);
-
- /* register the reset callback for the TAP */
- jtag_register_event_callback(&jtag_reset_callback, tap);
- jtag_tap_add(tap);
-
- LOG_DEBUG("Created Tap: %s @ abs position %d, "
- "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
- tap->abs_chain_position, tap->ir_length,
- (unsigned) tap->ir_capture_value,
- (unsigned) tap->ir_capture_mask);
-}
-
-void jtag_tap_free(struct jtag_tap *tap)
-{
- jtag_unregister_event_callback(&jtag_reset_callback, tap);
-
- free(tap->expected);
- free(tap->expected_mask);
- free(tap->expected_ids);
- free(tap->cur_instr);
- free(tap->chip);
- free(tap->tapname);
- free(tap->dotted_name);
- free(tap);
-}
-
-/**
- * Do low-level setup like initializing registers, output signals,
- * and clocking.
- */
-int adapter_init(struct command_context *cmd_ctx)
-{
- if (jtag)
- return ERROR_OK;
-
- if (!jtag_interface) {
- /* nothing was previously specified by "interface" command */
- LOG_ERROR("Debug Adapter has to be specified, "
- "see \"interface\" command");
- return ERROR_JTAG_INVALID_INTERFACE;
- }
-
- int retval;
- retval = jtag_interface->init();
- if (retval != ERROR_OK)
- return retval;
- jtag = jtag_interface;
-
- /* LEGACY SUPPORT ... adapter drivers must declare what
- * transports they allow. Until they all do so, assume
- * the legacy drivers are JTAG-only
- */
- if (!transports_are_declared()) {
- LOG_ERROR("Adapter driver '%s' did not declare "
- "which transports it allows; assuming "
- "JTAG-only", jtag->name);
- retval = allow_transports(cmd_ctx, jtag_only);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (jtag->speed == NULL) {
- LOG_INFO("This adapter doesn't support configurable speed");
- return ERROR_OK;
- }
-
- 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.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- int requested_khz = jtag_get_speed_khz();
- int actual_khz = requested_khz;
- int jtag_speed_var = 0;
- retval = jtag_get_speed(&jtag_speed_var);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag->speed(jtag_speed_var);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_get_speed_readable(&actual_khz);
- if (ERROR_OK != retval)
- LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var);
- else if (actual_khz) {
- /* Adaptive clocking -- JTAG-specific */
- if ((CLOCK_MODE_RCLK == clock_mode)
- || ((CLOCK_MODE_KHZ == clock_mode) && !requested_khz)) {
- LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz"
- , actual_khz);
- } else
- LOG_INFO("clock speed %d kHz", actual_khz);
- } else
- LOG_INFO("RCLK (adaptive clock speed)");
-
- return ERROR_OK;
-}
-
-int jtag_init_inner(struct command_context *cmd_ctx)
-{
- struct jtag_tap *tap;
- int retval;
- bool issue_setup = true;
-
- LOG_DEBUG("Init JTAG chain");
-
- tap = jtag_tap_next_enabled(NULL);
- if (tap == NULL) {
- /* Once JTAG itself is properly set up, and the scan chain
- * isn't absurdly large, IDCODE autoprobe should work fine.
- *
- * But ... IRLEN autoprobe can fail even on systems which
- * are fully conformant to JTAG. Also, JTAG setup can be
- * quite finicky on some systems.
- *
- * REVISIT: if TAP autoprobe works OK, then in many cases
- * we could escape to tcl code and set up targets based on
- * the TAP's IDCODE values.
- */
- LOG_WARNING("There are no enabled taps. "
- "AUTO PROBING MIGHT NOT WORK!!");
-
- /* REVISIT default clock will often be too fast ... */
- }
-
- jtag_add_tlr();
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* Examine DR values first. This discovers problems which will
- * prevent communication ... hardware issues like TDO stuck, or
- * configuring the wrong number of (enabled) TAPs.
- */
- retval = jtag_examine_chain();
- switch (retval) {
- case ERROR_OK:
- /* complete success */
- break;
- default:
- /* For backward compatibility reasons, try coping with
- * configuration errors involving only ID mismatches.
- * We might be able to talk to the devices.
- *
- * Also the device might be powered down during startup.
- *
- * After OpenOCD starts, we can try to power on the device
- * and run a reset.
- */
- LOG_ERROR("Trying to use configured scan chain anyway...");
- issue_setup = false;
- break;
- }
-
- /* Now look at IR values. Problems here will prevent real
- * communication. They mostly mean that the IR length is
- * wrong ... or that the IR capture value is wrong. (The
- * latter is uncommon, but easily worked around: provide
- * ircapture/irmask values during TAP setup.)
- */
- retval = jtag_validate_ircapture();
- if (retval != ERROR_OK) {
- /* The target might be powered down. The user
- * can power it up and reset it after firing
- * up OpenOCD.
- */
- issue_setup = false;
- }
-
- if (issue_setup)
- jtag_notify_event(JTAG_TAP_EVENT_SETUP);
- else
- LOG_WARNING("Bypassing JTAG setup events due to errors");
-
-
- return ERROR_OK;
-}
-
-int adapter_quit(void)
-{
- if (!jtag || !jtag->quit)
- return ERROR_OK;
-
- /* close the JTAG interface */
- int result = jtag->quit();
- if (ERROR_OK != result)
- LOG_ERROR("failed: %d", result);
-
- return ERROR_OK;
-}
-
-int swd_init_reset(struct command_context *cmd_ctx)
-{
- int retval = adapter_init(cmd_ctx);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("Initializing with hard SRST reset");
-
- if (jtag_reset_config & RESET_HAS_SRST)
- swd_add_reset(1);
- swd_add_reset(0);
- retval = jtag_execute_queue();
- return retval;
-}
-
-int jtag_init_reset(struct command_context *cmd_ctx)
-{
- int retval = adapter_init(cmd_ctx);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("Initializing with hard TRST+SRST reset");
-
- /*
- * This procedure is used by default when OpenOCD triggers a reset.
- * It's now done through an overridable Tcl "init_reset" wrapper.
- *
- * This started out as a more powerful "get JTAG working" reset than
- * jtag_init_inner(), applying TRST because some chips won't activate
- * JTAG without a TRST cycle (presumed to be async, though some of
- * those chips synchronize JTAG activation using TCK).
- *
- * But some chips only activate JTAG as part of an SRST cycle; SRST
- * got mixed in. So it became a hard reset routine, which got used
- * in more places, and which coped with JTAG reset being forced as
- * part of SRST (srst_pulls_trst).
- *
- * And even more corner cases started to surface: TRST and/or SRST
- * assertion timings matter; some chips need other JTAG operations;
- * TRST/SRST sequences can need to be different from these, etc.
- *
- * Systems should override that wrapper to support system-specific
- * requirements that this not-fully-generic code doesn't handle.
- *
- * REVISIT once Tcl code can read the reset_config modes, this won't
- * need to be a C routine at all...
- */
- if (jtag_reset_config & RESET_HAS_SRST) {
- jtag_add_reset(1, 1);
- if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
- jtag_add_reset(0, 1);
- } else {
- jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */
- }
-
- /* some targets enable us to connect with srst asserted */
- if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
- if (jtag_reset_config & RESET_SRST_NO_GATING)
- jtag_add_reset(0, 1);
- else {
- LOG_WARNING("\'srst_nogate\' reset_config option is required");
- jtag_add_reset(0, 0);
- }
- } else
- jtag_add_reset(0, 0);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* Check that we can communication on the JTAG chain + eventually we want to
- * be able to perform enumeration only after OpenOCD has started
- * telnet and GDB server
- *
- * That would allow users to more easily perform any magic they need to before
- * reset happens.
- */
- return jtag_init_inner(cmd_ctx);
-}
-
-int jtag_init(struct command_context *cmd_ctx)
-{
- int retval = adapter_init(cmd_ctx);
- if (retval != ERROR_OK)
- return retval;
-
- /* guard against oddball hardware: force resets to be inactive */
- jtag_add_reset(0, 0);
-
- /* some targets enable us to connect with srst asserted */
- if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
- if (jtag_reset_config & RESET_SRST_NO_GATING)
- jtag_add_reset(0, 1);
- else
- LOG_WARNING("\'srst_nogate\' reset_config option is required");
- }
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (Jim_Eval_Named(cmd_ctx->interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-unsigned jtag_get_speed_khz(void)
-{
- return speed_khz;
-}
-
-static int adapter_khz_to_speed(unsigned khz, int *speed)
-{
- LOG_DEBUG("convert khz to interface specific speed value");
- speed_khz = khz;
- if (jtag != NULL) {
- LOG_DEBUG("have interface set up");
- int speed_div1;
- int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1);
- if (ERROR_OK != retval)
- return retval;
- *speed = speed_div1;
- }
- return ERROR_OK;
-}
-
-static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed)
-{
- int retval = adapter_khz_to_speed(0, speed);
- if ((ERROR_OK != retval) && fallback_speed_khz) {
- LOG_DEBUG("trying fallback speed...");
- retval = adapter_khz_to_speed(fallback_speed_khz, speed);
- }
- return retval;
-}
-
-static int jtag_set_speed(int speed)
-{
- jtag_speed = speed;
- /* this command can be called during CONFIG,
- * in which case jtag isn't initialized */
- return jtag ? jtag->speed(speed) : ERROR_OK;
-}
-
-int jtag_config_khz(unsigned khz)
-{
- LOG_DEBUG("handle jtag khz");
- clock_mode = CLOCK_MODE_KHZ;
- int speed = 0;
- int retval = adapter_khz_to_speed(khz, &speed);
- return (ERROR_OK != retval) ? retval : jtag_set_speed(speed);
-}
-
-int jtag_config_rclk(unsigned fallback_speed_khz)
-{
- LOG_DEBUG("handle jtag rclk");
- clock_mode = CLOCK_MODE_RCLK;
- rclk_fallback_speed_khz = fallback_speed_khz;
- int speed = 0;
- int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed);
- return (ERROR_OK != retval) ? retval : jtag_set_speed(speed);
-}
-
-int jtag_get_speed(int *speed)
-{
- switch (clock_mode) {
- case CLOCK_MODE_KHZ:
- adapter_khz_to_speed(jtag_get_speed_khz(), speed);
- break;
- case CLOCK_MODE_RCLK:
- jtag_rclk_to_speed(rclk_fallback_speed_khz, speed);
- break;
- default:
- LOG_ERROR("BUG: unknown jtag clock mode");
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-int jtag_get_speed_readable(int *khz)
-{
- int jtag_speed_var = 0;
- int retval = jtag_get_speed(&jtag_speed_var);
- if (retval != ERROR_OK)
- return retval;
- return jtag ? jtag->speed_div(jtag_speed_var, khz) : ERROR_OK;
-}
-
-void jtag_set_verify(bool enable)
-{
- jtag_verify = enable;
-}
-
-bool jtag_will_verify()
-{
- return jtag_verify;
-}
-
-void jtag_set_verify_capture_ir(bool enable)
-{
- jtag_verify_capture_ir = enable;
-}
-
-bool jtag_will_verify_capture_ir()
-{
- return jtag_verify_capture_ir;
-}
-
-int jtag_power_dropout(int *dropout)
-{
- if (jtag == NULL) {
- /* TODO: as the jtag interface is not valid all
- * we can do at the moment is exit OpenOCD */
- LOG_ERROR("No Valid JTAG Interface Configured.");
- exit(-1);
- }
- return jtag->power_dropout(dropout);
-}
-
-int jtag_srst_asserted(int *srst_asserted)
-{
- return jtag->srst_asserted(srst_asserted);
-}
-
-enum reset_types jtag_get_reset_config(void)
-{
- return jtag_reset_config;
-}
-void jtag_set_reset_config(enum reset_types type)
-{
- jtag_reset_config = type;
-}
-
-int jtag_get_trst(void)
-{
- return jtag_trst;
-}
-int jtag_get_srst(void)
-{
- return jtag_srst;
-}
-
-void jtag_set_nsrst_delay(unsigned delay)
-{
- adapter_nsrst_delay = delay;
-}
-unsigned jtag_get_nsrst_delay(void)
-{
- return adapter_nsrst_delay;
-}
-void jtag_set_ntrst_delay(unsigned delay)
-{
- jtag_ntrst_delay = delay;
-}
-unsigned jtag_get_ntrst_delay(void)
-{
- return jtag_ntrst_delay;
-}
-
-
-void jtag_set_nsrst_assert_width(unsigned delay)
-{
- adapter_nsrst_assert_width = delay;
-}
-unsigned jtag_get_nsrst_assert_width(void)
-{
- return adapter_nsrst_assert_width;
-}
-void jtag_set_ntrst_assert_width(unsigned delay)
-{
- jtag_ntrst_assert_width = delay;
-}
-unsigned jtag_get_ntrst_assert_width(void)
-{
- return jtag_ntrst_assert_width;
-}
-
-static int jtag_select(struct command_context *ctx)
-{
- int retval;
-
- /* NOTE: interface init must already have been done.
- * That works with only C code ... no Tcl glue required.
- */
-
- retval = jtag_register_commands(ctx);
-
- if (retval != ERROR_OK)
- return retval;
-
- retval = svf_register_commands(ctx);
-
- if (retval != ERROR_OK)
- return retval;
-
- return xsvf_register_commands(ctx);
-}
-
-static struct transport jtag_transport = {
- .name = "jtag",
- .select = jtag_select,
- .init = jtag_init,
-};
-
-static void jtag_constructor(void) __attribute__((constructor));
-static void jtag_constructor(void)
-{
- transport_register(&jtag_transport);
-}
-
-/** Returns true if the current debug session
- * is using JTAG as its transport.
- */
-bool transport_is_jtag(void)
-{
- return get_current_transport() == &jtag_transport;
-}
-
-void adapter_assert_reset(void)
-{
- if (transport_is_jtag()) {
- if (jtag_reset_config & RESET_SRST_PULLS_TRST)
- jtag_add_reset(1, 1);
- else
- jtag_add_reset(0, 1);
- } else if (transport_is_swd())
- swd_add_reset(1);
- else if (get_current_transport() != NULL)
- LOG_ERROR("reset is not supported on %s",
- get_current_transport()->name);
- else
- LOG_ERROR("transport is not selected");
-}
-
-void adapter_deassert_reset(void)
-{
- if (transport_is_jtag())
- jtag_add_reset(0, 0);
- else if (transport_is_swd())
- swd_add_reset(0);
- else if (get_current_transport() != NULL)
- LOG_ERROR("reset is not supported on %s",
- get_current_transport()->name);
- else
- LOG_ERROR("transport is not selected");
-}
-
-int adapter_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
-{
- if (jtag->config_trace)
- return jtag->config_trace(enabled, pin_protocol, port_size,
- trace_freq);
- else if (enabled) {
- LOG_ERROR("The selected interface does not support tracing");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-int adapter_poll_trace(uint8_t *buf, size_t *size)
-{
- if (jtag->poll_trace)
- return jtag->poll_trace(buf, size);
-
- return ERROR_FAIL;
-}
diff --git a/src/jtag/driver.h b/src/jtag/driver.h
deleted file mode 100644
index ae00414..0000000
--- a/src/jtag/driver.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVER_H
-#define OPENOCD_JTAG_DRIVER_H
-
-struct command_context;
-
-int interface_register_commands(struct command_context *ctx);
-
-#endif /* OPENOCD_JTAG_DRIVER_H */
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
deleted file mode 100644
index 2aaf8fd..0000000
--- a/src/jtag/drivers/Makefile.am
+++ /dev/null
@@ -1,173 +0,0 @@
-include $(top_srcdir)/common.mk
-
-noinst_LTLIBRARIES = libocdjtagdrivers.la
-libocdjtagdrivers_la_LIBADD =
-
-libocdjtagdrivers_la_SOURCES = \
- $(DRIVERFILES)
-
-libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \
- $(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS)
-
-ULINK_FIRMWARE = $(srcdir)/OpenULINK
-
-EXTRA_DIST = $(ULINK_FIRMWARE) \
- usb_blaster/README.CheapClone \
- Makefile.rlink \
- rlink_call.m4 \
- rlink_init.m4
-
-DRIVERFILES =
-SUBDIRS=
-
-if JLINK
-if INTERNAL_LIBJAYLINK
-SUBDIRS += libjaylink
-
-libjaylink_internal_la_SOURCES = jlink.c
-libjaylink_internal_la_LIBADD = libjaylink/libjaylink/libjaylink.la
-libjaylink_internal_la_CPPFLAGS = -I$(builddir)/libjaylink/libjaylink \
- -I$(srcdir)/libjaylink $(AM_CPPFLAGS)
-
-noinst_LTLIBRARIES += libjaylink_internal.la
-libocdjtagdrivers_la_LIBADD += libjaylink_internal.la
-else
-DRIVERFILES += jlink.c
-endif
-endif
-
-# Standard Driver: common files
-DRIVERFILES += driver.c
-
-if USE_LIBUSB1
-DRIVERFILES += libusb1_common.c
-endif
-
-if USE_LIBUSB0
-DRIVERFILES += usb_common.c
-if !USE_LIBUSB1
-DRIVERFILES += libusb0_common.c
-endif
-endif
-
-if BITBANG
-DRIVERFILES += bitbang.c
-endif
-if PARPORT
-DRIVERFILES += parport.c
-endif
-if DUMMY
-DRIVERFILES += dummy.c
-endif
-if FT2232_DRIVER
-DRIVERFILES += ft2232.c
-endif
-if FTDI
-DRIVERFILES += ftdi.c mpsse.c
-endif
-if JTAG_VPI
-DRIVERFILES += jtag_vpi.c
-endif
-if USB_BLASTER_DRIVER
-SUBDIRS += usb_blaster
-libocdjtagdrivers_la_LIBADD += $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la
-endif
-if AMTJTAGACCEL
-DRIVERFILES += amt_jtagaccel.c
-endif
-if EP93XX
-DRIVERFILES += ep93xx.c
-endif
-if AT91RM9200
-DRIVERFILES += at91rm9200.c
-endif
-if GW16012
-DRIVERFILES += gw16012.c
-endif
-if BITQ
-DRIVERFILES += bitq.c
-endif
-if PRESTO_DRIVER
-DRIVERFILES += presto.c
-endif
-if USBPROG
-DRIVERFILES += usbprog.c
-endif
-if RLINK
-DRIVERFILES += rlink.c rlink_speed_table.c
-endif
-if ULINK
-DRIVERFILES += ulink.c
-ulinkdir = $(pkgdatadir)/OpenULINK
-dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex
-endif
-if VSLLINK
-DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c
-DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c
-DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c
-DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c
-DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c
-DRIVERFILES += versaloon/versaloon.c
-DRIVERFILES += vsllink.c
-endif
-if ARMJTAGEW
-DRIVERFILES += arm-jtag-ew.c
-endif
-if BUSPIRATE
-DRIVERFILES += buspirate.c
-endif
-if REMOTE_BITBANG
-DRIVERFILES += remote_bitbang.c
-endif
-if HLADAPTER
-DRIVERFILES += stlink_usb.c
-DRIVERFILES += ti_icdi_usb.c
-endif
-if OSBDM
-DRIVERFILES += osbdm.c
-endif
-if OPENDOUS
-DRIVERFILES += opendous.c
-endif
-if SYSFSGPIO
-DRIVERFILES += sysfsgpio.c
-endif
-if BCM2835GPIO
-DRIVERFILES += bcm2835gpio.c
-endif
-
-if OPENJTAG
-DRIVERFILES += openjtag.c
-endif
-
-if CMSIS_DAP
-DRIVERFILES += cmsis_dap_usb.c
-endif
-
-noinst_HEADERS = \
- bitbang.h \
- bitq.h \
- ftd2xx_common.h \
- libusb0_common.h \
- libusb1_common.h \
- libusb_common.h \
- minidriver_imp.h \
- mpsse.h \
- rlink.h \
- rlink_dtc_cmd.h \
- rlink_ep1_cmd.h \
- rlink_st7.h \
- usb_common.h \
- versaloon/usbtoxxx/usbtoxxx.h \
- versaloon/usbtoxxx/usbtoxxx_internal.h \
- versaloon/versaloon.h \
- versaloon/versaloon_include.h \
- versaloon/versaloon_internal.h
-
-DIST_SUBDIRS = usb_blaster
-
-if INTERNAL_LIBJAYLINK
-DIST_SUBDIRS += libjaylink
-endif
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/jtag/drivers/Makefile.rlink b/src/jtag/drivers/Makefile.rlink
deleted file mode 100644
index 6168332..0000000
--- a/src/jtag/drivers/Makefile.rlink
+++ /dev/null
@@ -1,71 +0,0 @@
-#***************************************************************************
-#* Copyright (C) 2008 Lou Deluxe *
-#* lou.openocd012@fixit.nospammail.net *
-#* *
-#* This program is free software; you can redistribute it and/or modify *
-#* it under the terms of the GNU General Public License as published by *
-#* the Free Software Foundation; either version 2 of the License, or *
-#* (at your option) any later version. *
-#* *
-#* This program is distributed in the hope that it will be useful, *
-#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-#* GNU General Public License for more details. *
-#* *
-#* You should have received a copy of the GNU General Public License *
-#* along with this program. If not, see <http://www.gnu.org/licenses/>. *
-#***************************************************************************
-
-TOP = ../../..
-INTERFACE_NAME = rlink
-
-PERL = perl
-M4 = m4
-
-TARGETDIR = ${TOP}/src/target
-TOOLSDIR = ${TOP}/tools
-
-MAKE_SPEED_TABLE = ${TOOLSDIR}/rlink_make_speed_table/rlink_make_speed_table
-ST7_DTC_AS = ${TOOLSDIR}/st7_dtc_as/st7_dtc_as
-
-OPENOCD = ${TOP}/src/openocd
-OPENOCD_CONFIG = -s ${TARGETDIR}
-OPENOCD_CONFIG += -f interface/rlink.cfg
-OPENOCD_CONFIG += -f board/stm32f10x_128k_eval.cfg
-
-PATCHFILE = /tmp/openocd_${INTERFACE_NAME}.diff.gz
-
-# relative to ${TOP}
-SVNADDFILES =
-SVNADDFILES += src/target/interface/rlink.cfg
-SVNADDFILES += src/jtag/${INTERFACE_NAME}.c
-SVNADDFILES += src/jtag/${INTERFACE_NAME}
-
-PRESCALERS = 64 11 8 2
-
-DTCFILES =
-DTCFILES += $(addsuffix _init.dtc, ${PRESCALERS})
-DTCFILES += $(addsuffix _call.dtc, ${PRESCALERS})
-
-default: rlink_speed_table.c clean
-
-%_init.fsm: rlink_init.m4
- ${M4} -P -DSHIFTER_PRESCALER=`echo "$@" | sed -e's/_.*//'` $< > $@
-
-%_call.fsm: rlink_call.m4
- ${M4} -P -DSHIFTER_PRESCALER=`echo "$@" | sed -e's/_.*//'` $< > $@
-
-%.dtc: %.fsm
- ${ST7_DTC_AS} -b -o $@ -i $< > /dev/null
-
-rlink_speed_table.c: ${DTCFILES}
- ${MAKE_SPEED_TABLE} ${PRESCALERS} > $@ || rm $@
-
-clean:
- -rm *.dtc *.fsm
-
-distclean: clean
-
-test: default
- (cd ${TOP} && (rm src/jtag/${INTERFACE_NAME}.o; ${MAKE}))
- ${OPENOCD} -d0 ${OPENOCD_CONFIG} -c init -c 'poll off'
diff --git a/src/jtag/drivers/OpenULINK/Makefile b/src/jtag/drivers/OpenULINK/Makefile
deleted file mode 100644
index 9f6acc6..0000000
--- a/src/jtag/drivers/OpenULINK/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-############################################################################
-# Copyright (C) 2011 by Martin Schmoelzer #
-# <martin.schmoelzer@student.tuwien.ac.at> #
-# #
-# This program is free software; you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation; either version 2 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-############################################################################
-
-# Define the name of our tools. Some distributions (e. g. Fedora) prefix
-# the SDCC executables, change this accordingly!
-PREFIX =
-
-# Small Device C Compiler: http://sdcc.sourceforge.net/
-CC = $(PREFIX)-sdcc
-
-# 8051 assembler, part of the SDCC software package.
-AS = $(PREFIX)-sdas8051
-
-# SDCC produces quite messy Intel HEX files. This tool is be used to re-format
-# those files. It is not required for the firmware download functionality in
-# the OpenOCD driver, but the resulting file is smaller.
-PACKIHX = $(PREFIX)-packihx
-
-# GNU binutils size. Used to print the size of the IHX file generated by SDCC.
-SIZE = size
-
-# Source and header directories.
-SRC_DIR = src
-INCLUDE_DIR = include
-
-CODE_SIZE = 0x1B00
-
-# Starting address of __xdata variables. Since the OpenULINK firmware does not
-# use any of the isochronous interrupts, we can use the isochronous buffer space
-# as XDATA memory.
-XRAM_LOC = 0x2000
-XRAM_SIZE = 0x0800
-
-CFLAGS = --std-sdcc99 --opt-code-size --model-small
-LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \
- --xram-size $(XRAM_SIZE) --iram-size 256 --model-small
-
-# list of base object files
-OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel
-HEADERS = $(INCLUDE_DIR)/main.h \
- $(INCLUDE_DIR)/usb.h \
- $(INCLUDE_DIR)/protocol.h \
- $(INCLUDE_DIR)/jtag.h \
- $(INCLUDE_DIR)/delay.h \
- $(INCLUDE_DIR)/reg_ezusb.h \
- $(INCLUDE_DIR)/io.h \
- $(INCLUDE_DIR)/msgtypes.h
-
-# Disable all built-in rules.
-.SUFFIXES:
-
-# Targets which are executed even when identically named file is present.
-.PHONY: all, clean
-
-all: ulink_firmware.ihx
- $(SIZE) ulink_firmware.ihx
-
-ulink_firmware.ihx: $(OBJECTS)
- $(CC) -mmcs51 $(LDFLAGS) -o $@ $^
-
-# Rebuild every C module (there are only 5 of them) if any header changes.
-%.rel: $(SRC_DIR)/%.c $(HEADERS)
- $(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
-
-%.rel: $(SRC_DIR)/%.a51
- $(AS) -lsgo $@ $<
-
-clean:
- rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lk *.map *.mem
-
-hex: ulink_firmware.ihx
- $(PACKIHX) ulink_firmware.ihx > ulink_firmware.hex
diff --git a/src/jtag/drivers/OpenULINK/README b/src/jtag/drivers/OpenULINK/README
deleted file mode 100644
index 445d770..0000000
--- a/src/jtag/drivers/OpenULINK/README
+++ /dev/null
@@ -1,34 +0,0 @@
-This is the OpenULINK firmware for the Keil ULINK JTAG adapter.
-
-The main components of the Keil ULINK adapter are:
-- Cypress EZ-USB microcontroller: enhanced 8051 CPU + USB core (1.1 Full-Speed)
-- SRAM memory chip
-- Level shifters to support different JTAG signal voltage levels
-- Pin headers for various JTAG pin assignments
-
-This firmware can only be run on the ORIGINAL Keil ULINK adapter, not on the
-newer ULINK2, ULINK-ME or ULINK-PRO, as these adapters are based on different
-hardware.
-
-To compile the firmware, the SDCC compiler package is required. Most Linux
-distributions include SDCC in their official package repositories. The SDCC
-source code can be found at http://sdcc.sourceforge.net/
-Simply type "make hex" in the OpenULINK directory to compile the firmware.
-"make clean" will remove all generated files except the Intel HEX file required
-for downloading the firmware to the ULINK adapter.
-
-Note that the EZ-USB microcontroller does not have on-chip flash, nor does the
-Keil ULINK include on-board memory to store the firmware program of the EZ-USB.
-Instead, upon initial connection of the ULINK adapter to the host PC via USB,
-the EZ-USB core has enough intelligence to act as a stand-alone USB device,
-responding to USB control requests and allowing firmware download via a special
-VENDOR-type control request. Then, the EZ-USB microcontroller simulates a
-disconnect and re-connect to the USB bus. It may take up to two seconds for the
-host to recognize the newly connected device before OpenOCD can proceed to
-execute JTAG commands. This delay is only visible when OpenOCD first uses a
-blank (unconfigured) ULINK device.
-
-Once the user disconnects the ULINK adapter, all its memory contents are lost
-and the firmware download process has to be executed again. This also maintains
-compatibility with the original Keil uVision IDE, which will happily download
-its own firmware image to a blank ULINK adapter.
diff --git a/src/jtag/drivers/OpenULINK/include/common.h b/src/jtag/drivers/OpenULINK/include/common.h
deleted file mode 100644
index 56222fe..0000000
--- a/src/jtag/drivers/OpenULINK/include/common.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef __COMMON_H
-#define __COMMON_H
-
-#define DIV_ROUND_UP(m, n) (((m) + (n) - 1) / (n))
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/delay.h b/src/jtag/drivers/OpenULINK/include/delay.h
deleted file mode 100644
index ed454be..0000000
--- a/src/jtag/drivers/OpenULINK/include/delay.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef __DELAY_H
-#define __DELAY_H
-
-#include <stdint.h>
-
-#define NOP { __asm nop __endasm; }
-
-void delay_5us(void);
-void delay_1ms(void);
-
-void delay_us(uint16_t delay);
-void delay_ms(uint16_t delay);
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/io.h b/src/jtag/drivers/OpenULINK/include/io.h
deleted file mode 100644
index a4a8b8a..0000000
--- a/src/jtag/drivers/OpenULINK/include/io.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef __IO_H
-#define __IO_H
-
-#include "reg_ezusb.h"
-
-/***************************************************************************
- * JTAG Signals: *
- ***************************************************************************
- * TMS ....... Test Mode Select *
- * TCK ....... Test Clock *
- * TDI ....... Test Data Input (from device point of view, not JTAG *
- * adapter point of view!) *
- * TDO ....... Test Data Output (from device point of view, not JTAG *
- * adapter point of view!) *
- * TRST ...... Test Reset: Used to reset the TAP Finite State Machine *
- * into the Test Logic Reset state *
- * RTCK ...... Return Test Clock *
- * OCDSE ..... Enable/Disable OCDS interface (Infineon specific) - shared *
- * with /JEN *
- * TRAP ...... Trap Condition (Infineon specific) - shared with TSTAT *
- * BRKIN ..... Hardware Break-In (Infineon specific) *
- * BRKOUT .... Hardware Break-Out (Infineon specific) *
- * /JEN ...... JTAG-Enable (STMicroelectronics specific) - shared *
- * with OCDSE *
- * TSTAT ..... JTAG ISP Status (STMicroelectronics specific) - shared *
- * with TRAP *
- * RESET ..... Chip Reset (STMicroelectronics specific) *
- * /TERR ..... JTAG ISP Error (STMicroelectronics specific) - shared *
- * with BRKOUT *
- ***************************************************************************/
-
-/* PORT A */
-#define PIN_U_OE OUTA0
-/* PA1 Not Connected */
-#define PIN_OE OUTA2
-/* PA3 Not Connected */
-#define PIN_RUN_LED OUTA4
-#define PIN_TDO PINA5
-#define PIN_BRKOUT PINA6
-#define PIN_COM_LED OUTA7
-
-/* PORT B */
-#define PIN_TDI OUTB0
-#define PIN_TMS OUTB1
-#define PIN_TCK OUTB2
-#define PIN_TRST OUTB3
-#define PIN_BRKIN OUTB4
-#define PIN_RESET OUTB5
-#define PIN_OCDSE OUTB6
-#define PIN_TRAP PINB7
-
-/* JTAG Signals with direction 'OUT' on port B */
-#define MASK_PORTB_DIRECTION_OUT (PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET | PIN_OCDSE)
-
-/* PORT C */
-#define PIN_RXD0 PINC0
-#define PIN_TXD0 OUTC1
-#define PIN_RESET_2 PINC2
-/* PC3 Not Connecte */
-/* PC4 Not Connected */
-#define PIN_RTCK PINC5
-#define PIN_WR OUTC6
-/* PC7 Not Connected */
-
-/* LED Macros */
-#define SET_RUN_LED() (OUTA &= ~PIN_RUN_LED)
-#define CLEAR_RUN_LED() (OUTA |= PIN_RUN_LED)
-
-#define SET_COM_LED() (OUTA &= ~PIN_COM_LED)
-#define CLEAR_COM_LED() (OUTA |= PIN_COM_LED)
-
-/* JTAG Pin Macros */
-#define GET_TMS() (PINSB & PIN_TMS)
-#define GET_TCK() (PINSB & PIN_TCK)
-
-#define GET_TDO() (PINSA & PIN_TDO)
-#define GET_BRKOUT() (PINSA & PIN_BRKOUT)
-#define GET_TRAP() (PINSB & PIN_TRAP)
-#define GET_RTCK() (PINSC & PIN_RTCK)
-
-#define SET_TMS_HIGH() (OUTB |= PIN_TMS)
-#define SET_TMS_LOW() (OUTB &= ~PIN_TMS)
-
-#define SET_TCK_HIGH() (OUTB |= PIN_TCK)
-#define SET_TCK_LOW() (OUTB &= ~PIN_TCK)
-
-#define SET_TDI_HIGH() (OUTB |= PIN_TDI)
-#define SET_TDI_LOW() (OUTB &= ~PIN_TDI)
-
-/* TRST and RESET are low-active and inverted by hardware. SET_HIGH de-asserts
- * the signal (enabling reset), SET_LOW asserts the signal (disabling reset) */
-#define SET_TRST_HIGH() (OUTB |= PIN_TRST)
-#define SET_TRST_LOW() (OUTB &= ~PIN_TRST)
-
-#define SET_RESET_HIGH() (OUTB |= PIN_RESET)
-#define SET_RESET_LOW() (OUTB &= ~PIN_RESET)
-
-#define SET_OCDSE_HIGH() (OUTB |= PIN_OCDSE)
-#define SET_OCDSE_LOW() (OUTB &= ~PIN_OCDSE)
-
-#define SET_BRKIN_HIGH() (OUTB |= PIN_BRKIN)
-#define SET_BRKIN_LOW() (OUTB &= ~PIN_BRKIN)
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/jtag.h b/src/jtag/drivers/OpenULINK/include/jtag.h
deleted file mode 100644
index fa492b9..0000000
--- a/src/jtag/drivers/OpenULINK/include/jtag.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef __JTAG_H
-#define __JTAG_H
-
-#include <stdint.h>
-
-#define NOP { __asm nop __endasm; }
-
-void jtag_scan_in(uint8_t out_offset, uint8_t in_offset);
-void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset);
-
-void jtag_scan_out(uint8_t out_offset);
-void jtag_slow_scan_out(uint8_t out_offset);
-
-void jtag_scan_io(uint8_t out_offset, uint8_t in_offset);
-void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset);
-
-void jtag_clock_tck(uint16_t count);
-void jtag_slow_clock_tck(uint16_t count);
-void jtag_clock_tms(uint8_t count, uint8_t sequence);
-void jtag_slow_clock_tms(uint8_t count, uint8_t sequence);
-
-uint16_t jtag_get_signals(void);
-void jtag_set_signals(uint8_t low, uint8_t high);
-
-void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
- uint8_t scan_io, uint8_t tck, uint8_t tms);
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/main.h b/src/jtag/drivers/OpenULINK/include/main.h
deleted file mode 100644
index 9e7dd5a86..0000000
--- a/src/jtag/drivers/OpenULINK/include/main.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef __MAIN_H
-#define __MAIN_H
-
-void io_init(void);
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/msgtypes.h b/src/jtag/drivers/OpenULINK/include/msgtypes.h
deleted file mode 100644
index f761a84..0000000
--- a/src/jtag/drivers/OpenULINK/include/msgtypes.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/**
- * @file
- * Definition of the commands supported by the OpenULINK firmware.
- *
- * Basically, two types of commands can be distinguished:
- * - Commands with fixed payload size
- * - Commands with variable payload size
- *
- * SCAN commands (in all variations) carry payloads of variable size, all
- * other commands carry payloads of fixed size.
- *
- * In the case of SCAN commands, the payload size (n) is calculated by
- * dividing the scan_size_bits variable by 8, rounding up the result.
- *
- * Offset zero always contains the command ID.
- *
- ****************************************************************************
- * CMD_SCAN_IN, CMD_SLOW_SCAN_IN: *
- * *
- * OUT: *
- * offset 1: scan_size_bytes *
- * offset 2: bits_last_byte *
- * offset 3: tms_count_start + tms_count_end *
- * offset 4: tms_sequence_start *
- * offset 5: tms_sequence_end *
- * *
- * IN: *
- * offset 0..n: TDO data *
- ****************************************************************************
- * CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT: *
- * *
- * OUT: *
- * offset 1: scan_size_bytes *
- * offset 2: bits_last_byte *
- * offset 3: tms_count_start + tms_count_end *
- * offset 4: tms_sequence_start *
- * offset 5: tms_sequence_end *
- * offset 6..x: TDI data *
- ****************************************************************************
- * CMD_SCAN_IO, CMD_SLOW_SCAN_IO: *
- * *
- * OUT: *
- * offset 1: scan_size_bytes *
- * offset 2: bits_last_byte *
- * offset 3: tms_count_start + tms_count_end *
- * offset 4: tms_sequence_start *
- * offset 5: tms_sequence_end *
- * offset 6..x: TDI data *
- * *
- * IN: *
- * offset 0..n: TDO data *
- ****************************************************************************
- * CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS: *
- * *
- * OUT: *
- * offset 1: tms_count *
- * offset 2: tms_sequence *
- ****************************************************************************
- * CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK: *
- * *
- * OUT: *
- * offset 1: low byte of tck_count *
- * offset 2: high byte of tck_count *
- ****************************************************************************
- * CMD_CLOCK_SLEEP_US: *
- * *
- * OUT: *
- * offset 1: low byte of sleep_us *
- * offset 2: high byte of sleep_us *
- ****************************************************************************
- * CMD_CLOCK_SLEEP_MS: *
- * *
- * OUT: *
- * offset 1: low byte of sleep_ms *
- * offset 2: high byte of sleep_ms *
- ****************************************************************************
- * CMD_GET_SIGNALS: *
- * *
- * IN: *
- * offset 0: current state of input signals *
- * offset 1: current state of output signals *
- ****************************************************************************
- * CMD_SET_SIGNALS: *
- * *
- * OUT: *
- * offset 1: signals that should be de-asserted *
- * offset 2: signals that should be asserted *
- ****************************************************************************
- * CMD_CONFIGURE_TCK_FREQ: *
- * *
- * OUT: *
- * offset 1: delay value for scan_in function *
- * offset 2: delay value for scan_out function *
- * offset 3: delay value for scan_io function *
- * offset 4: delay value for clock_tck function *
- * offset 5: delay value for clock_tms function *
- ****************************************************************************
- * CMD_SET_LEDS: *
- * *
- * OUT: *
- * offset 1: LED states: *
- * Bit 0: turn COM LED on *
- * Bit 1: turn RUN LED on *
- * Bit 2: turn COM LED off *
- * Bit 3: turn RUN LED off *
- * Bits 7..4: Reserved *
- ****************************************************************************
- * CMD_TEST: *
- * *
- * OUT: *
- * offset 1: unused dummy value *
- ****************************************************************************
- */
-
-#ifndef __MSGTYPES_H
-#define __MSGTYPES_H
-
-/*
- * Command IDs:
- *
- * Bits 7..6: Reserved, should always be zero
- * Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
- * the IDs 0x00..0x1F are commands with variable payload size,
- * the IDs 0x20..0x3F are commands with fixed payload size.
- */
-
-#define CMD_ID_MASK 0x3F
-
-/* Commands with variable payload size */
-#define CMD_SCAN_IN 0x00
-#define CMD_SLOW_SCAN_IN 0x01
-#define CMD_SCAN_OUT 0x02
-#define CMD_SLOW_SCAN_OUT 0x03
-#define CMD_SCAN_IO 0x04
-#define CMD_SLOW_SCAN_IO 0x05
-
-/* Commands with fixed payload size */
-#define CMD_CLOCK_TMS 0x20
-#define CMD_SLOW_CLOCK_TMS 0x21
-#define CMD_CLOCK_TCK 0x22
-#define CMD_SLOW_CLOCK_TCK 0x23
-#define CMD_SLEEP_US 0x24
-#define CMD_SLEEP_MS 0x25
-#define CMD_GET_SIGNALS 0x26
-#define CMD_SET_SIGNALS 0x27
-#define CMD_CONFIGURE_TCK_FREQ 0x28
-#define CMD_SET_LEDS 0x29
-#define CMD_TEST 0x2A
-
-/* JTAG signal definition for jtag_get_signals() -- Input signals! */
-#define SIGNAL_TDO (1<<0)
-#define SIGNAL_BRKOUT (1<<1)
-#define SIGNAL_TRAP (1<<2)
-#define SIGNAL_RTCK (1<<3)
-
-/* JTAG signal definition for jtag_get_signals() -- Output signals! */
-#define SIGNAL_TDI (1<<0)
-#define SIGNAL_TMS (1<<1)
-#define SIGNAL_TCK (1<<2)
-#define SIGNAL_TRST (1<<3)
-#define SIGNAL_BRKIN (1<<4)
-#define SIGNAL_RESET (1<<5)
-#define SIGNAL_OCDSE (1<<6)
-
-/* LED definitions for CMD_SET_LEDS and CMD_CLEAR_LEDS commands */
-#define COM_LED_ON (1<<0)
-#define RUN_LED_ON (1<<1)
-#define COM_LED_OFF (1<<2)
-#define RUN_LED_OFF (1<<3)
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/protocol.h b/src/jtag/drivers/OpenULINK/include/protocol.h
deleted file mode 100644
index 0b6a7d6..0000000
--- a/src/jtag/drivers/OpenULINK/include/protocol.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef __PROTOCOL_H
-#define __PROTOCOL_H
-
-#include "common.h"
-#include <stdbool.h>
-
-void execute_set_led_command(void);
-
-bool execute_command(void);
-void command_loop(void);
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/reg_ezusb.h b/src/jtag/drivers/OpenULINK/include/reg_ezusb.h
deleted file mode 100644
index 4988367..0000000
--- a/src/jtag/drivers/OpenULINK/include/reg_ezusb.h
+++ /dev/null
@@ -1,741 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef REG_EZUSB_H
-#define REG_EZUSB_H
-
-/**
- * @file
- * All information in this file was taken from the EZ-USB Technical
- * Reference Manual, Cypress Semiconductor, 3901 North First Street
- * San Jose, CA 95134 (www.cypress.com).
- *
- * The EZ-USB Technical Reference Manual is called "EZ-USB TRM" hereafter.
- *
- * The following bit name definitions differ from those in the EZ-USB TRM:
- * - All lowercase characters in the EZ-USB TRM bit names have been converted
- * to capitals (e. g. "WakeSRC" converted to "WAKESRC").
- * - CPUCS: 8051RES is named "RES8051".
- * - ISOCTL: Two MBZ ("Must Be Zero") bits are named "MBZ0" and "MBZ1".
- * - I2CS: STOP and START bits are preceded by "I2C_"
- * - INxCS, OUTxCS: the busy and stall bits are named "EPBSY" and "EPSTALL".
- * - TOGCTL: EZ-USB TRM bit names are preceded by "TOG_".
- */
-
-/* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */
-#include <mcs51/compiler.h>
-
-/* Bit vectors */
-#define bmBit0 0x01
-#define bmBit1 0x02
-#define bmBit2 0x04
-#define bmBit3 0x08
-#define bmBit4 0x10
-#define bmBit5 0x20
-#define bmBit6 0x40
-#define bmBit7 0x80
-
-/**************************************************************************
- ************************ Special Function Registers **********************
- ***************************************************************************/
-
-/* See EZ-USB TRM, pp. A-9 - A-10 */
-
-SFR(SP, 0x81);
-SFR(DPL0, 0x82);
-SFR(DPH0, 0x83);
-SFR(DPL1, 0x84);
-SFR(DPL2, 0x85);
-
-SFR(DPS, 0x86);
-#define SEL bmBit0
-/* Bit 1 read-only, always reads '0' */
-/* Bit 2 read-only, always reads '0' */
-/* Bit 3 read-only, always reads '0' */
-/* Bit 4 read-only, always reads '0' */
-/* Bit 5 read-only, always reads '0' */
-/* Bit 6 read-only, always reads '0' */
-/* Bit 7 read-only, always reads '0' */
-
-SFR(PCON, 0x87);
-#define IDLE bmBit0
-#define STOP bmBit1
-#define GF0 bmBit2
-#define GF1 bmBit3
-/* Bit 4 read-only, always reads '1' */
-/* Bit 5 read-only, always reads '1' */
-/* Bit 6 unused */
-#define SMOD0 bmBit7
-
-SFR(TCON, 0x88);
-SBIT(IT0, 0x88, 0);
-SBIT(IE0, 0x88, 1);
-SBIT(IT1, 0x88, 2);
-SBIT(IE1, 0x88, 3);
-SBIT(TR0, 0x88, 4);
-SBIT(TF0, 0x88, 5);
-SBIT(TR1, 0x88, 6);
-SBIT(TF1, 0x88, 7);
-
-SFR(TMOD, 0x89);
-/* Some bits in this register share the same name in the EZ-USB TRM. Therefore,
- * we add a '0'/'1' to distinguish them */
-#define M00 bmBit0
-#define M01 bmBit1
-#define CT0 bmBit2
-#define GATE0 bmBit3
-#define M10 bmBit4
-#define M11 bmBit5
-#define CT1 bmBit6
-#define GATE1 bmBit7
-
-SFR(TL0, 0x8A);
-SFR(TL1, 0x8B);
-SFR(TH0, 0x8C);
-SFR(TH1, 0x8D);
-
-SFR(CKCON, 0x8E);
-#define MD0 bmBit0
-#define MD1 bmBit1
-#define MD2 bmBit2
-#define T0M bmBit3
-#define T1M bmBit4
-#define T2M bmBit5
-/* Bit 6 unused */
-/* Bit 7 unused */
-
-SFR(SPC_FNC, 0x8D);
-#define bmWRS bmBit0
-/* Bit 1 read-only, always reads '0' */
-/* Bit 2 read-only, always reads '0' */
-/* Bit 3 read-only, always reads '0' */
-/* Bit 4 read-only, always reads '0' */
-/* Bit 5 read-only, always reads '0' */
-/* Bit 6 read-only, always reads '0' */
-/* Bit 7 read-only, always reads '0' */
-
-SFR(EXIF, 0x91);
-/* Bit 0 read-only, always reads '0' */
-/* Bit 1 read-only, always reads '0' */
-/* Bit 2 read-only, always reads '0' */
-/* Bit 3 read-only, always reads '1' */
-#define USBINT bmBit4
-#define I2CINT bmBit5
-#define IE4 bmBit6
-#define IE5 bmBit7
-
-/* Definition of the _XPAGE register, according to SDCC Compiler User Guide,
- * Version 3.0.1, Chapter 4, p. 61. Also see EZ-USB TRM, p. 2-4. */
-SFR(MPAGE, 0x92);
-SFR(_XPAGE, 0x92);
-
-SFR(SCON0, 0x98);
-SBIT(RI_0, 0x98, 0);
-SBIT(TI_0, 0x98, 1);
-SBIT(RB8_0, 0x98, 2);
-SBIT(TB8_0, 0x98, 3);
-SBIT(REN_0, 0x98, 4);
-SBIT(SM2_0, 0x98, 5);
-SBIT(SM1_0, 0x98, 6);
-SBIT(SM0_0, 0x98, 7);
-
-SFR(SBUF0, 0x99);
-
-SFR(IE, 0xA8);
-SBIT(EX0, 0xA8, 0);
-SBIT(ET0, 0xA8, 1);
-SBIT(EX1, 0xA8, 2);
-SBIT(ET1, 0xA8, 3);
-SBIT(ES0, 0xA8, 4);
-SBIT(ET2, 0xA8, 5);
-SBIT(ES1, 0xA8, 6);
-SBIT(EA, 0xA8, 7);
-
-SFR(IP, 0xB8);
-SBIT(PX0, 0xB8, 0);
-SBIT(PT0, 0xB8, 1);
-SBIT(PX1, 0xB8, 2);
-SBIT(PT1, 0xB8, 3);
-SBIT(PS0, 0xB8, 4);
-SBIT(PT2, 0xB8, 5);
-SBIT(PS1, 0xB8, 6);
-/* Bit 7 read-only, always reads '1' */
-
-SFR(SCON1, 0xC0);
-SBIT(RI_1, 0xC0, 0);
-SBIT(TI_1, 0xC0, 1);
-SBIT(RB8_1, 0xC0, 2);
-SBIT(TB8_1, 0xC0, 3);
-SBIT(REN_1, 0xC0, 4);
-SBIT(SM2_1, 0xC0, 5);
-SBIT(SM1_1, 0xC0, 6);
-SBIT(SM0_1, 0xC0, 7);
-
-SFR(SBUF1, 0xC1);
-
-SFR(T2CON, 0xC8);
-SBIT(CPRL2, 0xC8, 0);
-SBIT(CT2, 0xC8, 1);
-SBIT(TR2, 0xC8, 2);
-SBIT(EXEN2, 0xC8, 3);
-SBIT(TCLK, 0xC8, 4);
-SBIT(RCLK, 0xC8, 5);
-SBIT(EXF2, 0xC8, 6);
-SBIT(TF2, 0xC8, 7);
-
-SFR(RCAP2L, 0xCA);
-SFR(RCAP2H, 0xCB);
-SFR(TL2, 0xCC);
-SFR(TH2, 0xCD);
-
-SFR(PSW, 0xD0);
-SBIT(P, 0xD0, 0);
-SBIT(F1, 0xD0, 1);
-SBIT(OV, 0xD0, 2);
-SBIT(RS0, 0xD0, 3);
-SBIT(RS1, 0xD0, 4);
-SBIT(F0, 0xD0, 5);
-SBIT(AC, 0xD0, 6);
-SBIT(CY, 0xD0, 7);
-
-SFR(EICON, 0xD8);
-/* Bit 0 read-only, always reads '0' */
-/* Bit 1 read-only, always reads '0' */
-/* Bit 2 read-only, always reads '0' */
-SBIT(INT6, 0xD8, 3);
-SBIT(RESI, 0xD8, 4);
-SBIT(ERESI, 0xD8, 5);
-/* Bit 6 read-only, always reads '1' */
-SBIT(SMOD1, 0xD8, 7);
-
-SFR(ACC, 0xE0);
-
-SFR(EIE, 0xE8);
-SBIT(EUSB, 0xE8, 0);
-SBIT(EI2C, 0xE8, 1);
-SBIT(EX4, 0xE8, 2);
-SBIT(EX5, 0xE8, 3);
-SBIT(EWDI, 0xE8, 4);
-/* Bit 5 read-only, always reads '1' */
-/* Bit 6 read-only, always reads '1' */
-/* Bit 7 read-only, always reads '1' */
-
-SFR(B, 0xF0);
-
-SFR(EIP, 0xF8);
-SBIT(PUSB, 0xF8, 0);
-SBIT(PI2C, 0xF8, 1);
-SBIT(PX4, 0xF8, 2);
-SBIT(PX5, 0xF8, 3);
-SBIT(PX6, 0xF8, 4);
-/* Bit 5 read-only, always reads '1' */
-/* Bit 6 read-only, always reads '1' */
-/* Bit 7 read-only, always reads '1' */
-
-/**************************************************************************
- ***************************** XDATA Registers ****************************
- ***************************************************************************/
-
-/************************ Endpoint 0-7 Data Buffers ************************/
-SFRX(OUT7BUF[64], 0x7B40);
-SFRX(IN7BUF[64], 0x7B80);
-SFRX(OUT6BUF[64], 0x7BC0);
-SFRX(IN6BUF[64], 0x7C00);
-SFRX(OUT5BUF[64], 0x7C40);
-SFRX(IN5BUF[64], 0x7C80);
-SFRX(OUT4BUF[64], 0x7CC0);
-SFRX(IN4BUF[64], 0x7D00);
-SFRX(OUT3BUF[64], 0x7D40);
-SFRX(IN3BUF[64], 0x7D80);
-SFRX(OUT2BUF[64], 0x7DC0);
-SFRX(IN2BUF[64], 0x7E00);
-SFRX(OUT1BUF[64], 0x7E40);
-SFRX(IN1BUF[64], 0x7E80);
-SFRX(OUT0BUF[64], 0x7EC0);
-SFRX(IN0BUF[64], 0x7F00);
-/* 0x7F40 - 0x7F5F reserved */
-
-/**************************** Isochronous Data *****************************/
-SFRX(OUT8DATA, 0x7F60);
-SFRX(OUT9DATA, 0x7F61);
-SFRX(OUT10DATA, 0x7F62);
-SFRX(OUT11DATA, 0x7F63);
-SFRX(OUT12DATA, 0x7F64);
-SFRX(OUT13DATA, 0x7F65);
-SFRX(OUT14DATA, 0x7F66);
-SFRX(OUT15DATA, 0x7F67);
-
-SFRX(IN8DATA, 0x7F68);
-SFRX(IN9DATA, 0x7F69);
-SFRX(IN10DATA, 0x7F6A);
-SFRX(IN11DATA, 0x7F6B);
-SFRX(IN12DATA, 0x7F6C);
-SFRX(IN13DATA, 0x7F6D);
-SFRX(IN14DATA, 0x7F6E);
-SFRX(IN15DATA, 0x7F6F);
-
-/************************* Isochronous Byte Counts *************************/
-SFRX(OUT8BCH, 0x7F70);
-SFRX(OUT8BCL, 0x7F71);
-SFRX(OUT9BCH, 0x7F72);
-SFRX(OUT9BCL, 0x7F73);
-SFRX(OUT10BCH, 0x7F74);
-SFRX(OUT10BCL, 0x7F75);
-SFRX(OUT11BCH, 0x7F76);
-SFRX(OUT11BCL, 0x7F77);
-SFRX(OUT12BCH, 0x7F78);
-SFRX(OUT12BCL, 0x7F79);
-SFRX(OUT13BCH, 0x7F7A);
-SFRX(OUT13BCL, 0x7F7B);
-SFRX(OUT14BCH, 0x7F7C);
-SFRX(OUT14BCL, 0x7F7D);
-SFRX(OUT15BCH, 0x7F7E);
-SFRX(OUT16BCL, 0x7F7F);
-
-/****************************** CPU Registers ******************************/
-SFRX(CPUCS, 0x7F92);
-#define RES8051 bmBit0
-#define CLK24OE bmBit1
-/* Bit 2 read-only, always reads '0' */
-/* Bit 3 read-only, always reads '0' */
-/* Bits 4...7: Chip Revision */
-
-SFRX(PORTACFG, 0x7F93);
-#define T0OUT bmBit0
-#define T1OUT bmBit1
-#define OE bmBit2
-#define CS bmBit3
-#define FWR bmBit4
-#define FRD bmBit5
-#define RXD0OUT bmBit6
-#define RXD1OUT bmBit7
-
-SFRX(PORTBCFG, 0x7F94);
-#define T2 bmBit0
-#define T2EX bmBit1
-#define RXD1 bmBit2
-#define TXD1 bmBit3
-#define INT4 bmBit4
-#define INT5 bmBit5
-#define INT6 bmBit6
-#define T2OUT bmBit7
-
-SFRX(PORTCCFG, 0x7F95);
-#define RXD0 bmBit0
-#define TXD0 bmBit1
-#define INT0 bmBit2
-#define INT1 bmBit3
-#define T0 bmBit4
-#define T1 bmBit5
-#define WR bmBit6
-#define RD bmBit7
-
-/*********************** Input-Output Port Registers ***********************/
-SFRX(OUTA, 0x7F96);
-#define OUTA0 bmBit0
-#define OUTA1 bmBit1
-#define OUTA2 bmBit2
-#define OUTA3 bmBit3
-#define OUTA4 bmBit4
-#define OUTA5 bmBit5
-#define OUTA6 bmBit6
-#define OUTA7 bmBit7
-
-SFRX(OUTB, 0x7F97);
-#define OUTB0 bmBit0
-#define OUTB1 bmBit1
-#define OUTB2 bmBit2
-#define OUTB3 bmBit3
-#define OUTB4 bmBit4
-#define OUTB5 bmBit5
-#define OUTB6 bmBit6
-#define OUTB7 bmBit7
-
-SFRX(OUTC, 0x7F98);
-#define OUTC0 bmBit0
-#define OUTC1 bmBit1
-#define OUTC2 bmBit2
-#define OUTC3 bmBit3
-#define OUTC4 bmBit4
-#define OUTC5 bmBit5
-#define OUTC6 bmBit6
-#define OUTC7 bmBit7
-
-SFRX(PINSA, 0x7F99);
-#define PINA0 bmBit0
-#define PINA1 bmBit1
-#define PINA2 bmBit2
-#define PINA3 bmBit3
-#define PINA4 bmBit4
-#define PINA5 bmBit5
-#define PINA6 bmBit6
-#define PINA7 bmBit7
-
-SFRX(PINSB, 0x7F9A);
-#define PINB0 bmBit0
-#define PINB1 bmBit1
-#define PINB2 bmBit2
-#define PINB3 bmBit3
-#define PINB4 bmBit4
-#define PINB5 bmBit5
-#define PINB6 bmBit6
-#define PINB7 bmBit7
-
-SFRX(PINSC, 0x7F9B);
-#define PINC0 bmBit0
-#define PINC1 bmBit1
-#define PINC2 bmBit2
-#define PINC3 bmBit3
-#define PINC4 bmBit4
-#define PINC5 bmBit5
-#define PINC6 bmBit6
-#define PINC7 bmBit7
-
-SFRX(OEA, 0x7F9C);
-#define OEA0 bmBit0
-#define OEA1 bmBit1
-#define OEA2 bmBit2
-#define OEA3 bmBit3
-#define OEA4 bmBit4
-#define OEA5 bmBit5
-#define OEA6 bmBit6
-#define OEA7 bmBit7
-
-SFRX(OEB, 0x7F9D);
-#define OEB0 bmBit0
-#define OEB1 bmBit1
-#define OEB2 bmBit2
-#define OEB3 bmBit3
-#define OEB4 bmBit4
-#define OEB5 bmBit5
-#define OEB6 bmBit6
-#define OEB7 bmBit7
-
-SFRX(OEC, 0x7F9E);
-#define OEC0 bmBit0
-#define OEC1 bmBit1
-#define OEC2 bmBit2
-#define OEC3 bmBit3
-#define OEC4 bmBit4
-#define OEC5 bmBit5
-#define OEC6 bmBit6
-#define OEC7 bmBit7
-
-/* 0x7F9F reserved */
-
-/****************** Isochronous Control/Status Registers *******************/
-SFRX(ISOERR, 0x7FA0);
-#define ISO8ERR bmBit0
-#define ISO9ERR bmBit1
-#define ISO10ERR bmBit2
-#define ISO11ERR bmBit3
-#define ISO12ERR bmBit4
-#define ISO13ERR bmBit5
-#define ISO14ERR bmBit6
-#define ISO15ERR bmBit7
-
-SFRX(ISOCTL, 0x7FA1);
-#define ISODISAB bmBit0
-#define MBZ0 bmBit1
-#define MBZ1 bmBit2
-#define PPSTAT bmBit3
-/* Bit 4 unused */
-/* Bit 5 unused */
-/* Bit 6 unused */
-/* Bit 7 unused */
-
-SFRX(ZBCOUT, 0x7FA2);
-#define EP8 bmBit0
-#define EP9 bmBit1
-#define EP10 bmBit2
-#define EP11 bmBit3
-#define EP12 bmBit4
-#define EP13 bmBit5
-#define EP14 bmBit6
-#define EP15 bmBit7
-
-/* 0x7FA3 reserved */
-/* 0x7FA4 reserved */
-
-/****************************** I2C Registers ******************************/
-SFRX(I2CS, 0x7FA5);
-#define DONE bmBit0
-#define ACK bmBit1
-#define BERR bmBit2
-#define ID0 bmBit3
-#define ID1 bmBit4
-#define LASTRD bmBit5
-#define I2C_STOP bmBit6
-#define I2C_START bmBit7
-
-SFRX(I2DAT, 0x7FA6);
-/* 0x7FA7 reserved */
-
-/******************************* Interrupts ********************************/
-SFRX(IVEC, 0x7FA8);
-/* Bit 0 read-only, always reads '0' */
-/* Bit 1 read-only, always reads '0' */
-#define IV0 bmBit2
-#define IV1 bmBit3
-#define IV2 bmBit4
-#define IV3 bmBit5
-#define IV4 bmBit6
-/* Bit 7 read-only, always reads '0' */
-
-SFRX(IN07IRQ, 0x7FA9);
-#define IN0IR bmBit0
-#define IN1IR bmBit1
-#define IN2IR bmBit2
-#define IN3IR bmBit3
-#define IN4IR bmBit4
-#define IN5IR bmBit5
-#define IN6IR bmBit6
-#define IN7IR bmBit7
-
-SFRX(OUT07IRQ, 0x7FAA);
-#define OUT0IR bmBit0
-#define OUT1IR bmBit1
-#define OUT2IR bmBit2
-#define OUT3IR bmBit3
-#define OUT4IR bmBit4
-#define OUT5IR bmBit5
-#define OUT6IR bmBit6
-#define OUT7IR bmBit7
-
-SFRX(USBIRQ, 0x7FAB);
-#define SUDAVIR bmBit0
-#define SOFIR bmBit1
-#define SUTOKIR bmBit2
-#define SUSPIR bmBit3
-#define URESIR bmBit4
-/* Bit 5 unused */
-/* Bit 6 unused */
-/* Bit 7 unused */
-
-SFRX(IN07IEN, 0x7FAC);
-#define IN0IEN bmBit0
-#define IN1IEN bmBit1
-#define IN2IEN bmBit2
-#define IN3IEN bmBit3
-#define IN4IEN bmBit4
-#define IN5IEN bmBit5
-#define IN6IEN bmBit6
-#define IN7IEN bmBit7
-
-SFRX(OUT07IEN, 0x7FAD);
-#define OUT0IEN bmBit0
-#define OUT1IEN bmBit1
-#define OUT2IEN bmBit2
-#define OUT3IEN bmBit3
-#define OUT4IEN bmBit4
-#define OUT5IEN bmBit5
-#define OUT6IEN bmBit6
-#define OUT7IEN bmBit7
-
-SFRX(USBIEN, 0x7FAE);
-#define SUDAVIE bmBit0
-#define SOFIE bmBit1
-#define SUTOKIE bmBit2
-#define SUSPIE bmBit3
-#define URESIE bmBit4
-/* Bit 5 unused */
-/* Bit 6 unused */
-/* Bit 7 unused */
-
-SFRX(USBBAV, 0x7FAF);
-#define AVEN bmBit0
-#define BPEN bmBit1
-#define BPPULSE bmBit2
-#define BREAK bmBit3
-/* Bit 4 unused */
-/* Bit 5 unused */
-/* Bit 6 unused */
-/* Bit 7 unused */
-
-/* 0x7FB0 reserved */
-/* 0x7FB1 reserved */
-SFRX(BPADDRH, 0x7FB2);
-SFRX(BPADDRL, 0x7FB3);
-
-/****************************** Endpoints 0-7 ******************************/
-SFRX(EP0CS, 0x7FB4);
-#define EP0STALL bmBit0
-#define HSNAK bmBit1
-#define IN0BSY bmBit2
-#define OUT0BSY bmBit3
-/* Bit 4 unused */
-/* Bit 5 unused */
-/* Bit 6 unused */
-/* Bit 7 unused */
-
-SFRX(IN0BC, 0x7FB5);
-SFRX(IN1CS, 0x7FB6);
-SFRX(IN1BC, 0x7FB7);
-SFRX(IN2CS, 0x7FB8);
-SFRX(IN2BC, 0x7FB9);
-SFRX(IN3CS, 0x7FBA);
-SFRX(IN3BC, 0x7FBB);
-SFRX(IN4CS, 0x7FBC);
-SFRX(IN4BC, 0x7FBD);
-SFRX(IN5CS, 0x7FBE);
-SFRX(IN5BC, 0x7FBF);
-SFRX(IN6CS, 0x7FC0);
-SFRX(IN6BC, 0x7FC1);
-SFRX(IN7CS, 0x7FC2);
-SFRX(IN7BC, 0x7FC3);
-/* 0x7FC4 reserved */
-SFRX(OUT0BC, 0x7FC5);
-SFRX(OUT1CS, 0x7FC6);
-SFRX(OUT1BC, 0x7FC7);
-SFRX(OUT2CS, 0x7FC8);
-SFRX(OUT2BC, 0x7FC9);
-SFRX(OUT3CS, 0x7FCA);
-SFRX(OUT3BC, 0x7FCB);
-SFRX(OUT4CS, 0x7FCC);
-SFRX(OUT4BC, 0x7FCD);
-SFRX(OUT5CS, 0x7FCE);
-SFRX(OUT5BC, 0x7FCF);
-SFRX(OUT6CS, 0x7FD0);
-SFRX(OUT6BC, 0x7FD1);
-SFRX(OUT7CS, 0x7FD2);
-SFRX(OUT7BC, 0x7FD3);
-
-/* The INxSTALL, OUTxSTALL, INxBSY and OUTxBSY bits are the same for all
- * INxCS/OUTxCS registers. For better readability, we define them only once */
-#define EPSTALL bmBit0
-#define EPBSY bmBit1
-
-/************************** Global USB Registers ***************************/
-SFRX(SUDPTRH, 0x7FD4);
-SFRX(SUDPTRL, 0x7FD5);
-
-SFRX(USBCS, 0x7FD6);
-#define SIGRSUME bmBit0
-#define RENUM bmBit1
-#define DISCOE bmBit2
-#define DISCON bmBit3
-/* Bit 4 unused */
-/* Bit 5 unused */
-/* Bit 6 unused */
-#define WAKESRC bmBit7
-
-SFRX(TOGCTL, 0x7FD7);
-#define TOG_EP0 bmBit0
-#define TOG_EP1 bmBit1
-#define TOG_EP2 bmBit2
-/* Bit 3 is read-only, always reads '0' */
-#define TOG_IO bmBit4
-#define TOG_R bmBit5
-#define TOG_S bmBit6
-#define TOG_Q bmBit7
-
-SFRX(USBFRAMEL, 0x7FD8);
-SFRX(USBFRAMEH, 0x7FD9);
-/* 0x7FDA reserved */
-SFRX(FNADDR, 0x7FDB);
-/* 0x7FDC reserved */
-
-SFRX(USBPAIR, 0x7FDD);
-#define PR2IN bmBit0
-#define PR4IN bmBit1
-#define PR6IN bmBit2
-#define PR2OUT bmBit3
-#define PR4OUT bmBit4
-#define PR6OUT bmBit5
-/* Bit 6 unused */
-#define ISOSEND0 bmBit7
-
-SFRX(IN07VAL, 0x7FDE);
-/* Bit 0 is read-only, always reads '1' */
-#define IN1VAL bmBit1
-#define IN2VAL bmBit2
-#define IN3VAL bmBit3
-#define IN4VAL bmBit4
-#define IN5VAL bmBit5
-#define IN6VAL bmBit6
-#define IN7VAL bmBit7
-
-SFRX(OUT07VAL, 0x7FDF);
-/* Bit 0 is read-only, always reads '1' */
-#define OUT1VAL bmBit1
-#define OUT2VAL bmBit2
-#define OUT3VAL bmBit3
-#define OUT4VAL bmBit4
-#define OUT5VAL bmBit5
-#define OUT6VAL bmBit6
-#define OUT7VAL bmBit7
-
-SFRX(INISOVAL, 0x7FE0);
-#define IN8VAL bmBit0
-#define IN9VAL bmBit1
-#define IN10VAL bmBit2
-#define IN11VAL bmBit3
-#define IN12VAL bmBit4
-#define IN13VAL bmBit5
-#define IN14VAL bmBit6
-#define IN15VAL bmBit7
-
-SFRX(OUTISOVAL, 0x7FE1);
-#define OUT8VAL bmBit0
-#define OUT9VAL bmBit1
-#define OUT10VAL bmBit2
-#define OUT11VAL bmBit3
-#define OUT12VAL bmBit4
-#define OUT13VAL bmBit5
-#define OUT14VAL bmBit6
-#define OUT15VAL bmBit7
-
-SFRX(FASTXFR, 0x7FE2);
-#define WMOD0 bmBit0
-#define WMOD1 bmBit1
-#define WPOL bmBit2
-#define RMOD0 bmBit3
-#define RMOD1 bmBit4
-#define RPOL bmBit5
-#define FBLK bmBit6
-#define FISO bmBit7
-
-SFRX(AUTOPTRH, 0x7FE3);
-SFRX(AUTOPTRL, 0x7FE4);
-SFRX(AUTODATA, 0x7FE5);
-/* 0x7FE6 reserved */
-/* 0x7FE7 reserved */
-
-/******************************* Setup Data ********************************/
-SFRX(SETUPDAT[8], 0x7FE8);
-
-/************************* Isochronous FIFO sizes **************************/
-SFRX(OUT8ADDR, 0x7FF0);
-SFRX(OUT9ADDR, 0x7FF1);
-SFRX(OUT10ADDR, 0x7FF2);
-SFRX(OUT11ADDR, 0x7FF3);
-SFRX(OUT12ADDR, 0x7FF4);
-SFRX(OUT13ADDR, 0x7FF5);
-SFRX(OUT14ADDR, 0x7FF6);
-SFRX(OUT15ADDR, 0x7FF7);
-
-SFRX(IN8ADDR, 0x7FF8);
-SFRX(IN9ADDR, 0x7FF9);
-SFRX(IN10ADDR, 0x7FFA);
-SFRX(IN11ADDR, 0x7FFB);
-SFRX(IN12ADDR, 0x7FFC);
-SFRX(IN13ADDR, 0x7FFD);
-SFRX(IN14ADDR, 0x7FFE);
-SFRX(IN15ADDR, 0x7FFF);
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/include/usb.h b/src/jtag/drivers/OpenULINK/include/usb.h
deleted file mode 100644
index 9a261fe..0000000
--- a/src/jtag/drivers/OpenULINK/include/usb.h
+++ /dev/null
@@ -1,265 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef __USB_H
-#define __USB_H
-
-#include "reg_ezusb.h"
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#define NULL (void *)0;
-
-/* High and Low byte of a word (uint16_t) */
-#define HI8(word) (uint8_t)(((uint16_t)word >> 8) & 0xff)
-#define LO8(word) (uint8_t)((uint16_t)word & 0xff)
-
-/* Convenience functions */
-#define STALL_EP0() (EP0CS |= EP0STALL)
-#define CLEAR_IRQ() (EXIF &= ~USBINT)
-
-/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/
-
-/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */
-#define DESCRIPTOR_TYPE_DEVICE 0x01
-#define DESCRIPTOR_TYPE_CONFIGURATION 0x02
-#define DESCRIPTOR_TYPE_STRING 0x03
-#define DESCRIPTOR_TYPE_INTERFACE 0x04
-#define DESCRIPTOR_TYPE_ENDPOINT 0x05
-
-#define STR_DESCR(len, ...) { len * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } }
-
-/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */
-struct usb_device_descriptor {
- uint8_t bLength; /**< Size of this descriptor in bytes. */
- uint8_t bDescriptorType; /**< DEVICE Descriptor Type. */
- uint16_t bcdUSB; /**< USB specification release number (BCD). */
- uint8_t bDeviceClass; /**< Class code. */
- uint8_t bDeviceSubClass; /**< Subclass code. */
- uint8_t bDeviceProtocol; /**< Protocol code. */
- uint8_t bMaxPacketSize0; /**< Maximum packet size for EP0 (8, 16, 32, 64). */
- uint16_t idVendor; /**< USB Vendor ID. */
- uint16_t idProduct; /**< USB Product ID. */
- uint16_t bcdDevice; /**< Device Release Number (BCD). */
- uint8_t iManufacturer; /**< Index of manufacturer string descriptor. */
- uint8_t iProduct; /**< Index of product string descriptor. */
- uint8_t iSerialNumber; /**< Index of string descriptor containing serial #. */
- uint8_t bNumConfigurations; /**< Number of possible configurations. */
-};
-
-/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */
-struct usb_config_descriptor {
- uint8_t bLength; /**< Size of this descriptor in bytes. */
- uint8_t bDescriptorType; /**< CONFIGURATION descriptor type. */
- uint16_t wTotalLength; /**< Combined total length of all descriptors. */
- uint8_t bNumInterfaces; /**< Number of interfaces in this configuration. */
- uint8_t bConfigurationValue; /**< Value used to select this configuration. */
- uint8_t iConfiguration; /**< Index of configuration string descriptor. */
- uint8_t bmAttributes; /**< Configuration characteristics. */
- uint8_t MaxPower; /**< Maximum power consumption in 2 mA units. */
-};
-
-/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */
-struct usb_interface_descriptor {
- uint8_t bLength; /**< Size of this descriptor in bytes. */
- uint8_t bDescriptorType; /**< INTERFACE descriptor type. */
- uint8_t bInterfaceNumber; /**< Interface number. */
- uint8_t bAlternateSetting; /**< Value used to select alternate setting. */
- uint8_t bNumEndpoints; /**< Number of endpoints used by this interface. */
- uint8_t bInterfaceClass; /**< Class code. */
- uint8_t bInterfaceSubclass; /**< Subclass code. */
- uint8_t bInterfaceProtocol; /**< Protocol code. */
- uint8_t iInterface; /**< Index of interface string descriptor. */
-};
-
-/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */
-struct usb_endpoint_descriptor {
- uint8_t bLength; /**< Size of this descriptor in bytes. */
- uint8_t bDescriptorType; /**< ENDPOINT descriptor type. */
- uint8_t bEndpointAddress; /**< Endpoint Address: USB 1.1 spec, table 9-10. */
- uint8_t bmAttributes; /**< Endpoint Attributes: USB 1.1 spec, table 9-10. */
- uint16_t wMaxPacketSize; /**< Maximum packet size for this endpoint. */
- uint8_t bInterval; /**< Polling interval (in ms) for this endpoint. */
-};
-
-/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */
-struct usb_language_descriptor {
- uint8_t bLength; /**< Size of this descriptor in bytes. */
- uint8_t bDescriptorType; /**< STRING descriptor type. */
- uint16_t wLANGID[]; /**< LANGID codes. */
-};
-
-/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */
-struct usb_string_descriptor {
- uint8_t bLength; /**< Size of this descriptor in bytes. */
- uint8_t bDescriptorType; /**< STRING descriptor type. */
- uint16_t bString[]; /**< UNICODE encoded string. */
-};
-
-/********************** USB Control Endpoint 0 related *********************/
-
-/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */
-struct setup_data {
- uint8_t bmRequestType; /**< Characteristics of a request. */
- uint8_t bRequest; /**< Specific request. */
- uint16_t wValue; /**< Field that varies according to request. */
- uint16_t wIndex; /**< Field that varies according to request. */
- uint16_t wLength; /**< Number of bytes to transfer in data stage. */
-};
-
-/* External declarations for variables that need to be accessed outside of
- * the USB module */
-extern volatile bool EP2_out;
-extern volatile bool EP2_in;
-extern volatile __xdata __at 0x7FE8 struct setup_data setup_data;
-
-/*
- * USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2
- *
- * Bit 7: Data transfer direction
- * 0 = Host-to-device
- * 1 = Device-to-host
- * Bit 6...5: Type
- * 0 = Standard
- * 1 = Class
- * 2 = Vendor
- * 3 = Reserved
- * Bit 4...0: Recipient
- * 0 = Device
- * 1 = Interface
- * 2 = Endpoint
- * 3 = Other
- * 4...31 = Reserved
- */
-
-#define USB_DIR_OUT 0x00
-#define USB_DIR_IN 0x80
-
-#define USB_REQ_TYPE_STANDARD (0x00 << 5)
-#define USB_REQ_TYPE_CLASS (0x01 << 5)
-#define USB_REQ_TYPE_VENDOR (0x02 << 5)
-#define USB_REQ_TYPE_RESERVED (0x03 << 5)
-
-#define USB_RECIP_DEVICE 0x00
-#define USB_RECIP_INTERFACE 0x01
-#define USB_RECIP_ENDPOINT 0x02
-#define USB_RECIP_OTHER 0x03
-
-/* bmRequestType for USB Standard Requests */
-
-/* Clear Interface Request */
-#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
-#define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
-#define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
-
-/* Get Configuration Request */
-#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
-
-/* Get Descriptor Request */
-#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
-
-/* Get Interface Request */
-#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
-
-/* Get Status Request: See USB 1.1 spec, page 190 */
-#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
-#define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
-#define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
-
-/* Set Address Request is handled by EZ-USB core */
-
-/* Set Configuration Request */
-#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
-
-/* Set Descriptor Request */
-#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
-
-/* Set Feature Request */
-#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
-#define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
-#define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
-
-/* Set Interface Request */
-#define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
-
-/* Synch Frame Request */
-#define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
-
-/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */
-#define GET_STATUS 0
-#define CLEAR_FEATURE 1
-/* Value '2' is reserved for future use */
-#define SET_FEATURE 3
-/* Value '4' is reserved for future use */
-#define SET_ADDRESS 5
-#define GET_DESCRIPTOR 6
-#define SET_DESCRIPTOR 7
-#define GET_CONFIGURATION 8
-#define SET_CONFIGURATION 9
-#define GET_INTERFACE 10
-#define SET_INTERFACE 11
-#define SYNCH_FRAME 12
-
-/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */
-#define DEVICE_REMOTE_WAKEUP 1
-#define ENDPOINT_HALT 0
-
-/************************** EZ-USB specific stuff **************************/
-
-/** USB Interrupts. See AN2131-TRM, page 9-4 for details */
-enum usb_isr {
- SUDAV_ISR = 13,
- SOF_ISR,
- SUTOK_ISR,
- SUSPEND_ISR,
- USBRESET_ISR,
- IBN_ISR,
- EP0IN_ISR,
- EP0OUT_ISR,
- EP1IN_ISR,
- EP1OUT_ISR,
- EP2IN_ISR,
- EP2OUT_ISR,
- EP3IN_ISR,
- EP3OUT_ISR,
- EP4IN_ISR,
- EP4OUT_ISR,
- EP5IN_ISR,
- EP5OUT_ISR,
- EP6IN_ISR,
- EP6OUT_ISR,
- EP7IN_ISR,
- EP7OUT_ISR
-};
-
-/*************************** Function Prototypes ***************************/
-
-__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep);
-void usb_reset_data_toggle(uint8_t ep);
-
-bool usb_handle_get_status(void);
-bool usb_handle_clear_feature(void);
-bool usb_handle_set_feature(void);
-bool usb_handle_get_descriptor(void);
-void usb_handle_set_interface(void);
-
-void usb_handle_setup_data(void);
-void usb_init(void);
-
-#endif
diff --git a/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 b/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51
deleted file mode 100644
index f10ad48..0000000
--- a/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51
+++ /dev/null
@@ -1,81 +0,0 @@
-;--------------------------------------------------------------------------;
-; Copyright (C) 2011-2013 by Martin Schmoelzer ;
-; <martin.schmoelzer@student.tuwien.ac.at> ;
-; ;
-; This program is free software; you can redistribute it and/or modify ;
-; it under the terms of the GNU General Public License as published by ;
-; the Free Software Foundation; either version 2 of the License, or ;
-; (at your option) any later version. ;
-; ;
-; This program is distributed in the hope that it will be useful, ;
-; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
-; GNU General Public License for more details. ;
-; ;
-; You should have received a copy of the GNU General Public License ;
-; along with this program. If not, see <http://www.gnu.org/licenses/>. ;
-;--------------------------------------------------------------------------;
-
-.module JUMPTABLE
-.globl USB_AutoVector
-.globl USB_Jump_Table
-
-;--------------------------------------------------------------------------;
-; Interrupt Vectors ;
-;--------------------------------------------------------------------------;
-.area USB_JV (ABS,OVR) ; Absolute, Overlay
-.org 0x43 ; USB interrupt (INT2) jumps here
-USB_AutoVector = #. + 2
- ljmp USB_Jump_Table
-
-;--------------------------------------------------------------------------;
-; USB Jump Table ;
-;--------------------------------------------------------------------------;
-.area USB_JT (ABS) ; Absolute placement
-.org 0x1B00 ; Place jump table at 0x1B00
-
-USB_Jump_Table: ; autovector jump table
- ljmp _sudav_isr ; Setup Data Available
- .db 0
- ljmp _sof_isr ; Start of Frame
- .db 0
- ljmp _sutok_isr ; Setup Data Loading
- .db 0
- ljmp _suspend_isr ; Global Suspend
- .db 0
- ljmp _usbreset_isr ; USB Reset
- .db 0
- ljmp _ibn_isr ; IN Bulk NAK interrupt
- .db 0
- ljmp _ep0in_isr ; Endpoint 0 IN
- .db 0
- ljmp _ep0out_isr ; Endpoint 0 OUT
- .db 0
- ljmp _ep1in_isr ; Endpoint 1 IN
- .db 0
- ljmp _ep1out_isr ; Endpoint 1 OUT
- .db 0
- ljmp _ep2in_isr ; Endpoint 2 IN
- .db 0
- ljmp _ep2out_isr ; Endpoint 2 OUT
- .db 0
- ljmp _ep3in_isr ; Endpoint 3 IN
- .db 0
- ljmp _ep3out_isr ; Endpoint 3 OUT
- .db 0
- ljmp _ep4in_isr ; Endpoint 4 IN
- .db 0
- ljmp _ep4out_isr ; Endpoint 4 OUT
- .db 0
- ljmp _ep5in_isr ; Endpoint 5 IN
- .db 0
- ljmp _ep5out_isr ; Endpoint 5 OUT
- .db 0
- ljmp _ep6in_isr ; Endpoint 6 IN
- .db 0
- ljmp _ep6out_isr ; Endpoint 6 OUT
- .db 0
- ljmp _ep7in_isr ; Endpoint 7 IN
- .db 0
- ljmp _ep7out_isr ; Endpoint 7 OUT
- .db 0
diff --git a/src/jtag/drivers/OpenULINK/src/delay.c b/src/jtag/drivers/OpenULINK/src/delay.c
deleted file mode 100644
index 3260567..0000000
--- a/src/jtag/drivers/OpenULINK/src/delay.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#include "delay.h"
-
-void delay_5us(void)
-{
- NOP;
-}
-
-void delay_1ms(void)
-{
- uint16_t i;
-
- for (i = 0; i < 598; i++)
- ;
-}
-
-void delay_us(uint16_t delay)
-{
- uint16_t i;
- uint16_t maxcount = (delay / 5);
-
- for (i = 0; i < maxcount; i++)
- delay_5us();
-}
-
-void delay_ms(uint16_t delay)
-{
- uint16_t i;
-
- for (i = 0; i < delay; i++)
- delay_1ms();
-}
diff --git a/src/jtag/drivers/OpenULINK/src/jtag.c b/src/jtag/drivers/OpenULINK/src/jtag.c
deleted file mode 100644
index 4139455..0000000
--- a/src/jtag/drivers/OpenULINK/src/jtag.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#include "jtag.h"
-
-#include "io.h"
-#include "msgtypes.h"
-#include "common.h"
-
-#include <stdbool.h>
-
-/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
-uint8_t delay_scan_in;
-
-/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
-uint8_t delay_scan_out;
-
-/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
-uint8_t delay_scan_io;
-
-/** Delay value for CLOCK_TCK operations with less than maximum frequency */
-uint8_t delay_tck;
-
-/** Delay value for CLOCK_TMS operations with less than maximum frequency */
-uint8_t delay_tms;
-
-/**
- * Perform JTAG SCAN-IN operation at maximum TCK frequency.
- *
- * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
- * stored in the EP2 IN buffer.
- *
- * Maximum achievable TCK frequency is 182 kHz for ULINK clocked at 24 MHz.
- *
- * @param out_offset offset in OUT2BUF where payload data starts
- */
-void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
-{
- uint8_t scan_size_bytes, bits_last_byte;
- uint8_t tms_count_start, tms_count_end;
- uint8_t tms_sequence_start, tms_sequence_end;
- uint8_t tdo_data, i, j;
-
- uint8_t outb_buffer;
-
- /* Get parameters from OUT2BUF */
- scan_size_bytes = OUT2BUF[out_offset];
- bits_last_byte = OUT2BUF[out_offset + 1];
- tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
- tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
- tms_sequence_start = OUT2BUF[out_offset + 3];
- tms_sequence_end = OUT2BUF[out_offset + 4];
-
- if (tms_count_start > 0)
- jtag_clock_tms(tms_count_start, tms_sequence_start);
-
- outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
-
- /* Shift all bytes except the last byte */
- for (i = 0; i < scan_size_bytes - 1; i++) {
- tdo_data = 0;
-
- for (j = 0; j < 8; j++) {
- OUTB = outb_buffer; /* TCK changes here */
- tdo_data = tdo_data >> 1;
- OUTB = (outb_buffer | PIN_TCK);
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
- }
-
- tdo_data = 0;
-
- /* Shift the last byte */
- for (j = 0; j < bits_last_byte; j++) {
- /* Assert TMS signal if requested and this is the last bit */
- if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
- outb_buffer |= PIN_TMS;
- tms_count_end--;
- tms_sequence_end = tms_sequence_end >> 1;
- }
-
- OUTB = outb_buffer; /* TCK changes here */
- tdo_data = tdo_data >> 1;
- OUTB = (outb_buffer | PIN_TCK);
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
- tdo_data = tdo_data >> (8 - bits_last_byte);
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
-
- /* Move to correct end state */
- if (tms_count_end > 0)
- jtag_clock_tms(tms_count_end, tms_sequence_end);
-}
-
-/**
- * Perform JTAG SCAN-IN operation at variable TCK frequency.
- *
- * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
- * stored in the EP2 IN buffer.
- *
- * Maximum achievable TCK frequency is 113 kHz for ULINK clocked at 24 MHz.
- *
- * @param out_offset offset in OUT2BUF where payload data starts
- */
-void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
-{
- uint8_t scan_size_bytes, bits_last_byte;
- uint8_t tms_count_start, tms_count_end;
- uint8_t tms_sequence_start, tms_sequence_end;
- uint8_t tdo_data, i, j, k;
-
- uint8_t outb_buffer;
-
- /* Get parameters from OUT2BUF */
- scan_size_bytes = OUT2BUF[out_offset];
- bits_last_byte = OUT2BUF[out_offset + 1];
- tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
- tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
- tms_sequence_start = OUT2BUF[out_offset + 3];
- tms_sequence_end = OUT2BUF[out_offset + 4];
-
- if (tms_count_start > 0)
- jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
-
- outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
-
- /* Shift all bytes except the last byte */
- for (i = 0; i < scan_size_bytes - 1; i++) {
- tdo_data = 0;
-
- for (j = 0; j < 8; j++) {
- OUTB = outb_buffer; /* TCK changes here */
- for (k = 0; k < delay_scan_in; k++)
- ;
- tdo_data = tdo_data >> 1;
-
- OUTB = (outb_buffer | PIN_TCK);
- for (k = 0; k < delay_scan_in; k++)
- ;
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
- }
-
- tdo_data = 0;
-
- /* Shift the last byte */
- for (j = 0; j < bits_last_byte; j++) {
- /* Assert TMS signal if requested and this is the last bit */
- if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
- outb_buffer |= PIN_TMS;
- tms_count_end--;
- tms_sequence_end = tms_sequence_end >> 1;
- }
-
- OUTB = outb_buffer; /* TCK changes here */
- for (k = 0; k < delay_scan_in; k++)
- ;
- tdo_data = tdo_data >> 1;
-
- OUTB = (outb_buffer | PIN_TCK);
- for (k = 0; k < delay_scan_in; k++)
- ;
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
- tdo_data = tdo_data >> (8 - bits_last_byte);
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
-
- /* Move to correct end state */
- if (tms_count_end > 0)
- jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
-}
-
-/**
- * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
- *
- * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
- * data is not sampled.
- * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
- *
- * Maximum achievable TCK frequency is 142 kHz for ULINK clocked at 24 MHz.
- *
- * @param out_offset offset in OUT2BUF where payload data starts
- */
-void jtag_scan_out(uint8_t out_offset)
-{
- uint8_t scan_size_bytes, bits_last_byte;
- uint8_t tms_count_start, tms_count_end;
- uint8_t tms_sequence_start, tms_sequence_end;
- uint8_t tdi_data, i, j;
-
- uint8_t outb_buffer;
-
- /* Get parameters from OUT2BUF */
- scan_size_bytes = OUT2BUF[out_offset];
- bits_last_byte = OUT2BUF[out_offset + 1];
- tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
- tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
- tms_sequence_start = OUT2BUF[out_offset + 3];
- tms_sequence_end = OUT2BUF[out_offset + 4];
-
- if (tms_count_start > 0)
- jtag_clock_tms(tms_count_start, tms_sequence_start);
-
- outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
-
- /* Shift all bytes except the last byte */
- for (i = 0; i < scan_size_bytes - 1; i++) {
- tdi_data = OUT2BUF[i + out_offset + 5];
-
- for (j = 0; j < 8; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- tdi_data = tdi_data >> 1;
- OUTB = (outb_buffer | PIN_TCK);
- }
- }
-
- tdi_data = OUT2BUF[i + out_offset + 5];
-
- /* Shift the last byte */
- for (j = 0; j < bits_last_byte; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- /* Assert TMS signal if requested and this is the last bit */
- if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
- outb_buffer |= PIN_TMS;
- tms_count_end--;
- tms_sequence_end = tms_sequence_end >> 1;
- }
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- tdi_data = tdi_data >> 1;
- OUTB = (outb_buffer | PIN_TCK);
- }
-
- /* Move to correct end state */
- if (tms_count_end > 0)
- jtag_clock_tms(tms_count_end, tms_sequence_end);
-}
-
-/**
- * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
- *
- * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
- * data is not sampled.
- * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
- *
- * Maximum achievable TCK frequency is 97 kHz for ULINK clocked at 24 MHz.
- *
- * @param out_offset offset in OUT2BUF where payload data starts
- */
-void jtag_slow_scan_out(uint8_t out_offset)
-{
- uint8_t scan_size_bytes, bits_last_byte;
- uint8_t tms_count_start, tms_count_end;
- uint8_t tms_sequence_start, tms_sequence_end;
- uint8_t tdi_data, i, j, k;
-
- uint8_t outb_buffer;
-
- /* Get parameters from OUT2BUF */
- scan_size_bytes = OUT2BUF[out_offset];
- bits_last_byte = OUT2BUF[out_offset + 1];
- tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
- tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
- tms_sequence_start = OUT2BUF[out_offset + 3];
- tms_sequence_end = OUT2BUF[out_offset + 4];
-
- if (tms_count_start > 0)
- jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
-
- outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
-
- /* Shift all bytes except the last byte */
- for (i = 0; i < scan_size_bytes - 1; i++) {
- tdi_data = OUT2BUF[i + out_offset + 5];
-
- for (j = 0; j < 8; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- for (k = 0; k < delay_scan_out; k++)
- ;
- tdi_data = tdi_data >> 1;
-
- OUTB = (outb_buffer | PIN_TCK);
- for (k = 0; k < delay_scan_out; k++)
- ;
- }
- }
-
- tdi_data = OUT2BUF[i + out_offset + 5];
-
- /* Shift the last byte */
- for (j = 0; j < bits_last_byte; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- /* Assert TMS signal if requested and this is the last bit */
- if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
- outb_buffer |= PIN_TMS;
- tms_count_end--;
- tms_sequence_end = tms_sequence_end >> 1;
- }
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- for (k = 0; k < delay_scan_out; k++)
- ;
- tdi_data = tdi_data >> 1;
-
- OUTB = (outb_buffer | PIN_TCK);
- for (k = 0; k < delay_scan_out; k++)
- ;
- }
-
- /* Move to correct end state */
- if (tms_count_end > 0)
- jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
-}
-
-/**
- * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
- *
- * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
- * data is sampled and stored in the EP2 IN buffer.
- * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
- *
- * Maximum achievable TCK frequency is 100 kHz for ULINK clocked at 24 MHz.
- *
- * @param out_offset offset in OUT2BUF where payload data starts
- */
-void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
-{
- uint8_t scan_size_bytes, bits_last_byte;
- uint8_t tms_count_start, tms_count_end;
- uint8_t tms_sequence_start, tms_sequence_end;
- uint8_t tdi_data, tdo_data, i, j;
-
- uint8_t outb_buffer;
-
- /* Get parameters from OUT2BUF */
- scan_size_bytes = OUT2BUF[out_offset];
- bits_last_byte = OUT2BUF[out_offset + 1];
- tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
- tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
- tms_sequence_start = OUT2BUF[out_offset + 3];
- tms_sequence_end = OUT2BUF[out_offset + 4];
-
- if (tms_count_start > 0)
- jtag_clock_tms(tms_count_start, tms_sequence_start);
-
- outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
-
- /* Shift all bytes except the last byte */
- for (i = 0; i < scan_size_bytes - 1; i++) {
- tdi_data = OUT2BUF[i + out_offset + 5];
- tdo_data = 0;
-
- for (j = 0; j < 8; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- tdi_data = tdi_data >> 1;
- OUTB = (outb_buffer | PIN_TCK);
- tdo_data = tdo_data >> 1;
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
- }
-
- tdi_data = OUT2BUF[i + out_offset + 5];
- tdo_data = 0;
-
- /* Shift the last byte */
- for (j = 0; j < bits_last_byte; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- /* Assert TMS signal if requested and this is the last bit */
- if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
- outb_buffer |= PIN_TMS;
- tms_count_end--;
- tms_sequence_end = tms_sequence_end >> 1;
- }
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- tdi_data = tdi_data >> 1;
- OUTB = (outb_buffer | PIN_TCK);
- tdo_data = tdo_data >> 1;
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
- tdo_data = tdo_data >> (8 - bits_last_byte);
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
-
- /* Move to correct end state */
- if (tms_count_end > 0)
- jtag_clock_tms(tms_count_end, tms_sequence_end);
-}
-
-/**
- * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
- *
- * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
- * data is sampled and stored in the EP2 IN buffer.
- * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
- *
- * Maximum achievable TCK frequency is 78 kHz for ULINK clocked at 24 MHz.
- *
- * @param out_offset offset in OUT2BUF where payload data starts
- */
-void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
-{
- uint8_t scan_size_bytes, bits_last_byte;
- uint8_t tms_count_start, tms_count_end;
- uint8_t tms_sequence_start, tms_sequence_end;
- uint8_t tdi_data, tdo_data, i, j, k;
-
- uint8_t outb_buffer;
-
- /* Get parameters from OUT2BUF */
- scan_size_bytes = OUT2BUF[out_offset];
- bits_last_byte = OUT2BUF[out_offset + 1];
- tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
- tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
- tms_sequence_start = OUT2BUF[out_offset + 3];
- tms_sequence_end = OUT2BUF[out_offset + 4];
-
- if (tms_count_start > 0)
- jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
-
- outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
-
- /* Shift all bytes except the last byte */
- for (i = 0; i < scan_size_bytes - 1; i++) {
- tdi_data = OUT2BUF[i + out_offset + 5];
- tdo_data = 0;
-
- for (j = 0; j < 8; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- for (k = 0; k < delay_scan_io; k++)
- ;
- tdi_data = tdi_data >> 1;
-
- OUTB = (outb_buffer | PIN_TCK);
- for (k = 0; k < delay_scan_io; k++)
- ;
- tdo_data = tdo_data >> 1;
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
- }
-
- tdi_data = OUT2BUF[i + out_offset + 5];
- tdo_data = 0;
-
- /* Shift the last byte */
- for (j = 0; j < bits_last_byte; j++) {
- if (tdi_data & 0x01)
- outb_buffer |= PIN_TDI;
- else
- outb_buffer &= ~PIN_TDI;
-
- /* Assert TMS signal if requested and this is the last bit */
- if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
- outb_buffer |= PIN_TMS;
- tms_count_end--;
- tms_sequence_end = tms_sequence_end >> 1;
- }
-
- OUTB = outb_buffer; /* TDI and TCK change here */
- for (k = 0; k < delay_scan_io; k++)
- ;
- tdi_data = tdi_data >> 1;
-
- OUTB = (outb_buffer | PIN_TCK);
- for (k = 0; k < delay_scan_io; k++)
- ;
- tdo_data = tdo_data >> 1;
-
- if (GET_TDO())
- tdo_data |= 0x80;
- }
- tdo_data = tdo_data >> (8 - bits_last_byte);
-
- /* Copy TDO data to IN2BUF */
- IN2BUF[i + in_offset] = tdo_data;
-
- /* Move to correct end state */
- if (tms_count_end > 0)
- jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
-}
-
-/**
- * Generate TCK clock cycles.
- *
- * Maximum achievable TCK frequency is 375 kHz for ULINK clocked at 24 MHz.
- *
- * @param count number of TCK clock cyclces to generate.
- */
-void jtag_clock_tck(uint16_t count)
-{
- uint16_t i;
- uint8_t outb_buffer = OUTB & ~(PIN_TCK);
-
- for (i = 0; i < count; i++) {
- OUTB = outb_buffer;
- OUTB = outb_buffer | PIN_TCK;
- }
-}
-
-/**
- * Generate TCK clock cycles at variable frequency.
- *
- * Maximum achieveable TCK frequency is 166.6 kHz for ULINK clocked at 24 MHz.
- *
- * @param count number of TCK clock cyclces to generate.
- */
-void jtag_slow_clock_tck(uint16_t count)
-{
- uint16_t i;
- uint8_t j;
- uint8_t outb_buffer = OUTB & ~(PIN_TCK);
-
- for (i = 0; i < count; i++) {
- OUTB = outb_buffer;
- for (j = 0; j < delay_tck; j++)
- ;
- OUTB = outb_buffer | PIN_TCK;
- for (j = 0; j < delay_tck; j++)
- ;
- }
-}
-
-/**
- * Perform TAP FSM state transitions at maximum TCK frequency.
- *
- * Maximum achievable TCK frequency is 176 kHz for ULINK clocked at 24 MHz.
- *
- * @param count the number of state transitions to perform.
- * @param sequence the TMS pin levels for each state transition, starting with
- * the least-significant bit.
- */
-void jtag_clock_tms(uint8_t count, uint8_t sequence)
-{
- uint8_t outb_buffer = OUTB & ~(PIN_TCK);
- uint8_t i;
-
- for (i = 0; i < count; i++) {
- /* Set TMS pin according to sequence parameter */
- if (sequence & 0x1)
- outb_buffer |= PIN_TMS;
- else
- outb_buffer &= ~PIN_TMS;
-
- OUTB = outb_buffer;
- sequence = sequence >> 1;
- OUTB = outb_buffer | PIN_TCK;
- }
-}
-
-/**
- * Perform TAP-FSM state transitions at less than maximum TCK frequency.
- *
- * Maximum achievable TCK frequency is 117 kHz for ULINK clocked at 24 MHz.
- *
- * @param count the number of state transitions to perform.
- * @param sequence the TMS pin levels for each state transition, starting with
- * the least-significant bit.
- */
-void jtag_slow_clock_tms(uint8_t count, uint8_t sequence)
-{
- uint8_t outb_buffer = OUTB & ~(PIN_TCK);
- uint8_t i, j;
-
- for (i = 0; i < count; i++) {
- /* Set TMS pin according to sequence parameter */
- if (sequence & 0x1)
- outb_buffer |= PIN_TMS;
- else
- outb_buffer &= ~PIN_TMS;
-
- OUTB = outb_buffer;
- for (j = 0; j < delay_tms; j++)
- ;
- sequence = sequence >> 1;
- OUTB = outb_buffer | PIN_TCK;
- for (j = 0; j < delay_tms; j++)
- ;
- }
-}
-
-/**
- * Get current JTAG signal states.
- *
- * @return a 16-bit integer where the most-significant byte contains the state
- * of the JTAG input signals and the least-significant byte contains the state
- * of the JTAG output signals.
- */
-uint16_t jtag_get_signals(void)
-{
- uint8_t input_signal_state, output_signal_state;
-
- input_signal_state = 0;
- output_signal_state = 0;
-
- /* Get states of input pins */
- if (GET_TDO())
- input_signal_state |= SIGNAL_TDO;
- if (GET_BRKOUT())
- input_signal_state |= SIGNAL_BRKOUT;
- if (GET_TRAP())
- input_signal_state |= SIGNAL_TRAP;
- if (GET_RTCK()) {
- /* Using RTCK this way would be extremely slow,
- * implemented only for the sake of completeness */
- input_signal_state |= SIGNAL_RTCK;
- }
-
- /* Get states of output pins */
- output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
-
- return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state);
-}
-
-/**
- * Set state of JTAG output signals.
- *
- * @param low signals which should be de-asserted.
- * @param high signals which should be asserted.
- */
-void jtag_set_signals(uint8_t low, uint8_t high)
-{
- OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
- OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
-}
-
-/**
- * Configure TCK delay parameters.
- *
- * @param scan_in number of delay cycles in scan_in operations.
- * @param scan_out number of delay cycles in scan_out operations.
- * @param scan_io number of delay cycles in scan_io operations.
- * @param tck number of delay cycles in clock_tck operations.
- * @param tms number of delay cycles in clock_tms operations.
- */
-void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
- uint8_t scan_io, uint8_t tck, uint8_t tms)
-{
- delay_scan_in = scan_in;
- delay_scan_out = scan_out;
- delay_scan_io = scan_io;
- delay_tck = tck;
- delay_tms = tms;
-}
diff --git a/src/jtag/drivers/OpenULINK/src/main.c b/src/jtag/drivers/OpenULINK/src/main.c
deleted file mode 100644
index f331c9e..0000000
--- a/src/jtag/drivers/OpenULINK/src/main.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#include "main.h"
-
-#include "io.h"
-#include "usb.h"
-#include "protocol.h"
-
-extern void sudav_isr(void) __interrupt SUDAV_ISR;
-extern void sof_isr(void) __interrupt;
-extern void sutok_isr(void) __interrupt;
-extern void suspend_isr(void) __interrupt;
-extern void usbreset_isr(void) __interrupt;
-extern void ibn_isr(void) __interrupt;
-extern void ep0in_isr(void) __interrupt;
-extern void ep0out_isr(void) __interrupt;
-extern void ep1in_isr(void) __interrupt;
-extern void ep1out_isr(void) __interrupt;
-extern void ep2in_isr(void) __interrupt;
-extern void ep2out_isr(void) __interrupt;
-extern void ep3in_isr(void) __interrupt;
-extern void ep3out_isr(void) __interrupt;
-extern void ep4in_isr(void) __interrupt;
-extern void ep4out_isr(void) __interrupt;
-extern void ep5in_isr(void) __interrupt;
-extern void ep5out_isr(void) __interrupt;
-extern void ep6in_isr(void) __interrupt;
-extern void ep6out_isr(void) __interrupt;
-extern void ep7in_isr(void) __interrupt;
-extern void ep7out_isr(void) __interrupt;
-
-void io_init(void)
-{
- /* PORTxCFG register bits select alternate functions (1 == alternate function,
- * 0 == standard I/O)
- * OEx register bits turn on/off output buffer (1 == output, 0 == input)
- * OUTx register bits determine pin state of output
- * PINx register bits reflect pin state (high == 1, low == 0) */
-
- /* PORT A */
- PORTACFG = PIN_OE;
- OEA = PIN_U_OE | PIN_OE | PIN_RUN_LED | PIN_COM_LED;
- OUTA = PIN_RUN_LED | PIN_COM_LED;
-
- /* PORT B */
- PORTBCFG = 0x00;
- OEB = PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET
- | PIN_OCDSE;
-
- /* TRST and RESET signals are low-active but inverted by hardware, so we clear
- * these signals here! */
- OUTB = 0x00;
-
- /* PORT C */
- PORTCCFG = PIN_WR;
- OEC = PIN_TXD0 | PIN_WR;
- OUTC = 0x00;
-}
-
-int main(void)
-{
- io_init();
- usb_init();
-
- /* Enable Interrupts */
- EA = 1;
-
- /* Begin executing command(s). This function never returns. */
- command_loop();
-
- /* Never reached, but SDCC complains about missing return statement */
- return 0;
-}
diff --git a/src/jtag/drivers/OpenULINK/src/protocol.c b/src/jtag/drivers/OpenULINK/src/protocol.c
deleted file mode 100644
index 901f524..0000000
--- a/src/jtag/drivers/OpenULINK/src/protocol.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#include "protocol.h"
-#include "jtag.h"
-#include "delay.h"
-#include "usb.h"
-#include "io.h"
-#include "msgtypes.h"
-
-#include "reg_ezusb.h"
-
-/**
- * @file
- * Implementation of the OpenULINK communication protocol.
- *
- * The OpenULINK protocol uses one OUT and one IN endpoint. These two endpoints
- * are configured to use the maximum packet size for full-speed transfers,
- * 64 bytes. Commands always start with a command ID (see msgtypes.h for
- * command ID definitions) and contain zero or more payload data bytes in both
- * transfer directions (IN and OUT). The payload
- *
- * Almost all commands contain a fixed number of payload data bytes. The number
- * of payload data bytes for the IN and OUT direction does not need to be the
- * same.
- *
- * Multiple commands may be sent in one EP2 Bulk-OUT packet. Because the
- * OpenULINK firmware does not perform bounds checking for EP2 Bulk-IN packets,
- * the host MUST ensure that the commands sent in the OUT packet require a
- * maximum of 64 bytes of IN data.
- */
-
-/** Index in EP2 Bulk-OUT data buffer that contains the current command ID */
-volatile uint8_t cmd_id_index;
-
-/** Number of data bytes already in EP2 Bulk-IN buffer */
-volatile uint8_t payload_index_in;
-
-/**
- * Execute a SET_LEDS command.
- */
-void execute_set_led_command(void)
-{
- uint8_t led_state = OUT2BUF[cmd_id_index + 1];
-
- if (led_state & RUN_LED_ON)
- SET_RUN_LED();
-
- if (led_state & COM_LED_ON)
- SET_COM_LED();
-
- if (led_state & RUN_LED_OFF)
- CLEAR_RUN_LED();
-
- if (led_state & COM_LED_OFF)
- CLEAR_COM_LED();
-}
-
-/**
- * Executes one command and updates global command indexes.
- *
- * @return true if this command was the last command.
- * @return false if there are more commands within the current contents of the
- * Bulk EP2-OUT data buffer.
- */
-bool execute_command(void)
-{
- uint8_t usb_out_bytecount, usb_in_bytecount;
- uint16_t signal_state;
- uint16_t count;
-
- /* Most commands do not transfer IN data. To save code space, we write 0 to
- * usb_in_bytecount here, then modify it in the switch statement below where
- * neccessary */
- usb_in_bytecount = 0;
-
- switch (OUT2BUF[cmd_id_index] /* Command ID */) {
- case CMD_SCAN_IN:
- usb_out_bytecount = 5;
- usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
- jtag_scan_in(cmd_id_index + 1, payload_index_in);
- break;
- case CMD_SCAN_OUT:
- usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
- jtag_scan_out(cmd_id_index + 1);
- break;
- case CMD_SCAN_IO:
- usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
- usb_out_bytecount = usb_in_bytecount + 5;
- jtag_scan_io(cmd_id_index + 1, payload_index_in);
- break;
- case CMD_CLOCK_TMS:
- usb_out_bytecount = 2;
- jtag_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
- break;
- case CMD_CLOCK_TCK:
- usb_out_bytecount = 2;
- count = (uint16_t)OUT2BUF[cmd_id_index + 1];
- count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
- jtag_clock_tck(count);
- break;
- case CMD_SLOW_SCAN_IN:
- usb_out_bytecount = 5;
- usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
- jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
- break;
- case CMD_SLOW_SCAN_OUT:
- usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
- jtag_slow_scan_out(cmd_id_index + 1);
- break;
- case CMD_SLOW_SCAN_IO:
- usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
- usb_out_bytecount = usb_in_bytecount + 5;
- jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
- break;
- case CMD_SLOW_CLOCK_TMS:
- usb_out_bytecount = 2;
- jtag_slow_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
- break;
- case CMD_SLOW_CLOCK_TCK:
- usb_out_bytecount = 2;
- count = (uint16_t)OUT2BUF[cmd_id_index + 1];
- count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
- jtag_slow_clock_tck(count);
- break;
- case CMD_SLEEP_US:
- usb_out_bytecount = 2;
- count = (uint16_t)OUT2BUF[cmd_id_index + 1];
- count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
- delay_us(count);
- break;
- case CMD_SLEEP_MS:
- usb_out_bytecount = 2;
- count = (uint16_t)OUT2BUF[cmd_id_index + 1];
- count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
- delay_ms(count);
- break;
- case CMD_GET_SIGNALS:
- usb_out_bytecount = 0;
- usb_in_bytecount = 2;
- signal_state = jtag_get_signals();
- IN2BUF[payload_index_in] = (signal_state >> 8) & 0x00FF;
- IN2BUF[payload_index_in + 1] = signal_state & 0x00FF;
- break;
- case CMD_SET_SIGNALS:
- usb_out_bytecount = 2;
- jtag_set_signals(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
- break;
- case CMD_CONFIGURE_TCK_FREQ:
- usb_out_bytecount = 5;
- jtag_configure_tck_delay(
- OUT2BUF[cmd_id_index + 1], /* scan_in */
- OUT2BUF[cmd_id_index + 2], /* scan_out */
- OUT2BUF[cmd_id_index + 3], /* scan_io */
- OUT2BUF[cmd_id_index + 4], /* clock_tck */
- OUT2BUF[cmd_id_index + 5]); /* clock_tms */
- break;
- case CMD_SET_LEDS:
- usb_out_bytecount = 1;
- execute_set_led_command();
- break;
- case CMD_TEST:
- usb_out_bytecount = 1;
- /* Do nothing... This command is only used to test if the device is ready
- * to accept new commands */
- break;
- default:
- /* Should never be reached */
- usb_out_bytecount = 0;
- break;
- }
-
- /* Update EP2 Bulk-IN data byte count */
- payload_index_in += usb_in_bytecount;
-
- /* Determine if this was the last command */
- if ((cmd_id_index + usb_out_bytecount + 1) >= OUT2BC)
- return true;
- else {
- /* Not the last command, update cmd_id_index */
- cmd_id_index += (usb_out_bytecount + 1);
- return false;
- }
-}
-
-/**
- * Forever wait for commands and execute them as they arrive.
- */
-void command_loop(void)
-{
- bool last_command;
-
- while (1) {
- cmd_id_index = 0;
- payload_index_in = 0;
-
- /* Wait until host sends EP2 Bulk-OUT packet */
- while (!EP2_out)
- ;
- EP2_out = 0;
-
- /* Turn on COM LED to indicate command execution */
- SET_COM_LED();
-
- /* Execute the commands */
- last_command = false;
- while (last_command == false)
- last_command = execute_command();
-
- CLEAR_COM_LED();
-
- /* Send back EP2 Bulk-IN packet if required */
- if (payload_index_in > 0) {
- IN2BC = payload_index_in;
- while (!EP2_in)
- ;
- EP2_in = 0;
- }
-
- /* Re-arm EP2-OUT after command execution */
- OUT2BC = 0;
- }
-}
diff --git a/src/jtag/drivers/OpenULINK/src/usb.c b/src/jtag/drivers/OpenULINK/src/usb.c
deleted file mode 100644
index fb77f64..0000000
--- a/src/jtag/drivers/OpenULINK/src/usb.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011-2013 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/**
- * @file
- * Defines USB descriptors, interrupt routines and helper functions.
- * To minimize code size, we make the following assumptions:
- * - The OpenULINK has exactly one configuration
- * - and exactly one alternate setting
- *
- * Therefore, we do not have to support the Set Configuration USB request.
- */
-
-#include "usb.h"
-#include "delay.h"
-#include "io.h"
-
-/* Also update external declarations in "include/usb.h" if making changes to
- * these variables! */
-volatile bool EP2_out;
-volatile bool EP2_in;
-
-volatile __xdata __at 0x7FE8 struct setup_data setup_data;
-
-/* Define number of endpoints (except Control Endpoint 0) in a central place.
- * Be sure to include the neccessary endpoint descriptors! */
-#define NUM_ENDPOINTS 2
-
-__code struct usb_device_descriptor device_descriptor = {
- .bLength = sizeof(struct usb_device_descriptor),
- .bDescriptorType = DESCRIPTOR_TYPE_DEVICE,
- .bcdUSB = 0x0110, /* BCD: 01.00 (Version 1.0 USB spec) */
- .bDeviceClass = 0xFF, /* 0xFF = vendor-specific */
- .bDeviceSubClass = 0xFF,
- .bDeviceProtocol = 0xFF,
- .bMaxPacketSize0 = 64,
- .idVendor = 0xC251,
- .idProduct = 0x2710,
- .bcdDevice = 0x0100,
- .iManufacturer = 1,
- .iProduct = 2,
- .iSerialNumber = 3,
- .bNumConfigurations = 1
-};
-
-/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
-
-__code struct usb_config_descriptor config_descriptor = {
- .bLength = sizeof(struct usb_config_descriptor),
- .bDescriptorType = DESCRIPTOR_TYPE_CONFIGURATION,
- .wTotalLength = sizeof(struct usb_config_descriptor) +
- sizeof(struct usb_interface_descriptor) +
- (NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
- .bNumInterfaces = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 4, /* String describing this configuration */
- .bmAttributes = 0x80, /* Only MSB set according to USB spec */
- .MaxPower = 50 /* 100 mA */
-};
-
-__code struct usb_interface_descriptor interface_descriptor00 = {
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = DESCRIPTOR_TYPE_INTERFACE,
- .bInterfaceNumber = 0,
- .bAlternateSetting = 0,
- .bNumEndpoints = NUM_ENDPOINTS,
- .bInterfaceClass = 0xFF,
- .bInterfaceSubclass = 0xFF,
- .bInterfaceProtocol = 0xFF,
- .iInterface = 0
-};
-
-__code struct usb_endpoint_descriptor Bulk_EP2_IN_Endpoint_Descriptor = {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = 0x05,
- .bEndpointAddress = (2 | USB_DIR_IN),
- .bmAttributes = 0x02,
- .wMaxPacketSize = 64,
- .bInterval = 0
-};
-
-__code struct usb_endpoint_descriptor Bulk_EP2_OUT_Endpoint_Descriptor = {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = 0x05,
- .bEndpointAddress = (2 | USB_DIR_OUT),
- .bmAttributes = 0x02,
- .wMaxPacketSize = 64,
- .bInterval = 0
-};
-
-__code struct usb_language_descriptor language_descriptor = {
- .bLength = 4,
- .bDescriptorType = DESCRIPTOR_TYPE_STRING,
- .wLANGID = {0x0409 /* US English */}
-};
-
-__code struct usb_string_descriptor strManufacturer =
- STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
-
-__code struct usb_string_descriptor strProduct =
- STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
-
-__code struct usb_string_descriptor strSerialNumber =
- STR_DESCR(6, '0', '0', '0', '0', '0', '1');
-
-__code struct usb_string_descriptor strConfigDescr =
- STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
-
-/* Table containing pointers to string descriptors */
-__code struct usb_string_descriptor *__code en_string_descriptors[4] = {
- &strManufacturer,
- &strProduct,
- &strSerialNumber,
- &strConfigDescr
-};
-
-void sudav_isr(void) __interrupt SUDAV_ISR
-{
- CLEAR_IRQ();
-
- usb_handle_setup_data();
-
- USBIRQ = SUDAVIR;
- EP0CS |= HSNAK;
-}
-
-void sof_isr(void) __interrupt SOF_ISR
-{
-}
-void sutok_isr(void) __interrupt SUTOK_ISR
-{
-}
-void suspend_isr(void) __interrupt SUSPEND_ISR
-{
-}
-void usbreset_isr(void) __interrupt USBRESET_ISR
-{
-}
-void ibn_isr(void) __interrupt IBN_ISR
-{
-}
-
-void ep0in_isr(void) __interrupt EP0IN_ISR
-{
-}
-void ep0out_isr(void) __interrupt EP0OUT_ISR
-{
-}
-void ep1in_isr(void) __interrupt EP1IN_ISR
-{
-}
-void ep1out_isr(void) __interrupt EP1OUT_ISR
-{
-}
-
-/**
- * EP2 IN: called after the transfer from uC->Host has finished: we sent data
- */
-void ep2in_isr(void) __interrupt EP2IN_ISR
-{
- EP2_in = 1;
-
- CLEAR_IRQ();
- IN07IRQ = IN2IR;/* Clear OUT2 IRQ */
-}
-
-/**
- * EP2 OUT: called after the transfer from Host->uC has finished: we got data
- */
-void ep2out_isr(void) __interrupt EP2OUT_ISR
-{
- EP2_out = 1;
-
- CLEAR_IRQ();
- OUT07IRQ = OUT2IR; /* Clear OUT2 IRQ */
-}
-
-void ep3in_isr(void) __interrupt EP3IN_ISR
-{
-}
-void ep3out_isr(void) __interrupt EP3OUT_ISR
-{
-}
-void ep4in_isr(void) __interrupt EP4IN_ISR
-{
-}
-void ep4out_isr(void) __interrupt EP4OUT_ISR
-{
-}
-void ep5in_isr(void) __interrupt EP5IN_ISR
-{
-}
-void ep5out_isr(void) __interrupt EP5OUT_ISR
-{
-}
-void ep6in_isr(void) __interrupt EP6IN_ISR
-{
-}
-void ep6out_isr(void) __interrupt EP6OUT_ISR
-{
-}
-void ep7in_isr(void) __interrupt EP7IN_ISR
-{
-}
-void ep7out_isr(void) __interrupt EP7OUT_ISR
-{
-}
-
-/**
- * Return the control/status register for an endpoint
- *
- * @param ep endpoint address
- * @return on success: pointer to Control & Status register for endpoint
- * specified in \a ep
- * @return on failure: NULL
- */
-__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
-{
- /* Mask direction bit */
- uint8_t ep_num = ep & 0x7F;
-
- switch (ep_num) {
- case 0:
- return &EP0CS;
- break;
- case 1:
- return ep & 0x80 ? &IN1CS : &OUT1CS;
- break;
- case 2:
- return ep & 0x80 ? &IN2CS : &OUT2CS;
- break;
- case 3:
- return ep & 0x80 ? &IN3CS : &OUT3CS;
- break;
- case 4:
- return ep & 0x80 ? &IN4CS : &OUT4CS;
- break;
- case 5:
- return ep & 0x80 ? &IN5CS : &OUT5CS;
- break;
- case 6:
- return ep & 0x80 ? &IN6CS : &OUT6CS;
- break;
- case 7:
- return ep & 0x80 ? &IN7CS : &OUT7CS;
- break;
- }
-
- return NULL;
-}
-
-void usb_reset_data_toggle(uint8_t ep)
-{
- /* TOGCTL register:
- +----+-----+-----+------+-----+-------+-------+-------+
- | Q | S | R | IO | 0 | EP2 | EP1 | EP0 |
- +----+-----+-----+------+-----+-------+-------+-------+
-
- To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
- to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
- separate write cycle, the R bit needs to be set.
- */
- uint8_t togctl_value = (ep & 0x80 >> 3) | (ep & 0x7);
-
- /* First step: Write EP number and direction bit */
- TOGCTL = togctl_value;
-
- /* Second step: Set R bit */
- togctl_value |= TOG_R;
- TOGCTL = togctl_value;
-}
-
-/**
- * Handle GET_STATUS request.
- *
- * @return on success: true
- * @return on failure: false
- */
-bool usb_handle_get_status(void)
-{
- uint8_t *ep_cs;
-
- switch (setup_data.bmRequestType) {
- case GS_DEVICE:
- /* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
- * Byte 1: reserved, reset to zero */
- IN0BUF[0] = 0;
- IN0BUF[1] = 0;
-
- /* Send response */
- IN0BC = 2;
- break;
- case GS_INTERFACE:
- /* Always return two zero bytes according to USB 1.1 spec, p. 191 */
- IN0BUF[0] = 0;
- IN0BUF[1] = 0;
-
- /* Send response */
- IN0BC = 2;
- break;
- case GS_ENDPOINT:
- /* Get stall bit for endpoint specified in low byte of wIndex */
- ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex & 0xff);
-
- if (*ep_cs & EPSTALL)
- IN0BUF[0] = 0x01;
- else
- IN0BUF[0] = 0x00;
-
- /* Second byte sent has to be always zero */
- IN0BUF[1] = 0;
-
- /* Send response */
- IN0BC = 2;
- break;
- default:
- return false;
- break;
- }
-
- return true;
-}
-
-/**
- * Handle CLEAR_FEATURE request.
- *
- * @return on success: true
- * @return on failure: false
- */
-bool usb_handle_clear_feature(void)
-{
- __xdata uint8_t *ep_cs;
-
- switch (setup_data.bmRequestType) {
- case CF_DEVICE:
- /* Clear remote wakeup not supported: stall EP0 */
- STALL_EP0();
- break;
- case CF_ENDPOINT:
- if (setup_data.wValue == 0) {
- /* Unstall the endpoint specified in wIndex */
- ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
- if (!ep_cs)
- return false;
- *ep_cs &= ~EPSTALL;
- } else {
- /* Unsupported feature, stall EP0 */
- STALL_EP0();
- }
- break;
- default:
- /* Vendor commands... */
- }
-
- return true;
-}
-
-/**
- * Handle SET_FEATURE request.
- *
- * @return on success: true
- * @return on failure: false
- */
-bool usb_handle_set_feature(void)
-{
- __xdata uint8_t *ep_cs;
-
- switch (setup_data.bmRequestType) {
- case SF_DEVICE:
- if (setup_data.wValue == 2)
- return true;
- break;
- case SF_ENDPOINT:
- if (setup_data.wValue == 0) {
- /* Stall the endpoint specified in wIndex */
- ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
- if (!ep_cs)
- return false;
- *ep_cs |= EPSTALL;
- } else {
- /* Unsupported endpoint feature */
- return false;
- }
- break;
- default:
- /* Vendor commands... */
- break;
- }
-
- return true;
-}
-
-/**
- * Handle GET_DESCRIPTOR request.
- *
- * @return on success: true
- * @return on failure: false
- */
-bool usb_handle_get_descriptor(void)
-{
- __xdata uint8_t descriptor_type;
- __xdata uint8_t descriptor_index;
-
- descriptor_type = (setup_data.wValue & 0xff00) >> 8;
- descriptor_index = setup_data.wValue & 0x00ff;
-
- switch (descriptor_type) {
- case DESCRIPTOR_TYPE_DEVICE:
- SUDPTRH = HI8(&device_descriptor);
- SUDPTRL = LO8(&device_descriptor);
- break;
- case DESCRIPTOR_TYPE_CONFIGURATION:
- SUDPTRH = HI8(&config_descriptor);
- SUDPTRL = LO8(&config_descriptor);
- break;
- case DESCRIPTOR_TYPE_STRING:
- if (setup_data.wIndex == 0) {
- /* Supply language descriptor */
- SUDPTRH = HI8(&language_descriptor);
- SUDPTRL = LO8(&language_descriptor);
- } else if (setup_data.wIndex == 0x0409 /* US English */) {
- /* Supply string descriptor */
- SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
- SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
- } else
- return false;
- break;
- default:
- /* Unsupported descriptor type */
- return false;
- break;
- }
-
- return true;
-}
-
-/**
- * Handle SET_INTERFACE request.
- */
-void usb_handle_set_interface(void)
-{
- /* Reset Data Toggle */
- usb_reset_data_toggle(USB_DIR_IN | 2);
- usb_reset_data_toggle(USB_DIR_OUT | 2);
-
- /* Unstall & clear busy flag of all valid IN endpoints */
- IN2CS = 0 | EPBSY;
-
- /* Unstall all valid OUT endpoints, reset bytecounts */
- OUT2CS = 0;
- OUT2BC = 0;
-}
-
-/**
- * Handle the arrival of a USB Control Setup Packet.
- */
-void usb_handle_setup_data(void)
-{
- switch (setup_data.bRequest) {
- case GET_STATUS:
- if (!usb_handle_get_status())
- STALL_EP0();
- break;
- case CLEAR_FEATURE:
- if (!usb_handle_clear_feature())
- STALL_EP0();
- break;
- case 2: case 4:
- /* Reserved values */
- STALL_EP0();
- break;
- case SET_FEATURE:
- if (!usb_handle_set_feature())
- STALL_EP0();
- break;
- case SET_ADDRESS:
- /* Handled by USB core */
- break;
- case SET_DESCRIPTOR:
- /* Set Descriptor not supported. */
- STALL_EP0();
- break;
- case GET_DESCRIPTOR:
- if (!usb_handle_get_descriptor())
- STALL_EP0();
- break;
- case GET_CONFIGURATION:
- /* OpenULINK has only one configuration, return its index */
- IN0BUF[0] = config_descriptor.bConfigurationValue;
- IN0BC = 1;
- break;
- case SET_CONFIGURATION:
- /* OpenULINK has only one configuration -> nothing to do */
- break;
- case GET_INTERFACE:
- /* OpenULINK only has one interface, return its number */
- IN0BUF[0] = interface_descriptor00.bInterfaceNumber;
- IN0BC = 1;
- break;
- case SET_INTERFACE:
- usb_handle_set_interface();
- break;
- case SYNCH_FRAME:
- /* Isochronous endpoints not used -> nothing to do */
- break;
- default:
- /* Any other requests: do nothing */
- break;
- }
-}
-
-/**
- * USB initialization. Configures USB interrupts, endpoints and performs
- * ReNumeration.
- */
-void usb_init(void)
-{
- /* Mark endpoint 2 IN & OUT as valid */
- IN07VAL = IN2VAL;
- OUT07VAL = OUT2VAL;
-
- /* Make sure no isochronous endpoints are marked valid */
- INISOVAL = 0;
- OUTISOVAL = 0;
-
- /* Disable isochronous endpoints. This makes the isochronous data buffers
- * available as 8051 XDATA memory at address 0x2000 - 0x27FF */
- ISOCTL = ISODISAB;
-
- /* Enable USB Autovectoring */
- USBBAV |= AVEN;
-
- /* Enable SUDAV interrupt */
- USBIEN |= SUDAVIE;
-
- /* Enable EP2 OUT & IN interrupts */
- OUT07IEN = OUT2IEN;
- IN07IEN = IN2IEN;
-
- /* Enable USB interrupt (EIE register) */
- EUSB = 1;
-
- /* Perform ReNumeration */
- USBCS = DISCON | RENUM;
- delay_ms(200);
- USBCS = DISCOE | RENUM;
-}
diff --git a/src/jtag/drivers/OpenULINK/ulink_firmware.hex b/src/jtag/drivers/OpenULINK/ulink_firmware.hex
deleted file mode 100644
index efaea58..0000000
--- a/src/jtag/drivers/OpenULINK/ulink_firmware.hex
+++ /dev/null
@@ -1,347 +0,0 @@
-:040000000200713257
-:01000B0032C2
-:0100130032BA
-:01001B0032B2
-:0100230032AA
-:01002B0032A2
-:01003300329A
-:01003B003292
-:01004300328A
-:01004B003282
-:01005300327A
-:01005B003272
-:01006300326A
-:03006B000201107F
-:0300CA0002006EC3
-:03006E000201018B
-:1000CD00907F937404F0907F9C7495F0907F96745C
-:1000DD0090F0907F94E4F0907F9D747FF0907F97E7
-:1000ED00E4F0907F957440F0907F9E7442F0907F85
-:1000FD0098E4F0221200CD1204ADD2AF1208E090B8
-:10010D00000022C021C0E0C0F0C082C083C007C083
-:10011D0006C005C004C003C002C001C000C0D07538
-:10012D00D000AF9174EF5FF59112040C907FAB741A
-:10013D0001F0907FB4E04402F0D0D0D000D001D0D7
-:10014D0002D003D004D005D006D007D083D082D002
-:10015D00F0D0E0D02132323232323232323232C04D
-:10016D00E0C082C083C007C0D075D000D201AF916E
-:10017D0074EF5FF591907FA97404F0D0D0D007D0C3
-:10018D0083D082D0E032C0E0C082C083C007C0D02F
-:10019D0075D000D200AF9174EF5FF591907FAA7486
-:1001AD0004F0D0D0D007D083D082D0E032323232BA
-:1001BD0032323232323232AF82747F5FFE24F850E7
-:1001CD0003020278EE240A83F582EE240C83F58374
-:1001DD00E473EFF306192C3F52650101020202028E
-:1001ED000202907FB422EF30E7067DB67E7F800459
-:1001FD007DC67E7F8D828E8322EF30E7067DB87EB1
-:10020D007F80047DC87E7F8D828E8322EF30E7064E
-:10021D007DBA7E7F80047DCA7E7F8D828E8322EFA4
-:10022D0030E7067DBC7E7F80047DCC7E7F8D828E07
-:10023D008322EF30E7067DBE7E7F80047DCE7E7FFC
-:10024D008D828E8322EF30E7067DC07E7F80047D18
-:10025D00D07E7F8D828E8322EF30E7067EC27F7F38
-:10026D0080047ED27F7F8E828F832290000022AF0A
-:10027D008274105FFE74075F4206907FD7EEF074B4
-:10028D00204EF022907FE8E0C322907FE8E0FF60EF
-:10029D0005BF0246800A907FB4E0FF4401F0803A2A
-:1002AD00907FEAE0FEA3E0FF4E7027907FECE0FE2A
-:1002BD00A3E08E821201C4AE82AF83EE4F7002C3F3
-:1002CD00228E828F83E0FD5305FE8E828F83EDF0AB
-:1002DD008008907FB4E0FF4401F0D322907FE8E0E6
-:1002ED00FF6005BF02468010907FEAE0FEA3E0FFAD
-:1002FD00BE0239BF0036D322907FEAE0FEA3E0FFB5
-:10030D004E7027907FECE0FEA3E08E821201C4AE0A
-:10031D0082AF83EE4F7002C3228E828F83E0FD4346
-:10032D0005018E828F83EDF08002C322D322907F50
-:10033D00EAE0A3E0FF907FEAE0FDA3E07E00BF01CD
-:10034D0002800DBF02028021BF030280340203EC44
-:10035D007ED37F138F06907FD4EEF07ED37F137FF5
-:10036D0000907FD5EEF00203EE7EE57F138F0690B1
-:10037D007FD4EEF07EE57F137F00907FD5EEF08089
-:10038D0060907FECE0FEA3E0FF4E70187E057F14B9
-:10039D008F06907FD4EEF07E057F147F00907FD581
-:1003AD00EEF0803D907FECE0FEA3E0FFBE092EBF96
-:1003BD00042BED1475F002A42459F582741435F054
-:1003CD00F583E493FEA3E493FF8E048F058D0490D3
-:1003DD007FD4ECF07F00907FD5EEF08004C322C374
-:1003ED0022D32275828212027C75820212027C90C7
-:1003FD007FB87402F0907FC8E4F0907FC9F022902E
-:10040D007FE9E0FF24F3500122EFF5F0240B83F593
-:10041D0082E5F0241183F583E473414F5D655D72D0
-:10042D007B73889899A9AC0404040404040404049F
-:10043D0004040404120291500122907FB4E044019F
-:10044D00F022120297500122907FB4E04401F02275
-:10045D00907FB4E04401F0221202E94042907FB453
-:10046D00E04401F02222907FB4E04401F022120317
-:10047D003B402C907FB4E04401F0229013EAE493CA
-:10048D00907F00F0907FB57401F022229013F0E47C
-:10049D0093907F00F0907FB57401F0221203F0224B
-:1004AD00907FDE7404F0907FDF7404F0907FE0E4C1
-:1004BD00F0907FE1F0907FA17401F0907FAFE04468
-:1004CD0001F0907FAEE04401F0907FAD7404F090A8
-:1004DD007FAC7404F0D2E8907FD6740AF09000C817
-:0A04ED0012137C907FD67406F022F3
-:1013D30012011001FFFFFF4051C21027000101025B
-:1013E3000301090220000101048032090400000204
-:1013F300FFFFFF00070582024000000705020240CD
-:1014030000000403090414034F00700065006E001C
-:1014130055004C0049004E004B0014034F00700070
-:1014230065006E0055004C0049004E004B000E0352
-:101433003000300030003000300031001A034A0021
-:101443005400410047002000410064006100700027
-:0E14530074006500720009141D1431143F145A
-:1004F700E5080424C0F582E4347DF583E0FF30E1AC
-:1005070008907F96E0FE54EFF08F06EE30E00890FB
-:100517007F96E0FE547FF0EF30E308907F96E0FE91
-:100527004410F0EF30E208907F96E0FF4480F0221D
-:100537007F00E50824C0F582E4347DF583E0FE24DE
-:10054700D550030208A6EE240A83F582EE242F83F2
-:10055700F583E473B18AD7B0FAD3A6A6A6A6A6A652
-:10056700A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A624
-:10057700A6A6A6A621FA512A639CD5053493A205FF
-:1005870006050605060808080808080808080808F0
-:1005970008080808080808080808080808080806D6
-:1005A700060607070707080808087E05E508042464
-:1005B700C0F582E4347DF583E0FFE50804F5828524
-:1005C7000927C007C00612091DD006D0070208A8D0
-:1005D700E5080424C0F582E4347DF583E02405FEB4
-:1005E700E50804F582C007C006120BDED006D00767
-:1005F7000208A8E5080424C0F582E4347DF583E009
-:10060700FF2405FEE50804F58285093CC007C006FE
-:10061700120E79D006D0070208A87E02E508042446
-:10062700C0F582E4347DF583E0FD7402250824C01B
-:10063700F582E4347DF583E0F50A8D82C007C006B4
-:1006470012124AD006D0070208A87E02E508042441
-:10065700C0F582E4347DF583E0FC7D007402250853
-:1006670024C0F582E4347DF583E0FAE44204EA42EB
-:10067700058C828D83C007C0061211DDD006D00716
-:100687000208A87E05E5080424C0F582E4347DF558
-:1006970083E0FFE50804F58285092DC007C006122F
-:1006A7000A67D006D0070208A8E5080424C0F58227
-:1006B700E4347DF583E02405FEE50804F582C007F0
-:1006C700C006120D14D006D0070208A8E5080424B6
-:1006D700C0F582E4347DF583E0FF2405FEE50804D8
-:1006E700F582850943C007C006121013D006D0074C
-:1006F7000208A87E02E5080424C0F582E4347DF5EB
-:1007070083E0FB7402250824C0F582E4347DF58379
-:10071700E0F50A8B82C007C006121281D006D00707
-:100727000208A87E02E5080424C0F582E4347DF5BA
-:1007370083E0FC7D007402250824C0F582E4347D43
-:10074700F583E0FAE44204EA42058C828D83C00710
-:10075700C006121207D006D0070208A87E02E508D5
-:100767000424C0F582E4347DF583E0FC7D00740247
-:10077700250824C0F582E4347DF583E0FAE44204D9
-:10078700EA42058C828D83C007C006121349D00642
-:10079700D0070208A87E02E5080424C0F582E434E5
-:1007A7007DF583E0FC7D007402250824C0F582E412
-:1007B700347DF583E0FAE44204EA42058C828D83B6
-:1007C700C007C00612137CD006D0070208A87E0017
-:1007D7007F02C007C0061212CEAC82AD83D006D00E
-:1007E7000785098275837E8D03EBF0E509042400F4
-:1007F700F582E4347EF5837D00ECF00208A87E02E2
-:10080700E5080424C0F582E4347DF583E0FD740235
-:10081700250824C0F582E4347DF583E0F50A8D824E
-:10082700C007C006121311D006D00780747E05E5F5
-:10083700080424C0F582E4347DF583E0FD740225C5
-:100847000824C0F582E4347DF583E0F50A740325B6
-:100857000824C0F582E4347DF583E0F50B740425A4
-:100867000824C0F582E4347DF583E0F50C74052592
-:100877000824C0F582E4347DF583E0F50D8D82C050
-:1008870007C006121329D006D00780157E01C007BE
-:10089700C0061204F7D006D00780067E0180027ECC
-:1008A70000EF2509F509AD087F008E037C00EB2DCD
-:1008B700FDEC3FFF0DBD00010F907FC9E0FC7B0001
-:1008C700C3ED9CEF64808BF063F08095F04002D31A
-:1008D70022EE042508F508C32275080075090010E3
-:1008E700000280FB907F96E0FF547FF0C202200257
-:1008F70007120537920280F6907F96E0FF4480F05A
-:10090700E509600B907FB9E509F010010280FB90C3
-:100917007FC9E4F080C3E582FF24C0F582E4347D1B
-:10092700F583E0F528EF0424C0F582E4347DF583F0
-:10093700E0F52974022FFC24C0F582E4347DF583A9
-:10094700E0C4540FFB53030FEC24C0F582E4347D5D
-:10095700F583E0FC740F5CF52A74032F24C0F5823D
-:10096700E4347DF583E0FA74042F24C0F582E4347F
-:100977007DF583E0F52BEB60078A0A8B8212124A1A
-:10098700907F97E0FB5303F874044BFA7900A8288B
-:100997007C0018B8FF011C89067F00C3EE98EF643E
-:1009A700808CF063F08095F050347F007E00907F5C
-:1009B70097EBF0EFC313FF907F97EAF0907F99E0F2
-:1009C700FC30E5034307800EBE080040E1E5272918
-:1009D7002400F582E4347EF583EFF00980B0892C9A
-:1009E7007F00AC2A7A00C3EA95295040A8297900EC
-:1009F70018B8FF01198A057E00EDB50011EEB501A3
-:100A07000DEC600A4303021CE52BC313F52B907F03
-:100A170097EBF0EFC313FF907F9774044BF0907F31
-:100A270099E0FE30E5034307800A80BAAD297E00CE
-:100A37007408C39DFDE49EFE8DF005F0EF8002C3B0
-:100A470013D5F0FBFFE527252C2400F582E4347E3F
-:100A5700F583EFF0EC6008852B0A8C8202124A229C
-:100A6700E582FF24C0F582E4347DF583E0F52EEFBF
-:100A77000424C0F582E4347DF583E0F52F74022F5A
-:100A8700FC24C0F582E4347DF583E0C4540FFB53A6
-:100A9700030FEC24C0F582E4347DF583E0FC740F8A
-:100AA7005CF53074032F24C0F582E4347DF583E0D0
-:100AB700FA74042F24C0F582E4347DF583E0F53120
-:100AC700EB60078A0A8B82121281907F97E0FB53B3
-:100AD70003F874044BFA753200A82E7C0018B8FF8F
-:100AE700011CA9327E00C3E998EE64808CF063F0A4
-:100AF7008095F0504C7E007C00907F97EBF079005A
-:100B0700C3E9952250030980F7EEC313FE907F9740
-:100B1700EAF07900C3E9952250030980F7907F999D
-:100B2700E0F930E5034306800CBC080040CBE52D17
-:100B370025322400F582E4347EF583EEF005328019
-:100B4700987E00AA307900C3E9952F5056A82F7CCC
-:100B57000018B8FF011C89057F00EDB50011EFB53E
-:100B6700040DEA600A4303021AE531C313F5319015
-:100B77007F97EBF07F00C3EF952250030F80F7EECE
-:100B8700C313FE907F9774044BF07F00C3EF952249
-:100B970050030F80F7907F99E0FF30E5034306800D
-:100BA7000980A4AD2F7F007408C39DFDE49FFF8DCE
-:100BB700F005F0EE8002C313D5F0FBFEE52D2532DC
-:100BC7002400F582E4347EF583EEF0EA600885318F
-:100BD7000A8A8202128122E582FF24C0F582E43468
-:100BE7007DF583E0F533EF0424C0F582E4347DF529
-:100BF70083E0F53474022FFC24C0F582E4347DF5DC
-:100C070083E0C4540FFB53030FEC24C0F582E43494
-:100C17007DF583E0FC740F5CF53574032F24C0F574
-:100C270082E4347DF583E0FA74042F24C0F582E46E
-:100C3700347DF583E0F536EB600B8A0A8B82C007BB
-:100C470012124AD007907F97E0FB5303F97A00A866
-:100C5700337C0018B8FF011C8A017E00C3E998EEB7
-:100C670064808CF063F08095F05039EF2A240524D6
-:100C7700C0F582E4347DF583E0FE7C00EE30E005CC
-:100C870043030180068B0174FE59FB907F97EBF0BD
-:100C9700EEC313FE907F9774044BF00CBC08004022
-:100CA700DB0A80ABEF2A240524C0F582E4347DF506
-:100CB70083E0FEAF357C00C3EC95345044EE30E062
-:100CC7000543030180068B0274FE5AFBA9347A00A0
-:100CD70019B9FF011A8C007D00E8B50111EDB502C5
-:100CE7000DEF600A4303021FE536C313F536907F05
-:100CF70097EBF0EEC313FE907F9774044BF00C80D4
-:100D0700B6EF600885360A8F8202124A22E582F51D
-:100D17003724C0F582E4347DF583E0F538E5370400
-:100D270024C0F582E4347DF583E0F5397402253774
-:100D3700FC24C0F582E4347DF583E0C4540FFB53F3
-:100D4700030FEC24C0F582E4347DF583E0FC740FD7
-:100D57005CF53A7403253724C0F582E4347DF583C6
-:100D6700E0FA7404253724C0F582E4347DF583E086
-:100D7700F53BEB60078A0A8B82121281907F97E01E
-:100D8700FB5303F97A00A8387C0018B8FF011C8AC6
-:100D9700067F00C3EE98EF64808CF063F08095F0D7
-:100DA7005050E5372A240524C0F582E4347DF583C5
-:100DB700E0FF7E00EF30E00543030180068B0474FB
-:100DC700FE5CFB907F97EBF07C00C3EC9523500310
-:100DD7000C80F7EFC313FF907F9774044BF07C00F0
-:100DE700C3EC952350030C80F70EBE080040C50ADC
-:100DF7008094E5372A240524C0F582E4347DF58301
-:100E0700E0FFAE3A7C00C3EC9539505AEF30E0056D
-:100E170043030180068B0274FE5AFBA8397A001837
-:100E2700B8FF011A8C017D00E9B50011EDB5020D7F
-:100E3700EE600A4303021EE53BC313F53B907F9721
-:100E4700EBF07D00C3ED952350030D80F7EFC3133F
-:100E5700FF907F9774044BF07D00C3ED95235003FB
-:100E67000D80F70C80A0EE6008853B0A8E82021287
-:100E77008122E582FF24C0F582E4347DF583E0F525
-:100E87003DEF0424C0F582E4347DF583E0F53E743C
-:100E9700022FFC24C0F582E4347DF583E0C4540FAF
-:100EA700FB53030FEC24C0F582E4347DF583E0FCAB
-:100EB700740F5CF53F74032F24C0F582E4347DF58D
-:100EC70083E0FA74042F24C0F582E4347DF583E0CF
-:100ED700F540EB600B8A0A8B82C00712124AD007D3
-:100EE700907F97E0FB5303F97A00A83D7C0018B880
-:100EF700FF011C8A017E00C3E998EE64808CF063D1
-:100F0700F08095F0505CEF2A240524C0F582E43484
-:100F17007DF583E0F5417C007900E54130E005434C
-:100F2700030180068B0074FE58FB907F97EBF0E57A
-:100F370041C313F541907F9774044BF0ECC313FC46
-:100F4700907F99E0F830E50343048009B908004031
-:100F5700C9E53C2A2400F582E4347EF583ECF00AE7
-:100F670080888A01EF2A240524C0F582E4347DF5C0
-:100F770083E0F5417C00AF3F754200C3E542953EF3
-:100F87005057E54130E00543030180068B0074FEAE
-:100F970058FBA83E7D0018B8FF011DAA427E00EA53
-:100FA700B50011EEB5050DEF600A4303021FE540DA
-:100FB700C313F540907F97EBF0E541C313F54190DC
-:100FC7007F9774044BF0ECC313FC907F99E0FE30DD
-:100FD700E503430480054280A2AD3E7E007408C34A
-:100FE7009DFDE49EFE8DF005F0EC8002C313D5F065
-:100FF700FBFCE53C292400F582E4347EF583ECF024
-:10100700EF600885400A8F8202124A22E582F54482
-:1010170024C0F582E4347DF583E0F545E5440424F6
-:10102700C0F582E4347DF583E0F54674022544FC7F
-:1010370024C0F582E4347DF583E0C4540FFB5303E9
-:101047000FEC24C0F582E4347DF583E0FC740F5C7B
-:10105700F5477403254424C0F582E4347DF583E025
-:10106700FA7404254424C0F582E4347DF583E0F561
-:1010770048EB60078A0A8B82121281907F97E0FB08
-:101087005303F97A00A8457C0018B8FF011C8A06AB
-:101097007F00C3EE98EF64808CF063F08095F0508A
-:1010A70074E5442A240524C0F582E4347DF583E001
-:1010B700F5497E007C00E54930E0054303018006E1
-:1010C7008B0074FE58FB907F97EBF07800C3E89590
-:1010D7002450030880F7E549C313F549907F9774B7
-:1010E700044BF07800C3E8952450030880F7EEC35B
-:1010F70013FE907F99E0F830E5034306800CBC08A7
-:101107000040B3E5432A2400F582E4347EF583EEFC
-:10111700F00A02108C8A04E5442A240524C0F582CB
-:10112700E4347DF583E0F5497E00AA47754A00C39C
-:10113700E54A9546506DE54930E0054303018006D1
-:101147008B0174FE59FBA9467D0019B9FF011DA843
-:101157004A7F00E8B50111EFB5050DEA600A4303C0
-:10116700021AE548C313F548907F97EBF07F00C359
-:10117700EF952450030F80F7E549C313F549907F96
-:101187009774044BF07F00C3EF952450030F80F74B
-:10119700EEC313FE907F99E0FF30E5034306800519
-:1011A7004A808CAD467F007408C39DFDE49FFF8D88
-:1011B700F005F0EE8002C313D5F0FBFEE5432C24C7
-:1011C70000F582E4347EF583EEF0EA600885480A8C
-:1011D7008A8202128122AE82AF83907F97E0FD530D
-:1011E70005FB74044DFC7A007B00C3EA9EEB9F501D
-:1011F7000E907F97EDF0ECF00ABA00EE0B80EB2231
-:10120700AE82AF83907F97E0FD5305FB74044DFCDE
-:101217007A007B00C3EA9EEB9F5027907F97EDF003
-:101227007900C3E9952550030980F7907F97ECF083
-:101237007900C3E9952550030980F70ABA00D50B51
-:1012470080D222AF82907F97E0FE5306FB7D00C3DA
-:10125700ED9F5025E50A30E00543060280068E041F
-:1012670074FD5CFE907F97EEF0E50AC313F50A90D4
-:101277007F9774044EF00D80D622AF82907F97E05F
-:10128700FE5306FB7D00C3ED9F503BE50A30E005AA
-:1012970043060280068E0474FD5CFE907F97EEF095
-:1012A7007C00C3EC952650030C80F7E50AC313F5C1
-:1012B7000A907F9774044EF07C00C3EC9526500388
-:1012C7000C80F70D80C0227F00907F99E0FE30E50B
-:1012D700027F01907F99E0FE30E603430702907F8B
-:1012E7009AE0FE30E703430704907F9BE0FE30E57A
-:1012F70003430708907F9AE0FE53067F8F05E4FFBC
-:10130700FCEE4FF582EC4DF58322E582547FF4FF26
-:10131700907F97E05FF0747F550AFF907F97E04FCB
-:10132700F022858222850A23850B24850C25850DCD
-:10133700262200227E567F021EBEFF011FEE4F703F
-:10134700F722750A05750B001213A6AE82AF837CD0
-:10135700007D00C3EC9EED9F501AC007C006C00574
-:10136700C004121339D004D005D006D0070CBC0036
-:10137700E20D80DF22AE82AF837C007D00C3EC9E4E
-:10138700ED9F501AC007C006C005C00412133BD01A
-:0F13970004D005D006D0070CBC00E20D80DF2289
-:03004300021B009D
-:101B0000020110000201630002016400020165008D
-:101B1000020166000201670002016800020169001B
-:101B200002016A0002016B0002016C0002019300D5
-:101B30000201BA000201BB000201BC000201BD00AB
-:101B40000201BE000201BF000201C0000201C1008B
-:081B50000201C2000201C30002
-:1013A6007A10E4FBFCE58225E0F582E58333F583DC
-:1013B600EB33FBEC33FCEB950AF5F0EC950B4006B2
-:0913C600FCABF0438201DADD22E8
-:0600A000E478FFF6D8FD34
-:10007E007900E94400601B7A009014617800759253
-:10008E0020E493F2A308B800020592D9F4DAF275CF
-:02009E0092FFCF
-:1000A6007800E84400600A7900759220E4F309D8E4
-:1000B600FC7800E84400600C7900902000E4F0A38E
-:0400C600D8FCD9FA8F
-:0D00710075814A1213CFE582600302006E14
-:0413CF007582002201
-:00000001FF
diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c
deleted file mode 100644
index 57c0ce6..0000000
--- a/src/jtag/drivers/amt_jtagaccel.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-
-#if PARPORT_USE_PPDEV == 1
-#include <linux/parport.h>
-#include <linux/ppdev.h>
-#include <sys/ioctl.h>
-#else /* not PARPORT_USE_PPDEV */
-#ifndef _WIN32
-#include <sys/io.h>
-#endif
-#endif
-
-#if PARPORT_USE_GIVEIO == 1
-#if IS_CYGWIN == 1
-#include <windows.h>
-#endif
-#endif
-
-/**
- * @file
- * Support the Amontec Chameleon POD with JTAG Accelerator support.
- * This is a parallel port JTAG adapter with a CPLD between the
- * parallel port and the JTAG connection. VHDL code running in the
- * CPLD significantly accelerates JTAG operations compared to the
- * bitbanging "Wiggler" style of most parallel port adapters.
- */
-
-/* configuration */
-static uint16_t amt_jtagaccel_port;
-
-/* interface variables
- */
-static uint8_t aw_control_rst;
-static uint8_t aw_control_fsm = 0x10;
-static uint8_t aw_control_baudrate = 0x20;
-
-static int rtck_enabled;
-
-#if PARPORT_USE_PPDEV == 1
-static int device_handle;
-
-static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
-
-/* FIXME do something sane when these ioctl/read/write calls fail. */
-
-#define AMT_AW(val) \
- do { \
- int __retval; \
- \
- __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
- assert(__retval >= 0); \
- __retval = write(device_handle, &val, 1); \
- assert(__retval >= 0); \
- } while (0)
-#define AMT_AR(val) \
- do { \
- int __retval; \
- \
- __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
- assert(__retval >= 0); \
- __retval = read(device_handle, &val, 1); \
- assert(__retval >= 0); \
- } while (0)
-
-static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
-
-#define AMT_DW(val) \
- do { \
- int __retval; \
- \
- __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
- assert(__retval >= 0); \
- __retval = write(device_handle, &val, 1); \
- assert(__retval >= 0); \
- } while (0)
-#define AMT_DR(val) \
- do { \
- int __retval; \
- \
- __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
- assert(__retval >= 0); \
- __retval = read(device_handle, &val, 1); \
- assert(__retval >= 0); \
- } while (0)
-
-#else
-
-#define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
-#define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
-#define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
-#define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
-
-#endif /* PARPORT_USE_PPDEV */
-
-/* tap_move[i][j]: tap movement command to go from state i to state j
- * 0: Test-Logic-Reset
- * 1: Run-Test/Idle
- * 2: Shift-DR
- * 3: Pause-DR
- * 4: Shift-IR
- * 5: Pause-IR
- */
-static const uint8_t amt_jtagaccel_tap_move[6][6][2] = {
- /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
- { {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} }, /* RESET */
- { {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} }, /* IDLE */
- { {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRSHIFT */
- { {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRPAUSE */
- { {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} }, /* IRSHIFT */
- { {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} }, /* IRPAUSE */
-};
-
-static void amt_jtagaccel_reset(int trst, int srst)
-{
- if (trst == 1)
- aw_control_rst |= 0x4;
- else if (trst == 0)
- aw_control_rst &= ~0x4;
-
- if (srst == 1)
- aw_control_rst |= 0x1;
- else if (srst == 0)
- aw_control_rst &= ~0x1;
-
- AMT_AW(aw_control_rst);
-}
-
-static int amt_jtagaccel_speed(int speed)
-{
- aw_control_baudrate &= 0xf0;
- aw_control_baudrate |= speed & 0x0f;
- AMT_AW(aw_control_baudrate);
-
- return ERROR_OK;
-}
-
-static void amt_jtagaccel_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-static void amt_wait_scan_busy(void)
-{
- int timeout = 4096;
- uint8_t ar_status;
-
- AMT_AR(ar_status);
- while (((ar_status) & 0x80) && (timeout-- > 0))
- AMT_AR(ar_status);
-
- if (ar_status & 0x80) {
- LOG_ERROR(
- "amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x",
- (rtck_enabled) ? "enabled" : "disabled",
- ar_status);
- exit(-1);
- }
-}
-
-static void amt_jtagaccel_state_move(void)
-{
- uint8_t aw_scan_tms_5;
- uint8_t tms_scan[2];
-
- tap_state_t cur_state = tap_get_state();
- tap_state_t end_state = tap_get_end_state();
-
- tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0];
- tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1];
-
- aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
- AMT_AW(aw_scan_tms_5);
- int jtag_speed = 0;
- int retval = jtag_get_speed(&jtag_speed);
- assert(retval == ERROR_OK);
- if (jtag_speed > 3 || rtck_enabled)
- amt_wait_scan_busy();
-
- if (tms_scan[0] & 0x80) {
- aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
- AMT_AW(aw_scan_tms_5);
- if (jtag_speed > 3 || rtck_enabled)
- amt_wait_scan_busy();
- }
-
- tap_set_state(end_state);
-}
-
-static void amt_jtagaccel_runtest(int num_cycles)
-{
- int i = 0;
- uint8_t aw_scan_tms_5;
- uint8_t aw_scan_tms_1to4;
-
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- amt_jtagaccel_end_state(TAP_IDLE);
- amt_jtagaccel_state_move();
- }
-
- while (num_cycles - i >= 5) {
- aw_scan_tms_5 = 0x40;
- AMT_AW(aw_scan_tms_5);
- i += 5;
- }
-
- if (num_cycles - i > 0) {
- aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
- AMT_AW(aw_scan_tms_1to4);
- }
-
- amt_jtagaccel_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- amt_jtagaccel_state_move();
-}
-
-static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
-{
- int bits_left = scan_size;
- int bit_count = 0;
- tap_state_t saved_end_state = tap_get_end_state();
- uint8_t aw_tdi_option;
- uint8_t dw_tdi_scan;
- uint8_t dr_tdo;
- uint8_t aw_tms_scan;
- uint8_t tms_scan[2];
- int jtag_speed_var;
- int retval = jtag_get_speed(&jtag_speed_var);
- assert(retval == ERROR_OK);
-
- if (ir_scan)
- amt_jtagaccel_end_state(TAP_IRSHIFT);
- else
- amt_jtagaccel_end_state(TAP_DRSHIFT);
-
- /* Only move if we're not already there */
- if (tap_get_state() != tap_get_end_state())
- amt_jtagaccel_state_move();
-
- amt_jtagaccel_end_state(saved_end_state);
-
- /* handle unaligned bits at the beginning */
- if ((scan_size - 1) % 8) {
- aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
- AMT_AW(aw_tdi_option);
-
- dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
- AMT_DW(dw_tdi_scan);
- if (jtag_speed_var > 3 || rtck_enabled)
- amt_wait_scan_busy();
-
- if ((type == SCAN_IN) || (type == SCAN_IO)) {
- AMT_DR(dr_tdo);
- dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
- buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
- }
-
- bit_count += (scan_size - 1) % 8;
- bits_left -= (scan_size - 1) % 8;
- }
-
- while (bits_left - 1 >= 8) {
- dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
- AMT_DW(dw_tdi_scan);
- if (jtag_speed_var > 3 || rtck_enabled)
- amt_wait_scan_busy();
-
- if ((type == SCAN_IN) || (type == SCAN_IO)) {
- AMT_DR(dr_tdo);
- buf_set_u32(buffer, bit_count, 8, dr_tdo);
- }
-
- bit_count += 8;
- bits_left -= 8;
- }
-
- tms_scan[0] =
- amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
- tms_scan[1] =
- amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
- aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
- AMT_AW(aw_tms_scan);
- if (jtag_speed_var > 3 || rtck_enabled)
- amt_wait_scan_busy();
-
- if ((type == SCAN_IN) || (type == SCAN_IO)) {
- AMT_DR(dr_tdo);
- dr_tdo = dr_tdo >> 7;
- buf_set_u32(buffer, bit_count, 1, dr_tdo);
- }
-
- if (tms_scan[0] & 0x80) {
- aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
- AMT_AW(aw_tms_scan);
- if (jtag_speed_var > 3 || rtck_enabled)
- amt_wait_scan_busy();
- }
- tap_set_state(tap_get_end_state());
-}
-
-static int amt_jtagaccel_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
- int retval;
-
- /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
- * that wasn't handled by a caller-provided error handler
- */
- retval = ERROR_OK;
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-#endif
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
-#endif
- amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
- amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
- break;
- case JTAG_TLR_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
-#endif
- amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
- amt_jtagaccel_state_move();
- break;
- case JTAG_SCAN:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
-#endif
- amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- if (buffer)
- free(buffer);
- break;
- case JTAG_SLEEP:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
-#endif
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
- cmd = cmd->next;
- }
-
- return retval;
-}
-
-#if PARPORT_USE_GIVEIO == 1
-int amt_jtagaccel_get_giveio_access(void)
-{
- HANDLE h;
- OSVERSIONINFO version;
-
- version.dwOSVersionInfoSize = sizeof version;
- if (!GetVersionEx(&version)) {
- errno = EINVAL;
- return -1;
- }
- if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
- return 0;
-
- h = CreateFile("\\\\.\\giveio",
- GENERIC_READ,
- 0,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if (h == INVALID_HANDLE_VALUE) {
- errno = ENODEV;
- return -1;
- }
-
- CloseHandle(h);
-
- return 0;
-}
-#endif
-
-static int amt_jtagaccel_init(void)
-{
-#if PARPORT_USE_PPDEV == 1
- char buffer[256];
- int i = 0;
- uint8_t control_port;
-#else
- uint8_t status_port;
-#endif
- uint8_t ar_status;
-
-#if PARPORT_USE_PPDEV == 1
- if (device_handle > 0) {
- LOG_ERROR("device is already opened");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
- device_handle = open(buffer, O_RDWR);
-
- if (device_handle < 0) {
- LOG_ERROR(
- "cannot open device. check it exists and that user read and write rights are set");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- i = ioctl(device_handle, PPCLAIM);
- if (i < 0) {
- LOG_ERROR("cannot claim device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- i = IEEE1284_MODE_EPP;
- i = ioctl(device_handle, PPSETMODE, &i);
- if (i < 0) {
- LOG_ERROR(" cannot set compatible mode to device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- control_port = 0x00;
- i = ioctl(device_handle, PPWCONTROL, &control_port);
-
- control_port = 0x04;
- i = ioctl(device_handle, PPWCONTROL, &control_port);
-
-#else
- if (amt_jtagaccel_port == 0) {
- amt_jtagaccel_port = 0x378;
- LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
- }
-
-#if PARPORT_USE_GIVEIO == 1
- if (amt_jtagaccel_get_giveio_access() != 0) {
-#else /* PARPORT_USE_GIVEIO */
- if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
-#endif /* PARPORT_USE_GIVEIO */
- LOG_ERROR("missing privileges for direct i/o");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- /* prepare epp port
- * clear timeout */
- status_port = inb(amt_jtagaccel_port + 1);
- outb(status_port | 0x1, amt_jtagaccel_port + 1);
-
- /* reset epp port */
- outb(0x00, amt_jtagaccel_port + 2);
- outb(0x04, amt_jtagaccel_port + 2);
-#endif
-
- if (rtck_enabled) {
- /* set RTCK enable bit */
- aw_control_fsm |= 0x02;
- }
-
- /* enable JTAG port */
- aw_control_fsm |= 0x04;
- AMT_AW(aw_control_fsm);
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- aw_control_rst &= ~0x8;
- else
- aw_control_rst |= 0x8;
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- aw_control_rst &= ~0x2;
- else
- aw_control_rst |= 0x2;
-
- amt_jtagaccel_reset(0, 0);
-
- /* read status register */
- AMT_AR(ar_status);
- LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
-
- return ERROR_OK;
-}
-
-static int amt_jtagaccel_quit(void)
-{
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command)
-{
- if (CMD_ARGC == 1) {
- /* only if the port wasn't overwritten by cmdline */
- if (amt_jtagaccel_port == 0) {
- uint16_t port;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
- amt_jtagaccel_port = port;
- } else {
- LOG_ERROR("The parport port was already configured!");
- return ERROR_FAIL;
- }
- }
-
- command_print(CMD_CTX, "parport port = %u", amt_jtagaccel_port);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command)
-{
- if (CMD_ARGC == 0) {
- command_print(CMD_CTX,
- "amt_jtagaccel RTCK feature %s",
- (rtck_enabled) ? "enabled" : "disabled");
- return ERROR_OK;
- } else {
- if (strcmp(CMD_ARGV[0], "enabled") == 0)
- rtck_enabled = 1;
- else
- rtck_enabled = 0;
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration amtjtagaccel_command_handlers[] = {
- {
- .name = "parport_port",
- .handler = &amt_jtagaccel_handle_parport_port_command,
- .mode = COMMAND_CONFIG,
- .help = "configure or display the parallel port to use",
- .usage = "[port_num]",
- },
- {
- /**
- * @todo Remove this "rtck" command; just use the standard
- * mechanism to enable/disable adaptive clocking. First
- * implement the standard mechanism and deprecate "rtck";
- * after a year or so, it'll be safe to remove this.
- */
- .name = "rtck",
- .handler = &amt_jtagaccel_handle_rtck_command,
- .mode = COMMAND_CONFIG,
- .help = "configure or display RTCK support",
- .usage = "[enable|disable]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface amt_jtagaccel_interface = {
- .name = "amt_jtagaccel",
- .commands = amtjtagaccel_command_handlers,
-
- .init = amt_jtagaccel_init,
- .quit = amt_jtagaccel_quit,
- .speed = amt_jtagaccel_speed,
- .execute_queue = amt_jtagaccel_execute_queue,
-};
diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c
deleted file mode 100644
index d9ea367..0000000
--- a/src/jtag/drivers/arm-jtag-ew.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Dimitar Dimitrov <dinuxbg@gmail.com> *
- * based on Dominic Rath's and Benedikt Sauter's usbprog.c *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <usb.h>
-#include "usb_common.h"
-
-#define USB_VID 0x15ba
-#define USB_PID 0x001e
-
-#define ARMJTAGEW_EPT_BULK_OUT 0x01u
-#define ARMJTAGEW_EPT_BULK_IN 0x82u
-
-#define ARMJTAGEW_USB_TIMEOUT 2000
-
-#define ARMJTAGEW_IN_BUFFER_SIZE (4*1024)
-#define ARMJTAGEW_OUT_BUFFER_SIZE (4*1024)
-
-/* USB command request codes. */
-#define CMD_GET_VERSION 0x00
-#define CMD_SELECT_DPIMPL 0x10
-#define CMD_SET_TCK_FREQUENCY 0x11
-#define CMD_GET_TCK_FREQUENCY 0x12
-#define CMD_MEASURE_MAX_TCK_FREQ 0x15
-#define CMD_MEASURE_RTCK_RESPONSE 0x16
-#define CMD_TAP_SHIFT 0x17
-#define CMD_SET_TAPHW_STATE 0x20
-#define CMD_GET_TAPHW_STATE 0x21
-#define CMD_TGPWR_SETUP 0x22
-
-/* Global USB buffers */
-static uint8_t usb_in_buffer[ARMJTAGEW_IN_BUFFER_SIZE];
-static uint8_t usb_out_buffer[ARMJTAGEW_OUT_BUFFER_SIZE];
-
-/* Queue command functions */
-static void armjtagew_end_state(tap_state_t state);
-static void armjtagew_state_move(void);
-static void armjtagew_path_move(int num_states, tap_state_t *path);
-static void armjtagew_runtest(int num_cycles);
-static void armjtagew_scan(bool ir_scan,
- enum scan_type type,
- uint8_t *buffer,
- int scan_size,
- struct scan_command *command);
-static void armjtagew_reset(int trst, int srst);
-/* static void armjtagew_simple_command(uint8_t command); */
-static int armjtagew_get_status(void);
-
-/* tap buffer functions */
-static void armjtagew_tap_init(void);
-static int armjtagew_tap_execute(void);
-static void armjtagew_tap_ensure_space(int scans, int bits);
-static void armjtagew_tap_append_step(int tms, int tdi);
-static void armjtagew_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command);
-
-/* ARM-JTAG-EW lowlevel functions */
-struct armjtagew {
- struct usb_dev_handle *usb_handle;
-};
-
-static struct armjtagew *armjtagew_usb_open(void);
-static void armjtagew_usb_close(struct armjtagew *armjtagew);
-static int armjtagew_usb_message(struct armjtagew *armjtagew, int out_length, int in_length);
-static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length);
-static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length);
-
-/* helper functions */
-static int armjtagew_get_version_info(void);
-
-#ifdef _DEBUG_USB_COMMS_
-static void armjtagew_debug_buffer(uint8_t *buffer, int length);
-#endif
-
-static struct armjtagew *armjtagew_handle;
-
-/**************************************************************************
- * External interface implementation */
-
-static int armjtagew_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue;
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
-
- while (cmd != NULL) {
- switch (cmd->type) {
- case JTAG_RUNTEST:
- DEBUG_JTAG_IO("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles, \
- cmd->cmd.runtest->end_state);
-
- armjtagew_end_state(cmd->cmd.runtest->end_state);
- armjtagew_runtest(cmd->cmd.runtest->num_cycles);
- break;
-
- case JTAG_TLR_RESET:
- DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
-
- armjtagew_end_state(cmd->cmd.statemove->end_state);
- armjtagew_state_move();
- break;
-
- case JTAG_PATHMOVE:
- DEBUG_JTAG_IO("pathmove: %i states, end in %i", \
- cmd->cmd.pathmove->num_states, \
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-
- armjtagew_path_move(cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path);
- break;
-
- case JTAG_SCAN:
- DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state);
-
- armjtagew_end_state(cmd->cmd.scan->end_state);
-
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- DEBUG_JTAG_IO("scan input, length = %d", scan_size);
-
-#ifdef _DEBUG_USB_COMMS_
- armjtagew_debug_buffer(buffer, (scan_size + 7) / 8);
-#endif
- type = jtag_scan_type(cmd->cmd.scan);
- armjtagew_scan(cmd->cmd.scan->ir_scan,
- type, buffer,
- scan_size, cmd->cmd.scan);
- break;
-
- case JTAG_RESET:
- DEBUG_JTAG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-
- armjtagew_tap_execute();
-
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- armjtagew_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
-
- case JTAG_SLEEP:
- DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us);
- armjtagew_tap_execute();
- jtag_sleep(cmd->cmd.sleep->us);
- break;
-
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
- cmd = cmd->next;
- }
-
- return armjtagew_tap_execute();
-}
-
-/* Sets speed in kHz. */
-static int armjtagew_speed(int speed)
-{
- int result;
- int speed_real;
-
-
- usb_out_buffer[0] = CMD_SET_TCK_FREQUENCY;
- buf_set_u32(usb_out_buffer + 1, 0, 32, speed*1000);
-
- result = armjtagew_usb_message(armjtagew_handle, 5, 4);
-
- if (result < 0) {
- LOG_ERROR("ARM-JTAG-EW setting speed failed (%d)", result);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- usb_out_buffer[0] = CMD_GET_TCK_FREQUENCY;
- result = armjtagew_usb_message(armjtagew_handle, 1, 4);
- speed_real = (int)buf_get_u32(usb_in_buffer, 0, 32) / 1000;
- if (result < 0) {
- LOG_ERROR("ARM-JTAG-EW getting speed failed (%d)", result);
- return ERROR_JTAG_DEVICE_ERROR;
- } else
- LOG_INFO("Requested speed %dkHz, emulator reported %dkHz.", speed, speed_real);
-
- return ERROR_OK;
-}
-
-static int armjtagew_khz(int khz, int *jtag_speed)
-{
- *jtag_speed = khz;
-
- return ERROR_OK;
-}
-
-static int armjtagew_speed_div(int speed, int *khz)
-{
- *khz = speed;
-
- return ERROR_OK;
-}
-
-static int armjtagew_init(void)
-{
- int check_cnt;
-
- armjtagew_handle = armjtagew_usb_open();
-
- if (armjtagew_handle == 0) {
- LOG_ERROR(
- "Cannot find ARM-JTAG-EW Interface! Please check connection and permissions.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- check_cnt = 0;
- while (check_cnt < 3) {
- if (armjtagew_get_version_info() == ERROR_OK) {
- /* attempt to get status */
- armjtagew_get_status();
- break;
- }
-
- check_cnt++;
- }
-
- if (check_cnt == 3)
- LOG_INFO("ARM-JTAG-EW initial read failed, don't worry");
-
- /* Initial JTAG speed (for reset and initialization): 32 kHz */
- armjtagew_speed(32);
-
- LOG_INFO("ARM-JTAG-EW JTAG Interface ready");
-
- armjtagew_reset(0, 0);
- armjtagew_tap_init();
-
- return ERROR_OK;
-}
-
-static int armjtagew_quit(void)
-{
- armjtagew_usb_close(armjtagew_handle);
- return ERROR_OK;
-}
-
-/**************************************************************************
- * Queue command implementations */
-
-static void armjtagew_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-/* Goes to the end state. */
-static void armjtagew_state_move(void)
-{
- int i;
- int tms = 0;
- 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());
-
- for (i = 0; i < tms_count; i++) {
- tms = (tms_scan >> i) & 1;
- armjtagew_tap_append_step(tms, 0);
- }
-
- tap_set_state(tap_get_end_state());
-}
-
-static void armjtagew_path_move(int num_states, tap_state_t *path)
-{
- int i;
-
- for (i = 0; i < num_states; i++) {
- /*
- * TODO: The ARM-JTAG-EW hardware delays TDI with 3 TCK cycles when in RTCK mode.
- * Either handle that here, or update the documentation with examples
- * how to fix that in the configuration files.
- */
- if (path[i] == tap_state_transition(tap_get_state(), false))
- armjtagew_tap_append_step(0, 0);
- else if (path[i] == tap_state_transition(tap_get_state(), true))
- armjtagew_tap_append_step(1, 0);
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(tap_get_state()), tap_state_name(path[i]));
- exit(-1);
- }
-
- tap_set_state(path[i]);
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void armjtagew_runtest(int num_cycles)
-{
- int i;
-
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- armjtagew_end_state(TAP_IDLE);
- armjtagew_state_move();
- }
-
- /* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
- armjtagew_tap_append_step(0, 0);
-
- /* finish in end_state */
- armjtagew_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- armjtagew_state_move();
-}
-
-static void armjtagew_scan(bool ir_scan,
- enum scan_type type,
- uint8_t *buffer,
- int scan_size,
- struct scan_command *command)
-{
- tap_state_t saved_end_state;
-
- armjtagew_tap_ensure_space(1, scan_size + 8);
-
- saved_end_state = tap_get_end_state();
-
- /* Move to appropriate scan state */
- armjtagew_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
-
- /* Only move if we're not already there */
- if (tap_get_state() != tap_get_end_state())
- armjtagew_state_move();
-
- armjtagew_end_state(saved_end_state);
-
- /* Scan */
- armjtagew_tap_append_scan(scan_size, buffer, command);
-
- /* We are in Exit1, go to Pause */
- armjtagew_tap_append_step(0, 0);
-
- tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
-
- if (tap_get_state() != tap_get_end_state())
- armjtagew_state_move();
-}
-
-static void armjtagew_reset(int trst, int srst)
-{
- const uint8_t trst_mask = (1u << 5);
- const uint8_t srst_mask = (1u << 6);
- uint8_t val = 0;
- uint8_t outp_en = 0;
- uint8_t change_mask = 0;
- int result;
-
- LOG_DEBUG("trst: %i, srst: %i", trst, srst);
-
- if (srst == 0) {
- val |= srst_mask;
- outp_en &= ~srst_mask; /* tristate */
- change_mask |= srst_mask;
- } else if (srst == 1) {
- val &= ~srst_mask;
- outp_en |= srst_mask;
- change_mask |= srst_mask;
- }
-
- if (trst == 0) {
- val |= trst_mask;
- outp_en &= ~trst_mask; /* tristate */
- change_mask |= trst_mask;
- } else if (trst == 1) {
- val &= ~trst_mask;
- outp_en |= trst_mask;
- change_mask |= trst_mask;
- }
-
- usb_out_buffer[0] = CMD_SET_TAPHW_STATE;
- usb_out_buffer[1] = val;
- usb_out_buffer[2] = outp_en;
- usb_out_buffer[3] = change_mask;
- result = armjtagew_usb_write(armjtagew_handle, 4);
- if (result != 4)
- LOG_ERROR("ARM-JTAG-EW TRST/SRST pin set failed failed (%d)", result);
-}
-
-static int armjtagew_get_status(void)
-{
- int result;
-
- usb_out_buffer[0] = CMD_GET_TAPHW_STATE;
- result = armjtagew_usb_message(armjtagew_handle, 1, 12);
-
- if (result == 0) {
- unsigned int u_tg = buf_get_u32(usb_in_buffer, 0, 16);
- LOG_INFO(
- "U_tg = %d mV, U_aux = %d mV, U_tgpwr = %d mV, I_tgpwr = %d mA, D1 = %d, Target power %s %s",
- (int)(buf_get_u32(usb_in_buffer + 0, 0, 16)),
- (int)(buf_get_u32(usb_in_buffer + 2, 0, 16)),
- (int)(buf_get_u32(usb_in_buffer + 4, 0, 16)),
- (int)(buf_get_u32(usb_in_buffer + 6, 0, 16)),
- usb_in_buffer[9],
- usb_in_buffer[11] ? "OVERCURRENT" : "OK",
- usb_in_buffer[10] ? "enabled" : "disabled");
-
- if (u_tg < 1500)
- LOG_ERROR("Vref too low. Check Target Power");
- } else
- LOG_ERROR("ARM-JTAG-EW command CMD_GET_TAPHW_STATE failed (%d)", result);
-
- return ERROR_OK;
-}
-
-static int armjtagew_get_version_info(void)
-{
- int result;
- char sn[16];
- char auxinfo[257];
-
- /* query hardware version */
- usb_out_buffer[0] = CMD_GET_VERSION;
- result = armjtagew_usb_message(armjtagew_handle, 1, 4 + 15 + 256);
-
- if (result != 0) {
- LOG_ERROR("ARM-JTAG-EW command CMD_GET_VERSION failed (%d)", result);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- memcpy(sn, usb_in_buffer + 4, 15);
- sn[15] = '\0';
- memcpy(auxinfo, usb_in_buffer + 4+15, 256);
- auxinfo[256] = '\0';
-
- LOG_INFO(
- "ARM-JTAG-EW firmware version %d.%d, hardware revision %c, SN=%s, Additional info: %s", \
- usb_in_buffer[1],
- usb_in_buffer[0], \
- isgraph(usb_in_buffer[2]) ? usb_in_buffer[2] : 'X', \
- sn,
- auxinfo);
-
- if (1 != usb_in_buffer[1] || 6 != usb_in_buffer[0])
- LOG_WARNING(
- "ARM-JTAG-EW firmware version %d.%d is untested with this version of OpenOCD. You might experience unexpected behavior.",
- usb_in_buffer[1],
- usb_in_buffer[0]);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(armjtagew_handle_armjtagew_info_command)
-{
- if (armjtagew_get_version_info() == ERROR_OK) {
- /* attempt to get status */
- armjtagew_get_status();
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration armjtagew_command_handlers[] = {
- {
- .name = "armjtagew_info",
- .handler = &armjtagew_handle_armjtagew_info_command,
- .mode = COMMAND_EXEC,
- .help = "query armjtagew info",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface armjtagew_interface = {
- .name = "arm-jtag-ew",
- .commands = armjtagew_command_handlers,
- .transports = jtag_only,
- .execute_queue = armjtagew_execute_queue,
- .speed = armjtagew_speed,
- .speed_div = armjtagew_speed_div,
- .khz = armjtagew_khz,
- .init = armjtagew_init,
- .quit = armjtagew_quit,
-};
-
-/**************************************************************************
- * ARM-JTAG-EW tap functions */
-
-/* 2048 is the max value we can use here */
-#define ARMJTAGEW_TAP_BUFFER_SIZE 2048
-
-static int tap_length;
-static uint8_t tms_buffer[ARMJTAGEW_TAP_BUFFER_SIZE];
-static uint8_t tdi_buffer[ARMJTAGEW_TAP_BUFFER_SIZE];
-static uint8_t tdo_buffer[ARMJTAGEW_TAP_BUFFER_SIZE];
-
-struct pending_scan_result {
- int first; /* First bit position in tdo_buffer to read */
- int length; /* Number of bits to read */
- struct scan_command *command; /* Corresponding scan command */
- uint8_t *buffer;
-};
-
-#define MAX_PENDING_SCAN_RESULTS 256
-
-static int pending_scan_results_length;
-static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
-
-static int last_tms;
-
-static void armjtagew_tap_init(void)
-{
- tap_length = 0;
- pending_scan_results_length = 0;
-}
-
-static void armjtagew_tap_ensure_space(int scans, int bits)
-{
- int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length;
- int available_bits = ARMJTAGEW_TAP_BUFFER_SIZE * 8 - tap_length;
-
- if (scans > available_scans || bits > available_bits)
- armjtagew_tap_execute();
-}
-
-static void armjtagew_tap_append_step(int tms, int tdi)
-{
- last_tms = tms;
- int index_local = tap_length / 8;
-
- if (index_local < ARMJTAGEW_TAP_BUFFER_SIZE) {
- int bit_index = tap_length % 8;
- uint8_t bit = 1 << bit_index;
-
- if (tms)
- tms_buffer[index_local] |= bit;
- else
- tms_buffer[index_local] &= ~bit;
-
- if (tdi)
- tdi_buffer[index_local] |= bit;
- else
- tdi_buffer[index_local] &= ~bit;
-
- tap_length++;
- } else
- LOG_ERROR("armjtagew_tap_append_step, overflow");
-}
-
-void armjtagew_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command)
-{
- struct pending_scan_result *pending_scan_result =
- &pending_scan_results_buffer[pending_scan_results_length];
- int i;
-
- pending_scan_result->first = tap_length;
- pending_scan_result->length = length;
- pending_scan_result->command = command;
- pending_scan_result->buffer = buffer;
-
- for (i = 0; i < length; i++)
- armjtagew_tap_append_step((i < length-1 ? 0 : 1), (buffer[i/8] >> (i%8)) & 1);
- pending_scan_results_length++;
-}
-
-/* Pad and send a tap sequence to the device, and receive the answer.
- * For the purpose of padding we assume that we are in idle or pause state. */
-static int armjtagew_tap_execute(void)
-{
- int byte_length;
- int tms_offset;
- int tdi_offset;
- int i;
- int result;
-
- if (tap_length > 0) {
- /* Pad last byte so that tap_length is divisible by 8 */
- while (tap_length % 8 != 0) {
- /* More of the last TMS value keeps us in the same state,
- * analogous to free-running JTAG interfaces. */
- armjtagew_tap_append_step(last_tms, 0);
- }
-
- byte_length = tap_length / 8;
-
- usb_out_buffer[0] = CMD_TAP_SHIFT;
- buf_set_u32(usb_out_buffer + 1, 0, 16, byte_length);
-
- tms_offset = 3;
- for (i = 0; i < byte_length; i++)
- usb_out_buffer[tms_offset + i] = flip_u32(tms_buffer[i], 8);
-
- tdi_offset = tms_offset + byte_length;
- for (i = 0; i < byte_length; i++)
- usb_out_buffer[tdi_offset + i] = flip_u32(tdi_buffer[i], 8);
-
- result = armjtagew_usb_message(armjtagew_handle,
- 3 + 2 * byte_length,
- byte_length + 4);
-
- if (result == 0) {
- int stat_local;
-
- stat_local = (int)buf_get_u32(usb_in_buffer + byte_length, 0, 32);
- if (stat_local) {
- LOG_ERROR(
- "armjtagew_tap_execute, emulator returned error code %d for a CMD_TAP_SHIFT command",
- stat_local);
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- for (i = 0; i < byte_length; i++)
- tdo_buffer[i] = flip_u32(usb_in_buffer[i], 8);
-
- for (i = 0; i < pending_scan_results_length; i++) {
- struct pending_scan_result *pending_scan_result =
- &pending_scan_results_buffer[i];
- uint8_t *buffer = pending_scan_result->buffer;
- int length = pending_scan_result->length;
- int first = pending_scan_result->first;
- struct scan_command *command = pending_scan_result->command;
-
- /* Copy to buffer */
- buf_set_buf(tdo_buffer, first, buffer, 0, length);
-
- DEBUG_JTAG_IO("pending scan result, length = %d", length);
-
-#ifdef _DEBUG_USB_COMMS_
- armjtagew_debug_buffer(buffer, byte_length);
-#endif
-
- if (jtag_read_buffer(buffer, command) != ERROR_OK) {
- armjtagew_tap_init();
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- if (pending_scan_result->buffer != NULL)
- free(pending_scan_result->buffer);
- }
- } else {
- LOG_ERROR("armjtagew_tap_execute, wrong result %d, expected %d",
- result,
- byte_length);
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- armjtagew_tap_init();
- }
-
- return ERROR_OK;
-}
-
-/****************************************************************************
- * JLink USB low-level functions */
-
-static struct armjtagew *armjtagew_usb_open()
-{
- usb_init();
-
- const uint16_t vids[] = { USB_VID, 0 };
- const uint16_t pids[] = { USB_PID, 0 };
- struct usb_dev_handle *dev;
- if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
- return NULL;
-
- struct armjtagew *result = malloc(sizeof(struct armjtagew));
- result->usb_handle = dev;
-
-#if 0
- /* usb_set_configuration required under win32 */
- usb_set_configuration(dev, dev->config[0].bConfigurationValue);
-#endif
- usb_claim_interface(dev, 0);
-#if 0
- /*
- * This makes problems under Mac OS X. And is not needed
- * under Windows. Hopefully this will not break a linux build
- */
- usb_set_altinterface(dev, 0);
-#endif
- return result;
-}
-
-static void armjtagew_usb_close(struct armjtagew *armjtagew)
-{
- usb_close(armjtagew->usb_handle);
- free(armjtagew);
-}
-
-/* Send a message and receive the reply. */
-static int armjtagew_usb_message(struct armjtagew *armjtagew, int out_length, int in_length)
-{
- int result;
-
- result = armjtagew_usb_write(armjtagew, out_length);
- if (result == out_length) {
- result = armjtagew_usb_read(armjtagew, in_length);
- if (result != in_length) {
- LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)",
- in_length,
- result);
- return -1;
- }
- } else {
- LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result);
- return -1;
- }
- return 0;
-}
-
-/* Write data from out_buffer to USB. */
-static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
-{
- int result;
-
- if (out_length > ARMJTAGEW_OUT_BUFFER_SIZE) {
- LOG_ERROR("armjtagew_write illegal out_length=%d (max=%d)",
- out_length,
- ARMJTAGEW_OUT_BUFFER_SIZE);
- return -1;
- }
-
- result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT, \
- (char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT);
-
- DEBUG_JTAG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result);
-
-#ifdef _DEBUG_USB_COMMS_
- armjtagew_debug_buffer(usb_out_buffer, out_length);
-#endif
- return result;
-}
-
-/* Read data from USB into in_buffer. */
-static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length)
-{
- int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN, \
- (char *)usb_in_buffer, exp_in_length, ARMJTAGEW_USB_TIMEOUT);
-
- DEBUG_JTAG_IO("armjtagew_usb_read, result = %d", result);
-
-#ifdef _DEBUG_USB_COMMS_
- armjtagew_debug_buffer(usb_in_buffer, result);
-#endif
- return result;
-}
-
-#ifdef _DEBUG_USB_COMMS_
-#define BYTES_PER_LINE 16
-
-static void armjtagew_debug_buffer(uint8_t *buffer, int length)
-{
- char line[81];
- char s[4];
- int i;
- int j;
-
- for (i = 0; i < length; i += BYTES_PER_LINE) {
- snprintf(line, 5, "%04x", i);
- for (j = i; j < i + BYTES_PER_LINE && j < length; j++) {
- snprintf(s, 4, " %02x", buffer[j]);
- strcat(line, s);
- }
- LOG_DEBUG("%s", line);
-
- /* Prevent GDB timeout (writing to log might take some time) */
- keep_alive();
- }
-}
-#endif
diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c
deleted file mode 100644
index 8f65413..0000000
--- a/src/jtag/drivers/at91rm9200.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Anders Larsen *
- * al@alarsen.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include "bitbang.h"
-
-#include <sys/mman.h>
-
-/* AT91RM9200 */
-#define AT91C_BASE_SYS (0xfffff000)
-
-/* GPIO assignment */
-#define PIOA (0 << 7)
-#define PIOB (1 << 7)
-#define PIOC (2 << 7)
-#define PIOD (3 << 7)
-
-#define PIO_PER (0) /* PIO enable */
-#define PIO_OER (4) /* output enable */
-#define PIO_ODR (5) /* output disable */
-#define PIO_SODR (12) /* set output data */
-#define PIO_CODR (13) /* clear output data */
-#define PIO_PDSR (15) /* pin data status */
-#define PIO_PPUER (25) /* pull-up enable */
-
-#define NC (0) /* not connected */
-#define P0 (1 << 0)
-#define P1 (1 << 1)
-#define P2 (1 << 2)
-#define P3 (1 << 3)
-#define P4 (1 << 4)
-#define P5 (1 << 5)
-#define P6 (1 << 6)
-#define P7 (1 << 7)
-#define P8 (1 << 8)
-#define P9 (1 << 9)
-#define P10 (1 << 10)
-#define P11 (1 << 11)
-#define P12 (1 << 12)
-#define P13 (1 << 13)
-#define P14 (1 << 14)
-#define P15 (1 << 15)
-#define P16 (1 << 16)
-#define P17 (1 << 17)
-#define P18 (1 << 18)
-#define P19 (1 << 19)
-#define P20 (1 << 20)
-#define P21 (1 << 21)
-#define P22 (1 << 22)
-#define P23 (1 << 23)
-#define P24 (1 << 24)
-#define P25 (1 << 25)
-#define P26 (1 << 26)
-#define P27 (1 << 27)
-#define P28 (1 << 28)
-#define P29 (1 << 29)
-#define P30 (1 << 30)
-#define P31 (1 << 31)
-
-struct device_t {
- const char *name;
- int TDO_PIO; /* PIO holding TDO */
- uint32_t TDO_MASK; /* TDO bitmask */
- int TRST_PIO; /* PIO holding TRST */
- uint32_t TRST_MASK; /* TRST bitmask */
- int TMS_PIO; /* PIO holding TMS */
- uint32_t TMS_MASK; /* TMS bitmask */
- int TCK_PIO; /* PIO holding TCK */
- uint32_t TCK_MASK; /* TCK bitmask */
- int TDI_PIO; /* PIO holding TDI */
- uint32_t TDI_MASK; /* TDI bitmask */
- int SRST_PIO; /* PIO holding SRST */
- uint32_t SRST_MASK; /* SRST bitmask */
-};
-
-static const struct device_t devices[] = {
- { "rea_ecr", PIOD, P27, PIOA, NC, PIOD, P23, PIOD, P24, PIOD, P26, PIOC, P5 },
- { .name = NULL },
-};
-
-/* configuration */
-static char *at91rm9200_device;
-
-/* interface variables
- */
-static const struct device_t *device;
-static int dev_mem_fd;
-static void *sys_controller;
-static uint32_t *pio_base;
-
-/* low level command set
- */
-static int at91rm9200_read(void);
-static void at91rm9200_write(int tck, int tms, int tdi);
-static void at91rm9200_reset(int trst, int srst);
-
-static int at91rm9200_init(void);
-static int at91rm9200_quit(void);
-
-static struct bitbang_interface at91rm9200_bitbang = {
- .read = at91rm9200_read,
- .write = at91rm9200_write,
- .reset = at91rm9200_reset,
- .blink = 0
-};
-
-static int at91rm9200_read(void)
-{
- return (pio_base[device->TDO_PIO + PIO_PDSR] & device->TDO_MASK) != 0;
-}
-
-static void at91rm9200_write(int tck, int tms, int tdi)
-{
- if (tck)
- pio_base[device->TCK_PIO + PIO_SODR] = device->TCK_MASK;
- else
- pio_base[device->TCK_PIO + PIO_CODR] = device->TCK_MASK;
-
- if (tms)
- pio_base[device->TMS_PIO + PIO_SODR] = device->TMS_MASK;
- else
- pio_base[device->TMS_PIO + PIO_CODR] = device->TMS_MASK;
-
- if (tdi)
- pio_base[device->TDI_PIO + PIO_SODR] = device->TDI_MASK;
- else
- pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK;
-}
-
-/* (1) assert or (0) deassert reset lines */
-static void at91rm9200_reset(int trst, int srst)
-{
- if (trst == 0)
- pio_base[device->TRST_PIO + PIO_SODR] = device->TRST_MASK;
- else if (trst == 1)
- pio_base[device->TRST_PIO + PIO_CODR] = device->TRST_MASK;
-
- if (srst == 0)
- pio_base[device->SRST_PIO + PIO_SODR] = device->SRST_MASK;
- else if (srst == 1)
- pio_base[device->SRST_PIO + PIO_CODR] = device->SRST_MASK;
-}
-
-COMMAND_HANDLER(at91rm9200_handle_device_command)
-{
- if (CMD_ARGC == 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* only if the device name wasn't overwritten by cmdline */
- if (at91rm9200_device == 0) {
- at91rm9200_device = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
- strcpy(at91rm9200_device, CMD_ARGV[0]);
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration at91rm9200_command_handlers[] = {
- {
- .name = "at91rm9200_device",
- .handler = &at91rm9200_handle_device_command,
- .mode = COMMAND_CONFIG,
- .help = "query armjtagew info",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface at91rm9200_interface = {
- .name = "at91rm9200",
- .execute_queue = bitbang_execute_queue,
- .commands = at91rm9200_command_handlers,
- .init = at91rm9200_init,
- .quit = at91rm9200_quit,
-};
-
-static int at91rm9200_init(void)
-{
- const struct device_t *cur_device;
-
- cur_device = devices;
-
- if (at91rm9200_device == NULL || at91rm9200_device[0] == 0) {
- at91rm9200_device = "rea_ecr";
- LOG_WARNING("No at91rm9200 device specified, using default 'rea_ecr'");
- }
-
- while (cur_device->name) {
- if (strcmp(cur_device->name, at91rm9200_device) == 0) {
- device = cur_device;
- break;
- }
- cur_device++;
- }
-
- if (!device) {
- LOG_ERROR("No matching device found for %s", at91rm9200_device);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- bitbang_interface = &at91rm9200_bitbang;
-
- dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
- if (dev_mem_fd < 0) {
- perror("open");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- sys_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
- MAP_SHARED, dev_mem_fd, AT91C_BASE_SYS);
- if (sys_controller == MAP_FAILED) {
- perror("mmap");
- close(dev_mem_fd);
- return ERROR_JTAG_INIT_FAILED;
- }
- pio_base = (uint32_t *)sys_controller + 0x100;
-
- /*
- * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
- * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
- */
- pio_base[device->TDI_PIO + PIO_CODR] = device->TDI_MASK;
- pio_base[device->TDI_PIO + PIO_OER] = device->TDI_MASK;
- pio_base[device->TDI_PIO + PIO_PER] = device->TDI_MASK;
- pio_base[device->TCK_PIO + PIO_CODR] = device->TCK_MASK;
- pio_base[device->TCK_PIO + PIO_OER] = device->TCK_MASK;
- pio_base[device->TCK_PIO + PIO_PER] = device->TCK_MASK;
- pio_base[device->TMS_PIO + PIO_SODR] = device->TMS_MASK;
- pio_base[device->TMS_PIO + PIO_OER] = device->TMS_MASK;
- pio_base[device->TMS_PIO + PIO_PER] = device->TMS_MASK;
- pio_base[device->TRST_PIO + PIO_SODR] = device->TRST_MASK;
- pio_base[device->TRST_PIO + PIO_OER] = device->TRST_MASK;
- pio_base[device->TRST_PIO + PIO_PER] = device->TRST_MASK;
- pio_base[device->SRST_PIO + PIO_SODR] = device->SRST_MASK;
- pio_base[device->SRST_PIO + PIO_OER] = device->SRST_MASK;
- pio_base[device->SRST_PIO + PIO_PER] = device->SRST_MASK;
- pio_base[device->TDO_PIO + PIO_ODR] = device->TDO_MASK;
- pio_base[device->TDO_PIO + PIO_PPUER] = device->TDO_MASK;
- pio_base[device->TDO_PIO + PIO_PER] = device->TDO_MASK;
-
- return ERROR_OK;
-}
-
-static int at91rm9200_quit(void)
-{
-
- return ERROR_OK;
-}
diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
deleted file mode 100644
index 1622b22..0000000
--- a/src/jtag/drivers/bcm2835gpio.c
+++ /dev/null
@@ -1,531 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Paul Fertser, fercerpav@gmail.com *
- * *
- * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
- * Based on at91rm9200.c (c) Anders Larsen *
- * and RPi GPIO examples by Gert van Loo & Dom *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include "bitbang.h"
-
-#include <sys/mman.h>
-
-uint32_t bcm2835_peri_base = 0x20000000;
-#define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
-
-#define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
-#define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
-
-/* GPIO setup macros */
-#define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7)
-#define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0)
-#define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \
- INP_GPIO(g); \
- *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
-#define OUT_GPIO(g) SET_MODE_GPIO(g, 1)
-
-#define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */
-#define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
-#define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
-
-static int dev_mem_fd;
-static volatile uint32_t *pio_base;
-
-static int bcm2835gpio_read(void);
-static void bcm2835gpio_write(int tck, int tms, int tdi);
-static void bcm2835gpio_reset(int trst, int srst);
-
-static int bcm2835_swdio_read(void);
-static void bcm2835_swdio_drive(bool is_output);
-
-static int bcm2835gpio_init(void);
-static int bcm2835gpio_quit(void);
-
-static struct bitbang_interface bcm2835gpio_bitbang = {
- .read = bcm2835gpio_read,
- .write = bcm2835gpio_write,
- .reset = bcm2835gpio_reset,
- .swdio_read = bcm2835_swdio_read,
- .swdio_drive = bcm2835_swdio_drive,
- .blink = NULL
-};
-
-/* GPIO numbers for each signal. Negative values are invalid */
-static int tck_gpio = -1;
-static int tck_gpio_mode;
-static int tms_gpio = -1;
-static int tms_gpio_mode;
-static int tdi_gpio = -1;
-static int tdi_gpio_mode;
-static int tdo_gpio = -1;
-static int tdo_gpio_mode;
-static int trst_gpio = -1;
-static int trst_gpio_mode;
-static int srst_gpio = -1;
-static int srst_gpio_mode;
-static int swclk_gpio = -1;
-static int swclk_gpio_mode;
-static int swdio_gpio = -1;
-static int swdio_gpio_mode;
-
-/* Transition delay coefficients */
-static int speed_coeff = 113714;
-static int speed_offset = 28;
-static unsigned int jtag_delay;
-
-static int bcm2835gpio_read(void)
-{
- return !!(GPIO_LEV & 1<<tdo_gpio);
-}
-
-static void bcm2835gpio_write(int tck, int tms, int tdi)
-{
- uint32_t set = tck<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
- uint32_t clear = !tck<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
-
- GPIO_SET = set;
- GPIO_CLR = clear;
-
- for (unsigned int i = 0; i < jtag_delay; i++)
- asm volatile ("");
-}
-
-static void bcm2835gpio_swd_write(int tck, int tms, int tdi)
-{
- uint32_t set = tck<<swclk_gpio | tdi<<swdio_gpio;
- uint32_t clear = !tck<<swclk_gpio | !tdi<<swdio_gpio;
-
- GPIO_SET = set;
- GPIO_CLR = clear;
-
- for (unsigned int i = 0; i < jtag_delay; i++)
- asm volatile ("");
-}
-
-/* (1) assert or (0) deassert reset lines */
-static void bcm2835gpio_reset(int trst, int srst)
-{
- uint32_t set = 0;
- uint32_t clear = 0;
-
- if (trst_gpio > 0) {
- set |= !trst<<trst_gpio;
- clear |= trst<<trst_gpio;
- }
-
- if (srst_gpio > 0) {
- set |= !srst<<srst_gpio;
- clear |= srst<<srst_gpio;
- }
-
- GPIO_SET = set;
- GPIO_CLR = clear;
-}
-
-static void bcm2835_swdio_drive(bool is_output)
-{
- if (is_output)
- OUT_GPIO(swdio_gpio);
- else
- INP_GPIO(swdio_gpio);
-}
-
-static int bcm2835_swdio_read(void)
-{
- return !!(GPIO_LEV & 1 << swdio_gpio);
-}
-
-static int bcm2835gpio_khz(int khz, int *jtag_speed)
-{
- if (!khz) {
- LOG_DEBUG("RCLK not supported");
- return ERROR_FAIL;
- }
- *jtag_speed = speed_coeff/khz - speed_offset;
- if (*jtag_speed < 0)
- *jtag_speed = 0;
- return ERROR_OK;
-}
-
-static int bcm2835gpio_speed_div(int speed, int *khz)
-{
- *khz = speed_coeff/(speed + speed_offset);
- return ERROR_OK;
-}
-
-static int bcm2835gpio_speed(int speed)
-{
- jtag_delay = speed;
- return ERROR_OK;
-}
-
-static int is_gpio_valid(int gpio)
-{
- return gpio >= 0 && gpio <= 53;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionums)
-{
- if (CMD_ARGC == 4) {
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
- } else if (CMD_ARGC != 0) {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- command_print(CMD_CTX,
- "BCM2835 GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
- tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tck)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
-
- command_print(CMD_CTX, "BCM2835 GPIO config: tck = %d", tck_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tms)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
-
- command_print(CMD_CTX, "BCM2835 GPIO config: tms = %d", tms_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdo)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
-
- command_print(CMD_CTX, "BCM2835 GPIO config: tdo = %d", tdo_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdi)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
-
- command_print(CMD_CTX, "BCM2835 GPIO config: tdi = %d", tdi_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_srst)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
-
- command_print(CMD_CTX, "BCM2835 GPIO config: srst = %d", srst_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_trst)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
-
- command_print(CMD_CTX, "BCM2835 GPIO config: trst = %d", trst_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionums)
-{
- if (CMD_ARGC == 2) {
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
- } else if (CMD_ARGC != 0) {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- command_print(CMD_CTX,
- "BCM2835 GPIO nums: swclk = %d, swdio = %d",
- swclk_gpio, swdio_gpio);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swclk)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
-
- command_print(CMD_CTX, "BCM2835 num: swclk = %d", swclk_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swdio)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
-
- command_print(CMD_CTX, "BCM2835 num: swdio = %d", swdio_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs)
-{
- if (CMD_ARGC == 2) {
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bcm2835_peri_base);
- return ERROR_OK;
-}
-
-static const struct command_registration bcm2835gpio_command_handlers[] = {
- {
- .name = "bcm2835gpio_jtag_nums",
- .handler = &bcm2835gpio_handle_jtag_gpionums,
- .mode = COMMAND_CONFIG,
- .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
- .usage = "(tck tms tdi tdo)* ",
- },
- {
- .name = "bcm2835gpio_tck_num",
- .handler = &bcm2835gpio_handle_jtag_gpionum_tck,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tck.",
- },
- {
- .name = "bcm2835gpio_tms_num",
- .handler = &bcm2835gpio_handle_jtag_gpionum_tms,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tms.",
- },
- {
- .name = "bcm2835gpio_tdo_num",
- .handler = &bcm2835gpio_handle_jtag_gpionum_tdo,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tdo.",
- },
- {
- .name = "bcm2835gpio_tdi_num",
- .handler = &bcm2835gpio_handle_jtag_gpionum_tdi,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tdi.",
- },
- {
- .name = "bcm2835gpio_swd_nums",
- .handler = &bcm2835gpio_handle_swd_gpionums,
- .mode = COMMAND_CONFIG,
- .help = "gpio numbers for swclk, swdio. (in that order)",
- .usage = "(swclk swdio)* ",
- },
- {
- .name = "bcm2835gpio_swclk_num",
- .handler = &bcm2835gpio_handle_swd_gpionum_swclk,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for swclk.",
- },
- {
- .name = "bcm2835gpio_swdio_num",
- .handler = &bcm2835gpio_handle_swd_gpionum_swdio,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for swdio.",
- },
- {
- .name = "bcm2835gpio_srst_num",
- .handler = &bcm2835gpio_handle_jtag_gpionum_srst,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for srst.",
- },
- {
- .name = "bcm2835gpio_trst_num",
- .handler = &bcm2835gpio_handle_jtag_gpionum_trst,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for trst.",
- },
- {
- .name = "bcm2835gpio_speed_coeffs",
- .handler = &bcm2835gpio_handle_speed_coeffs,
- .mode = COMMAND_CONFIG,
- .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
- },
- {
- .name = "bcm2835gpio_peripheral_base",
- .handler = &bcm2835gpio_handle_peripheral_base,
- .mode = COMMAND_CONFIG,
- .help = "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
-
-struct jtag_interface bcm2835gpio_interface = {
- .name = "bcm2835gpio",
- .supported = DEBUG_CAP_TMS_SEQ,
- .execute_queue = bitbang_execute_queue,
- .transports = bcm2835_transports,
- .swd = &bitbang_swd,
- .speed = bcm2835gpio_speed,
- .khz = bcm2835gpio_khz,
- .speed_div = bcm2835gpio_speed_div,
- .commands = bcm2835gpio_command_handlers,
- .init = bcm2835gpio_init,
- .quit = bcm2835gpio_quit,
-};
-
-static bool bcm2835gpio_jtag_mode_possible(void)
-{
- if (!is_gpio_valid(tck_gpio))
- return 0;
- if (!is_gpio_valid(tms_gpio))
- return 0;
- if (!is_gpio_valid(tdi_gpio))
- return 0;
- if (!is_gpio_valid(tdo_gpio))
- return 0;
- return 1;
-}
-
-static bool bcm2835gpio_swd_mode_possible(void)
-{
- if (!is_gpio_valid(swclk_gpio))
- return 0;
- if (!is_gpio_valid(swdio_gpio))
- return 0;
- return 1;
-}
-
-static int bcm2835gpio_init(void)
-{
- bitbang_interface = &bcm2835gpio_bitbang;
-
- LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
-
- if (bcm2835gpio_jtag_mode_possible()) {
- if (bcm2835gpio_swd_mode_possible())
- LOG_INFO("JTAG and SWD modes enabled");
- else
- LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
- if (!is_gpio_valid(trst_gpio) && !is_gpio_valid(srst_gpio)) {
- LOG_ERROR("Require at least one of trst or srst gpios to be specified");
- return ERROR_JTAG_INIT_FAILED;
- }
- } else if (bcm2835gpio_swd_mode_possible()) {
- LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
- } else {
- LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
- if (dev_mem_fd < 0) {
- perror("open");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- pio_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
- MAP_SHARED, dev_mem_fd, BCM2835_GPIO_BASE);
-
- if (pio_base == MAP_FAILED) {
- perror("mmap");
- close(dev_mem_fd);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- static volatile uint32_t *pads_base;
- pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
- MAP_SHARED, dev_mem_fd, BCM2835_PADS_GPIO_0_27);
-
- if (pads_base == MAP_FAILED) {
- perror("mmap");
- close(dev_mem_fd);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- /* set 16mA drive strength */
- pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000018 + 7;
-
- tdo_gpio_mode = MODE_GPIO(tdo_gpio);
- tdi_gpio_mode = MODE_GPIO(tdi_gpio);
- tck_gpio_mode = MODE_GPIO(tck_gpio);
- tms_gpio_mode = MODE_GPIO(tms_gpio);
- swclk_gpio_mode = MODE_GPIO(swclk_gpio);
- swdio_gpio_mode = MODE_GPIO(swdio_gpio);
- /*
- * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
- * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
- */
- INP_GPIO(tdo_gpio);
-
- GPIO_CLR = 1<<tdi_gpio | 1<<tck_gpio | 1<<swdio_gpio | 1<<swclk_gpio;
- GPIO_SET = 1<<tms_gpio;
-
- OUT_GPIO(tdi_gpio);
- OUT_GPIO(tck_gpio);
- OUT_GPIO(tms_gpio);
- OUT_GPIO(swclk_gpio);
- OUT_GPIO(swdio_gpio);
- if (trst_gpio != -1) {
- trst_gpio_mode = MODE_GPIO(trst_gpio);
- GPIO_SET = 1 << trst_gpio;
- OUT_GPIO(trst_gpio);
- }
- if (srst_gpio != -1) {
- srst_gpio_mode = MODE_GPIO(srst_gpio);
- GPIO_SET = 1 << srst_gpio;
- OUT_GPIO(srst_gpio);
- }
-
- LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
- "tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
- tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode);
-
- if (swd_mode) {
- bcm2835gpio_bitbang.write = bcm2835gpio_swd_write;
- bitbang_switch_to_swd();
- }
-
- return ERROR_OK;
-}
-
-static int bcm2835gpio_quit(void)
-{
- SET_MODE_GPIO(tdo_gpio, tdo_gpio_mode);
- SET_MODE_GPIO(tdi_gpio, tdi_gpio_mode);
- SET_MODE_GPIO(tck_gpio, tck_gpio_mode);
- SET_MODE_GPIO(tms_gpio, tms_gpio_mode);
- SET_MODE_GPIO(swclk_gpio, swclk_gpio_mode);
- SET_MODE_GPIO(swdio_gpio, swdio_gpio_mode);
- if (trst_gpio != -1)
- SET_MODE_GPIO(trst_gpio, trst_gpio_mode);
- if (srst_gpio != -1)
- SET_MODE_GPIO(srst_gpio, srst_gpio_mode);
-
- return ERROR_OK;
-}
diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
deleted file mode 100644
index c9ec9c9..0000000
--- a/src/jtag/drivers/bitbang.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* 2014-12: Addition of the SWD protocol support is based on the initial work
- * by Paul Fertser and modifications by Jean-Christian de Rivaz. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "bitbang.h"
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-
-/* YUK! - but this is currently a global.... */
-extern struct jtag_interface *jtag_interface;
-
-/**
- * Function bitbang_stableclocks
- * issues a number of clock cycles while staying in a stable state.
- * Because the TMS value required to stay in the RESET state is a 1, whereas
- * the TMS value required to stay in any of the other stable states is a 0,
- * this function checks the current stable state to decide on the value of TMS
- * to use.
- */
-static void bitbang_stableclocks(int num_cycles);
-
-static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk);
-
-struct bitbang_interface *bitbang_interface;
-
-/* DANGER!!!! clock absolutely *MUST* be 0 in idle or reset won't work!
- *
- * Set this to 1 and str912 reset halt will fail.
- *
- * If someone can submit a patch with an explanation it will be greatly
- * appreciated, but as far as I can tell (ØH) DCLK is generated upon
- * clk = 0 in TAP_IDLE. Good luck deducing that from the ARM documentation!
- * The ARM documentation uses the term "DCLK is asserted while in the TAP_IDLE
- * state". With hardware there is no such thing as *while* in a state. There
- * are only edges. So clk => 0 is in fact a very subtle state transition that
- * happens *while* in the TAP_IDLE state. "#&¤"#¤&"#&"#&
- *
- * For "reset halt" the last thing that happens before srst is asserted
- * is that the breakpoint is set up. If DCLK is not wiggled one last
- * time before the reset, then the breakpoint is not set up and
- * "reset halt" will fail to halt.
- *
- */
-#define CLOCK_IDLE() 0
-
-/* The bitbang driver leaves the TCK 0 when in idle */
-static void bitbang_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-static void bitbang_state_move(int skip)
-{
- int i = 0, tms = 0;
- 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());
-
- for (i = skip; i < tms_count; i++) {
- tms = (tms_scan >> i) & 1;
- bitbang_interface->write(0, tms, 0);
- bitbang_interface->write(1, tms, 0);
- }
- bitbang_interface->write(CLOCK_IDLE(), tms, 0);
-
- tap_set_state(tap_get_end_state());
-}
-
-/**
- * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG
- * (or SWD) state machine.
- */
-static int bitbang_execute_tms(struct jtag_command *cmd)
-{
- unsigned num_bits = cmd->cmd.tms->num_bits;
- const uint8_t *bits = cmd->cmd.tms->bits;
-
- DEBUG_JTAG_IO("TMS: %d bits", num_bits);
-
- int tms = 0;
- for (unsigned i = 0; i < num_bits; i++) {
- tms = ((bits[i/8] >> (i % 8)) & 1);
- bitbang_interface->write(0, tms, 0);
- bitbang_interface->write(1, tms, 0);
- }
- bitbang_interface->write(CLOCK_IDLE(), tms, 0);
-
- return ERROR_OK;
-}
-
-static void bitbang_path_move(struct pathmove_command *cmd)
-{
- int num_states = cmd->num_states;
- int state_count;
- int tms = 0;
-
- state_count = 0;
- while (num_states) {
- if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
- tms = 0;
- else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
- tms = 1;
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(tap_get_state()),
- tap_state_name(cmd->path[state_count]));
- exit(-1);
- }
-
- bitbang_interface->write(0, tms, 0);
- bitbang_interface->write(1, tms, 0);
-
- tap_set_state(cmd->path[state_count]);
- state_count++;
- num_states--;
- }
-
- bitbang_interface->write(CLOCK_IDLE(), tms, 0);
-
- tap_set_end_state(tap_get_state());
-}
-
-static void bitbang_runtest(int num_cycles)
-{
- int i;
-
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- bitbang_end_state(TAP_IDLE);
- bitbang_state_move(0);
- }
-
- /* execute num_cycles */
- for (i = 0; i < num_cycles; i++) {
- bitbang_interface->write(0, 0, 0);
- bitbang_interface->write(1, 0, 0);
- }
- bitbang_interface->write(CLOCK_IDLE(), 0, 0);
-
- /* finish in end_state */
- bitbang_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- bitbang_state_move(0);
-}
-
-static void bitbang_stableclocks(int num_cycles)
-{
- int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
- int i;
-
- /* send num_cycles clocks onto the cable */
- for (i = 0; i < num_cycles; i++) {
- bitbang_interface->write(1, tms, 0);
- bitbang_interface->write(0, tms, 0);
- }
-}
-
-static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
-{
- tap_state_t saved_end_state = tap_get_end_state();
- int bit_cnt;
-
- if (!((!ir_scan &&
- (tap_get_state() == TAP_DRSHIFT)) ||
- (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) {
- if (ir_scan)
- bitbang_end_state(TAP_IRSHIFT);
- else
- bitbang_end_state(TAP_DRSHIFT);
-
- bitbang_state_move(0);
- bitbang_end_state(saved_end_state);
- }
-
- for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) {
- int val = 0;
- int tms = (bit_cnt == scan_size-1) ? 1 : 0;
- int tdi;
- int bytec = bit_cnt/8;
- int bcval = 1 << (bit_cnt % 8);
-
- /* if we're just reading the scan, but don't care about the output
- * default to outputting 'low', this also makes valgrind traces more readable,
- * as it removes the dependency on an uninitialised value
- */
- tdi = 0;
- if ((type != SCAN_IN) && (buffer[bytec] & bcval))
- tdi = 1;
-
- bitbang_interface->write(0, tms, tdi);
-
- if (type != SCAN_OUT)
- val = bitbang_interface->read();
-
- bitbang_interface->write(1, tms, tdi);
-
- if (type != SCAN_OUT) {
- if (val)
- buffer[bytec] |= bcval;
- else
- buffer[bytec] &= ~bcval;
- }
- }
-
- if (tap_get_state() != tap_get_end_state()) {
- /* we *KNOW* the above loop transitioned out of
- * the shift state, so we skip the first state
- * and move directly to the end state.
- */
- bitbang_state_move(1);
- }
-}
-
-int bitbang_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
- int retval;
-
- if (!bitbang_interface) {
- LOG_ERROR("BUG: Bitbang interface called, but not yet initialized");
- exit(-1);
- }
-
- /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
- * that wasn't handled by a caller-provided error handler
- */
- retval = ERROR_OK;
-
- if (bitbang_interface->blink)
- bitbang_interface->blink(1);
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-#endif
- if ((cmd->cmd.reset->trst == 1) ||
- (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
- bitbang_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("runtest %i cycles, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
-#endif
- bitbang_end_state(cmd->cmd.runtest->end_state);
- bitbang_runtest(cmd->cmd.runtest->num_cycles);
- break;
-
- case JTAG_STABLECLOCKS:
- /* this is only allowed while in a stable state. A check for a stable
- * state was done in jtag_add_clocks()
- */
- bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles);
- break;
-
- case JTAG_TLR_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("statemove end in %s",
- tap_state_name(cmd->cmd.statemove->end_state));
-#endif
- bitbang_end_state(cmd->cmd.statemove->end_state);
- bitbang_state_move(0);
- break;
- case JTAG_PATHMOVE:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("pathmove: %i states, end in %s",
- cmd->cmd.pathmove->num_states,
- tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
-#endif
- bitbang_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_SCAN:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("%s scan end in %s",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
- tap_state_name(cmd->cmd.scan->end_state));
-#endif
- bitbang_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- if (buffer)
- free(buffer);
- break;
- case JTAG_SLEEP:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
-#endif
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- case JTAG_TMS:
- retval = bitbang_execute_tms(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
- cmd = cmd->next;
- }
- if (bitbang_interface->blink)
- bitbang_interface->blink(0);
-
- return retval;
-}
-
-
-bool swd_mode;
-static int queued_retval;
-
-static int bitbang_swd_init(void)
-{
- LOG_DEBUG("bitbang_swd_init");
- swd_mode = true;
- return ERROR_OK;
-}
-
-static void bitbang_exchange(bool rnw, uint8_t buf[], unsigned int offset, unsigned int bit_cnt)
-{
- LOG_DEBUG("bitbang_exchange");
- int tdi;
-
- for (unsigned int i = offset; i < bit_cnt + offset; i++) {
- int bytec = i/8;
- int bcval = 1 << (i % 8);
- tdi = !rnw && (buf[bytec] & bcval);
-
- bitbang_interface->write(0, 0, tdi);
-
- if (rnw && buf) {
- if (bitbang_interface->swdio_read())
- buf[bytec] |= bcval;
- else
- buf[bytec] &= ~bcval;
- }
-
- bitbang_interface->write(1, 0, tdi);
- }
-}
-
-int bitbang_swd_switch_seq(enum swd_special_seq seq)
-{
- LOG_DEBUG("bitbang_swd_switch_seq");
-
- switch (seq) {
- case LINE_RESET:
- LOG_DEBUG("SWD line reset");
- bitbang_exchange(false, (uint8_t *)swd_seq_line_reset, 0, swd_seq_line_reset_len);
- break;
- case JTAG_TO_SWD:
- LOG_DEBUG("JTAG-to-SWD");
- bitbang_exchange(false, (uint8_t *)swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len);
- break;
- case SWD_TO_JTAG:
- LOG_DEBUG("SWD-to-JTAG");
- bitbang_exchange(false, (uint8_t *)swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len);
- break;
- default:
- LOG_ERROR("Sequence %d not supported", seq);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-void bitbang_switch_to_swd(void)
-{
- LOG_DEBUG("bitbang_switch_to_swd");
- bitbang_exchange(false, (uint8_t *)swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len);
-}
-
-static void swd_clear_sticky_errors(void)
-{
- bitbang_swd_write_reg(swd_cmd(false, false, DP_ABORT),
- STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
-}
-
-static void bitbang_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
-{
- LOG_DEBUG("bitbang_swd_read_reg");
- assert(cmd & SWD_CMD_RnW);
-
- if (queued_retval != ERROR_OK) {
- LOG_DEBUG("Skip bitbang_swd_read_reg because queued_retval=%d", queued_retval);
- return;
- }
-
- for (;;) {
- uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)];
-
- cmd |= SWD_CMD_START | (1 << 7);
- bitbang_exchange(false, &cmd, 0, 8);
-
- bitbang_interface->swdio_drive(false);
- bitbang_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3 + 32 + 1 + 1);
- bitbang_interface->swdio_drive(true);
-
- int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
- uint32_t data = buf_get_u32(trn_ack_data_parity_trn, 1 + 3, 32);
- int parity = buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 32, 1);
-
- LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
- ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
- cmd & SWD_CMD_APnDP ? "AP" : "DP",
- cmd & SWD_CMD_RnW ? "read" : "write",
- (cmd & SWD_CMD_A32) >> 1,
- data);
-
- switch (ack) {
- case SWD_ACK_OK:
- if (parity != parity_u32(data)) {
- LOG_DEBUG("Wrong parity detected");
- queued_retval = ERROR_FAIL;
- return;
- }
- if (value)
- *value = data;
- if (cmd & SWD_CMD_APnDP)
- bitbang_exchange(true, NULL, 0, ap_delay_clk);
- return;
- case SWD_ACK_WAIT:
- LOG_DEBUG("SWD_ACK_WAIT");
- swd_clear_sticky_errors();
- break;
- case SWD_ACK_FAULT:
- LOG_DEBUG("SWD_ACK_FAULT");
- queued_retval = ack;
- return;
- default:
- LOG_DEBUG("No valid acknowledge: ack=%d", ack);
- queued_retval = ack;
- return;
- }
- }
-}
-
-static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
-{
- LOG_DEBUG("bitbang_swd_write_reg");
- assert(!(cmd & SWD_CMD_RnW));
-
- if (queued_retval != ERROR_OK) {
- LOG_DEBUG("Skip bitbang_swd_write_reg because queued_retval=%d", queued_retval);
- return;
- }
-
- for (;;) {
- uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)];
- buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32, value);
- buf_set_u32(trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(value));
-
- cmd |= SWD_CMD_START | (1 << 7);
- bitbang_exchange(false, &cmd, 0, 8);
-
- bitbang_interface->swdio_drive(false);
- bitbang_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3 + 1);
- bitbang_interface->swdio_drive(true);
- bitbang_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1);
-
- int ack = buf_get_u32(trn_ack_data_parity_trn, 1, 3);
- LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
- ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
- cmd & SWD_CMD_APnDP ? "AP" : "DP",
- cmd & SWD_CMD_RnW ? "read" : "write",
- (cmd & SWD_CMD_A32) >> 1,
- buf_get_u32(trn_ack_data_parity_trn, 1 + 3 + 1, 32));
-
- switch (ack) {
- case SWD_ACK_OK:
- if (cmd & SWD_CMD_APnDP)
- bitbang_exchange(true, NULL, 0, ap_delay_clk);
- return;
- case SWD_ACK_WAIT:
- LOG_DEBUG("SWD_ACK_WAIT");
- swd_clear_sticky_errors();
- break;
- case SWD_ACK_FAULT:
- LOG_DEBUG("SWD_ACK_FAULT");
- queued_retval = ack;
- return;
- default:
- LOG_DEBUG("No valid acknowledge: ack=%d", ack);
- queued_retval = ack;
- return;
- }
- }
-}
-
-static int bitbang_swd_run_queue(void)
-{
- LOG_DEBUG("bitbang_swd_run_queue");
- /* A transaction must be followed by another transaction or at least 8 idle cycles to
- * ensure that data is clocked through the AP. */
- bitbang_exchange(true, NULL, 0, 8);
-
- int retval = queued_retval;
- queued_retval = ERROR_OK;
- LOG_DEBUG("SWD queue return value: %02x", retval);
- return retval;
-}
-
-const struct swd_driver bitbang_swd = {
- .init = bitbang_swd_init,
- .switch_seq = bitbang_swd_switch_seq,
- .read_reg = bitbang_swd_read_reg,
- .write_reg = bitbang_swd_write_reg,
- .run = bitbang_swd_run_queue,
-};
diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h
deleted file mode 100644
index c5b44bf..0000000
--- a/src/jtag/drivers/bitbang.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_BITBANG_H
-#define OPENOCD_JTAG_DRIVERS_BITBANG_H
-
-#include <jtag/swd.h>
-
-struct bitbang_interface {
- /* low level callbacks (for bitbang)
- */
- int (*read)(void);
- void (*write)(int tck, int tms, int tdi);
- void (*reset)(int trst, int srst);
- void (*blink)(int on);
- int (*swdio_read)(void);
- void (*swdio_drive)(bool on);
-};
-
-const struct swd_driver bitbang_swd;
-
-extern bool swd_mode;
-
-int bitbang_execute_queue(void);
-
-extern struct bitbang_interface *bitbang_interface;
-void bitbang_switch_to_swd(void);
-int bitbang_swd_switch_seq(enum swd_special_seq seq);
-
-#endif /* OPENOCD_JTAG_DRIVERS_BITBANG_H */
diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c
deleted file mode 100644
index 66285f7..0000000
--- a/src/jtag/drivers/bitq.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/***************************************************************************
-* Copyright (C) 2007 by Pavel Chromy *
-* chromy@asix.cz *
-* *
-* This program is free software; you can redistribute it and/or modify *
-* it under the terms of the GNU General Public License as published by *
-* the Free Software Foundation; either version 2 of the License, or *
-* (at your option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-* GNU General Public License for more details. *
-* *
-* You should have received a copy of the GNU General Public License *
-* along with this program. If not, see <http://www.gnu.org/licenses/>. *
-***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/jtag.h>
-#include "bitq.h"
-#include <jtag/interface.h>
-
-struct bitq_interface *bitq_interface; /* low level bit queue interface */
-
-/* state of input queue */
-struct bitq_state {
- struct jtag_command *cmd; /* command currently processed */
- int field_idx; /* index of field currently being processed */
- int bit_pos; /* position of bit currently being processed */
- int status; /* processing status */
-};
-static struct bitq_state bitq_in_state;
-
-/*
- * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
- * no parameters, makes use of stored state information
- */
-static void bitq_in_proc(void)
-{
- /* loop through the queue */
- while (bitq_in_state.cmd) {
- /* only JTAG_SCAN command may return data */
- if (bitq_in_state.cmd->type == JTAG_SCAN) {
- /* loop through the fields */
- while (bitq_in_state.field_idx < bitq_in_state.cmd->cmd.scan->num_fields) {
- struct scan_field *field;
- field = &bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
- if (field->in_value) {
- /* field scanning */
- while (bitq_in_state.bit_pos < field->num_bits) {
- /* index of byte being scanned */
- int in_idx = bitq_in_state.bit_pos / 8;
- /* mask of next bit to be scanned */
- uint8_t in_mask = 1 << (bitq_in_state.bit_pos % 8);
-
- int tdo = bitq_interface->in();
- if (tdo < 0) {
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("bitq in EOF");
-#endif
- return;
- }
- if (in_mask == 0x01)
- field->in_value[in_idx] = 0;
- if (tdo)
- field->in_value[in_idx] |= in_mask;
- bitq_in_state.bit_pos++;
- }
- }
-
- bitq_in_state.field_idx++; /* advance to next field */
- bitq_in_state.bit_pos = 0; /* start next field from the first bit */
- }
- }
- bitq_in_state.cmd = bitq_in_state.cmd->next; /* advance to next command */
- bitq_in_state.field_idx = 0; /* preselect first field */
- }
-}
-
-static void bitq_io(int tms, int tdi, int tdo_req)
-{
- bitq_interface->out(tms, tdi, tdo_req);
- /* check and process the input queue */
- if (bitq_interface->in_rdy())
- bitq_in_proc();
-}
-
-static void bitq_end_state(tap_state_t state)
-{
- if (!tap_is_state_stable(state)) {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
- tap_set_end_state(state);
-}
-
-static void bitq_state_move(tap_state_t new_state)
-{
- int i = 0;
- uint8_t tms_scan;
-
- if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state)) {
- LOG_ERROR("TAP move from or to unstable state");
- exit(-1);
- }
-
- tms_scan = tap_get_tms_path(tap_get_state(), new_state);
- int tms_count = tap_get_tms_path_len(tap_get_state(), new_state);
-
- for (i = 0; i < tms_count; i++) {
- bitq_io(tms_scan & 1, 0, 0);
- tms_scan >>= 1;
- }
-
- tap_set_state(new_state);
-}
-
-static void bitq_path_move(struct pathmove_command *cmd)
-{
- int i;
-
- for (i = 0; i <= cmd->num_states; i++) {
- if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
- bitq_io(0, 0, 0);
- else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
- bitq_io(1, 0, 0);
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(
- tap_get_state()), tap_state_name(cmd->path[i]));
- exit(-1);
- }
-
- tap_set_state(cmd->path[i]);
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void bitq_runtest(int num_cycles)
-{
- int i;
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE)
- bitq_state_move(TAP_IDLE);
-
- /* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
- bitq_io(0, 0, 0);
-
- /* finish in end_state */
- if (tap_get_state() != tap_get_end_state())
- bitq_state_move(tap_get_end_state());
-}
-
-static void bitq_scan_field(struct scan_field *field, int do_pause)
-{
- int bit_cnt;
- int tdo_req;
-
- const uint8_t *out_ptr;
- uint8_t out_mask;
-
- if (field->in_value)
- tdo_req = 1;
- else
- tdo_req = 0;
-
- if (field->out_value == NULL) {
- /* just send zeros and request data from TDO */
- for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--)
- bitq_io(0, 0, tdo_req);
-
- bitq_io(do_pause, 0, tdo_req);
- } else {
- /* send data, and optionally request TDO */
- out_mask = 0x01;
- out_ptr = field->out_value;
- for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) {
- bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req);
- if (out_mask == 0x80) {
- out_mask = 0x01;
- out_ptr++;
- } else
- out_mask <<= 1;
- }
-
- bitq_io(do_pause, ((*out_ptr) & out_mask) != 0, tdo_req);
- }
-
- if (do_pause) {
- bitq_io(0, 0, 0);
- if (tap_get_state() == TAP_IRSHIFT)
- tap_set_state(TAP_IRPAUSE);
- else if (tap_get_state() == TAP_DRSHIFT)
- tap_set_state(TAP_DRPAUSE);
- }
-}
-
-static void bitq_scan(struct scan_command *cmd)
-{
- int i;
-
- if (cmd->ir_scan)
- bitq_state_move(TAP_IRSHIFT);
- else
- bitq_state_move(TAP_DRSHIFT);
-
- for (i = 0; i < cmd->num_fields - 1; i++)
- bitq_scan_field(&cmd->fields[i], 0);
-
- bitq_scan_field(&cmd->fields[i], 1);
-}
-
-int bitq_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
-
- bitq_in_state.cmd = jtag_command_queue;
- bitq_in_state.field_idx = 0;
- bitq_in_state.bit_pos = 0;
- bitq_in_state.status = ERROR_OK;
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-#endif
- if ((cmd->cmd.reset->trst == 1) ||
- (cmd->cmd.reset->srst &&
- (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
- bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- if (bitq_interface->in_rdy())
- bitq_in_proc();
- break;
-
- case JTAG_RUNTEST:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
-#endif
- bitq_end_state(cmd->cmd.runtest->end_state);
- bitq_runtest(cmd->cmd.runtest->num_cycles);
- break;
-
- case JTAG_TLR_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
-#endif
- bitq_end_state(cmd->cmd.statemove->end_state);
- bitq_state_move(tap_get_end_state()); /* uncoditional TAP move */
- break;
-
- case JTAG_PATHMOVE:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-#endif
- bitq_path_move(cmd->cmd.pathmove);
- break;
-
- case JTAG_SCAN:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
- if (cmd->cmd.scan->ir_scan)
- LOG_DEBUG("scan ir");
- else
- LOG_DEBUG("scan dr");
-#endif
- bitq_end_state(cmd->cmd.scan->end_state);
- bitq_scan(cmd->cmd.scan);
- if (tap_get_state() != tap_get_end_state())
- bitq_state_move(tap_get_end_state());
- break;
-
- case JTAG_SLEEP:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
-#endif
- bitq_interface->sleep(cmd->cmd.sleep->us);
- if (bitq_interface->in_rdy())
- bitq_in_proc();
- break;
-
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
-
- cmd = cmd->next;
- }
-
- bitq_interface->flush();
- bitq_in_proc();
-
- if (bitq_in_state.cmd) {
- LOG_ERROR("missing data from bitq interface");
- return ERROR_JTAG_QUEUE_FAILED;
- }
- if (bitq_interface->in() >= 0) {
- LOG_ERROR("extra data from bitq interface");
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- return bitq_in_state.status;
-}
-
-void bitq_cleanup(void)
-{
-}
diff --git a/src/jtag/drivers/bitq.h b/src/jtag/drivers/bitq.h
deleted file mode 100644
index df6a08d..0000000
--- a/src/jtag/drivers/bitq.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Pavel Chromy *
- * chromy@asix.cz *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_BITQ_H
-#define OPENOCD_JTAG_DRIVERS_BITQ_H
-
-#include <jtag/commands.h>
-
-struct bitq_interface {
- /* function to enqueueing low level IO requests */
- int (*out)(int tms, int tdi, int tdo_req);
- int (*flush)(void);
-
- int (*sleep)(unsigned long us);
- int (*reset)(int trst, int srst);
-
- /* delayed read of requested TDO data,
- * the input shall be checked after call to any enqueuing function
- */
- int (*in_rdy)(void);
- int (*in)(void);
-};
-
-extern struct bitq_interface *bitq_interface;
-
-int bitq_execute_queue(void);
-
-void bitq_cleanup(void);
-
-#endif /* OPENOCD_JTAG_DRIVERS_BITQ_H */
diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c
deleted file mode 100644
index aa0d8cc..0000000
--- a/src/jtag/drivers/buspirate.c
+++ /dev/null
@@ -1,1126 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Michal Demin *
- * based on usbprog.c and arm-jtag-ew.c *
- * Several fixes by R. Diez in 2013. *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-
-#include <termios.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#undef DEBUG_SERIAL
-/*#define DEBUG_SERIAL */
-static int buspirate_execute_queue(void);
-static int buspirate_init(void);
-static int buspirate_quit(void);
-
-static void buspirate_end_state(tap_state_t state);
-static void buspirate_state_move(void);
-static void buspirate_path_move(int num_states, tap_state_t *path);
-static void buspirate_runtest(int num_cycles);
-static void buspirate_scan(bool ir_scan, enum scan_type type,
- uint8_t *buffer, int scan_size, struct scan_command *command);
-static void buspirate_stableclocks(int num_cycles);
-
-#define CMD_UNKNOWN 0x00
-#define CMD_PORT_MODE 0x01
-#define CMD_FEATURE 0x02
-#define CMD_READ_ADCS 0x03
-/*#define CMD_TAP_SHIFT 0x04 // old protocol */
-#define CMD_TAP_SHIFT 0x05
-#define CMD_ENTER_OOCD 0x06
-#define CMD_UART_SPEED 0x07
-#define CMD_JTAG_SPEED 0x08
-
-/* Not all OSes have this speed defined */
-#if !defined(B1000000)
-#define B1000000 0010010
-#endif
-
-enum {
- MODE_HIZ = 0,
- MODE_JTAG = 1, /* push-pull outputs */
- MODE_JTAG_OD = 2, /* open-drain outputs */
-};
-
-enum {
- FEATURE_LED = 0x01,
- FEATURE_VREG = 0x02,
- FEATURE_TRST = 0x04,
- FEATURE_SRST = 0x08,
- FEATURE_PULLUP = 0x10
-};
-
-enum {
- ACTION_DISABLE = 0,
- ACTION_ENABLE = 1
-};
-
-enum {
- SERIAL_NORMAL = 0,
- SERIAL_FAST = 1
-};
-
-static const cc_t SHORT_TIMEOUT = 1; /* Must be at least 1. */
-static const cc_t NORMAL_TIMEOUT = 10;
-
-static int buspirate_fd = -1;
-static int buspirate_pinmode = MODE_JTAG_OD;
-static int buspirate_baudrate = SERIAL_NORMAL;
-static int buspirate_vreg;
-static int buspirate_pullup;
-static char *buspirate_port;
-
-static enum tap_state last_tap_state = TAP_RESET;
-
-
-/* TAP interface */
-static void buspirate_tap_init(void);
-static int buspirate_tap_execute(void);
-static void buspirate_tap_append(int tms, int tdi);
-static void buspirate_tap_append_scan(int length, uint8_t *buffer,
- struct scan_command *command);
-static void buspirate_tap_make_space(int scan, int bits);
-
-static void buspirate_reset(int trst, int srst);
-
-/* low level interface */
-static void buspirate_jtag_reset(int);
-static void buspirate_jtag_enable(int);
-static unsigned char buspirate_jtag_command(int, char *, int);
-static void buspirate_jtag_set_speed(int, char);
-static void buspirate_jtag_set_mode(int, char);
-static void buspirate_jtag_set_feature(int, char, char);
-static void buspirate_jtag_get_adcs(int);
-
-/* low level HW communication interface */
-static int buspirate_serial_open(char *port);
-static int buspirate_serial_setspeed(int fd, char speed, cc_t timeout);
-static int buspirate_serial_write(int fd, char *buf, int size);
-static int buspirate_serial_read(int fd, char *buf, int size);
-static void buspirate_serial_close(int fd);
-static void buspirate_print_buffer(char *buf, int size);
-
-static int buspirate_execute_queue(void)
-{
- /* currently processed command */
- struct jtag_command *cmd = jtag_command_queue;
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_RUNTEST:
- DEBUG_JTAG_IO("runtest %i cycles, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest
- ->end_state));
- buspirate_end_state(cmd->cmd.runtest
- ->end_state);
- buspirate_runtest(cmd->cmd.runtest
- ->num_cycles);
- break;
- case JTAG_TLR_RESET:
- DEBUG_JTAG_IO("statemove end in %s",
- tap_state_name(cmd->cmd.statemove
- ->end_state));
- buspirate_end_state(cmd->cmd.statemove
- ->end_state);
- buspirate_state_move();
- break;
- case JTAG_PATHMOVE:
- DEBUG_JTAG_IO("pathmove: %i states, end in %s",
- cmd->cmd.pathmove->num_states,
- tap_state_name(cmd->cmd.pathmove
- ->path[cmd->cmd.pathmove
- ->num_states - 1]));
- buspirate_path_move(cmd->cmd.pathmove
- ->num_states,
- cmd->cmd.pathmove->path);
- break;
- case JTAG_SCAN:
- DEBUG_JTAG_IO("scan end in %s",
- tap_state_name(cmd->cmd.scan
- ->end_state));
-
- buspirate_end_state(cmd->cmd.scan
- ->end_state);
-
- scan_size = jtag_build_buffer(cmd->cmd.scan,
- &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- buspirate_scan(cmd->cmd.scan->ir_scan, type,
- buffer, scan_size, cmd->cmd.scan);
-
- break;
- case JTAG_RESET:
- DEBUG_JTAG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-
- /* flush buffers, so we can reset */
- buspirate_tap_execute();
-
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- buspirate_reset(cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
- break;
- case JTAG_SLEEP:
- DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us);
- buspirate_tap_execute();
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- case JTAG_STABLECLOCKS:
- DEBUG_JTAG_IO("stable clock %i cycles", cmd->cmd.stableclocks->num_cycles);
- buspirate_stableclocks(cmd->cmd.stableclocks->num_cycles);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
-
- cmd = cmd->next;
- }
-
- return buspirate_tap_execute();
-}
-
-
-/* Returns true if successful, false if error. */
-
-static bool read_and_discard_all_data(const int fd)
-{
- /* LOG_INFO("Discarding any stale data from a previous connection..."); */
-
- bool was_msg_already_printed = false;
-
- for ( ; ; ) {
- char buffer[1024]; /* Any size will do, it's a trade-off between stack size and performance. */
-
- const ssize_t read_count = read(fd, buffer, sizeof(buffer));
-
- if (read_count == 0) {
- /* This is the "end of file" or "connection closed at the other end" condition. */
- return true;
- }
-
- if (read_count > 0) {
- if (!was_msg_already_printed) {
- LOG_INFO("Some stale data from a previous connection was discarded.");
- was_msg_already_printed = true;
- }
-
- continue;
- }
-
- assert(read_count == -1); /* According to the specification. */
-
- const int errno_code = errno;
-
- if (errno_code == EINTR)
- continue;
-
- if (errno_code == EAGAIN ||
- errno_code == EWOULDBLOCK) {
- /* We know that the file descriptor has been opened with O_NONBLOCK or O_NDELAY,
- and these codes mean that there is no data to read at present. */
- return true;
- }
-
- /* Some other error has occurred. */
- return false;
- }
-}
-
-
-static int buspirate_init(void)
-{
- if (buspirate_port == NULL) {
- LOG_ERROR("You need to specify the serial port!");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- buspirate_fd = buspirate_serial_open(buspirate_port);
- if (buspirate_fd == -1) {
- LOG_ERROR("Could not open serial port");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- /* The Operating System or the device itself may deliver stale data from the last connection,
- so discard all available bytes right after the new connection has been established.
- After all, we are implementing here a master/slave protocol, so the slave should have nothing
- to say until the master sends the first command.
-
- In the past, there was a tcflush() call in buspirate_serial_setspeed(), but that
- was not enough. I guess you must actively read from the serial port to trigger any
- data collection from the device and/or lower USB layers. If you disable the serial port
- read timeout (if you set SHORT_TIMEOUT to 0), then the discarding does not work any more.
-
- Note that we are lowering the serial port timeout for this first read operation,
- otherwise the normal initialisation would be delayed for too long. */
-
- if (-1 == buspirate_serial_setspeed(buspirate_fd, SERIAL_NORMAL, SHORT_TIMEOUT)) {
- LOG_ERROR("Error configuring the serial port.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (!read_and_discard_all_data(buspirate_fd)) {
- LOG_ERROR("Error while attempting to discard any stale data right after establishing the connection.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (-1 == buspirate_serial_setspeed(buspirate_fd, SERIAL_NORMAL, NORMAL_TIMEOUT)) {
- LOG_ERROR("Error configuring the serial port.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- buspirate_jtag_enable(buspirate_fd);
-
- if (buspirate_baudrate != SERIAL_NORMAL)
- buspirate_jtag_set_speed(buspirate_fd, SERIAL_FAST);
-
- LOG_INFO("Buspirate Interface ready!");
-
- buspirate_tap_init();
- buspirate_jtag_set_mode(buspirate_fd, buspirate_pinmode);
- buspirate_jtag_set_feature(buspirate_fd, FEATURE_VREG,
- (buspirate_vreg == 1) ? ACTION_ENABLE : ACTION_DISABLE);
- buspirate_jtag_set_feature(buspirate_fd, FEATURE_PULLUP,
- (buspirate_pullup == 1) ? ACTION_ENABLE : ACTION_DISABLE);
- buspirate_reset(0, 0);
-
- return ERROR_OK;
-}
-
-static int buspirate_quit(void)
-{
- LOG_INFO("Shutting down buspirate.");
- buspirate_jtag_set_mode(buspirate_fd, MODE_HIZ);
-
- buspirate_jtag_set_speed(buspirate_fd, SERIAL_NORMAL);
- buspirate_jtag_reset(buspirate_fd);
-
- buspirate_serial_close(buspirate_fd);
-
- if (buspirate_port) {
- free(buspirate_port);
- buspirate_port = NULL;
- }
- return ERROR_OK;
-}
-
-/* openocd command interface */
-COMMAND_HANDLER(buspirate_handle_adc_command)
-{
- if (buspirate_fd == -1)
- return ERROR_OK;
-
- /* send the command */
- buspirate_jtag_get_adcs(buspirate_fd);
-
- return ERROR_OK;
-
-}
-
-COMMAND_HANDLER(buspirate_handle_vreg_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (atoi(CMD_ARGV[0]) == 1)
- buspirate_vreg = 1;
- else if (atoi(CMD_ARGV[0]) == 0)
- buspirate_vreg = 0;
- else
- LOG_ERROR("usage: buspirate_vreg <1|0>");
-
- return ERROR_OK;
-
-}
-
-COMMAND_HANDLER(buspirate_handle_pullup_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (atoi(CMD_ARGV[0]) == 1)
- buspirate_pullup = 1;
- else if (atoi(CMD_ARGV[0]) == 0)
- buspirate_pullup = 0;
- else
- LOG_ERROR("usage: buspirate_pullup <1|0>");
-
- return ERROR_OK;
-
-}
-
-COMMAND_HANDLER(buspirate_handle_led_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (atoi(CMD_ARGV[0]) == 1) {
- /* enable led */
- buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED,
- ACTION_ENABLE);
- } else if (atoi(CMD_ARGV[0]) == 0) {
- /* disable led */
- buspirate_jtag_set_feature(buspirate_fd, FEATURE_LED,
- ACTION_DISABLE);
- } else {
- LOG_ERROR("usage: buspirate_led <1|0>");
- }
-
- return ERROR_OK;
-
-}
-
-COMMAND_HANDLER(buspirate_handle_mode_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGV[0][0] == 'n')
- buspirate_pinmode = MODE_JTAG;
- else if (CMD_ARGV[0][0] == 'o')
- buspirate_pinmode = MODE_JTAG_OD;
- else
- LOG_ERROR("usage: buspirate_mode <normal|open-drain>");
-
- return ERROR_OK;
-
-}
-
-COMMAND_HANDLER(buspirate_handle_speed_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGV[0][0] == 'n')
- buspirate_baudrate = SERIAL_NORMAL;
- else if (CMD_ARGV[0][0] == 'f')
- buspirate_baudrate = SERIAL_FAST;
- else
- LOG_ERROR("usage: buspirate_speed <normal|fast>");
-
- return ERROR_OK;
-
-}
-
-COMMAND_HANDLER(buspirate_handle_port_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (buspirate_port == NULL)
- buspirate_port = strdup(CMD_ARGV[0]);
-
- return ERROR_OK;
-
-}
-
-static const struct command_registration buspirate_command_handlers[] = {
- {
- .name = "buspirate_adc",
- .handler = &buspirate_handle_adc_command,
- .mode = COMMAND_EXEC,
- .help = "reads voltages on adc pins",
- },
- {
- .name = "buspirate_vreg",
- .usage = "<1|0>",
- .handler = &buspirate_handle_vreg_command,
- .mode = COMMAND_CONFIG,
- .help = "changes the state of voltage regulators",
- },
- {
- .name = "buspirate_pullup",
- .usage = "<1|0>",
- .handler = &buspirate_handle_pullup_command,
- .mode = COMMAND_CONFIG,
- .help = "changes the state of pullup",
- },
- {
- .name = "buspirate_led",
- .usage = "<1|0>",
- .handler = &buspirate_handle_led_command,
- .mode = COMMAND_EXEC,
- .help = "changes the state of led",
- },
- {
- .name = "buspirate_speed",
- .usage = "<normal|fast>",
- .handler = &buspirate_handle_speed_command,
- .mode = COMMAND_CONFIG,
- .help = "speed of the interface",
- },
- {
- .name = "buspirate_mode",
- .usage = "<normal|open-drain>",
- .handler = &buspirate_handle_mode_command,
- .mode = COMMAND_CONFIG,
- .help = "pin mode of the interface",
- },
- {
- .name = "buspirate_port",
- .usage = "/dev/ttyUSB0",
- .handler = &buspirate_handle_port_command,
- .mode = COMMAND_CONFIG,
- .help = "name of the serial port to open",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface buspirate_interface = {
- .name = "buspirate",
- .execute_queue = buspirate_execute_queue,
- .commands = buspirate_command_handlers,
- .init = buspirate_init,
- .quit = buspirate_quit
-};
-
-/*************** jtag execute commands **********************/
-static void buspirate_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-static void buspirate_state_move(void)
-{
- int i = 0, tms = 0;
- 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());
-
- for (i = 0; i < tms_count; i++) {
- tms = (tms_scan >> i) & 1;
- buspirate_tap_append(tms, 0);
- }
-
- tap_set_state(tap_get_end_state());
-}
-
-static void buspirate_path_move(int num_states, tap_state_t *path)
-{
- int i;
-
- for (i = 0; i < num_states; i++) {
- if (tap_state_transition(tap_get_state(), false) == path[i]) {
- buspirate_tap_append(0, 0);
- } else if (tap_state_transition(tap_get_state(), true)
- == path[i]) {
- buspirate_tap_append(1, 0);
- } else {
- LOG_ERROR("BUG: %s -> %s isn't a valid "
- "TAP transition",
- tap_state_name(tap_get_state()),
- tap_state_name(path[i]));
- exit(-1);
- }
-
- tap_set_state(path[i]);
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void buspirate_runtest(int num_cycles)
-{
- int i;
-
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- buspirate_end_state(TAP_IDLE);
- buspirate_state_move();
- }
-
- for (i = 0; i < num_cycles; i++)
- buspirate_tap_append(0, 0);
-
- DEBUG_JTAG_IO("runtest: cur_state %s end_state %s",
- tap_state_name(tap_get_state()),
- tap_state_name(tap_get_end_state()));
-
- /* finish in end_state */
- buspirate_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- buspirate_state_move();
-}
-
-static void buspirate_scan(bool ir_scan, enum scan_type type,
- uint8_t *buffer, int scan_size, struct scan_command *command)
-{
- tap_state_t saved_end_state;
-
- buspirate_tap_make_space(1, scan_size+8);
- /* is 8 correct ? (2 moves = 16) */
-
- saved_end_state = tap_get_end_state();
-
- buspirate_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
-
- /* Only move if we're not already there */
- if (tap_get_state() != tap_get_end_state())
- buspirate_state_move();
-
- buspirate_tap_append_scan(scan_size, buffer, command);
-
- /* move to PAUSE */
- buspirate_tap_append(0, 0);
-
- /* restore the saved state */
- buspirate_end_state(saved_end_state);
- tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
-
- if (tap_get_state() != tap_get_end_state())
- buspirate_state_move();
-}
-
-static void buspirate_stableclocks(int num_cycles)
-{
- int i;
- int tms = (tap_get_state() == TAP_RESET ? 1 : 0);
-
- buspirate_tap_make_space(0, num_cycles);
-
- for (i = 0; i < num_cycles; i++)
- buspirate_tap_append(tms, 0);
-}
-
-/************************* TAP related stuff **********/
-
-/* This buffer size matches the maximum CMD_TAP_SHIFT bit length in the Bus Pirate firmware,
- look for constant 0x2000 in OpenOCD.c . */
-#define BUSPIRATE_BUFFER_SIZE 1024
-
-/* The old value of 32 scans was not enough to achieve near 100% utilisation ratio
- for the current BUSPIRATE_BUFFER_SIZE value of 1024.
- With 128 scans I am getting full USB 2.0 high speed packets (512 bytes long) when
- using the JtagDue firmware on the Arduino Due instead of the Bus Pirate, which
- amounts approximately to a 10% overall speed gain. Bigger packets should also
- benefit the Bus Pirate, but the speed difference is much smaller.
- Unfortunately, each 512-byte packet is followed by a 329-byte one, which is not ideal.
- However, increasing BUSPIRATE_BUFFER_SIZE for the benefit of the JtagDue would
- make it incompatible with the Bus Pirate firmware. */
-#define BUSPIRATE_MAX_PENDING_SCANS 128
-
-static char tms_chain[BUSPIRATE_BUFFER_SIZE]; /* send */
-static char tdi_chain[BUSPIRATE_BUFFER_SIZE]; /* send */
-static int tap_chain_index;
-
-struct pending_scan_result /* this was stolen from arm-jtag-ew */
-{
- int first; /* First bit position in tdo_buffer to read */
- int length; /* Number of bits to read */
- struct scan_command *command; /* Corresponding scan command */
- uint8_t *buffer;
-};
-
-static struct pending_scan_result
-tap_pending_scans[BUSPIRATE_MAX_PENDING_SCANS];
-static int tap_pending_scans_num;
-
-static void buspirate_tap_init(void)
-{
- tap_chain_index = 0;
- tap_pending_scans_num = 0;
-}
-
-static int buspirate_tap_execute(void)
-{
- static const int CMD_TAP_SHIFT_HEADER_LEN = 3;
-
- char tmp[4096];
- uint8_t *in_buf;
- int i;
- int fill_index = 0;
- int ret;
- int bytes_to_send;
-
- if (tap_chain_index <= 0)
- return ERROR_OK;
-
- LOG_DEBUG("executing tap num bits = %i scans = %i",
- tap_chain_index, tap_pending_scans_num);
-
- bytes_to_send = DIV_ROUND_UP(tap_chain_index, 8);
-
- tmp[0] = CMD_TAP_SHIFT; /* this command expects number of bits */
- tmp[1] = (char)(tap_chain_index >> 8); /* high */
- tmp[2] = (char)(tap_chain_index); /* low */
-
- fill_index = CMD_TAP_SHIFT_HEADER_LEN;
- for (i = 0; i < bytes_to_send; i++) {
- tmp[fill_index] = tdi_chain[i];
- fill_index++;
- tmp[fill_index] = tms_chain[i];
- fill_index++;
- }
-
- /* jlink.c calls the routine below, which may be useful for debugging purposes.
- For example, enabling this allows you to compare the log outputs from jlink.c
- and from this module for JTAG development or troubleshooting purposes. */
- if (false) {
- last_tap_state = jtag_debug_state_machine(tms_chain, tdi_chain,
- tap_chain_index, last_tap_state);
- }
-
- ret = buspirate_serial_write(buspirate_fd, tmp, CMD_TAP_SHIFT_HEADER_LEN + bytes_to_send*2);
- if (ret != bytes_to_send*2+CMD_TAP_SHIFT_HEADER_LEN) {
- LOG_ERROR("error writing :(");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- ret = buspirate_serial_read(buspirate_fd, tmp, bytes_to_send + CMD_TAP_SHIFT_HEADER_LEN);
- if (ret != bytes_to_send + CMD_TAP_SHIFT_HEADER_LEN) {
- LOG_ERROR("error reading");
- return ERROR_FAIL;
- }
- in_buf = (uint8_t *)(&tmp[CMD_TAP_SHIFT_HEADER_LEN]);
-
- /* parse the scans */
- for (i = 0; i < tap_pending_scans_num; i++) {
- uint8_t *buffer = tap_pending_scans[i].buffer;
- int length = tap_pending_scans[i].length;
- int first = tap_pending_scans[i].first;
- struct scan_command *command = tap_pending_scans[i].command;
-
- /* copy bits from buffer */
- buf_set_buf(in_buf, first, buffer, 0, length);
-
- /* return buffer to higher level */
- if (jtag_read_buffer(buffer, command) != ERROR_OK) {
- buspirate_tap_init();
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- free(buffer);
- }
- buspirate_tap_init();
- return ERROR_OK;
-}
-
-static void buspirate_tap_make_space(int scans, int bits)
-{
- int have_scans = BUSPIRATE_MAX_PENDING_SCANS - tap_pending_scans_num;
- int have_bits = BUSPIRATE_BUFFER_SIZE * 8 - tap_chain_index;
-
- if ((have_scans < scans) || (have_bits < bits))
- buspirate_tap_execute();
-}
-
-static void buspirate_tap_append(int tms, int tdi)
-{
- int chain_index;
-
- buspirate_tap_make_space(0, 1);
- chain_index = tap_chain_index / 8;
-
- if (chain_index < BUSPIRATE_BUFFER_SIZE) {
- int bit_index = tap_chain_index % 8;
- uint8_t bit = 1 << bit_index;
-
- if (0 == bit_index) {
- /* Let's say that the TAP shift operation wants to shift 9 bits,
- so we will be sending to the Bus Pirate a bit count of 9 but still
- full 16 bits (2 bytes) of shift data.
- If we don't clear all bits at this point, the last 7 bits will contain
- random data from the last buffer contents, which is not pleasant to the eye.
- Besides, the Bus Pirate (or some clone) may want to assert in debug builds
- that, after consuming all significant data bits, the rest of them are zero.
- Therefore, for aesthetic and for assert purposes, we clear all bits below. */
- tms_chain[chain_index] = 0;
- tdi_chain[chain_index] = 0;
- }
-
- if (tms)
- tms_chain[chain_index] |= bit;
- else
- tms_chain[chain_index] &= ~bit;
-
- if (tdi)
- tdi_chain[chain_index] |= bit;
- else
- tdi_chain[chain_index] &= ~bit;
-
- tap_chain_index++;
- } else {
- LOG_ERROR("tap_chain overflow, bad things will happen");
- /* Exit abruptly, like jlink.c does. After a buffer overflow we don't want
- to carry on, as data will be corrupt. Another option would be to return
- some error code at this point. */
- exit(-1);
- }
-}
-
-static void buspirate_tap_append_scan(int length, uint8_t *buffer,
- struct scan_command *command)
-{
- int i;
- tap_pending_scans[tap_pending_scans_num].length = length;
- tap_pending_scans[tap_pending_scans_num].buffer = buffer;
- tap_pending_scans[tap_pending_scans_num].command = command;
- tap_pending_scans[tap_pending_scans_num].first = tap_chain_index;
-
- for (i = 0; i < length; i++) {
- int tms = (i < length-1 ? 0 : 1);
- int tdi = (buffer[i/8] >> (i%8)) & 1;
- buspirate_tap_append(tms, tdi);
- }
- tap_pending_scans_num++;
-}
-
-/*************** jtag wrapper functions *********************/
-
-/* (1) assert or (0) deassert reset lines */
-static void buspirate_reset(int trst, int srst)
-{
- LOG_DEBUG("trst: %i, srst: %i", trst, srst);
-
- if (trst)
- buspirate_jtag_set_feature(buspirate_fd,
- FEATURE_TRST, ACTION_DISABLE);
- else
- buspirate_jtag_set_feature(buspirate_fd,
- FEATURE_TRST, ACTION_ENABLE);
-
- if (srst)
- buspirate_jtag_set_feature(buspirate_fd,
- FEATURE_SRST, ACTION_DISABLE);
- else
- buspirate_jtag_set_feature(buspirate_fd,
- FEATURE_SRST, ACTION_ENABLE);
-}
-
-/*************** jtag lowlevel functions ********************/
-static void buspirate_jtag_enable(int fd)
-{
- int ret;
- char tmp[21] = { [0 ... 20] = 0x00 };
- int done = 0;
- int cmd_sent = 0;
-
- LOG_DEBUG("Entering binary mode");
- buspirate_serial_write(fd, tmp, 20);
- usleep(10000);
-
- /* reads 1 to n "BBIO1"s and one "OCD1" */
- while (!done) {
- ret = buspirate_serial_read(fd, tmp, 4);
- if (ret != 4) {
- LOG_ERROR("Buspirate error. Is binary"
- "/OpenOCD support enabled?");
- exit(-1);
- }
- if (strncmp(tmp, "BBIO", 4) == 0) {
- ret = buspirate_serial_read(fd, tmp, 1);
- if (ret != 1) {
- LOG_ERROR("Buspirate did not answer correctly! "
- "Do you have correct firmware?");
- exit(-1);
- }
- if (tmp[0] != '1') {
- LOG_ERROR("Unsupported binary protocol");
- exit(-1);
- }
- if (cmd_sent == 0) {
- cmd_sent = 1;
- tmp[0] = CMD_ENTER_OOCD;
- ret = buspirate_serial_write(fd, tmp, 1);
- if (ret != 1) {
- LOG_ERROR("error reading");
- exit(-1);
- }
- }
- } else if (strncmp(tmp, "OCD1", 4) == 0)
- done = 1;
- else {
- LOG_ERROR("Buspirate did not answer correctly! "
- "Do you have correct firmware?");
- exit(-1);
- }
- }
-
-}
-
-static void buspirate_jtag_reset(int fd)
-{
- char tmp[5];
-
- tmp[0] = 0x00; /* exit OCD1 mode */
- buspirate_serial_write(fd, tmp, 1);
- usleep(10000);
- /* We ignore the return value here purposly, nothing we can do */
- buspirate_serial_read(fd, tmp, 5);
- if (strncmp(tmp, "BBIO1", 5) == 0) {
- tmp[0] = 0x0F; /* reset BP */
- buspirate_serial_write(fd, tmp, 1);
- } else
- LOG_ERROR("Unable to restart buspirate!");
-}
-
-static void buspirate_jtag_set_speed(int fd, char speed)
-{
- int ret;
- char tmp[2];
- char ack[2];
-
- ack[0] = 0xAA;
- ack[1] = 0x55;
-
- tmp[0] = CMD_UART_SPEED;
- tmp[1] = speed;
- buspirate_jtag_command(fd, tmp, 2);
-
- /* here the adapter changes speed, we need follow */
- if (-1 == buspirate_serial_setspeed(fd, speed, NORMAL_TIMEOUT)) {
- LOG_ERROR("Error configuring the serial port.");
- exit(-1);
- }
-
- buspirate_serial_write(fd, ack, 2);
- ret = buspirate_serial_read(fd, tmp, 2);
- if (ret != 2) {
- LOG_ERROR("Buspirate did not ack speed change");
- exit(-1);
- }
- if ((tmp[0] != CMD_UART_SPEED) || (tmp[1] != speed)) {
- LOG_ERROR("Buspirate did not reply as expected to the speed change command");
- exit(-1);
- }
- LOG_INFO("Buspirate switched to %s mode",
- (speed == SERIAL_NORMAL) ? "normal" : "FAST");
-}
-
-
-static void buspirate_jtag_set_mode(int fd, char mode)
-{
- char tmp[2];
- tmp[0] = CMD_PORT_MODE;
- tmp[1] = mode;
- buspirate_jtag_command(fd, tmp, 2);
-}
-
-static void buspirate_jtag_set_feature(int fd, char feat, char action)
-{
- char tmp[3];
- tmp[0] = CMD_FEATURE;
- tmp[1] = feat; /* what */
- tmp[2] = action; /* action */
- buspirate_jtag_command(fd, tmp, 3);
-}
-
-static void buspirate_jtag_get_adcs(int fd)
-{
- uint8_t tmp[10];
- uint16_t a, b, c, d;
- tmp[0] = CMD_READ_ADCS;
- buspirate_jtag_command(fd, (char *)tmp, 1);
- a = tmp[2] << 8 | tmp[3];
- b = tmp[4] << 8 | tmp[5];
- c = tmp[6] << 8 | tmp[7];
- d = tmp[8] << 8 | tmp[9];
-
- LOG_INFO("ADC: ADC_Pin = %.02f VPullup = %.02f V33 = %.02f "
- "V50 = %.02f",
- ((float)a)/155.1515, ((float)b)/155.1515,
- ((float)c)/155.1515, ((float)d)/155.1515);
-}
-
-static unsigned char buspirate_jtag_command(int fd,
- char *cmd, int cmdlen)
-{
- int res;
- int len = 0;
-
- res = buspirate_serial_write(fd, cmd, cmdlen);
-
- if ((cmd[0] == CMD_UART_SPEED)
- || (cmd[0] == CMD_PORT_MODE)
- || (cmd[0] == CMD_FEATURE)
- || (cmd[0] == CMD_JTAG_SPEED))
- return 1;
-
- if (res == cmdlen) {
- switch (cmd[0]) {
- case CMD_READ_ADCS:
- len = 10; /* 2*sizeof(char)+4*sizeof(uint16_t) */
- break;
- case CMD_TAP_SHIFT:
- len = cmdlen;
- break;
- default:
- LOG_INFO("Wrong !");
- }
- res = buspirate_serial_read(fd, cmd, len);
- if (res > 0)
- return (unsigned char)cmd[1];
- else
- return -1;
- } else
- return -1;
- return 0;
-}
-
-/* low level serial port */
-/* TODO add support for WIN32 and others ! */
-static int buspirate_serial_open(char *port)
-{
- int fd;
- fd = open(buspirate_port, O_RDWR | O_NOCTTY | O_NDELAY);
- return fd;
-}
-
-
-/* Returns -1 on error. */
-
-static int buspirate_serial_setspeed(int fd, char speed, cc_t timeout)
-{
- struct termios t_opt;
- speed_t baud = (speed == SERIAL_FAST) ? B1000000 : B115200;
-
- /* set the serial port parameters */
- fcntl(fd, F_SETFL, 0);
- if (0 != tcgetattr(fd, &t_opt))
- return -1;
-
- if (0 != cfsetispeed(&t_opt, baud))
- return -1;
-
- if (0 != cfsetospeed(&t_opt, baud))
- return -1;
-
- t_opt.c_cflag |= (CLOCAL | CREAD);
- t_opt.c_cflag &= ~PARENB;
- t_opt.c_cflag &= ~CSTOPB;
- t_opt.c_cflag &= ~CSIZE;
- t_opt.c_cflag |= CS8;
- t_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
-
- /* The serial port may have been configured for human interaction with
- the Bus Pirate console, but OpenOCD is going to use a binary protocol,
- so make sure to turn off any CR/LF translation and the like. */
- t_opt.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL);
-
- t_opt.c_oflag &= ~OPOST;
- t_opt.c_cc[VMIN] = 0;
- t_opt.c_cc[VTIME] = timeout;
-
- /* Note that, in the past, TCSANOW was used below instead of TCSADRAIN,
- and CMD_UART_SPEED did not work properly then, at least with
- the Bus Pirate v3.5 (USB). */
- if (0 != tcsetattr(fd, TCSADRAIN, &t_opt)) {
- /* According to the Linux documentation, this is actually not enough
- to detect errors, you need to call tcgetattr() and check that
- all changes have been performed successfully. */
- return -1;
- }
-
- return 0;
-}
-
-static int buspirate_serial_write(int fd, char *buf, int size)
-{
- int ret = 0;
-
- ret = write(fd, buf, size);
-
- LOG_DEBUG("size = %d ret = %d", size, ret);
- buspirate_print_buffer(buf, size);
-
- if (ret != size)
- LOG_ERROR("Error sending data");
-
- return ret;
-}
-
-static int buspirate_serial_read(int fd, char *buf, int size)
-{
- int len = 0;
- int ret = 0;
- int timeout = 0;
-
- while (len < size) {
- ret = read(fd, buf+len, size-len);
- if (ret == -1)
- return -1;
-
- if (ret == 0) {
- timeout++;
-
- if (timeout >= 10)
- break;
-
- continue;
- }
-
- len += ret;
- }
-
- LOG_DEBUG("should have read = %d actual size = %d", size, len);
- buspirate_print_buffer(buf, len);
-
- if (len != size)
- LOG_ERROR("Error reading data");
-
- return len;
-}
-
-static void buspirate_serial_close(int fd)
-{
- close(fd);
-}
-
-#define LINE_SIZE 81
-#define BYTES_PER_LINE 16
-static void buspirate_print_buffer(char *buf, int size)
-{
- char line[LINE_SIZE];
- char tmp[10];
- int offset = 0;
-
- line[0] = 0;
- while (offset < size) {
- snprintf(tmp, 5, "%02x ", (uint8_t)buf[offset]);
- offset++;
-
- strcat(line, tmp);
-
- if (offset % BYTES_PER_LINE == 0) {
- LOG_DEBUG("%s", line);
- line[0] = 0;
- }
- }
-
- if (line[0] != 0)
- LOG_DEBUG("%s", line);
-}
diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c
deleted file mode 100644
index a07064b..0000000
--- a/src/jtag/drivers/cmsis_dap_usb.c
+++ /dev/null
@@ -1,1630 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2016 by Maksym Hilliaka *
- * oter@frozen-team.com *
- * *
- * Copyright (C) 2016 by Phillip Pearson *
- * pp@myelin.co.nz *
- * *
- * Copyright (C) 2014 by Paul Fertser *
- * fercerpav@gmail.com *
- * *
- * Copyright (C) 2013 by mike brown *
- * mike@theshedworks.org.uk *
- * *
- * Copyright (C) 2013 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <transport/transport.h>
-#include <jtag/swd.h>
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <jtag/tcl.h>
-
-#include <hidapi.h>
-
-/*
- * See CMSIS-DAP documentation:
- * Version 0.01 - Beta.
- */
-
-/* USB Config */
-
-/* Known vid/pid pairs:
- * VID 0xc251: Keil Software
- * PID 0xf001: LPC-Link-II CMSIS_DAP
- * PID 0xf002: OPEN-SDA CMSIS_DAP (Freedom Board)
- * PID 0x2722: Keil ULINK2 CMSIS-DAP
- *
- * VID 0x0d28: mbed Software
- * PID 0x0204: MBED CMSIS-DAP
- */
-
-#define MAX_USB_IDS 8
-/* vid = pid = 0 marks the end of the list */
-static uint16_t cmsis_dap_vid[MAX_USB_IDS + 1] = { 0 };
-static uint16_t cmsis_dap_pid[MAX_USB_IDS + 1] = { 0 };
-static wchar_t *cmsis_dap_serial;
-static bool swd_mode;
-
-#define PACKET_SIZE (64 + 1) /* 64 bytes plus report id */
-#define USB_TIMEOUT 1000
-
-/* CMSIS-DAP General Commands */
-#define CMD_DAP_INFO 0x00
-#define CMD_DAP_LED 0x01
-#define CMD_DAP_CONNECT 0x02
-#define CMD_DAP_DISCONNECT 0x03
-#define CMD_DAP_WRITE_ABORT 0x08
-#define CMD_DAP_DELAY 0x09
-#define CMD_DAP_RESET_TARGET 0x0A
-
-/* CMD_INFO */
-#define INFO_ID_VID 0x00 /* string */
-#define INFO_ID_PID 0x02 /* string */
-#define INFO_ID_SERNUM 0x03 /* string */
-#define INFO_ID_FW_VER 0x04 /* string */
-#define INFO_ID_TD_VEND 0x05 /* string */
-#define INFO_ID_TD_NAME 0x06 /* string */
-#define INFO_ID_CAPS 0xf0 /* byte */
-#define INFO_ID_PKT_CNT 0xfe /* byte */
-#define INFO_ID_PKT_SZ 0xff /* short */
-
-#define INFO_CAPS_SWD 0x01
-#define INFO_CAPS_JTAG 0x02
-
-/* CMD_LED */
-#define LED_ID_CONNECT 0x00
-#define LED_ID_RUN 0x01
-
-#define LED_OFF 0x00
-#define LED_ON 0x01
-
-/* CMD_CONNECT */
-#define CONNECT_DEFAULT 0x00
-#define CONNECT_SWD 0x01
-#define CONNECT_JTAG 0x02
-
-/* CMSIS-DAP Common SWD/JTAG Commands */
-#define CMD_DAP_DELAY 0x09
-#define CMD_DAP_SWJ_PINS 0x10
-#define CMD_DAP_SWJ_CLOCK 0x11
-#define CMD_DAP_SWJ_SEQ 0x12
-
-/*
- * PINS
- * Bit 0: SWCLK/TCK
- * Bit 1: SWDIO/TMS
- * Bit 2: TDI
- * Bit 3: TDO
- * Bit 5: nTRST
- * Bit 7: nRESET
- */
-
-/* CMSIS-DAP SWD Commands */
-#define CMD_DAP_SWD_CONFIGURE 0x13
-
-/* CMSIS-DAP JTAG Commands */
-#define CMD_DAP_JTAG_SEQ 0x14
-#define CMD_DAP_JTAG_CONFIGURE 0x15
-#define CMD_DAP_JTAG_IDCODE 0x16
-
-/* CMSIS-DAP JTAG sequence info masks */
-/* Number of bits to clock through (0 means 64) */
-#define DAP_JTAG_SEQ_TCK 0x3F
-/* TMS will be set during the sequence if this bit is set */
-#define DAP_JTAG_SEQ_TMS 0x40
-/* TDO output will be captured if this bit is set */
-#define DAP_JTAG_SEQ_TDO 0x80
-
-
-/* CMSIS-DAP Transfer Commands */
-#define CMD_DAP_TFER_CONFIGURE 0x04
-#define CMD_DAP_TFER 0x05
-#define CMD_DAP_TFER_BLOCK 0x06
-#define CMD_DAP_TFER_ABORT 0x07
-
-/* DAP Status Code */
-#define DAP_OK 0
-#define DAP_ERROR 0xFF
-
-/* CMSIS-DAP Vendor Commands
- * None as yet... */
-
-static const char * const info_caps_str[] = {
- "SWD Supported",
- "JTAG Supported"
-};
-
-/* max clock speed (kHz) */
-#define DAP_MAX_CLOCK 5000
-
-struct cmsis_dap {
- hid_device *dev_handle;
- uint16_t packet_size;
- uint16_t packet_count;
- uint8_t *packet_buffer;
- uint8_t caps;
- uint8_t mode;
-};
-
-struct pending_transfer_result {
- uint8_t cmd;
- uint32_t data;
- void *buffer;
-};
-
-struct pending_scan_result {
- /** Offset in bytes in the CMD_DAP_JTAG_SEQ response buffer. */
- unsigned first;
- /** Number of bits to read. */
- unsigned length;
- /** Location to store the result */
- uint8_t *buffer;
- /** Offset in the destination buffer */
- unsigned buffer_offset;
-};
-
-static int pending_transfer_count, pending_queue_len;
-static struct pending_transfer_result *pending_transfers;
-
-/* pointers to buffers that will receive jtag scan results on the next flush */
-#define MAX_PENDING_SCAN_RESULTS 256
-static int pending_scan_result_count;
-static struct pending_scan_result pending_scan_results[MAX_PENDING_SCAN_RESULTS];
-
-/* queued JTAG sequences that will be executed on the next flush */
-#define QUEUED_SEQ_BUF_LEN (cmsis_dap_handle->packet_size - 3)
-static int queued_seq_count;
-static int queued_seq_buf_end;
-static int queued_seq_tdo_ptr;
-static uint8_t queued_seq_buf[1024]; /* TODO: make dynamic / move into cmsis object */
-
-static int queued_retval;
-
-static struct cmsis_dap *cmsis_dap_handle;
-
-static int cmsis_dap_usb_open(void)
-{
- hid_device *dev = NULL;
- int i;
- struct hid_device_info *devs, *cur_dev;
- unsigned short target_vid, target_pid;
- wchar_t *target_serial = NULL;
-
- bool found = false;
- bool serial_found = false;
-
- target_vid = 0;
- target_pid = 0;
-
- /*
- * The CMSIS-DAP specification stipulates:
- * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the
- * debuggers to identify a CMSIS-DAP compliant Debug Unit that is connected to a host computer."
- */
- devs = hid_enumerate(0x0, 0x0);
- cur_dev = devs;
- while (NULL != cur_dev) {
- if (0 == cmsis_dap_vid[0]) {
- if (NULL == cur_dev->product_string) {
- LOG_DEBUG("Cannot read product string of device 0x%x:0x%x",
- cur_dev->vendor_id, cur_dev->product_id);
- } else {
- if (wcsstr(cur_dev->product_string, L"CMSIS-DAP")) {
- /* if the user hasn't specified VID:PID *and*
- * product string contains "CMSIS-DAP", pick it
- */
- found = true;
- }
- }
- } else {
- /* otherwise, exhaustively compare against all VID:PID in list */
- for (i = 0; cmsis_dap_vid[i] || cmsis_dap_pid[i]; i++) {
- if ((cmsis_dap_vid[i] == cur_dev->vendor_id) && (cmsis_dap_pid[i] == cur_dev->product_id))
- found = true;
- }
-
- if (cmsis_dap_vid[i] || cmsis_dap_pid[i])
- found = true;
- }
-
- if (found) {
- /* we have found an adapter, so exit further checks */
- /* check serial number matches if given */
- if (cmsis_dap_serial != NULL) {
- if ((cur_dev->serial_number != NULL) && wcscmp(cmsis_dap_serial, cur_dev->serial_number) == 0) {
- serial_found = true;
- break;
- }
- } else
- break;
-
- found = false;
- }
-
- cur_dev = cur_dev->next;
- }
-
- if (NULL != cur_dev) {
- target_vid = cur_dev->vendor_id;
- target_pid = cur_dev->product_id;
- if (serial_found)
- target_serial = cmsis_dap_serial;
- }
-
- hid_free_enumeration(devs);
-
- if (target_vid == 0 && target_pid == 0) {
- LOG_ERROR("unable to find CMSIS-DAP device");
- return ERROR_FAIL;
- }
-
- if (hid_init() != 0) {
- LOG_ERROR("unable to open HIDAPI");
- return ERROR_FAIL;
- }
-
- dev = hid_open(target_vid, target_pid, target_serial);
-
- if (dev == NULL) {
- LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid);
- return ERROR_FAIL;
- }
-
- struct cmsis_dap *dap = malloc(sizeof(struct cmsis_dap));
- if (dap == NULL) {
- LOG_ERROR("unable to allocate memory");
- return ERROR_FAIL;
- }
-
- dap->dev_handle = dev;
- dap->caps = 0;
- dap->mode = 0;
-
- cmsis_dap_handle = dap;
-
- /* allocate default packet buffer, may be changed later.
- * currently with HIDAPI we have no way of getting the output report length
- * without this info we cannot communicate with the adapter.
- * For the moment we ahve to hard code the packet size */
-
- int packet_size = PACKET_SIZE;
-
- /* atmel cmsis-dap uses 512 byte reports */
- /* TODO: HID report descriptor should be parsed instead of
- * hardcoding a match by VID */
- if (target_vid == 0x03eb)
- packet_size = 512 + 1;
-
- cmsis_dap_handle->packet_buffer = malloc(packet_size);
- cmsis_dap_handle->packet_size = packet_size;
-
- if (cmsis_dap_handle->packet_buffer == NULL) {
- LOG_ERROR("unable to allocate memory");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static void cmsis_dap_usb_close(struct cmsis_dap *dap)
-{
- hid_close(dap->dev_handle);
- hid_exit();
-
- free(cmsis_dap_handle->packet_buffer);
- free(cmsis_dap_handle);
- cmsis_dap_handle = NULL;
- free(cmsis_dap_serial);
- cmsis_dap_serial = NULL;
- free(pending_transfers);
- pending_transfers = NULL;
-
- return;
-}
-
-/* Send a message and receive the reply */
-static int cmsis_dap_usb_xfer(struct cmsis_dap *dap, int txlen)
-{
-#ifdef CMSIS_DAP_JTAG_DEBUG
- LOG_DEBUG("cmsis-dap usb xfer cmd=%02X", dap->packet_buffer[1]);
-#endif
- /* Pad the rest of the TX buffer with 0's */
- memset(dap->packet_buffer + txlen, 0, dap->packet_size - txlen);
-
- /* write data to device */
- int retval = hid_write(dap->dev_handle, dap->packet_buffer, dap->packet_size);
- if (retval == -1) {
- LOG_ERROR("error writing data: %ls", hid_error(dap->dev_handle));
- return ERROR_FAIL;
- }
-
- /* get reply */
- retval = hid_read_timeout(dap->dev_handle, dap->packet_buffer, dap->packet_size, USB_TIMEOUT);
- if (retval == -1 || retval == 0) {
- LOG_DEBUG("error reading data: %ls", hid_error(dap->dev_handle));
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_SWJ_Pins(uint8_t pins, uint8_t mask, uint32_t delay, uint8_t *input)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_SWJ_PINS;
- buffer[2] = pins;
- buffer[3] = mask;
- buffer[4] = delay & 0xff;
- buffer[5] = (delay >> 8) & 0xff;
- buffer[6] = (delay >> 16) & 0xff;
- buffer[7] = (delay >> 24) & 0xff;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 8);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_PINS failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (input)
- *input = buffer[1];
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- /* set clock in Hz */
- swj_clock *= 1000;
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_SWJ_CLOCK;
- buffer[2] = swj_clock & 0xff;
- buffer[3] = (swj_clock >> 8) & 0xff;
- buffer[4] = (swj_clock >> 16) & 0xff;
- buffer[5] = (swj_clock >> 24) & 0xff;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 6);
-
- if (retval != ERROR_OK || buffer[1] != DAP_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_CLOCK failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-/* clock a sequence of bits out on TMS, to change JTAG states */
-static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t *sequence)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
-#ifdef CMSIS_DAP_JTAG_DEBUG
- LOG_DEBUG("cmsis-dap TMS sequence: len=%d", s_len);
- for (int i = 0; i < DIV_ROUND_UP(s_len, 8); ++i)
- printf("%02X ", sequence[i]);
-
- printf("\n");
-#endif
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_SWJ_SEQ;
- buffer[2] = s_len;
- bit_copy(&buffer[3], 0, sequence, 0, s_len);
-
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3);
-
- if (retval != ERROR_OK || buffer[1] != DAP_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_INFO;
- buffer[2] = info;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_INFO failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- *data = &(buffer[1]);
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_LED(uint8_t leds)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_LED;
- buffer[2] = 0x00;
- buffer[3] = leds;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4);
-
- if (retval != ERROR_OK || buffer[1] != 0x00) {
- LOG_ERROR("CMSIS-DAP command CMD_LED failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_Connect(uint8_t mode)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_CONNECT;
- buffer[2] = mode;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_CONNECT failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (buffer[1] != mode) {
- LOG_ERROR("CMSIS-DAP failed to connect in mode (%d)", mode);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_Disconnect(void)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_DISCONNECT;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 2);
-
- if (retval != ERROR_OK || buffer[1] != DAP_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_DISCONNECT failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_TFER_Configure(uint8_t idle, uint16_t retry_count, uint16_t match_retry)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_TFER_CONFIGURE;
- buffer[2] = idle;
- buffer[3] = retry_count & 0xff;
- buffer[4] = (retry_count >> 8) & 0xff;
- buffer[5] = match_retry & 0xff;
- buffer[6] = (match_retry >> 8) & 0xff;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 7);
-
- if (retval != ERROR_OK || buffer[1] != DAP_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_TFER_Configure failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_cmd_DAP_SWD_Configure(uint8_t cfg)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_SWD_CONFIGURE;
- buffer[2] = cfg;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3);
-
- if (retval != ERROR_OK || buffer[1] != DAP_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_SWD_Configure failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-#if 0
-static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us)
-{
- int retval;
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_DELAY;
- buffer[2] = delay_us & 0xff;
- buffer[3] = (delay_us >> 8) & 0xff;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4);
-
- if (retval != ERROR_OK || buffer[1] != DAP_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_Delay failed.");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-#endif
-
-static int cmsis_dap_swd_run_queue(void)
-{
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
-
- LOG_DEBUG("Executing %d queued transactions", pending_transfer_count);
-
- if (queued_retval != ERROR_OK) {
- LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
- goto skip;
- }
-
- if (!pending_transfer_count)
- goto skip;
-
- size_t idx = 0;
- buffer[idx++] = 0; /* report number */
- buffer[idx++] = CMD_DAP_TFER;
- buffer[idx++] = 0x00; /* DAP Index */
- buffer[idx++] = pending_transfer_count;
-
- for (int i = 0; i < pending_transfer_count; i++) {
- uint8_t cmd = pending_transfers[i].cmd;
- uint32_t data = pending_transfers[i].data;
-
- LOG_DEBUG("%s %s reg %x %"PRIx32,
- cmd & SWD_CMD_APnDP ? "AP" : "DP",
- cmd & SWD_CMD_RnW ? "read" : "write",
- (cmd & SWD_CMD_A32) >> 1, data);
-
- /* When proper WAIT handling is implemented in the
- * common SWD framework, this kludge can be
- * removed. However, this might lead to minor
- * performance degradation as the adapter wouldn't be
- * able to automatically retry anything (because ARM
- * has forgotten to implement sticky error flags
- * clearing). See also comments regarding
- * cmsis_dap_cmd_DAP_TFER_Configure() and
- * cmsis_dap_cmd_DAP_SWD_Configure() in
- * cmsis_dap_init().
- */
- if (!(cmd & SWD_CMD_RnW) &&
- !(cmd & SWD_CMD_APnDP) &&
- (cmd & SWD_CMD_A32) >> 1 == DP_CTRL_STAT &&
- (data & CORUNDETECT)) {
- LOG_DEBUG("refusing to enable sticky overrun detection");
- data &= ~CORUNDETECT;
- }
-
- buffer[idx++] = (cmd >> 1) & 0x0f;
- if (!(cmd & SWD_CMD_RnW)) {
- buffer[idx++] = (data) & 0xff;
- buffer[idx++] = (data >> 8) & 0xff;
- buffer[idx++] = (data >> 16) & 0xff;
- buffer[idx++] = (data >> 24) & 0xff;
- }
- }
-
- queued_retval = cmsis_dap_usb_xfer(cmsis_dap_handle, idx);
- if (queued_retval != ERROR_OK)
- goto skip;
-
- idx = 2;
- uint8_t ack = buffer[idx] & 0x07;
- if (ack != SWD_ACK_OK || (buffer[idx] & 0x08)) {
- LOG_DEBUG("SWD ack not OK: %d %s", buffer[idx-1],
- ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
- queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
- goto skip;
- }
- idx++;
-
- if (pending_transfer_count != buffer[1])
- LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d",
- pending_transfer_count, buffer[1]);
-
- for (int i = 0; i < buffer[1]; i++) {
- if (pending_transfers[i].cmd & SWD_CMD_RnW) {
- static uint32_t last_read;
- uint32_t data = le_to_h_u32(&buffer[idx]);
- uint32_t tmp = data;
- idx += 4;
-
- LOG_DEBUG("Read result: %"PRIx32, data);
-
- /* Imitate posted AP reads */
- if ((pending_transfers[i].cmd & SWD_CMD_APnDP) ||
- ((pending_transfers[i].cmd & SWD_CMD_A32) >> 1 == DP_RDBUFF)) {
- tmp = last_read;
- last_read = data;
- }
-
- if (pending_transfers[i].buffer)
- *(uint32_t *)pending_transfers[i].buffer = tmp;
- }
- }
-
-skip:
- pending_transfer_count = 0;
- int retval = queued_retval;
- queued_retval = ERROR_OK;
-
- return retval;
-}
-
-static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
-{
- if (pending_transfer_count == pending_queue_len) {
- /* Not enough room in the queue. Run the queue. */
- queued_retval = cmsis_dap_swd_run_queue();
- }
-
- if (queued_retval != ERROR_OK)
- return;
-
- pending_transfers[pending_transfer_count].data = data;
- pending_transfers[pending_transfer_count].cmd = cmd;
- if (cmd & SWD_CMD_RnW) {
- /* Queue a read transaction */
- pending_transfers[pending_transfer_count].buffer = dst;
- }
- pending_transfer_count++;
-}
-
-static void cmsis_dap_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
-{
- assert(!(cmd & SWD_CMD_RnW));
- cmsis_dap_swd_queue_cmd(cmd, NULL, value);
-}
-
-static void cmsis_dap_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
-{
- assert(cmd & SWD_CMD_RnW);
- cmsis_dap_swd_queue_cmd(cmd, value, 0);
-}
-
-static int cmsis_dap_get_version_info(void)
-{
- uint8_t *data;
-
- /* INFO_ID_FW_VER - string */
- int retval = cmsis_dap_cmd_DAP_Info(INFO_ID_FW_VER, &data);
- if (retval != ERROR_OK)
- return retval;
-
- if (data[0]) /* strlen */
- LOG_INFO("CMSIS-DAP: FW Version = %s", &data[1]);
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_get_caps_info(void)
-{
- uint8_t *data;
-
- /* INFO_ID_CAPS - byte */
- int retval = cmsis_dap_cmd_DAP_Info(INFO_ID_CAPS, &data);
- if (retval != ERROR_OK)
- return retval;
-
- if (data[0] == 1) {
- uint8_t caps = data[1];
-
- cmsis_dap_handle->caps = caps;
-
- if (caps & INFO_CAPS_SWD)
- LOG_INFO("CMSIS-DAP: %s", info_caps_str[0]);
- if (caps & INFO_CAPS_JTAG)
- LOG_INFO("CMSIS-DAP: %s", info_caps_str[1]);
- }
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_get_status(void)
-{
- uint8_t d;
-
- int retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, 0, 0, &d);
-
- if (retval == ERROR_OK) {
- LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d",
- (d & (0x01 << 0)) ? 1 : 0, /* Bit 0: SWCLK/TCK */
- (d & (0x01 << 1)) ? 1 : 0, /* Bit 1: SWDIO/TMS */
- (d & (0x01 << 2)) ? 1 : 0, /* Bit 2: TDI */
- (d & (0x01 << 3)) ? 1 : 0, /* Bit 3: TDO */
- (d & (0x01 << 5)) ? 1 : 0, /* Bit 5: nTRST */
- (d & (0x01 << 7)) ? 1 : 0); /* Bit 7: nRESET */
- }
-
- return retval;
-}
-
-static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
-{
- const uint8_t *s;
- unsigned int s_len;
- int retval;
-
- /* First disconnect before connecting, Atmel EDBG needs it for SAMD/R/L/C */
- cmsis_dap_cmd_DAP_Disconnect();
-
- /* When we are reconnecting, DAP_Connect needs to be rerun, at
- * least on Keil ULINK-ME */
- retval = cmsis_dap_cmd_DAP_Connect(seq == LINE_RESET || seq == JTAG_TO_SWD ?
- CONNECT_SWD : CONNECT_JTAG);
- if (retval != ERROR_OK)
- return retval;
-
- switch (seq) {
- case LINE_RESET:
- LOG_DEBUG("SWD line reset");
- s = swd_seq_line_reset;
- s_len = swd_seq_line_reset_len;
- break;
- case JTAG_TO_SWD:
- LOG_DEBUG("JTAG-to-SWD");
- s = swd_seq_jtag_to_swd;
- s_len = swd_seq_jtag_to_swd_len;
- break;
- case SWD_TO_JTAG:
- LOG_DEBUG("SWD-to-JTAG");
- s = swd_seq_swd_to_jtag;
- s_len = swd_seq_swd_to_jtag_len;
- break;
- default:
- LOG_ERROR("Sequence %d not supported", seq);
- return ERROR_FAIL;
- }
-
- return cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s);
-}
-
-static int cmsis_dap_swd_open(void)
-{
- int retval;
-
- if (cmsis_dap_handle == NULL) {
- /* SWD init */
- retval = cmsis_dap_usb_open();
- if (retval != ERROR_OK)
- return retval;
-
- retval = cmsis_dap_get_caps_info();
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (!(cmsis_dap_handle->caps & INFO_CAPS_SWD)) {
- LOG_ERROR("CMSIS-DAP: SWD not supported");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- retval = cmsis_dap_cmd_DAP_Connect(CONNECT_SWD);
- if (retval != ERROR_OK)
- return retval;
-
- /* Add more setup here.??... */
-
- LOG_INFO("CMSIS-DAP: Interface Initialised (SWD)");
- return ERROR_OK;
-}
-
-static int cmsis_dap_init(void)
-{
- int retval;
- uint8_t *data;
-
- if (swd_mode) {
- retval = cmsis_dap_swd_open();
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (cmsis_dap_handle == NULL) {
-
- /* JTAG init */
- retval = cmsis_dap_usb_open();
- if (retval != ERROR_OK)
- return retval;
-
- retval = cmsis_dap_get_caps_info();
- if (retval != ERROR_OK)
- return retval;
-
- /* Connect in JTAG mode */
- if (!(cmsis_dap_handle->caps & INFO_CAPS_JTAG)) {
- LOG_ERROR("CMSIS-DAP: JTAG not supported");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- retval = cmsis_dap_cmd_DAP_Connect(CONNECT_JTAG);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_INFO("CMSIS-DAP: Interface Initialised (JTAG)");
- }
-
- retval = cmsis_dap_get_version_info();
- if (retval != ERROR_OK)
- return retval;
-
- /* INFO_ID_PKT_SZ - short */
- retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_SZ, &data);
- if (retval != ERROR_OK)
- return retval;
-
- if (data[0] == 2) { /* short */
- uint16_t pkt_sz = data[1] + (data[2] << 8);
-
- /* 4 bytes of command header + 5 bytes per register
- * write. For bulk read sequences just 4 bytes are
- * needed per transfer, so this is suboptimal. */
- pending_queue_len = (pkt_sz - 4) / 5;
- pending_transfers = malloc(pending_queue_len * sizeof(*pending_transfers));
- if (!pending_transfers) {
- LOG_ERROR("Unable to allocate memory for CMSIS-DAP queue");
- return ERROR_FAIL;
- }
-
- if (cmsis_dap_handle->packet_size != pkt_sz + 1) {
- /* reallocate buffer */
- cmsis_dap_handle->packet_size = pkt_sz + 1;
- cmsis_dap_handle->packet_buffer = realloc(cmsis_dap_handle->packet_buffer,
- cmsis_dap_handle->packet_size);
- if (cmsis_dap_handle->packet_buffer == NULL) {
- LOG_ERROR("unable to reallocate memory");
- return ERROR_FAIL;
- }
- }
-
- LOG_DEBUG("CMSIS-DAP: Packet Size = %" PRId16, pkt_sz);
- }
-
- /* INFO_ID_PKT_CNT - byte */
- retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_CNT, &data);
- if (retval != ERROR_OK)
- return retval;
-
- if (data[0] == 1) { /* byte */
- uint16_t pkt_cnt = data[1];
- cmsis_dap_handle->packet_count = pkt_cnt;
- LOG_DEBUG("CMSIS-DAP: Packet Count = %" PRId16, pkt_cnt);
- }
-
- retval = cmsis_dap_get_status();
- if (retval != ERROR_OK)
- return ERROR_FAIL;
-
- /* Now try to connect to the target
- * TODO: This is all SWD only @ present */
- retval = cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz());
- if (retval != ERROR_OK)
- return ERROR_FAIL;
-
- /* Ask CMSIS-DAP to automatically retry on receiving WAIT for
- * up to 64 times. This must be changed to 0 if sticky
- * overrun detection is enabled. */
- retval = cmsis_dap_cmd_DAP_TFER_Configure(0, 64, 0);
- if (retval != ERROR_OK)
- return ERROR_FAIL;
- /* Data Phase (bit 2) must be set to 1 if sticky overrun
- * detection is enabled */
- retval = cmsis_dap_cmd_DAP_SWD_Configure(0); /* 1 TRN, no Data Phase */
- if (retval != ERROR_OK)
- return ERROR_FAIL;
-
- retval = cmsis_dap_cmd_DAP_LED(0x03); /* Both LEDs on */
- if (retval != ERROR_OK)
- return ERROR_FAIL;
-
- /* support connecting with srst asserted */
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
- if (jtag_reset_config & RESET_SRST_NO_GATING) {
- retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, (1 << 7), 0, NULL);
- if (retval != ERROR_OK)
- return ERROR_FAIL;
- LOG_INFO("Connecting under reset");
- }
- }
-
- cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
-
- LOG_INFO("CMSIS-DAP: Interface ready");
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_swd_init(void)
-{
- swd_mode = true;
- return ERROR_OK;
-}
-
-static int cmsis_dap_quit(void)
-{
- cmsis_dap_cmd_DAP_Disconnect();
- cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
-
- cmsis_dap_usb_close(cmsis_dap_handle);
-
- return ERROR_OK;
-}
-
-static void cmsis_dap_execute_reset(struct jtag_command *cmd)
-{
- int retval = cmsis_dap_cmd_DAP_SWJ_Pins(cmd->cmd.reset->srst ? 0 : (1 << 7), \
- (1 << 7), 0, NULL);
- if (retval != ERROR_OK)
- LOG_ERROR("CMSIS-DAP: Interface reset failed");
-}
-
-static void cmsis_dap_execute_sleep(struct jtag_command *cmd)
-{
-#if 0
- int retval = cmsis_dap_cmd_DAP_Delay(cmd->cmd.sleep->us);
- if (retval != ERROR_OK)
-#endif
- jtag_sleep(cmd->cmd.sleep->us);
-}
-
-/* Set TMS high for five TCK clocks, to move the TAP to the Test-Logic-Reset state */
-static int cmsis_dap_execute_tlr_reset(struct jtag_command *cmd)
-{
- LOG_INFO("cmsis-dap JTAG TLR_RESET");
- uint8_t seq = 0xff;
- int ret = cmsis_dap_cmd_DAP_SWJ_Sequence(8, &seq);
- if (ret == ERROR_OK)
- tap_set_state(TAP_RESET);
- return ret;
-}
-
-/* Set new end state */
-static void cmsis_dap_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-#ifdef SPRINT_BINARY
-static void sprint_binary(char *s, const uint8_t *buf, int offset, int len)
-{
- if (!len)
- return;
-
- /*
- buf = { 0x18 } len=5 should result in: 11000
- buf = { 0xff 0x18 } len=13 should result in: 11111111 11000
- buf = { 0xc0 0x18 } offset=3 len=10 should result in: 11000 11000
- i=3 there means i/8 = 0 so c = 0xFF, and
- */
- for (int i = offset; i < offset + len; ++i) {
- uint8_t c = buf[i / 8], mask = 1 << (i % 8);
- if ((i != offset) && !(i % 8))
- putchar(' ');
- *s++ = (c & mask) ? '1' : '0';
- }
- *s = 0;
-}
-#endif
-
-#ifdef CMSIS_DAP_JTAG_DEBUG
-static void debug_parse_cmsis_buf(const uint8_t *cmd, int cmdlen)
-{
- /* cmd is a usb packet to go to the cmsis-dap interface */
- printf("cmsis-dap buffer (%d b): ", cmdlen);
- for (int i = 0; i < cmdlen; ++i)
- printf(" %02x", cmd[i]);
- printf("\n");
- switch (cmd[1]) {
- case CMD_DAP_JTAG_SEQ: {
- printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[1], cmd[2]);
- /*
- * #2 = number of sequences
- * #3 = sequence info 1
- * #4...4+n_bytes-1 = sequence 1
- * #4+n_bytes = sequence info 2
- * #5+n_bytes = sequence 2 (single bit)
- */
- int pos = 3;
- for (int seq = 0; seq < cmd[2]; ++seq) {
- uint8_t info = cmd[pos++];
- int len = info & DAP_JTAG_SEQ_TCK;
- if (len == 0)
- len = 64;
- printf(" sequence %d starting %d: info %02x (len=%d tms=%d read_tdo=%d): ",
- seq, pos, info, len, info & DAP_JTAG_SEQ_TMS, info & DAP_JTAG_SEQ_TDO);
- for (int i = 0; i < DIV_ROUND_UP(len, 8); ++i)
- printf(" %02x", cmd[pos+i]);
- pos += DIV_ROUND_UP(len, 8);
- printf("\n");
- }
- if (pos != cmdlen) {
- printf("BUFFER LENGTH MISMATCH looks like %d but %d specified", pos, cmdlen);
- exit(-1);
- }
-
- break;
- }
- default:
- LOG_DEBUG("unknown cmsis-dap command %02x", cmd[1]);
- break;
- }
-}
-#endif
-
-static void cmsis_dap_flush(void)
-{
- if (!queued_seq_count)
- return;
-
- DEBUG_JTAG_IO("Flushing %d queued sequences (%d bytes) with %d pending scan results to capture",
- queued_seq_count, queued_seq_buf_end, pending_scan_result_count);
-
- /* prep CMSIS-DAP packet */
- uint8_t *buffer = cmsis_dap_handle->packet_buffer;
- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_JTAG_SEQ;
- buffer[2] = queued_seq_count;
- memcpy(buffer + 3, queued_seq_buf, queued_seq_buf_end);
-
-#ifdef CMSIS_DAP_JTAG_DEBUG
- debug_parse_cmsis_buf(buffer, queued_seq_buf_end + 3);
-#endif
-
- /* send command to USB device */
- int retval = cmsis_dap_usb_xfer(cmsis_dap_handle, queued_seq_buf_end + 3);
- if (retval != ERROR_OK || buffer[1] != DAP_OK) {
- LOG_ERROR("CMSIS-DAP command CMD_DAP_JTAG_SEQ failed.");
- exit(-1);
- }
-
-#ifdef CMSIS_DAP_JTAG_DEBUG
- DEBUG_JTAG_IO("USB response buf:");
- for (int c = 0; c < queued_seq_buf_end + 3; ++c)
- printf("%02X ", buffer[c]);
- printf("\n");
-#endif
-
- /* copy scan results into client buffers */
- for (int i = 0; i < pending_scan_result_count; ++i) {
- struct pending_scan_result *scan = &pending_scan_results[i];
- DEBUG_JTAG_IO("Copying pending_scan_result %d/%d: %d bits from byte %d -> buffer + %d bits",
- i, pending_scan_result_count, scan->length, scan->first + 2, scan->buffer_offset);
-#ifdef CMSIS_DAP_JTAG_DEBUG
- for (uint32_t b = 0; b < DIV_ROUND_UP(scan->length, 8); ++b)
- printf("%02X ", buffer[2+scan->first+b]);
- printf("\n");
-#endif
- bit_copy(scan->buffer, scan->buffer_offset, buffer + 2 + scan->first, 0, scan->length);
- }
-
- /* reset */
- queued_seq_count = 0;
- queued_seq_buf_end = 0;
- queued_seq_tdo_ptr = 0;
- pending_scan_result_count = 0;
-}
-
-/* queue a sequence of bits to clock out TDI / in TDO, executing if the buffer is full.
- *
- * sequence=NULL means clock out zeros on TDI
- * tdo_buffer=NULL means don't capture TDO
- */
-static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int s_offset,
- bool tms, uint8_t *tdo_buffer, int tdo_buffer_offset)
-{
- DEBUG_JTAG_IO("[at %d] %d bits, tms %s, seq offset %d, tdo buf %p, tdo offset %d",
- queued_seq_buf_end,
- s_len, tms ? "HIGH" : "LOW", s_offset, tdo_buffer, tdo_buffer_offset);
-
- if (s_len == 0)
- return;
-
- if (s_len > 64) {
- DEBUG_JTAG_IO("START JTAG SEQ SPLIT");
- for (int offset = 0; offset < s_len; offset += 64) {
- int len = s_len - offset;
- if (len > 64)
- len = 64;
- DEBUG_JTAG_IO("Splitting long jtag sequence: %d-bit chunk starting at offset %d", len, offset);
- cmsis_dap_add_jtag_sequence(
- len,
- sequence,
- s_offset + offset,
- tms,
- tdo_buffer,
- tdo_buffer == NULL ? 0 : (tdo_buffer_offset + offset)
- );
- }
- DEBUG_JTAG_IO("END JTAG SEQ SPLIT");
- return;
- }
-
- int cmd_len = 1 + DIV_ROUND_UP(s_len, 8);
- if (queued_seq_count >= 255 || queued_seq_buf_end + cmd_len > QUEUED_SEQ_BUF_LEN)
- /* empty out the buffer */
- cmsis_dap_flush();
-
- ++queued_seq_count;
-
- /* control byte */
- queued_seq_buf[queued_seq_buf_end] =
- (tms ? DAP_JTAG_SEQ_TMS : 0) |
- (tdo_buffer != NULL ? DAP_JTAG_SEQ_TDO : 0) |
- (s_len == 64 ? 0 : s_len);
-
- if (sequence != NULL)
- bit_copy(&queued_seq_buf[queued_seq_buf_end + 1], 0, sequence, s_offset, s_len);
- else
- memset(&queued_seq_buf[queued_seq_buf_end + 1], 0, DIV_ROUND_UP(s_len, 8));
-
- queued_seq_buf_end += cmd_len;
-
- if (tdo_buffer != NULL) {
- struct pending_scan_result *scan = &pending_scan_results[pending_scan_result_count++];
- scan->first = queued_seq_tdo_ptr;
- queued_seq_tdo_ptr += DIV_ROUND_UP(s_len, 8);
- scan->length = s_len;
- scan->buffer = tdo_buffer;
- scan->buffer_offset = tdo_buffer_offset;
- }
-}
-
-/* queue a sequence of bits to clock out TMS, executing if the buffer is full */
-static void cmsis_dap_add_tms_sequence(const uint8_t *sequence, int s_len)
-{
- DEBUG_JTAG_IO("%d bits: %02X", s_len, *sequence);
- /* we use a series of CMD_DAP_JTAG_SEQ commands to toggle TMS,
- because even though it seems ridiculously inefficient, it
- allows us to combine TMS and scan sequences into the same
- USB packet. */
- /* TODO: combine runs of the same tms value */
- for (int i = 0; i < s_len; ++i) {
- bool bit = (sequence[i / 8] & (1 << (i % 8))) != 0;
- cmsis_dap_add_jtag_sequence(1, NULL, 0, bit, NULL, 0);
- }
-}
-
-/* Move to the end state by queuing a sequence to clock into TMS */
-static void cmsis_dap_state_move(void)
-{
- uint8_t tms_scan;
- uint8_t tms_scan_bits;
-
- tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
- tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
-
- DEBUG_JTAG_IO("state move from %s to %s: %d clocks, %02X on tms",
- tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()),
- tms_scan_bits, tms_scan);
- cmsis_dap_add_tms_sequence(&tms_scan, tms_scan_bits);
-
- tap_set_state(tap_get_end_state());
-}
-
-
-/* Execute a JTAG scan operation by queueing TMS and TDI/TDO sequences */
-static void cmsis_dap_execute_scan(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN",
- jtag_scan_type(cmd->cmd.scan));
-
- /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */
- while (cmd->cmd.scan->num_fields > 0
- && cmd->cmd.scan->fields[cmd->cmd.scan->num_fields - 1].num_bits == 0) {
- cmd->cmd.scan->num_fields--;
- LOG_DEBUG("discarding trailing empty field");
- }
-
- if (cmd->cmd.scan->num_fields == 0) {
- LOG_DEBUG("empty scan, doing nothing");
- return;
- }
-
- if (cmd->cmd.scan->ir_scan) {
- if (tap_get_state() != TAP_IRSHIFT) {
- cmsis_dap_end_state(TAP_IRSHIFT);
- cmsis_dap_state_move();
- }
- } else {
- if (tap_get_state() != TAP_DRSHIFT) {
- cmsis_dap_end_state(TAP_DRSHIFT);
- cmsis_dap_state_move();
- }
- }
-
- cmsis_dap_end_state(cmd->cmd.scan->end_state);
-
- struct scan_field *field = cmd->cmd.scan->fields;
- unsigned scan_size = 0;
-
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
- scan_size += field->num_bits;
- DEBUG_JTAG_IO("%s%s field %d/%d %d bits",
- field->in_value ? "in" : "",
- field->out_value ? "out" : "",
- i,
- cmd->cmd.scan->num_fields,
- field->num_bits);
-
- if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) {
- DEBUG_JTAG_IO("Last field and have to move out of SHIFT state");
- /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap
- * movement. This last field can't have length zero, it was checked above. */
- cmsis_dap_add_jtag_sequence(
- field->num_bits - 1, /* number of bits to clock */
- field->out_value, /* output sequence */
- 0, /* output offset */
- false, /* TMS low */
- field->in_value,
- 0);
-
- /* Clock the last bit out, with TMS high */
- uint8_t last_bit = 0;
- if (field->out_value)
- bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1);
- cmsis_dap_add_jtag_sequence(
- 1,
- &last_bit,
- 0,
- true,
- field->in_value,
- field->num_bits - 1);
- tap_set_state(tap_state_transition(tap_get_state(), 1));
-
- /* Now clock one more cycle, with TMS low, to get us into a PAUSE state */
- cmsis_dap_add_jtag_sequence(
- 1,
- &last_bit,
- 0,
- false,
- NULL,
- 0);
- tap_set_state(tap_state_transition(tap_get_state(), 0));
- } else {
- DEBUG_JTAG_IO("Internal field, staying in SHIFT state afterwards");
- /* Clocking part of a sequence into DR or IR with TMS=0,
- leaving TMS=0 at the end so we can continue later */
- cmsis_dap_add_jtag_sequence(
- field->num_bits,
- field->out_value,
- 0,
- false,
- field->in_value,
- 0);
- }
- }
-
- if (tap_get_state() != tap_get_end_state()) {
- cmsis_dap_end_state(tap_get_end_state());
- cmsis_dap_state_move();
- }
-
- DEBUG_JTAG_IO("%s scan, %i bits, end in %s",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
- tap_state_name(tap_get_end_state()));
-}
-
-static void cmsis_dap_pathmove(int num_states, tap_state_t *path)
-{
- int i;
- uint8_t tms0 = 0x00;
- uint8_t tms1 = 0xff;
-
- for (i = 0; i < num_states; i++) {
- if (path[i] == tap_state_transition(tap_get_state(), false))
- cmsis_dap_add_tms_sequence(&tms0, 1);
- else if (path[i] == tap_state_transition(tap_get_state(), true))
- cmsis_dap_add_tms_sequence(&tms1, 1);
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.",
- tap_state_name(tap_get_state()), tap_state_name(path[i]));
- exit(-1);
- }
-
- tap_set_state(path[i]);
- }
-
- cmsis_dap_end_state(tap_get_state());
-}
-
-static void cmsis_dap_execute_pathmove(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("pathmove: %i states, end in %i",
- cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-
- cmsis_dap_pathmove(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
-}
-
-static void cmsis_dap_stableclocks(int num_cycles)
-{
- int i;
-
- uint8_t tms = tap_get_state() == TAP_RESET;
- /* TODO: Perform optimizations? */
- /* Execute num_cycles. */
- for (i = 0; i < num_cycles; i++)
- cmsis_dap_add_tms_sequence(&tms, 1);
-}
-
-static void cmsis_dap_runtest(int num_cycles)
-{
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* Only do a state_move when we're not already in IDLE. */
- if (tap_get_state() != TAP_IDLE) {
- cmsis_dap_end_state(TAP_IDLE);
- cmsis_dap_state_move();
- }
- cmsis_dap_stableclocks(num_cycles);
-
- /* Finish in end_state. */
- cmsis_dap_end_state(saved_end_state);
-
- if (tap_get_state() != tap_get_end_state())
- cmsis_dap_state_move();
-}
-
-static void cmsis_dap_execute_runtest(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
-
- cmsis_dap_end_state(cmd->cmd.runtest->end_state);
- cmsis_dap_runtest(cmd->cmd.runtest->num_cycles);
-}
-
-static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
- cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles);
-}
-
-/* TODO: Is there need to call cmsis_dap_flush() for the JTAG_PATHMOVE,
- * JTAG_RUNTEST, JTAG_STABLECLOCKS? */
-static void cmsis_dap_execute_command(struct jtag_command *cmd)
-{
- switch (cmd->type) {
- case JTAG_RESET:
- cmsis_dap_flush();
- cmsis_dap_execute_reset(cmd);
- break;
- case JTAG_SLEEP:
- cmsis_dap_flush();
- cmsis_dap_execute_sleep(cmd);
- break;
- case JTAG_TLR_RESET:
- cmsis_dap_flush();
- cmsis_dap_execute_tlr_reset(cmd);
- break;
- case JTAG_SCAN:
- cmsis_dap_execute_scan(cmd);
- break;
- case JTAG_PATHMOVE:
- cmsis_dap_execute_pathmove(cmd);
- break;
- case JTAG_RUNTEST:
- cmsis_dap_execute_runtest(cmd);
- break;
- case JTAG_STABLECLOCKS:
- cmsis_dap_execute_stableclocks(cmd);
- break;
- case JTAG_TMS:
- default:
- LOG_ERROR("BUG: unknown JTAG command type 0x%X encountered", cmd->type);
- exit(-1);
- }
-}
-
-static int cmsis_dap_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue;
-
- while (cmd != NULL) {
- cmsis_dap_execute_command(cmd);
- cmd = cmd->next;
- }
-
- cmsis_dap_flush();
-
- return ERROR_OK;
-}
-
-static int cmsis_dap_speed(int speed)
-{
- if (speed > DAP_MAX_CLOCK) {
- LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, DAP_MAX_CLOCK);
- speed = DAP_MAX_CLOCK;
- }
-
- if (speed == 0) {
- LOG_INFO("RTCK not supported");
- return ERROR_JTAG_NOT_IMPLEMENTED;
- }
-
- return cmsis_dap_cmd_DAP_SWJ_Clock(speed);
-}
-
-static int cmsis_dap_speed_div(int speed, int *khz)
-{
- *khz = speed;
- return ERROR_OK;
-}
-
-static int cmsis_dap_khz(int khz, int *jtag_speed)
-{
- *jtag_speed = khz;
- return ERROR_OK;
-}
-
-static int_least32_t cmsis_dap_swd_frequency(int_least32_t hz)
-{
- if (hz > 0)
- cmsis_dap_speed(hz / 1000);
-
- return hz;
-}
-
-
-COMMAND_HANDLER(cmsis_dap_handle_info_command)
-{
- if (cmsis_dap_get_version_info() == ERROR_OK)
- cmsis_dap_get_status();
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command)
-{
- if (CMD_ARGC > MAX_USB_IDS * 2) {
- LOG_WARNING("ignoring extra IDs in cmsis_dap_vid_pid "
- "(maximum is %d pairs)", MAX_USB_IDS);
- CMD_ARGC = MAX_USB_IDS * 2;
- }
- if (CMD_ARGC < 2 || (CMD_ARGC & 1)) {
- LOG_WARNING("incomplete cmsis_dap_vid_pid configuration directive");
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- /* remove the incomplete trailing id */
- CMD_ARGC -= 1;
- }
-
- unsigned i;
- for (i = 0; i < CMD_ARGC; i += 2) {
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], cmsis_dap_vid[i >> 1]);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], cmsis_dap_pid[i >> 1]);
- }
-
- /*
- * Explicitly terminate, in case there are multiples instances of
- * cmsis_dap_vid_pid.
- */
- cmsis_dap_vid[i >> 1] = cmsis_dap_pid[i >> 1] = 0;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(cmsis_dap_handle_serial_command)
-{
- if (CMD_ARGC == 1) {
- size_t len = mbstowcs(NULL, CMD_ARGV[0], 0);
- cmsis_dap_serial = calloc(len + 1, sizeof(wchar_t));
- if (cmsis_dap_serial == NULL) {
- LOG_ERROR("unable to allocate memory");
- return ERROR_OK;
- }
- if (mbstowcs(cmsis_dap_serial, CMD_ARGV[0], len + 1) == (size_t)-1) {
- free(cmsis_dap_serial);
- cmsis_dap_serial = NULL;
- LOG_ERROR("unable to convert serial");
- }
- } else {
- LOG_ERROR("expected exactly one argument to cmsis_dap_serial <serial-number>");
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration cmsis_dap_subcommand_handlers[] = {
- {
- .name = "info",
- .handler = &cmsis_dap_handle_info_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "show cmsis-dap info",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration cmsis_dap_command_handlers[] = {
- {
- .name = "cmsis-dap",
- .mode = COMMAND_ANY,
- .help = "perform CMSIS-DAP management",
- .usage = "<cmd>",
- .chain = cmsis_dap_subcommand_handlers,
- },
- {
- .name = "cmsis_dap_vid_pid",
- .handler = &cmsis_dap_handle_vid_pid_command,
- .mode = COMMAND_CONFIG,
- .help = "the vendor ID and product ID of the CMSIS-DAP device",
- .usage = "(vid pid)* ",
- },
- {
- .name = "cmsis_dap_serial",
- .handler = &cmsis_dap_handle_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the adapter",
- .usage = "serial_string",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct swd_driver cmsis_dap_swd_driver = {
- .init = cmsis_dap_swd_init,
- .frequency = cmsis_dap_swd_frequency,
- .switch_seq = cmsis_dap_swd_switch_seq,
- .read_reg = cmsis_dap_swd_read_reg,
- .write_reg = cmsis_dap_swd_write_reg,
- .run = cmsis_dap_swd_run_queue,
-};
-
-static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL };
-
-struct jtag_interface cmsis_dap_interface = {
- .name = "cmsis-dap",
- .commands = cmsis_dap_command_handlers,
- .swd = &cmsis_dap_swd_driver,
- .transports = cmsis_dap_transport,
-
- .execute_queue = cmsis_dap_execute_queue,
- .speed = cmsis_dap_speed,
- .speed_div = cmsis_dap_speed_div,
- .khz = cmsis_dap_khz,
- .init = cmsis_dap_init,
- .quit = cmsis_dap_quit,
-};
diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c
deleted file mode 100644
index daf7cd4..0000000
--- a/src/jtag/drivers/driver.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/jtag.h>
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <jtag/minidriver.h>
-#include <helper/command.h>
-
-struct jtag_callback_entry {
- struct jtag_callback_entry *next;
-
- jtag_callback_t callback;
- jtag_callback_data_t data0;
- jtag_callback_data_t data1;
- jtag_callback_data_t data2;
- jtag_callback_data_t data3;
-};
-
-static struct jtag_callback_entry *jtag_callback_queue_head;
-static struct jtag_callback_entry *jtag_callback_queue_tail;
-
-static void jtag_callback_queue_reset(void)
-{
- jtag_callback_queue_head = NULL;
- jtag_callback_queue_tail = NULL;
-}
-
-/**
- * Copy a struct scan_field for insertion into the queue.
- *
- * This allocates a new copy of out_value using cmd_queue_alloc.
- */
-static void cmd_queue_scan_field_clone(struct scan_field *dst, const struct scan_field *src)
-{
- dst->num_bits = src->num_bits;
- dst->out_value = buf_cpy(src->out_value, cmd_queue_alloc(DIV_ROUND_UP(src->num_bits, 8)), src->num_bits);
- dst->in_value = src->in_value;
-}
-
-/**
- * see jtag_add_ir_scan()
- *
- */
-int interface_jtag_add_ir_scan(struct jtag_tap *active,
- const struct scan_field *in_fields, tap_state_t state)
-{
- size_t num_taps = jtag_tap_count_enabled();
-
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
- struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
- struct scan_field *out_fields = cmd_queue_alloc(num_taps * sizeof(struct scan_field));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_SCAN;
- cmd->cmd.scan = scan;
-
- scan->ir_scan = true;
- scan->num_fields = num_taps; /* one field per device */
- scan->fields = out_fields;
- scan->end_state = state;
-
- struct scan_field *field = out_fields; /* keep track where we insert data */
-
- /* loop over all enabled TAPs */
-
- for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
- /* search the input field list for fields for the current TAP */
-
- if (tap == active) {
- /* if TAP is listed in input fields, copy the value */
- tap->bypass = 0;
-
- cmd_queue_scan_field_clone(field, in_fields);
- } else {
- /* if a TAP isn't listed in input fields, set it to BYPASS */
-
- tap->bypass = 1;
-
- field->num_bits = tap->ir_length;
- field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
- field->in_value = NULL; /* do not collect input for tap's in bypass */
- }
-
- /* update device information */
- buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
-
- field++;
- }
- /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
- assert(field == out_fields + num_taps);
-
- return ERROR_OK;
-}
-
-/**
- * see jtag_add_dr_scan()
- *
- */
-int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields,
- const struct scan_field *in_fields, tap_state_t state)
-{
- /* count devices in bypass */
-
- size_t bypass_devices = 0;
-
- for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
- if (tap->bypass)
- bypass_devices++;
- }
-
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
- struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
- struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_SCAN;
- cmd->cmd.scan = scan;
-
- scan->ir_scan = false;
- scan->num_fields = in_num_fields + bypass_devices;
- scan->fields = out_fields;
- scan->end_state = state;
-
- struct scan_field *field = out_fields; /* keep track where we insert data */
-
- /* loop over all enabled TAPs */
-
- for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
- /* if TAP is not bypassed insert matching input fields */
-
- if (!tap->bypass) {
- assert(active == tap);
-#ifndef NDEBUG
- /* remember initial position for assert() */
- struct scan_field *start_field = field;
-#endif /* NDEBUG */
-
- for (int j = 0; j < in_num_fields; j++) {
- cmd_queue_scan_field_clone(field, in_fields + j);
-
- field++;
- }
-
- assert(field > start_field); /* must have at least one input field per not bypassed TAP */
- }
-
- /* if a TAP is bypassed, generated a dummy bit*/
- else {
- field->num_bits = 1;
- field->out_value = NULL;
- field->in_value = NULL;
-
- field++;
- }
- }
-
- assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
-
- return ERROR_OK;
-}
-
-static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits,
- uint8_t *in_bits, tap_state_t state, bool ir_scan)
-{
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
- struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
- struct scan_field *out_fields = cmd_queue_alloc(sizeof(struct scan_field));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_SCAN;
- cmd->cmd.scan = scan;
-
- scan->ir_scan = ir_scan;
- scan->num_fields = 1;
- scan->fields = out_fields;
- scan->end_state = state;
-
- out_fields->num_bits = num_bits;
- out_fields->out_value = buf_cpy(out_bits, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
- out_fields->in_value = in_bits;
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
-{
- return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false);
-}
-
-int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
-{
- return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true);
-}
-
-int interface_jtag_add_tlr(void)
-{
- tap_state_t state = TAP_RESET;
-
- /* allocate memory for a new list member */
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_TLR_RESET;
-
- cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command));
- cmd->cmd.statemove->end_state = state;
-
- return ERROR_OK;
-}
-
-int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
-{
- struct jtag_command *cmd;
-
- cmd = cmd_queue_alloc(sizeof(struct jtag_command));
- if (cmd == NULL)
- return ERROR_FAIL;
-
- cmd->type = JTAG_TMS;
- cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms));
- if (!cmd->cmd.tms)
- return ERROR_FAIL;
-
- /* copy the bits; our caller doesn't guarantee they'll persist */
- cmd->cmd.tms->num_bits = num_bits;
- cmd->cmd.tms->bits = buf_cpy(seq,
- cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
- if (!cmd->cmd.tms->bits)
- return ERROR_FAIL;
-
- jtag_queue_command(cmd);
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
-{
- /* allocate memory for a new list member */
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_PATHMOVE;
-
- cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command));
- cmd->cmd.pathmove->num_states = num_states;
- cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
-
- for (int i = 0; i < num_states; i++)
- cmd->cmd.pathmove->path[i] = path[i];
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
-{
- /* allocate memory for a new list member */
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_RUNTEST;
-
- cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command));
- cmd->cmd.runtest->num_cycles = num_cycles;
- cmd->cmd.runtest->end_state = state;
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_clocks(int num_cycles)
-{
- /* allocate memory for a new list member */
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_STABLECLOCKS;
-
- cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command));
- cmd->cmd.stableclocks->num_cycles = num_cycles;
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_reset(int req_trst, int req_srst)
-{
- /* allocate memory for a new list member */
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_RESET;
-
- cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command));
- cmd->cmd.reset->trst = req_trst;
- cmd->cmd.reset->srst = req_srst;
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_sleep(uint32_t us)
-{
- /* allocate memory for a new list member */
- struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
-
- jtag_queue_command(cmd);
-
- cmd->type = JTAG_SLEEP;
-
- cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command));
- cmd->cmd.sleep->us = us;
-
- return ERROR_OK;
-}
-
-/* add callback to end of queue */
-void interface_jtag_add_callback4(jtag_callback_t callback,
- jtag_callback_data_t data0, jtag_callback_data_t data1,
- jtag_callback_data_t data2, jtag_callback_data_t data3)
-{
- struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry));
-
- entry->next = NULL;
- entry->callback = callback;
- entry->data0 = data0;
- entry->data1 = data1;
- entry->data2 = data2;
- entry->data3 = data3;
-
- if (jtag_callback_queue_head == NULL) {
- jtag_callback_queue_head = entry;
- jtag_callback_queue_tail = entry;
- } else {
- jtag_callback_queue_tail->next = entry;
- jtag_callback_queue_tail = entry;
- }
-}
-
-int interface_jtag_execute_queue(void)
-{
- static int reentry;
-
- assert(reentry == 0);
- reentry++;
-
- int retval = default_interface_jtag_execute_queue();
- if (retval == ERROR_OK) {
- struct jtag_callback_entry *entry;
- for (entry = jtag_callback_queue_head; entry != NULL; entry = entry->next) {
- retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3);
- if (retval != ERROR_OK)
- break;
- }
- }
-
- jtag_command_queue_reset();
- jtag_callback_queue_reset();
-
- reentry--;
-
- return retval;
-}
-
-static int jtag_convert_to_callback4(jtag_callback_data_t data0,
- jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
-{
- ((jtag_callback1_t)data1)(data0);
- return ERROR_OK;
-}
-
-void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
-{
- jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
-}
-
-void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
-{
- interface_jtag_add_callback(f, data0);
-}
-
-void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
- jtag_callback_data_t data1, jtag_callback_data_t data2,
- jtag_callback_data_t data3)
-{
- interface_jtag_add_callback4(f, data0, data1, data2, data3);
-}
diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c
deleted file mode 100644
index 0f7c12d..0000000
--- a/src/jtag/drivers/dummy.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include "bitbang.h"
-#include "hello.h"
-
-/* my private tap controller state, which tracks state for calling code */
-static tap_state_t dummy_state = TAP_RESET;
-
-static int dummy_clock; /* edge detector */
-
-static int clock_count; /* count clocks in any stable state, only stable states */
-
-static uint32_t dummy_data;
-
-static int dummy_read(void)
-{
- int data = 1 & dummy_data;
- dummy_data = (dummy_data >> 1) | (1 << 31);
- return data;
-}
-
-static void dummy_write(int tck, int tms, int tdi)
-{
- /* TAP standard: "state transitions occur on rising edge of clock" */
- if (tck != dummy_clock) {
- if (tck) {
- tap_state_t old_state = dummy_state;
- dummy_state = tap_state_transition(old_state, tms);
-
- if (old_state != dummy_state) {
- if (clock_count) {
- LOG_DEBUG("dummy_tap: %d stable clocks", clock_count);
- clock_count = 0;
- }
-
- LOG_DEBUG("dummy_tap: %s", tap_state_name(dummy_state));
-
-#if defined(DEBUG)
- if (dummy_state == TAP_DRCAPTURE)
- dummy_data = 0x01255043;
-#endif
- } else {
- /* this is a stable state clock edge, no change of state here,
- * simply increment clock_count for subsequent logging
- */
- ++clock_count;
- }
- }
- dummy_clock = tck;
- }
-}
-
-static void dummy_reset(int trst, int srst)
-{
- dummy_clock = 0;
-
- if (trst || (srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- dummy_state = TAP_RESET;
-
- LOG_DEBUG("reset to: %s", tap_state_name(dummy_state));
-}
-
-static void dummy_led(int on)
-{
-}
-
-static struct bitbang_interface dummy_bitbang = {
- .read = &dummy_read,
- .write = &dummy_write,
- .reset = &dummy_reset,
- .blink = &dummy_led,
- };
-
-static int dummy_khz(int khz, int *jtag_speed)
-{
- if (khz == 0)
- *jtag_speed = 0;
- else
- *jtag_speed = 64000/khz;
- return ERROR_OK;
-}
-
-static int dummy_speed_div(int speed, int *khz)
-{
- if (speed == 0)
- *khz = 0;
- else
- *khz = 64000/speed;
-
- return ERROR_OK;
-}
-
-static int dummy_speed(int speed)
-{
- return ERROR_OK;
-}
-
-static int dummy_init(void)
-{
- bitbang_interface = &dummy_bitbang;
-
- return ERROR_OK;
-}
-
-static int dummy_quit(void)
-{
- return ERROR_OK;
-}
-
-static const struct command_registration dummy_command_handlers[] = {
- {
- .name = "dummy",
- .mode = COMMAND_ANY,
- .help = "dummy interface driver commands",
-
- .chain = hello_command_handlers,
- },
- COMMAND_REGISTRATION_DONE,
-};
-
-/* The dummy driver is used to easily check the code path
- * where the target is unresponsive.
- */
-struct jtag_interface dummy_interface = {
- .name = "dummy",
-
- .supported = DEBUG_CAP_TMS_SEQ,
- .commands = dummy_command_handlers,
- .transports = jtag_only,
-
- .execute_queue = &bitbang_execute_queue,
-
- .speed = &dummy_speed,
- .khz = &dummy_khz,
- .speed_div = &dummy_speed_div,
-
- .init = &dummy_init,
- .quit = &dummy_quit,
- };
diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c
deleted file mode 100644
index ccd9795..0000000
--- a/src/jtag/drivers/ep93xx.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include "bitbang.h"
-
-#define TDO_BIT 1
-#define TDI_BIT 2
-#define TCK_BIT 4
-#define TMS_BIT 8
-#define TRST_BIT 16
-#define SRST_BIT 32
-#define VCC_BIT 64
-
-#include <sys/mman.h>
-
-static uint8_t output_value;
-static int dev_mem_fd;
-static void *gpio_controller;
-static volatile uint8_t *gpio_data_register;
-static volatile uint8_t *gpio_data_direction_register;
-
-/* low level command set
- */
-static int ep93xx_read(void);
-static void ep93xx_write(int tck, int tms, int tdi);
-static void ep93xx_reset(int trst, int srst);
-
-static int ep93xx_init(void);
-static int ep93xx_quit(void);
-
-struct timespec ep93xx_zzzz;
-
-struct jtag_interface ep93xx_interface = {
- .name = "ep93xx",
-
- .supported = DEBUG_CAP_TMS_SEQ,
- .execute_queue = bitbang_execute_queue,
-
- .init = ep93xx_init,
- .quit = ep93xx_quit,
-};
-
-static struct bitbang_interface ep93xx_bitbang = {
- .read = ep93xx_read,
- .write = ep93xx_write,
- .reset = ep93xx_reset,
- .blink = 0,
-};
-
-static int ep93xx_read(void)
-{
- return !!(*gpio_data_register & TDO_BIT);
-}
-
-static void ep93xx_write(int tck, int tms, int tdi)
-{
- if (tck)
- output_value |= TCK_BIT;
- else
- output_value &= ~TCK_BIT;
-
- if (tms)
- output_value |= TMS_BIT;
- else
- output_value &= ~TMS_BIT;
-
- if (tdi)
- output_value |= TDI_BIT;
- else
- output_value &= ~TDI_BIT;
-
- *gpio_data_register = output_value;
- nanosleep(&ep93xx_zzzz, NULL);
-}
-
-/* (1) assert or (0) deassert reset lines */
-static void ep93xx_reset(int trst, int srst)
-{
- if (trst == 0)
- output_value |= TRST_BIT;
- else if (trst == 1)
- output_value &= ~TRST_BIT;
-
- if (srst == 0)
- output_value |= SRST_BIT;
- else if (srst == 1)
- output_value &= ~SRST_BIT;
-
- *gpio_data_register = output_value;
- nanosleep(&ep93xx_zzzz, NULL);
-}
-
-static int set_gonk_mode(void)
-{
- void *syscon;
- uint32_t devicecfg;
-
- syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
- MAP_SHARED, dev_mem_fd, 0x80930000);
- if (syscon == MAP_FAILED) {
- perror("mmap");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- devicecfg = *((volatile int *)(syscon + 0x80));
- *((volatile int *)(syscon + 0xc0)) = 0xaa;
- *((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000;
-
- munmap(syscon, 4096);
-
- return ERROR_OK;
-}
-
-static int ep93xx_init(void)
-{
- int ret;
-
- bitbang_interface = &ep93xx_bitbang;
-
- ep93xx_zzzz.tv_sec = 0;
- ep93xx_zzzz.tv_nsec = 10000000;
-
- dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
- if (dev_mem_fd < 0) {
- perror("open");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
- MAP_SHARED, dev_mem_fd, 0x80840000);
- if (gpio_controller == MAP_FAILED) {
- perror("mmap");
- close(dev_mem_fd);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- ret = set_gonk_mode();
- if (ret != ERROR_OK) {
- munmap(gpio_controller, 4096);
- close(dev_mem_fd);
- return ret;
- }
-
-#if 0
- /* Use GPIO port A. */
- gpio_data_register = gpio_controller + 0x00;
- gpio_data_direction_register = gpio_controller + 0x10;
-
-
- /* Use GPIO port B. */
- gpio_data_register = gpio_controller + 0x04;
- gpio_data_direction_register = gpio_controller + 0x14;
-
- /* Use GPIO port C. */
- gpio_data_register = gpio_controller + 0x08;
- gpio_data_direction_register = gpio_controller + 0x18;
-
- /* Use GPIO port D. */
- gpio_data_register = gpio_controller + 0x0c;
- gpio_data_direction_register = gpio_controller + 0x1c;
-#endif
-
- /* Use GPIO port C. */
- gpio_data_register = gpio_controller + 0x08;
- gpio_data_direction_register = gpio_controller + 0x18;
-
- LOG_INFO("gpio_data_register = %p", gpio_data_register);
- LOG_INFO("gpio_data_direction_reg = %p", gpio_data_direction_register);
- /*
- * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK
- * TMS, TRST, SRST) as outputs. Drive TDI and TCK low, and
- * TMS/TRST/SRST high.
- */
- output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
- *gpio_data_register = output_value;
- nanosleep(&ep93xx_zzzz, NULL);
-
- /*
- * Configure the direction register. 1 = output, 0 = input.
- */
- *gpio_data_direction_register =
- TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
-
- nanosleep(&ep93xx_zzzz, NULL);
- return ERROR_OK;
-}
-
-static int ep93xx_quit(void)
-{
-
- return ERROR_OK;
-}
diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c
deleted file mode 100644
index 621da8e..0000000
--- a/src/jtag/drivers/ft2232.c
+++ /dev/null
@@ -1,4308 +0,0 @@
-/***************************************************************************
-* Copyright (C) 2009 by Øyvind Harboe *
-* Øyvind Harboe <oyvind.harboe@zylin.com> *
-* *
-* Copyright (C) 2009 by SoftPLC Corporation. http://softplc.com *
-* Dick Hollenbeck <dick@softplc.com> *
-* *
-* Copyright (C) 2004, 2006 by Dominic Rath *
-* Dominic.Rath@gmx.de *
-* *
-* Copyright (C) 2008 by Spencer Oliver *
-* spen@spen-soft.co.uk *
-* *
-* This program is free software; you can redistribute it and/or modify *
-* it under the terms of the GNU General Public License as published by *
-* the Free Software Foundation; either version 2 of the License, or *
-* (at your option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-* GNU General Public License for more details. *
-* *
-* You should have received a copy of the GNU General Public License *
-* along with this program. If not, see <http://www.gnu.org/licenses/>. *
-***************************************************************************/
-
-/**
- * @file
- * JTAG adapters based on the FT2232 full and high speed USB parts are
- * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters
- * are discrete, but development boards may integrate them as alternatives
- * to more capable (and expensive) third party JTAG pods.
- *
- * JTAG uses only one of the two communications channels ("MPSSE engines")
- * on these devices. Adapters based on FT4232 parts have four ports/channels
- * (A/B/C/D), instead of just two (A/B).
- *
- * Especially on development boards integrating one of these chips (as
- * opposed to discrete pods/dongles), the additional channels can be used
- * for a variety of purposes, but OpenOCD only uses one channel at a time.
- *
- * - As a USB-to-serial adapter for the target's console UART ...
- * which may be able to support ROM boot loaders that load initial
- * firmware images to flash (or SRAM).
- *
- * - On systems which support ARM's SWD in addition to JTAG, or instead
- * of it, that second port can be used for reading SWV/SWO trace data.
- *
- * - Additional JTAG links, e.g. to a CPLD or * FPGA.
- *
- * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG
- * request/response interactions involve round trips over the USB link.
- * A "smart" JTAG adapter has intelligence close to the scan chain, so it
- * can for example poll quickly for a status change (usually taking on the
- * order of microseconds not milliseconds) before beginning a queued
- * transaction which require the previous one to have completed.
- *
- * There are dozens of adapters of this type, differing in details which
- * this driver needs to understand. Those "layout" details are required
- * as part of FT2232 driver configuration.
- *
- * This code uses information contained in the MPSSE specification which was
- * found here:
- * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf
- * Hereafter this is called the "MPSSE Spec".
- *
- * The datasheet for the ftdichip.com's FT2232D part is here:
- * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf
- *
- * Also note the issue with code 0x4b (clock data to TMS) noted in
- * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html
- * which can affect longer JTAG state paths.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <transport/transport.h>
-#include <helper/time_support.h>
-
-#if IS_CYGWIN == 1
-#include <windows.h>
-#endif
-
-#include <assert.h>
-
-#if (BUILD_FT2232_FTD2XX == 1 && BUILD_FT2232_LIBFTDI == 1)
-#error "BUILD_FT2232_FTD2XX && BUILD_FT2232_LIBFTDI are mutually exclusive"
-#elif (BUILD_FT2232_FTD2XX != 1 && BUILD_FT2232_LIBFTDI != 1)
-#error "BUILD_FT2232_FTD2XX || BUILD_FT2232_LIBFTDI must be chosen"
-#endif
-
-/* FT2232 access library includes */
-#if BUILD_FT2232_FTD2XX == 1
-#include <ftd2xx.h>
-#include "ftd2xx_common.h"
-
-enum ftdi_interface {
- INTERFACE_ANY = 0,
- INTERFACE_A = 1,
- INTERFACE_B = 2,
- INTERFACE_C = 3,
- INTERFACE_D = 4
-};
-
-#elif BUILD_FT2232_LIBFTDI == 1
-#include <ftdi.h>
-#endif
-
-/* max TCK for the high speed devices 30000 kHz */
-#define FTDI_x232H_MAX_TCK 30000
-/* max TCK for the full speed devices 6000 kHz */
-#define FTDI_2232C_MAX_TCK 6000
-/* this speed value tells that RTCK is requested */
-#define RTCK_SPEED -1
-
-/*
- * On my Athlon XP 1900+ EHCI host with FT2232H JTAG dongle I get read timeout
- * errors with a retry count of 100. Increasing it solves the problem for me.
- * - Dimitar
- *
- * FIXME There's likely an issue with the usb_read_timeout from libftdi.
- * Fix that (libusb? kernel? libftdi? here?) and restore the retry count
- * to something sane.
- */
-#define LIBFTDI_READ_RETRY_COUNT 2000
-
-#ifndef BUILD_FT2232_HIGHSPEED
- #if BUILD_FT2232_FTD2XX == 1
- enum { FT_DEVICE_2232H = 6, FT_DEVICE_4232H, FT_DEVICE_232H };
- #elif BUILD_FT2232_LIBFTDI == 1
- enum ftdi_chip_type { TYPE_2232H = 4, TYPE_4232H = 5, TYPE_232H = 6 };
- #endif
-#endif
-
-/**
- * Send out \a num_cycles on the TCK line while the TAP(s) are in a
- * stable state. Calling code must ensure that current state is stable,
- * that verification is not done in here.
- *
- * @param num_cycles The number of clocks cycles to send.
- * @param cmd The command to send.
- *
- * @returns ERROR_OK on success, or ERROR_JTAG_QUEUE_FAILED on failure.
- */
-static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd);
-
-static char *ft2232_device_desc_A;
-static char *ft2232_device_desc;
-static char *ft2232_serial;
-static uint8_t ft2232_latency = 2;
-static unsigned ft2232_max_tck = FTDI_2232C_MAX_TCK;
-static int ft2232_channel = INTERFACE_ANY;
-
-#define MAX_USB_IDS 8
-/* vid = pid = 0 marks the end of the list */
-static uint16_t ft2232_vid[MAX_USB_IDS + 1] = { 0x0403, 0 };
-static uint16_t ft2232_pid[MAX_USB_IDS + 1] = { 0x6010, 0 };
-
-struct ft2232_layout {
- const char *name;
- int (*init)(void);
- void (*reset)(int trst, int srst);
- void (*blink)(void);
- int channel;
-};
-
-/* init procedures for supported layouts */
-static int usbjtag_init(void);
-static int jtagkey_init(void);
-static int lm3s811_jtag_init(void);
-static int icdi_jtag_init(void);
-static int olimex_jtag_init(void);
-static int flyswatter1_init(void);
-static int flyswatter2_init(void);
-static int minimodule_init(void);
-static int turtle_init(void);
-static int comstick_init(void);
-static int stm32stick_init(void);
-static int axm0432_jtag_init(void);
-static int sheevaplug_init(void);
-static int icebear_jtag_init(void);
-static int cortino_jtag_init(void);
-static int signalyzer_init(void);
-static int signalyzer_h_init(void);
-static int ktlink_init(void);
-static int redbee_init(void);
-static int lisa_l_init(void);
-static int flossjtag_init(void);
-static int xds100v2_init(void);
-static int digilent_hs1_init(void);
-
-/* reset procedures for supported layouts */
-static void ftx23_reset(int trst, int srst);
-static void jtagkey_reset(int trst, int srst);
-static void olimex_jtag_reset(int trst, int srst);
-static void flyswatter1_reset(int trst, int srst);
-static void flyswatter2_reset(int trst, int srst);
-static void minimodule_reset(int trst, int srst);
-static void turtle_reset(int trst, int srst);
-static void comstick_reset(int trst, int srst);
-static void stm32stick_reset(int trst, int srst);
-static void axm0432_jtag_reset(int trst, int srst);
-static void sheevaplug_reset(int trst, int srst);
-static void icebear_jtag_reset(int trst, int srst);
-static void signalyzer_h_reset(int trst, int srst);
-static void ktlink_reset(int trst, int srst);
-static void redbee_reset(int trst, int srst);
-static void xds100v2_reset(int trst, int srst);
-static void digilent_hs1_reset(int trst, int srst);
-
-/* blink procedures for layouts that support a blinking led */
-static void olimex_jtag_blink(void);
-static void flyswatter1_jtag_blink(void);
-static void flyswatter2_jtag_blink(void);
-static void turtle_jtag_blink(void);
-static void signalyzer_h_blink(void);
-static void ktlink_blink(void);
-static void lisa_l_blink(void);
-static void flossjtag_blink(void);
-
-/* common transport support options */
-
-/* static const char *jtag_and_swd[] = { "jtag", "swd", NULL }; */
-
-static const struct ft2232_layout ft2232_layouts[] = {
- { .name = "usbjtag",
- .init = usbjtag_init,
- .reset = ftx23_reset,
- },
- { .name = "jtagkey",
- .init = jtagkey_init,
- .reset = jtagkey_reset,
- },
- { .name = "jtagkey_prototype_v1",
- .init = jtagkey_init,
- .reset = jtagkey_reset,
- },
- { .name = "oocdlink",
- .init = jtagkey_init,
- .reset = jtagkey_reset,
- },
- { .name = "signalyzer",
- .init = signalyzer_init,
- .reset = ftx23_reset,
- },
- { .name = "evb_lm3s811",
- .init = lm3s811_jtag_init,
- .reset = ftx23_reset,
- },
- { .name = "luminary_icdi",
- .init = icdi_jtag_init,
- .reset = ftx23_reset,
- },
- { .name = "olimex-jtag",
- .init = olimex_jtag_init,
- .reset = olimex_jtag_reset,
- .blink = olimex_jtag_blink
- },
- { .name = "flyswatter",
- .init = flyswatter1_init,
- .reset = flyswatter1_reset,
- .blink = flyswatter1_jtag_blink
- },
- { .name = "flyswatter2",
- .init = flyswatter2_init,
- .reset = flyswatter2_reset,
- .blink = flyswatter2_jtag_blink
- },
- { .name = "minimodule",
- .init = minimodule_init,
- .reset = minimodule_reset,
- },
- { .name = "turtelizer2",
- .init = turtle_init,
- .reset = turtle_reset,
- .blink = turtle_jtag_blink
- },
- { .name = "comstick",
- .init = comstick_init,
- .reset = comstick_reset,
- },
- { .name = "stm32stick",
- .init = stm32stick_init,
- .reset = stm32stick_reset,
- },
- { .name = "axm0432_jtag",
- .init = axm0432_jtag_init,
- .reset = axm0432_jtag_reset,
- },
- { .name = "sheevaplug",
- .init = sheevaplug_init,
- .reset = sheevaplug_reset,
- },
- { .name = "icebear",
- .init = icebear_jtag_init,
- .reset = icebear_jtag_reset,
- },
- { .name = "cortino",
- .init = cortino_jtag_init,
- .reset = comstick_reset,
- },
- { .name = "signalyzer-h",
- .init = signalyzer_h_init,
- .reset = signalyzer_h_reset,
- .blink = signalyzer_h_blink
- },
- { .name = "ktlink",
- .init = ktlink_init,
- .reset = ktlink_reset,
- .blink = ktlink_blink
- },
- { .name = "redbee-econotag",
- .init = redbee_init,
- .reset = redbee_reset,
- },
- { .name = "redbee-usb",
- .init = redbee_init,
- .reset = redbee_reset,
- .channel = INTERFACE_B,
- },
- { .name = "lisa-l",
- .init = lisa_l_init,
- .reset = ftx23_reset,
- .blink = lisa_l_blink,
- .channel = INTERFACE_B,
- },
- { .name = "flossjtag",
- .init = flossjtag_init,
- .reset = ftx23_reset,
- .blink = flossjtag_blink,
- },
- { .name = "xds100v2",
- .init = xds100v2_init,
- .reset = xds100v2_reset,
- },
- { .name = "digilent-hs1",
- .init = digilent_hs1_init,
- .reset = digilent_hs1_reset,
- .channel = INTERFACE_A,
- },
- { .name = NULL, /* END OF TABLE */ },
-};
-
-/* bitmask used to drive nTRST; usually a GPIOLx signal */
-static uint8_t nTRST;
-static uint8_t nTRSTnOE;
-/* bitmask used to drive nSRST; usually a GPIOLx signal */
-static uint8_t nSRST;
-static uint8_t nSRSTnOE;
-
-/** the layout being used with this debug session */
-static const struct ft2232_layout *layout;
-
-/** default bitmask values driven on DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */
-static uint8_t low_output;
-
-/* note that direction bit == 1 means that signal is an output */
-
-/** default direction bitmask for DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */
-static uint8_t low_direction;
-/** default value bitmask for CBUS GPIOH(0..4) */
-static uint8_t high_output;
-/** default direction bitmask for CBUS GPIOH(0..4) */
-static uint8_t high_direction;
-
-#if BUILD_FT2232_FTD2XX == 1
-static FT_HANDLE ftdih;
-static FT_DEVICE ftdi_device;
-#elif BUILD_FT2232_LIBFTDI == 1
-static struct ftdi_context ftdic;
-static enum ftdi_chip_type ftdi_device;
-#endif
-
-static struct jtag_command *first_unsent; /* next command that has to be sent */
-static int require_send;
-
-/* http://urjtag.wiki.sourceforge.net/Cable + FT2232 says:
-
- "There is a significant difference between libftdi and libftd2xx. The latter
- one allows to schedule up to 64*64 bytes of result data while libftdi fails
- with more than 4*64. As a consequence, the FT2232 driver is forced to
- perform around 16x more USB transactions for long command streams with TDO
- capture when running with libftdi."
-
- No idea how we get
- #define FT2232_BUFFER_SIZE 131072
- a comment would have been nice.
-*/
-
-#if BUILD_FT2232_FTD2XX == 1
-#define FT2232_BUFFER_READ_QUEUE_SIZE (64*64)
-#else
-#define FT2232_BUFFER_READ_QUEUE_SIZE (64*4)
-#endif
-
-#define FT2232_BUFFER_SIZE 131072
-
-static uint8_t *ft2232_buffer;
-static int ft2232_buffer_size;
-static int ft2232_read_pointer;
-static int ft2232_expect_read;
-
-/**
- * Function buffer_write
- * writes a byte into the byte buffer, "ft2232_buffer", which must be sent later.
- * @param val is the byte to send.
- */
-static inline void buffer_write(uint8_t val)
-{
- assert(ft2232_buffer);
- assert((unsigned) ft2232_buffer_size < (unsigned) FT2232_BUFFER_SIZE);
- ft2232_buffer[ft2232_buffer_size++] = val;
-}
-
-/**
- * Function buffer_read
- * returns a byte from the byte buffer.
- */
-static inline uint8_t buffer_read(void)
-{
- assert(ft2232_buffer);
- assert(ft2232_read_pointer < ft2232_buffer_size);
- return ft2232_buffer[ft2232_read_pointer++];
-}
-
-/**
- * Clocks out \a bit_count bits on the TMS line, starting with the least
- * significant bit of tms_bits and progressing to more significant bits.
- * Rigorous state transition logging is done here via tap_set_state().
- *
- * @param mpsse_cmd One of the MPSSE TMS oriented commands such as
- * 0x4b or 0x6b. See the MPSSE spec referenced above for their
- * functionality. The MPSSE command "Clock Data to TMS/CS Pin (no Read)"
- * is often used for this, 0x4b.
- *
- * @param tms_bits Holds the sequence of bits to send.
- * @param tms_count Tells how many bits in the sequence.
- * @param tdi_bit A single bit to pass on to TDI before the first TCK
- * cycle and held static for the duration of TMS clocking.
- *
- * See the MPSSE spec referenced above.
- */
-static void clock_tms(uint8_t mpsse_cmd, int tms_bits, int tms_count, bool tdi_bit)
-{
- uint8_t tms_byte;
- int i;
- int tms_ndx; /* bit index into tms_byte */
-
- assert(tms_count > 0);
-
- DEBUG_JTAG_IO("mpsse cmd=%02x, tms_bits = 0x%08x, bit_count=%d",
- mpsse_cmd, tms_bits, tms_count);
-
- for (tms_byte = tms_ndx = i = 0; i < tms_count; ++i, tms_bits >>= 1) {
- bool bit = tms_bits & 1;
-
- if (bit)
- tms_byte |= (1 << tms_ndx);
-
- /* always do state transitions in public view */
- tap_set_state(tap_state_transition(tap_get_state(), bit));
-
- /* we wrote a bit to tms_byte just above, increment bit index. if bit was zero
- * also increment.
- */
- ++tms_ndx;
-
- if (tms_ndx == 7 || i == tms_count-1) {
- buffer_write(mpsse_cmd);
- buffer_write(tms_ndx - 1);
-
- /* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of
- * TMS/CS and is held static for the duration of TMS/CS clocking.
- */
- buffer_write(tms_byte | (tdi_bit << 7));
- }
- }
-}
-
-/**
- * Function get_tms_buffer_requirements
- * returns what clock_tms() will consume if called with
- * same \a bit_count.
- */
-static inline int get_tms_buffer_requirements(int bit_count)
-{
- return ((bit_count + 6)/7) * 3;
-}
-
-/**
- * Function move_to_state
- * moves the TAP controller from the current state to a
- * \a goal_state through a path given by tap_get_tms_path(). State transition
- * logging is performed by delegation to clock_tms().
- *
- * @param goal_state is the destination state for the move.
- */
-static void move_to_state(tap_state_t goal_state)
-{
- tap_state_t start_state = tap_get_state();
-
- /* goal_state is 1/2 of a tuple/pair of states which allow convenient
- * lookup of the required TMS pattern to move to this state from the start state.
- */
-
- /* do the 2 lookups */
- int tms_bits = tap_get_tms_path(start_state, goal_state);
- int tms_count = tap_get_tms_path_len(start_state, goal_state);
-
- DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state));
-
- clock_tms(0x4b, tms_bits, tms_count, 0);
-}
-
-static int ft2232_write(uint8_t *buf, int size, uint32_t *bytes_written)
-{
-#if BUILD_FT2232_FTD2XX == 1
- FT_STATUS status;
- DWORD dw_bytes_written = 0;
- status = FT_Write(ftdih, buf, size, &dw_bytes_written);
- if (status != FT_OK) {
- *bytes_written = dw_bytes_written;
- LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- } else
- *bytes_written = dw_bytes_written;
-
-#elif BUILD_FT2232_LIBFTDI == 1
- int retval = ftdi_write_data(&ftdic, buf, size);
- if (retval < 0) {
- *bytes_written = 0;
- LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- } else
- *bytes_written = retval;
-
-#endif
-
- if (*bytes_written != (uint32_t)size)
- return ERROR_JTAG_DEVICE_ERROR;
-
- return ERROR_OK;
-}
-
-static int ft2232_read(uint8_t *buf, uint32_t size, uint32_t *bytes_read)
-{
-#if BUILD_FT2232_FTD2XX == 1
- DWORD dw_bytes_read;
- FT_STATUS status;
- int timeout = 5;
- *bytes_read = 0;
-
- while ((*bytes_read < size) && timeout--) {
- status = FT_Read(ftdih, buf + *bytes_read, size -
- *bytes_read, &dw_bytes_read);
- if (status != FT_OK) {
- *bytes_read = 0;
- LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_read += dw_bytes_read;
- }
-
-#elif BUILD_FT2232_LIBFTDI == 1
- int retval;
- int timeout = LIBFTDI_READ_RETRY_COUNT;
- *bytes_read = 0;
-
- while ((*bytes_read < size) && timeout--) {
- retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read);
- if (retval < 0) {
- *bytes_read = 0;
- LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_read += retval;
- }
-
-#endif
-
- if (*bytes_read < size) {
- LOG_ERROR("couldn't read enough bytes from "
- "FT2232 device (%i < %i)",
- (unsigned)*bytes_read,
- (unsigned)size);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static bool ft2232_device_is_highspeed(void)
-{
-#if BUILD_FT2232_FTD2XX == 1
- return (ftdi_device == FT_DEVICE_2232H) || (ftdi_device == FT_DEVICE_4232H)
- #ifdef HAS_ENUM_FT232H
- || (ftdi_device == FT_DEVICE_232H)
- #endif
- ;
-#elif BUILD_FT2232_LIBFTDI == 1
- return (ftdi_device == TYPE_2232H || ftdi_device == TYPE_4232H
- #ifdef HAS_ENUM_FT232H
- || ftdi_device == TYPE_232H
- #endif
- );
-#endif
-}
-
-/*
- * Commands that only apply to the highspeed FTx232H devices (FT2232H, FT4232H, FT232H).
- * See chapter 6 in http://www.ftdichip.com/Documents/AppNotes/
- * AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
- */
-
-static int ftx232h_adaptive_clocking(bool enable)
-{
- uint8_t buf = enable ? 0x96 : 0x97;
- LOG_DEBUG("%2.2x", buf);
-
- uint32_t bytes_written;
- int retval;
-
- retval = ft2232_write(&buf, sizeof(buf), &bytes_written);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't write command to %s adaptive clocking"
- , enable ? "enable" : "disable");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Enable/disable the clk divide by 5 of the 60MHz master clock.
- * This result in a JTAG clock speed range of 91.553Hz-6MHz
- * respective 457.763Hz-30MHz.
- */
-static int ftx232h_clk_divide_by_5(bool enable)
-{
- uint32_t bytes_written;
- uint8_t buf = enable ? 0x8b : 0x8a;
-
- if (ft2232_write(&buf, sizeof(buf), &bytes_written) != ERROR_OK) {
- LOG_ERROR("couldn't write command to %s clk divide by 5"
- , enable ? "enable" : "disable");
- return ERROR_JTAG_INIT_FAILED;
- }
- ft2232_max_tck = enable ? FTDI_2232C_MAX_TCK : FTDI_x232H_MAX_TCK;
- LOG_INFO("max TCK change to: %u kHz", ft2232_max_tck);
-
- return ERROR_OK;
-}
-
-static int ft2232_speed(int speed)
-{
- uint8_t buf[3];
- int retval;
- uint32_t bytes_written;
-
- retval = ERROR_OK;
- bool enable_adaptive_clocking = (RTCK_SPEED == speed);
- if (ft2232_device_is_highspeed())
- retval = ftx232h_adaptive_clocking(enable_adaptive_clocking);
- else if (enable_adaptive_clocking) {
- LOG_ERROR("ft2232 device %lu does not support RTCK"
- , (long unsigned int)ftdi_device);
- return ERROR_FAIL;
- }
-
- if ((enable_adaptive_clocking) || (ERROR_OK != retval))
- return retval;
-
- buf[0] = 0x86; /* command "set divisor" */
- buf[1] = speed & 0xff; /* valueL (0 = 6MHz, 1 = 3MHz, 2 = 2.0MHz, ...*/
- buf[2] = (speed >> 8) & 0xff; /* valueH */
-
- LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
- retval = ft2232_write(buf, sizeof(buf), &bytes_written);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't set FT2232 TCK speed");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int ft2232_speed_div(int speed, int *khz)
-{
- /* Take a look in the FT2232 manual,
- * AN2232C-01 Command Processor for
- * MPSSE and MCU Host Bus. Chapter 3.8 */
-
- *khz = (RTCK_SPEED == speed) ? 0 : ft2232_max_tck / (1 + speed);
-
- return ERROR_OK;
-}
-
-static int ft2232_khz(int khz, int *jtag_speed)
-{
- if (khz == 0) {
- if (ft2232_device_is_highspeed()) {
- *jtag_speed = RTCK_SPEED;
- return ERROR_OK;
- } else {
- LOG_DEBUG("RCLK not supported");
- return ERROR_FAIL;
- }
- }
-
- /* Take a look in the FT2232 manual,
- * AN2232C-01 Command Processor for
- * MPSSE and MCU Host Bus. Chapter 3.8
- *
- * We will calc here with a multiplier
- * of 10 for better rounding later. */
-
- /* Calc speed, (ft2232_max_tck / khz) - 1
- * Use 65000 for better rounding */
- *jtag_speed = ((ft2232_max_tck*10) / khz) - 10;
-
- /* Add 0.9 for rounding */
- *jtag_speed += 9;
-
- /* Calc real speed */
- *jtag_speed = *jtag_speed / 10;
-
- /* Check if speed is greater than 0 */
- if (*jtag_speed < 0)
- *jtag_speed = 0;
-
- /* Check max value */
- if (*jtag_speed > 0xFFFF)
- *jtag_speed = 0xFFFF;
-
- return ERROR_OK;
-}
-
-static void ft2232_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %s is not a stable end state", tap_state_name(state));
- exit(-1);
- }
-}
-
-static void ft2232_read_scan(enum scan_type type, uint8_t *buffer, int scan_size)
-{
- int num_bytes = (scan_size + 7) / 8;
- int bits_left = scan_size;
- int cur_byte = 0;
-
- while (num_bytes-- > 1) {
- buffer[cur_byte++] = buffer_read();
- bits_left -= 8;
- }
-
- buffer[cur_byte] = 0x0;
-
- /* There is one more partial byte left from the clock data in/out instructions */
- if (bits_left > 1)
- buffer[cur_byte] = buffer_read() >> 1;
- /* This shift depends on the length of the
- *clock data to tms instruction, insterted
- *at end of the scan, now fixed to a two
- *step transition in ft2232_add_scan */
- buffer[cur_byte] = (buffer[cur_byte] | (((buffer_read()) << 1) & 0x80)) >> (8 - bits_left);
-}
-
-static void ft2232_debug_dump_buffer(void)
-{
- int i;
- char line[256];
- char *line_p = line;
-
- for (i = 0; i < ft2232_buffer_size; i++) {
- line_p += snprintf(line_p,
- sizeof(line) - (line_p - line),
- "%2.2x ",
- ft2232_buffer[i]);
- if (i % 16 == 15) {
- LOG_DEBUG("%s", line);
- line_p = line;
- }
- }
-
- if (line_p != line)
- LOG_DEBUG("%s", line);
-}
-
-static int ft2232_send_and_recv(struct jtag_command *first, struct jtag_command *last)
-{
- struct jtag_command *cmd;
- uint8_t *buffer;
- int scan_size;
- enum scan_type type;
- int retval;
- uint32_t bytes_written = 0;
- uint32_t bytes_read = 0;
-
-#ifdef _DEBUG_USB_IO_
- struct timeval start, inter, inter2, end;
- struct timeval d_inter, d_inter2, d_end;
-#endif
-
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("write buffer (size %i):", ft2232_buffer_size);
- ft2232_debug_dump_buffer();
-#endif
-
-#ifdef _DEBUG_USB_IO_
- gettimeofday(&start, NULL);
-#endif
-
- retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't write MPSSE commands to FT2232");
- return retval;
- }
-
-#ifdef _DEBUG_USB_IO_
- gettimeofday(&inter, NULL);
-#endif
-
- if (ft2232_expect_read) {
- /* FIXME this "timeout" is never changed ... */
- int timeout = LIBFTDI_READ_RETRY_COUNT;
- ft2232_buffer_size = 0;
-
-#ifdef _DEBUG_USB_IO_
- gettimeofday(&inter2, NULL);
-#endif
-
- retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read from FT2232");
- return retval;
- }
-
-#ifdef _DEBUG_USB_IO_
- gettimeofday(&end, NULL);
-
- timeval_subtract(&d_inter, &inter, &start);
- timeval_subtract(&d_inter2, &inter2, &start);
- timeval_subtract(&d_end, &end, &start);
-
- LOG_INFO("inter: %u.%06u, inter2: %u.%06u end: %u.%06u",
- (unsigned)d_inter.tv_sec, (unsigned)d_inter.tv_usec,
- (unsigned)d_inter2.tv_sec, (unsigned)d_inter2.tv_usec,
- (unsigned)d_end.tv_sec, (unsigned)d_end.tv_usec);
-#endif
-
- ft2232_buffer_size = bytes_read;
-
- if (ft2232_expect_read != ft2232_buffer_size) {
- LOG_ERROR("ft2232_expect_read (%i) != "
- "ft2232_buffer_size (%i) "
- "(%i retries)",
- ft2232_expect_read,
- ft2232_buffer_size,
- LIBFTDI_READ_RETRY_COUNT - timeout);
- ft2232_debug_dump_buffer();
-
- exit(-1);
- }
-
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("read buffer (%i retries): %i bytes",
- LIBFTDI_READ_RETRY_COUNT - timeout,
- ft2232_buffer_size);
- ft2232_debug_dump_buffer();
-#endif
- }
-
- ft2232_expect_read = 0;
- ft2232_read_pointer = 0;
-
- /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
- * that wasn't handled by a caller-provided error handler
- */
- retval = ERROR_OK;
-
- cmd = first;
- while (cmd != last) {
- switch (cmd->type) {
- case JTAG_SCAN:
- type = jtag_scan_type(cmd->cmd.scan);
- if (type != SCAN_OUT) {
- scan_size = jtag_scan_size(cmd->cmd.scan);
- buffer = calloc(DIV_ROUND_UP(scan_size, 8), 1);
- ft2232_read_scan(type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- free(buffer);
- }
- break;
-
- default:
- break;
- }
-
- cmd = cmd->next;
- }
-
- ft2232_buffer_size = 0;
-
- return retval;
-}
-
-/**
- * Function ft2232_add_pathmove
- * moves the TAP controller from the current state to a new state through the
- * given path, where path is an array of tap_state_t's.
- *
- * @param path is an array of tap_stat_t which gives the states to traverse through
- * ending with the last state at path[num_states-1]
- * @param num_states is the count of state steps to move through
- */
-static void ft2232_add_pathmove(tap_state_t *path, int num_states)
-{
- int state_count = 0;
-
- assert((unsigned) num_states <= 32u); /* tms_bits only holds 32 bits */
-
- DEBUG_JTAG_IO("-");
-
- /* this loop verifies that the path is legal and logs each state in the path */
- while (num_states) {
- unsigned char tms_byte = 0; /* zero this on each MPSSE batch */
- int bit_count = 0;
- int num_states_batch = num_states > 7 ? 7 : num_states;
-
- /* command "Clock Data to TMS/CS Pin (no Read)" */
- buffer_write(0x4b);
-
- /* number of states remaining */
- buffer_write(num_states_batch - 1);
-
- while (num_states_batch--) {
- /* either TMS=0 or TMS=1 must work ... */
- if (tap_state_transition(tap_get_state(), false) == path[state_count])
- buf_set_u32(&tms_byte, bit_count++, 1, 0x0);
- else if (tap_state_transition(tap_get_state(), true) == path[state_count])
- buf_set_u32(&tms_byte, bit_count++, 1, 0x1);
-
- /* ... or else the caller goofed BADLY */
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid "
- "TAP state transition",
- tap_state_name(tap_get_state()),
- tap_state_name(path[state_count]));
- exit(-1);
- }
-
- tap_set_state(path[state_count]);
- state_count++;
- num_states--;
- }
-
- buffer_write(tms_byte);
- }
- tap_set_end_state(tap_get_state());
-}
-
-static void ft2232_add_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
-{
- int num_bytes = (scan_size + 7) / 8;
- int bits_left = scan_size;
- int cur_byte = 0;
- int last_bit;
-
- if (!ir_scan) {
- if (tap_get_state() != TAP_DRSHIFT)
- move_to_state(TAP_DRSHIFT);
- } else {
- if (tap_get_state() != TAP_IRSHIFT)
- move_to_state(TAP_IRSHIFT);
- }
-
- /* add command for complete bytes */
- while (num_bytes > 1) {
- int thisrun_bytes;
- if (type == SCAN_IO) {
- /* Clock Data Bytes In and Out LSB First */
- buffer_write(0x39);
- /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */
- } else if (type == SCAN_OUT) {
- /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
- buffer_write(0x19);
- /* LOG_DEBUG("added TDI bytes (o)"); */
- } else if (type == SCAN_IN) {
- /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
- buffer_write(0x28);
- /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */
- }
-
- thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
- num_bytes -= thisrun_bytes;
-
- buffer_write((uint8_t) (thisrun_bytes - 1));
- buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8));
-
- if (type != SCAN_IN) {
- /* add complete bytes */
- while (thisrun_bytes-- > 0) {
- buffer_write(buffer[cur_byte++]);
- bits_left -= 8;
- }
- } else /* (type == SCAN_IN) */
- bits_left -= 8 * (thisrun_bytes);
- }
-
- /* the most signifcant bit is scanned during TAP movement */
- if (type != SCAN_IN)
- last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
- else
- last_bit = 0;
-
- /* process remaining bits but the last one */
- if (bits_left > 1) {
- if (type == SCAN_IO) {
- /* Clock Data Bits In and Out LSB First */
- buffer_write(0x3b);
- /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
- } else if (type == SCAN_OUT) {
- /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
- buffer_write(0x1b);
- /* LOG_DEBUG("added TDI bits (o)"); */
- } else if (type == SCAN_IN) {
- /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
- buffer_write(0x2a);
- /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
- }
-
- buffer_write(bits_left - 2);
- if (type != SCAN_IN)
- buffer_write(buffer[cur_byte]);
- }
-
- if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT))
- || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))) {
- if (type == SCAN_IO) {
- /* Clock Data Bits In and Out LSB First */
- buffer_write(0x3b);
- /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
- } else if (type == SCAN_OUT) {
- /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
- buffer_write(0x1b);
- /* LOG_DEBUG("added TDI bits (o)"); */
- } else if (type == SCAN_IN) {
- /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
- buffer_write(0x2a);
- /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
- }
- buffer_write(0x0);
- if (type != SCAN_IN)
- buffer_write(last_bit);
- } else {
- int tms_bits;
- int tms_count;
- uint8_t mpsse_cmd;
-
- /* move from Shift-IR/DR to end state */
- if (type != SCAN_OUT) {
- /* We always go to the PAUSE state in two step at the end of an IN or IO
- *scan
- * This must be coordinated with the bit shifts in ft2232_read_scan */
- tms_bits = 0x01;
- tms_count = 2;
- /* Clock Data to TMS/CS Pin with Read */
- mpsse_cmd = 0x6b;
- } else {
- tms_bits = tap_get_tms_path(tap_get_state(), tap_get_end_state());
- tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- /* Clock Data to TMS/CS Pin (no Read) */
- mpsse_cmd = 0x4b;
- }
-
- DEBUG_JTAG_IO("finish %s", (type == SCAN_OUT) ? "without read" : "via PAUSE");
- clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit);
- }
-
- if (tap_get_state() != tap_get_end_state())
- move_to_state(tap_get_end_state());
-}
-
-static int ft2232_large_scan(struct scan_command *cmd,
- enum scan_type type,
- uint8_t *buffer,
- int scan_size)
-{
- int num_bytes = (scan_size + 7) / 8;
- int bits_left = scan_size;
- int cur_byte = 0;
- int last_bit;
- uint8_t *receive_buffer = malloc(DIV_ROUND_UP(scan_size, 8));
- uint8_t *receive_pointer = receive_buffer;
- uint32_t bytes_written;
- uint32_t bytes_read;
- int retval;
- int thisrun_read = 0;
-
- if (!receive_buffer) {
- LOG_ERROR("failed to allocate memory");
- exit(-1);
- }
-
- if (cmd->ir_scan) {
- LOG_ERROR("BUG: large IR scans are not supported");
- exit(-1);
- }
-
- if (tap_get_state() != TAP_DRSHIFT)
- move_to_state(TAP_DRSHIFT);
-
- retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't write MPSSE commands to FT2232");
- exit(-1);
- }
- LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i",
- ft2232_buffer_size, (int)bytes_written);
- ft2232_buffer_size = 0;
-
- /* add command for complete bytes */
- while (num_bytes > 1) {
- int thisrun_bytes;
-
- if (type == SCAN_IO) {
- /* Clock Data Bytes In and Out LSB First */
- buffer_write(0x39);
- /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */
- } else if (type == SCAN_OUT) {
- /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
- buffer_write(0x19);
- /* LOG_DEBUG("added TDI bytes (o)"); */
- } else if (type == SCAN_IN) {
- /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
- buffer_write(0x28);
- /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */
- }
-
- thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
- thisrun_read = thisrun_bytes;
- num_bytes -= thisrun_bytes;
- buffer_write((uint8_t) (thisrun_bytes - 1));
- buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8));
-
- if (type != SCAN_IN) {
- /* add complete bytes */
- while (thisrun_bytes-- > 0) {
- buffer_write(buffer[cur_byte]);
- cur_byte++;
- bits_left -= 8;
- }
- } else /* (type == SCAN_IN) */
- bits_left -= 8 * (thisrun_bytes);
-
- retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't write MPSSE commands to FT2232");
- exit(-1);
- }
- LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i",
- ft2232_buffer_size,
- (int)bytes_written);
- ft2232_buffer_size = 0;
-
- if (type != SCAN_OUT) {
- retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read from FT2232");
- exit(-1);
- }
- LOG_DEBUG("thisrun_read: %i, bytes_read: %i",
- thisrun_read,
- (int)bytes_read);
- receive_pointer += bytes_read;
- }
- }
-
- thisrun_read = 0;
-
- /* the most signifcant bit is scanned during TAP movement */
- if (type != SCAN_IN)
- last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
- else
- last_bit = 0;
-
- /* process remaining bits but the last one */
- if (bits_left > 1) {
- if (type == SCAN_IO) {
- /* Clock Data Bits In and Out LSB First */
- buffer_write(0x3b);
- /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
- } else if (type == SCAN_OUT) {
- /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
- buffer_write(0x1b);
- /* LOG_DEBUG("added TDI bits (o)"); */
- } else if (type == SCAN_IN) {
- /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
- buffer_write(0x2a);
- /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
- }
- buffer_write(bits_left - 2);
- if (type != SCAN_IN)
- buffer_write(buffer[cur_byte]);
-
- if (type != SCAN_OUT)
- thisrun_read += 2;
- }
-
- if (tap_get_end_state() == TAP_DRSHIFT) {
- if (type == SCAN_IO) {
- /* Clock Data Bits In and Out LSB First */
- buffer_write(0x3b);
- /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */
- } else if (type == SCAN_OUT) {
- /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
- buffer_write(0x1b);
- /* LOG_DEBUG("added TDI bits (o)"); */
- } else if (type == SCAN_IN) {
- /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
- buffer_write(0x2a);
- /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */
- }
- buffer_write(0x0);
- buffer_write(last_bit);
- } else {
- int tms_bits = 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());
- uint8_t mpsse_cmd;
-
- /* move from Shift-IR/DR to end state */
- if (type != SCAN_OUT) {
- /* Clock Data to TMS/CS Pin with Read */
- mpsse_cmd = 0x6b;
- /* LOG_DEBUG("added TMS scan (read)"); */
- } else {
- /* Clock Data to TMS/CS Pin (no Read) */
- mpsse_cmd = 0x4b;
- /* LOG_DEBUG("added TMS scan (no read)"); */
- }
-
- DEBUG_JTAG_IO("finish, %s", (type == SCAN_OUT) ? "no read" : "read");
- clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit);
- }
-
- if (type != SCAN_OUT)
- thisrun_read += 1;
-
- retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't write MPSSE commands to FT2232");
- exit(-1);
- }
- LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i",
- ft2232_buffer_size,
- (int)bytes_written);
- ft2232_buffer_size = 0;
-
- if (type != SCAN_OUT) {
- retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't read from FT2232");
- exit(-1);
- }
- LOG_DEBUG("thisrun_read: %i, bytes_read: %i",
- thisrun_read,
- (int)bytes_read);
- }
-
- free(receive_buffer);
-
- return ERROR_OK;
-}
-
-static int ft2232_predict_scan_out(int scan_size, enum scan_type type)
-{
- int predicted_size = 3;
- int num_bytes = (scan_size - 1) / 8;
-
- if (tap_get_state() != TAP_DRSHIFT)
- predicted_size += get_tms_buffer_requirements(
- tap_get_tms_path_len(tap_get_state(), TAP_DRSHIFT));
-
- if (type == SCAN_IN) { /* only from device to host */
- /* complete bytes */
- predicted_size += DIV_ROUND_UP(num_bytes, 65536) * 3;
-
- /* remaining bits - 1 (up to 7) */
- predicted_size += ((scan_size - 1) % 8) ? 2 : 0;
- } else {/* host to device, or bidirectional
- * complete bytes */
- predicted_size += num_bytes + DIV_ROUND_UP(num_bytes, 65536) * 3;
-
- /* remaining bits -1 (up to 7) */
- predicted_size += ((scan_size - 1) % 8) ? 3 : 0;
- }
-
- return predicted_size;
-}
-
-static int ft2232_predict_scan_in(int scan_size, enum scan_type type)
-{
- int predicted_size = 0;
-
- if (type != SCAN_OUT) {
- /* complete bytes */
- predicted_size +=
- (DIV_ROUND_UP(scan_size, 8) > 1) ? (DIV_ROUND_UP(scan_size, 8) - 1) : 0;
-
- /* remaining bits - 1 */
- predicted_size += ((scan_size - 1) % 8) ? 1 : 0;
-
- /* last bit (from TMS scan) */
- predicted_size += 1;
- }
-
- /* LOG_DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); */
-
- return predicted_size;
-}
-
-/* semi-generic FT2232/FT4232 reset code */
-static void ftx23_reset(int trst, int srst)
-{
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (trst == 1) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- low_direction |= nTRSTnOE; /* switch to output pin (output is low) */
- else
- low_output &= ~nTRST; /* switch output low */
- } else if (trst == 0) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal
- *and external pullup) */
- else
- low_output |= nTRST; /* switch output high */
- }
-
- if (srst == 1) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- low_output &= ~nSRST; /* switch output low */
- else
- low_direction |= nSRSTnOE; /* switch to output pin (output is low) */
- } else if (srst == 0) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- low_output |= nSRST; /* switch output high */
- else
- low_direction &= ~nSRSTnOE; /* switch to input pin (high-Z) */
- }
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
-}
-
-static void jtagkey_reset(int trst, int srst)
-{
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (trst == 1) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output &= ~nTRSTnOE;
- else
- high_output &= ~nTRST;
- } else if (trst == 0) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output |= nTRSTnOE;
- else
- high_output |= nTRST;
- }
-
- if (srst == 1) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- high_output &= ~nSRST;
- else
- high_output &= ~nSRSTnOE;
- } else if (srst == 0) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- high_output |= nSRST;
- else
- high_output |= nSRSTnOE;
- }
-
- /* command "set data bits high byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x",
- trst,
- srst,
- high_output,
- high_direction);
-}
-
-static void olimex_jtag_reset(int trst, int srst)
-{
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (trst == 1) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output &= ~nTRSTnOE;
- else
- high_output &= ~nTRST;
- } else if (trst == 0) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output |= nTRSTnOE;
- else
- high_output |= nTRST;
- }
-
- if (srst == 1)
- high_output |= nSRST;
- else if (srst == 0)
- high_output &= ~nSRST;
-
- /* command "set data bits high byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x",
- trst,
- srst,
- high_output,
- high_direction);
-}
-
-static void axm0432_jtag_reset(int trst, int srst)
-{
- if (trst == 1) {
- tap_set_state(TAP_RESET);
- high_output &= ~nTRST;
- } else if (trst == 0)
- high_output |= nTRST;
-
- if (srst == 1)
- high_output &= ~nSRST;
- else if (srst == 0)
- high_output |= nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x",
- trst,
- srst,
- high_output,
- high_direction);
-}
-
-static void flyswatter_reset(int trst, int srst)
-{
- if (trst == 1)
- low_output &= ~nTRST;
- else if (trst == 0)
- low_output |= nTRST;
-
- if (srst == 1)
- low_output |= nSRST;
- else if (srst == 0)
- low_output &= ~nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
- LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x",
- trst,
- srst,
- low_output,
- low_direction);
-}
-
-static void flyswatter1_reset(int trst, int srst)
-{
- flyswatter_reset(trst, srst);
-}
-
-static void flyswatter2_reset(int trst, int srst)
-{
- flyswatter_reset(trst, !srst);
-}
-
-static void minimodule_reset(int trst, int srst)
-{
- if (srst == 1)
- low_output &= ~nSRST;
- else if (srst == 0)
- low_output |= nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
- LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x",
- trst,
- srst,
- low_output,
- low_direction);
-}
-
-static void turtle_reset(int trst, int srst)
-{
- if (trst == 1)
- LOG_ERROR("Can't assert TRST: the adapter lacks this signal");
-
- if (srst == 1)
- low_output |= nSRST;
- else if (srst == 0)
- low_output &= ~nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
- LOG_DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x",
- srst,
- low_output,
- low_direction);
-}
-
-static void comstick_reset(int trst, int srst)
-{
- if (trst == 1)
- high_output &= ~nTRST;
- else if (trst == 0)
- high_output |= nTRST;
-
- if (srst == 1)
- high_output &= ~nSRST;
- else if (srst == 0)
- high_output |= nSRST;
-
- /* command "set data bits high byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x",
- trst,
- srst,
- high_output,
- high_direction);
-}
-
-static void stm32stick_reset(int trst, int srst)
-{
- if (trst == 1)
- high_output &= ~nTRST;
- else if (trst == 0)
- high_output |= nTRST;
-
- if (srst == 1)
- low_output &= ~nSRST;
- else if (srst == 0)
- low_output |= nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
-
- /* command "set data bits high byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x",
- trst,
- srst,
- high_output,
- high_direction);
-}
-
-static void sheevaplug_reset(int trst, int srst)
-{
- if (trst == 1)
- high_output &= ~nTRST;
- else if (trst == 0)
- high_output |= nTRST;
-
- if (srst == 1)
- high_output &= ~nSRSTnOE;
- else if (srst == 0)
- high_output |= nSRSTnOE;
-
- /* command "set data bits high byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x",
- trst,
- srst,
- high_output,
- high_direction);
-}
-
-static void redbee_reset(int trst, int srst)
-{
- if (trst == 1) {
- tap_set_state(TAP_RESET);
- high_output &= ~nTRST;
- } else if (trst == 0)
- high_output |= nTRST;
-
- if (srst == 1)
- high_output &= ~nSRST;
- else if (srst == 0)
- high_output |= nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, "
- "high_direction: 0x%2.2x", trst, srst, high_output,
- high_direction);
-}
-
-static void xds100v2_reset(int trst, int srst)
-{
- if (trst == 1) {
- tap_set_state(TAP_RESET);
- high_output &= ~nTRST;
- } else if (trst == 0)
- high_output |= nTRST;
-
- if (srst == 1)
- high_output |= nSRST;
- else if (srst == 0)
- high_output &= ~nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, "
- "high_direction: 0x%2.2x", trst, srst, high_output,
- high_direction);
-}
-
-static int ft2232_execute_runtest(struct jtag_command *cmd)
-{
- int retval;
- int i;
- int predicted_size = 0;
- retval = ERROR_OK;
-
- DEBUG_JTAG_IO("runtest %i cycles, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
-
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 0;
- if (tap_get_state() != TAP_IDLE)
- predicted_size += 3;
- predicted_size += 3 * DIV_ROUND_UP(cmd->cmd.runtest->num_cycles, 7);
- if (cmd->cmd.runtest->end_state != TAP_IDLE)
- predicted_size += 3;
- if (tap_get_end_state() != TAP_IDLE)
- predicted_size += 3;
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) {
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- require_send = 0;
- first_unsent = cmd;
- }
- if (tap_get_state() != TAP_IDLE) {
- move_to_state(TAP_IDLE);
- require_send = 1;
- }
- i = cmd->cmd.runtest->num_cycles;
- while (i > 0) {
- /* there are no state transitions in this code, so omit state tracking */
-
- /* command "Clock Data to TMS/CS Pin (no Read)" */
- buffer_write(0x4b);
-
- /* scan 7 bits */
- buffer_write((i > 7) ? 6 : (i - 1));
-
- /* TMS data bits */
- buffer_write(0x0);
-
- i -= (i > 7) ? 7 : i;
- /* LOG_DEBUG("added TMS scan (no read)"); */
- }
-
- ft2232_end_state(cmd->cmd.runtest->end_state);
-
- if (tap_get_state() != tap_get_end_state())
- move_to_state(tap_get_end_state());
-
- require_send = 1;
- DEBUG_JTAG_IO("runtest: %i, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(tap_get_end_state()));
- return retval;
-}
-
-static int ft2232_execute_statemove(struct jtag_command *cmd)
-{
- int predicted_size = 0;
- int retval = ERROR_OK;
-
- DEBUG_JTAG_IO("statemove end in %s",
- tap_state_name(cmd->cmd.statemove->end_state));
-
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 3;
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) {
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- require_send = 0;
- first_unsent = cmd;
- }
- ft2232_end_state(cmd->cmd.statemove->end_state);
-
- /* For TAP_RESET, ignore the current recorded state. It's often
- * wrong at server startup, and this transation is critical whenever
- * it's requested.
- */
- if (tap_get_end_state() == TAP_RESET) {
- clock_tms(0x4b, 0xff, 5, 0);
- require_send = 1;
-
- /* shortest-path move to desired end state */
- } else if (tap_get_state() != tap_get_end_state()) {
- move_to_state(tap_get_end_state());
- require_send = 1;
- }
-
- return retval;
-}
-
-/**
- * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG
- * (or SWD) state machine.
- */
-static int ft2232_execute_tms(struct jtag_command *cmd)
-{
- int retval = ERROR_OK;
- unsigned num_bits = cmd->cmd.tms->num_bits;
- const uint8_t *bits = cmd->cmd.tms->bits;
- unsigned count;
-
- DEBUG_JTAG_IO("TMS: %d bits", num_bits);
-
- /* only send the maximum buffer size that FT2232C can handle */
- count = 3 * DIV_ROUND_UP(num_bits, 4);
- if (ft2232_buffer_size + 3*count + 1 > FT2232_BUFFER_SIZE) {
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
-
- require_send = 0;
- first_unsent = cmd;
- }
-
- /* Shift out in batches of at most 6 bits; there's a report of an
- * FT2232 bug in this area, where shifting exactly 7 bits can make
- * problems with TMS signaling for the last clock cycle:
- *
- * http://developer.intra2net.com/mailarchive/html/
- * libftdi/2009/msg00292.html
- *
- * Command 0x4b is: "Clock Data to TMS/CS Pin (no Read)"
- *
- * Note that pathmoves in JTAG are not often seven bits, so that
- * isn't a particularly likely situation outside of "special"
- * signaling such as switching between JTAG and SWD modes.
- */
- while (num_bits) {
- if (num_bits <= 6) {
- buffer_write(0x4b);
- buffer_write(num_bits - 1);
- buffer_write(*bits & 0x3f);
- break;
- }
-
- /* Yes, this is lazy ... we COULD shift out more data
- * bits per operation, but doing it in nybbles is easy
- */
- buffer_write(0x4b);
- buffer_write(3);
- buffer_write(*bits & 0xf);
- num_bits -= 4;
-
- count = (num_bits > 4) ? 4 : num_bits;
-
- buffer_write(0x4b);
- buffer_write(count - 1);
- buffer_write((*bits >> 4) & 0xf);
- num_bits -= count;
-
- bits++;
- }
-
- require_send = 1;
- return retval;
-}
-
-static int ft2232_execute_pathmove(struct jtag_command *cmd)
-{
- int predicted_size = 0;
- int retval = ERROR_OK;
-
- tap_state_t *path = cmd->cmd.pathmove->path;
- int num_states = cmd->cmd.pathmove->num_states;
-
- DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states,
- tap_state_name(tap_get_state()),
- tap_state_name(path[num_states-1]));
-
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 3 * DIV_ROUND_UP(num_states, 7);
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) {
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
-
- require_send = 0;
- first_unsent = cmd;
- }
-
- ft2232_add_pathmove(path, num_states);
- require_send = 1;
-
- return retval;
-}
-
-static int ft2232_execute_scan(struct jtag_command *cmd)
-{
- uint8_t *buffer;
- int scan_size; /* size of IR or DR scan */
- int predicted_size = 0;
- int retval = ERROR_OK;
-
- enum scan_type type = jtag_scan_type(cmd->cmd.scan);
-
- DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", type);
-
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
-
- predicted_size = ft2232_predict_scan_out(scan_size, type);
- if ((predicted_size + 1) > FT2232_BUFFER_SIZE) {
- LOG_DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)");
- /* unsent commands before this */
- if (first_unsent != cmd)
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
-
- /* current command */
- ft2232_end_state(cmd->cmd.scan->end_state);
- ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size);
- require_send = 0;
- first_unsent = cmd->next;
- if (buffer)
- free(buffer);
- return retval;
- } else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) {
- LOG_DEBUG(
- "ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)",
- first_unsent,
- cmd);
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- require_send = 0;
- first_unsent = cmd;
- }
- ft2232_expect_read += ft2232_predict_scan_in(scan_size, type);
- /* LOG_DEBUG("new read size: %i", ft2232_expect_read); */
- ft2232_end_state(cmd->cmd.scan->end_state);
- ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- require_send = 1;
- if (buffer)
- free(buffer);
- DEBUG_JTAG_IO("%s scan, %i bits, end in %s",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
- tap_state_name(tap_get_end_state()));
- return retval;
-
-}
-
-static int ft2232_execute_reset(struct jtag_command *cmd)
-{
- int retval;
- int predicted_size = 0;
- retval = ERROR_OK;
-
- DEBUG_JTAG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 3;
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) {
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- require_send = 0;
- first_unsent = cmd;
- }
-
- if ((cmd->cmd.reset->trst == 1) ||
- (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
-
- layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- require_send = 1;
-
- DEBUG_JTAG_IO("trst: %i, srst: %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- return retval;
-}
-
-static int ft2232_execute_sleep(struct jtag_command *cmd)
-{
- int retval;
- retval = ERROR_OK;
-
- DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us);
-
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- first_unsent = cmd->next;
- jtag_sleep(cmd->cmd.sleep->us);
- DEBUG_JTAG_IO("sleep %" PRIi32 " usec while in %s",
- cmd->cmd.sleep->us,
- tap_state_name(tap_get_state()));
- return retval;
-}
-
-static int ft2232_execute_stableclocks(struct jtag_command *cmd)
-{
- int retval;
- retval = ERROR_OK;
-
- /* this is only allowed while in a stable state. A check for a stable
- * state was done in jtag_add_clocks()
- */
- if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- DEBUG_JTAG_IO("clocks %i while in %s",
- cmd->cmd.stableclocks->num_cycles,
- tap_state_name(tap_get_state()));
- return retval;
-}
-
-static int ft2232_execute_command(struct jtag_command *cmd)
-{
- int retval;
-
- switch (cmd->type) {
- case JTAG_RESET:
- retval = ft2232_execute_reset(cmd);
- break;
- case JTAG_RUNTEST:
- retval = ft2232_execute_runtest(cmd);
- break;
- case JTAG_TLR_RESET:
- retval = ft2232_execute_statemove(cmd);
- break;
- case JTAG_PATHMOVE:
- retval = ft2232_execute_pathmove(cmd);
- break;
- case JTAG_SCAN:
- retval = ft2232_execute_scan(cmd);
- break;
- case JTAG_SLEEP:
- retval = ft2232_execute_sleep(cmd);
- break;
- case JTAG_STABLECLOCKS:
- retval = ft2232_execute_stableclocks(cmd);
- break;
- case JTAG_TMS:
- retval = ft2232_execute_tms(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- retval = ERROR_JTAG_QUEUE_FAILED;
- break;
- }
- return retval;
-}
-
-static int ft2232_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
- int retval;
-
- first_unsent = cmd; /* next command that has to be sent */
- require_send = 0;
-
- /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check
- * that wasn't handled by a caller-provided error handler
- */
- retval = ERROR_OK;
-
- ft2232_buffer_size = 0;
- ft2232_expect_read = 0;
-
- /* blink, if the current layout has that feature */
- if (layout->blink)
- layout->blink();
-
- while (cmd) {
- /* fill the write buffer with the desired command */
- if (ft2232_execute_command(cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- /* Start reading input before FT2232 TX buffer fills up.
- * Sometimes this happens because we don't know the
- * length of the last command before we execute it. So
- * we simple inform the user.
- */
- cmd = cmd->next;
-
- if (ft2232_expect_read >= FT2232_BUFFER_READ_QUEUE_SIZE) {
- if (ft2232_expect_read > (FT2232_BUFFER_READ_QUEUE_SIZE+1))
- LOG_DEBUG("read buffer size looks too high %d/%d",
- ft2232_expect_read,
- (FT2232_BUFFER_READ_QUEUE_SIZE+1));
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- first_unsent = cmd;
- }
- }
-
- if (require_send > 0)
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
-
- return retval;
-}
-
-#if BUILD_FT2232_FTD2XX == 1
-static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int *try_more)
-{
- FT_STATUS status;
- DWORD deviceID;
- char SerialNumber[16];
- char Description[64];
- DWORD openex_flags = 0;
- char *openex_string = NULL;
- uint8_t latency_timer;
-
- if (layout == NULL) {
- LOG_WARNING("No ft2232 layout specified'");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)",
- layout->name, vid, pid);
-
-#if IS_WIN32 == 0
- /* Add non-standard Vid/Pid to the linux driver */
- status = FT_SetVIDPID(vid, pid);
- if (status != FT_OK)
- LOG_WARNING("couldn't add %4.4x:%4.4x", vid, pid);
-
-#endif
-
- if (ft2232_device_desc && ft2232_serial) {
- LOG_WARNING(
- "can't open by device description and serial number, giving precedence to serial");
- ft2232_device_desc = NULL;
- }
-
- if (ft2232_device_desc) {
- openex_string = ft2232_device_desc;
- openex_flags = FT_OPEN_BY_DESCRIPTION;
- } else if (ft2232_serial) {
- openex_string = ft2232_serial;
- openex_flags = FT_OPEN_BY_SERIAL_NUMBER;
- } else {
- LOG_ERROR("neither device description nor serial number specified");
- LOG_ERROR(
- "please add \"ft2232_device_desc <string>\" or \"ft2232_serial <string>\" to your .cfg file");
-
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_OpenEx(openex_string, openex_flags, &ftdih);
- if (status != FT_OK) {
- /* under Win32, the FTD2XX driver appends an "A" to the end
- * of the description, if we tried by the desc, then
- * try by the alternate "A" description. */
- if (openex_string == ft2232_device_desc) {
- /* Try the alternate method. */
- openex_string = ft2232_device_desc_A;
- status = FT_OpenEx(openex_string, openex_flags, &ftdih);
- if (status == FT_OK) {
- /* yea, the "alternate" method worked! */
- } else {
- /* drat, give the user a meaningfull message.
- * telling the use we tried *BOTH* methods. */
- LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'",
- ft2232_device_desc,
- ft2232_device_desc_A);
- }
- }
- }
-
- if (status != FT_OK) {
- DWORD num_devices;
-
- if (more) {
- LOG_WARNING("unable to open ftdi device (trying more): %s",
- ftd2xx_status_string(status));
- *try_more = 1;
- return ERROR_JTAG_INIT_FAILED;
- }
- LOG_ERROR("unable to open ftdi device: %s",
- ftd2xx_status_string(status));
- status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
- if (status == FT_OK) {
- char **desc_array = malloc(sizeof(char *) * (num_devices + 1));
- uint32_t i;
-
- for (i = 0; i < num_devices; i++)
- desc_array[i] = malloc(64);
-
- desc_array[num_devices] = NULL;
-
- status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags);
-
- if (status == FT_OK) {
- LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices);
- for (i = 0; i < num_devices; i++)
- LOG_ERROR("%" PRIu32 ": \"%s\"", i, desc_array[i]);
- }
-
- for (i = 0; i < num_devices; i++)
- free(desc_array[i]);
-
- free(desc_array);
- } else
- LOG_ERROR("ListDevices: NONE");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_SetLatencyTimer(ftdih, ft2232_latency);
- if (status != FT_OK) {
- LOG_ERROR("unable to set latency timer: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_GetLatencyTimer(ftdih, &latency_timer);
- if (status != FT_OK) {
- /* ftd2xx 1.04 (linux) has a bug when calling FT_GetLatencyTimer
- * so ignore errors if using this driver version */
- DWORD dw_version;
-
- status = FT_GetDriverVersion(ftdih, &dw_version);
- LOG_ERROR("unable to get latency timer: %s",
- ftd2xx_status_string(status));
-
- if ((status == FT_OK) && (dw_version == 0x10004)) {
- LOG_ERROR("ftd2xx 1.04 detected - this has known issues " \
- "with FT_GetLatencyTimer, upgrade to a newer version");
- } else
- return ERROR_JTAG_INIT_FAILED;
- } else
- LOG_DEBUG("current latency timer: %i", latency_timer);
-
- status = FT_SetTimeouts(ftdih, 5000, 5000);
- if (status != FT_OK) {
- LOG_ERROR("unable to set timeouts: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_SetBitMode(ftdih, 0x0b, 2);
- if (status != FT_OK) {
- LOG_ERROR("unable to enable bit i/o mode: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID,
- SerialNumber, Description, NULL);
- if (status != FT_OK) {
- LOG_ERROR("unable to get FT_GetDeviceInfo: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_INIT_FAILED;
- } else {
- static const char *type_str[] = {
- "BM", "AM", "100AX", "UNKNOWN", "2232C", "232R", "2232H", "4232H", "232H"
- };
- unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1;
- unsigned type_index = ((unsigned)ftdi_device <= no_of_known_types)
- ? ftdi_device : FT_DEVICE_UNKNOWN;
- LOG_INFO("device: %" PRIu32 " \"%s\"", (uint32_t)ftdi_device, type_str[type_index]);
- LOG_INFO("deviceID: %" PRIu32, (uint32_t)deviceID);
- LOG_INFO("SerialNumber: %s", SerialNumber);
- LOG_INFO("Description: %s", Description);
- }
-
- return ERROR_OK;
-}
-
-static int ft2232_purge_ftd2xx(void)
-{
- FT_STATUS status;
-
- status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
- if (status != FT_OK) {
- LOG_ERROR("error purging ftd2xx device: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-#endif /* BUILD_FT2232_FTD2XX == 1 */
-
-#if BUILD_FT2232_LIBFTDI == 1
-static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int *try_more, int channel)
-{
- uint8_t latency_timer;
-
- if (layout == NULL) {
- LOG_WARNING("No ft2232 layout specified'");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- LOG_DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)",
- layout->name, vid, pid);
-
- if (ftdi_init(&ftdic) < 0)
- return ERROR_JTAG_INIT_FAILED;
-
- /* default to INTERFACE_A */
- if (channel == INTERFACE_ANY)
- channel = INTERFACE_A;
- if (ftdi_set_interface(&ftdic, channel) < 0) {
- LOG_ERROR("unable to select FT2232 channel A: %s", ftdic.error_str);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- /* context, vendor id, product id */
- if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc, ft2232_serial) < 0) {
- if (more)
- LOG_WARNING("unable to open ftdi device (trying more): %s",
- ftdic.error_str);
- else
- LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
- *try_more = 1;
- return ERROR_JTAG_INIT_FAILED;
- }
-
- /* There is already a reset in ftdi_usb_open_desc, this should be redundant */
- if (ftdi_usb_reset(&ftdic) < 0) {
- LOG_ERROR("unable to reset ftdi device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0) {
- LOG_ERROR("unable to set latency timer");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) {
- LOG_ERROR("unable to get latency timer");
- return ERROR_JTAG_INIT_FAILED;
- } else
- LOG_DEBUG("current latency timer: %i", latency_timer);
-
- ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */
-
- ftdi_device = ftdic.type;
- static const char *type_str[] = {
- "AM", "BM", "2232C", "R", "2232H", "4232H", "232H", "Unknown"
- };
- unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1;
- unsigned type_index = ((unsigned)ftdi_device < no_of_known_types)
- ? ftdi_device : no_of_known_types;
- LOG_DEBUG("FTDI chip type: %i \"%s\"", (int)ftdi_device, type_str[type_index]);
- return ERROR_OK;
-}
-
-static int ft2232_purge_libftdi(void)
-{
- if (ftdi_usb_purge_buffers(&ftdic) < 0) {
- LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-#endif /* BUILD_FT2232_LIBFTDI == 1 */
-
-static int ft2232_set_data_bits_low_byte(uint8_t value, uint8_t direction)
-{
- uint8_t buf[3];
- uint32_t bytes_written;
-
- buf[0] = 0x80; /* command "set data bits low byte" */
- buf[1] = value; /* value */
- buf[2] = direction; /* direction */
-
- LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
- if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) {
- LOG_ERROR("couldn't initialize data bits low byte");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int ft2232_set_data_bits_high_byte(uint8_t value, uint8_t direction)
-{
- uint8_t buf[3];
- uint32_t bytes_written;
-
- buf[0] = 0x82; /* command "set data bits high byte" */
- buf[1] = value; /* value */
- buf[2] = direction; /* direction */
-
- LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
- if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) {
- LOG_ERROR("couldn't initialize data bits high byte");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int ft2232_init(void)
-{
- uint8_t buf[1];
- int retval;
- uint32_t bytes_written;
-
- LOG_WARNING("Using DEPRECATED interface driver 'ft2232'");
-#if BUILD_FTDI
- LOG_INFO("Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/...");
-#endif
-
- if (tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRPAUSE) == 7)
- LOG_DEBUG("ft2232 interface using 7 step jtag state transitions");
- else
- LOG_DEBUG("ft2232 interface using shortest path jtag state transitions");
- if (layout == NULL) {
- LOG_WARNING("No ft2232 layout specified'");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- for (int i = 0; 1; i++) {
- /*
- * "more indicates that there are more IDs to try, so we should
- * not print an error for an ID mismatch (but for anything
- * else, we should).
- *
- * try_more indicates that the error code returned indicates an
- * ID mismatch (and nothing else) and that we should proceeed
- * with the next ID pair.
- */
- int more = ft2232_vid[i + 1] || ft2232_pid[i + 1];
- int try_more = 0;
-
-#if BUILD_FT2232_FTD2XX == 1
- retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i],
- more, &try_more);
-#elif BUILD_FT2232_LIBFTDI == 1
- retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i],
- more, &try_more, ft2232_channel);
-#endif
- if (retval >= 0)
- break;
- if (!more || !try_more)
- return retval;
- }
-
- ft2232_buffer_size = 0;
- ft2232_buffer = malloc(FT2232_BUFFER_SIZE);
-
- if (layout->init() != ERROR_OK)
- return ERROR_JTAG_INIT_FAILED;
-
- if (ft2232_device_is_highspeed()) {
-#ifndef BUILD_FT2232_HIGHSPEED
- #if BUILD_FT2232_FTD2XX == 1
- LOG_WARNING(
- "High Speed device found - You need a newer FTD2XX driver (version 2.04.16 or later)");
- #elif BUILD_FT2232_LIBFTDI == 1
- LOG_WARNING(
- "High Speed device found - You need a newer libftdi version (0.16 or later)");
- #endif
-#endif
- /* make sure the legacy mode is disabled */
- if (ftx232h_clk_divide_by_5(false) != ERROR_OK)
- return ERROR_JTAG_INIT_FAILED;
- }
-
- buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */
- retval = ft2232_write(buf, 1, &bytes_written);
- if (retval != ERROR_OK) {
- LOG_ERROR("couldn't write to FT2232 to disable loopback");
- return ERROR_JTAG_INIT_FAILED;
- }
-
-#if BUILD_FT2232_FTD2XX == 1
- return ft2232_purge_ftd2xx();
-#elif BUILD_FT2232_LIBFTDI == 1
- return ft2232_purge_libftdi();
-#endif
-
- return ERROR_OK;
-}
-
-/** Updates defaults for DBUS signals: the four JTAG signals
- * (TCK, TDI, TDO, TMS) and * the four GPIOL signals.
- */
-static inline void ftx232_dbus_init(void)
-{
- low_output = 0x08;
- low_direction = 0x0b;
-}
-
-/** Initializes DBUS signals: the four JTAG signals (TCK, TDI, TDO, TMS),
- * the four GPIOL signals. Initialization covers value and direction,
- * as customized for each layout.
- */
-static int ftx232_dbus_write(void)
-{
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) {
- low_direction &= ~nTRSTnOE; /* nTRST input */
- low_output &= ~nTRST; /* nTRST = 0 */
- } else {
- low_direction |= nTRSTnOE; /* nTRST output */
- low_output |= nTRST; /* nTRST = 1 */
- }
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL) {
- low_direction |= nSRSTnOE; /* nSRST output */
- low_output |= nSRST; /* nSRST = 1 */
- } else {
- low_direction &= ~nSRSTnOE; /* nSRST input */
- low_output &= ~nSRST; /* nSRST = 0 */
- }
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 DBUS");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int usbjtag_init(void)
-{
- /*
- * NOTE: This is now _specific_ to the "usbjtag" layout.
- * Don't try cram any more layouts into this.
- */
- ftx232_dbus_init();
-
- nTRST = 0x10;
- nTRSTnOE = 0x10;
- nSRST = 0x40;
- nSRSTnOE = 0x40;
-
- return ftx232_dbus_write();
-}
-
-static int lm3s811_jtag_init(void)
-{
- ftx232_dbus_init();
-
- /* There are multiple revisions of LM3S811 eval boards:
- * - Rev B (and older?) boards have no SWO trace support.
- * - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN;
- * they should use the "luminary_icdi" layout instead.
- */
- nTRST = 0x0;
- nTRSTnOE = 0x00;
- nSRST = 0x20;
- nSRSTnOE = 0x20;
- low_output = 0x88;
- low_direction = 0x8b;
-
- return ftx232_dbus_write();
-}
-
-static int icdi_jtag_init(void)
-{
- ftx232_dbus_init();
-
- /* Most Luminary eval boards support SWO trace output,
- * and should use this "luminary_icdi" layout.
- *
- * ADBUS 0..3 are used for JTAG as usual. GPIOs are used
- * to switch between JTAG and SWD, or switch the ft2232 UART
- * on the second MPSSE channel/interface (BDBUS)
- * between (i) the stellaris UART (on Luminary boards)
- * or (ii) SWO trace data (generic).
- *
- * We come up in JTAG mode and may switch to SWD later (with
- * SWO/trace option if SWD is active).
- *
- * DBUS == GPIO-Lx
- * CBUS == GPIO-Hx
- */
-
-
-#define ICDI_JTAG_EN (1 << 7) /* ADBUS 7 (a.k.a. DBGMOD) */
-#define ICDI_DBG_ENn (1 << 6) /* ADBUS 6 */
-#define ICDI_SRST (1 << 5) /* ADBUS 5 */
-
-
- /* GPIOs on second channel/interface (UART) ... */
-#define ICDI_SWO_EN (1 << 4) /* BDBUS 4 */
-#define ICDI_TX_SWO (1 << 1) /* BDBUS 1 */
-#define ICDI_VCP_RX (1 << 0) /* BDBUS 0 (to stellaris UART) */
-
- nTRST = 0x0;
- nTRSTnOE = 0x00;
- nSRST = ICDI_SRST;
- nSRSTnOE = ICDI_SRST;
-
- low_direction |= ICDI_JTAG_EN | ICDI_DBG_ENn;
- low_output |= ICDI_JTAG_EN;
- low_output &= ~ICDI_DBG_ENn;
-
- return ftx232_dbus_write();
-}
-
-static int signalyzer_init(void)
-{
- ftx232_dbus_init();
-
- nTRST = 0x10;
- nTRSTnOE = 0x10;
- nSRST = 0x20;
- nSRSTnOE = 0x20;
- return ftx232_dbus_write();
-}
-
-static int axm0432_jtag_init(void)
-{
- low_output = 0x08;
- low_direction = 0x2b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (strcmp(layout->name, "axm0432_jtag") == 0) {
- nTRST = 0x08;
- nTRSTnOE = 0x0; /* No output enable for TRST*/
- nSRST = 0x04;
- nSRSTnOE = 0x0; /* No output enable for SRST*/
- } else {
- LOG_ERROR("BUG: axm0432_jtag_init called for non axm0432 layout");
- exit(-1);
- }
-
- high_output = 0x0;
- high_direction = 0x0c;
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- LOG_ERROR("can't set nTRSTOE to push-pull on the Dicarlo jtag");
- else
- high_output |= nTRST;
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- LOG_ERROR("can't set nSRST to push-pull on the Dicarlo jtag");
- else
- high_output |= nSRST;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int redbee_init(void)
-{
- low_output = 0x08;
- low_direction = 0x2b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRST = 0x08;
- nTRSTnOE = 0x0; /* No output enable for TRST*/
- nSRST = 0x04;
- nSRSTnOE = 0x0; /* No output enable for SRST*/
-
- high_output = 0x0;
- high_direction = 0x0c;
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- LOG_ERROR("can't set nTRSTOE to push-pull on redbee");
- else
- high_output |= nTRST;
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- LOG_ERROR("can't set nSRST to push-pull on redbee");
- else
- high_output |= nSRST;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int jtagkey_init(void)
-{
- low_output = 0x08;
- low_direction = 0x1b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (strcmp(layout->name, "jtagkey") == 0) {
- nTRST = 0x01;
- nTRSTnOE = 0x4;
- nSRST = 0x02;
- nSRSTnOE = 0x08;
- } else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0)
- || (strcmp(layout->name, "oocdlink") == 0)) {
- nTRST = 0x02;
- nTRSTnOE = 0x1;
- nSRST = 0x08;
- nSRSTnOE = 0x04;
- } else {
- LOG_ERROR("BUG: jtagkey_init called for non jtagkey layout");
- exit(-1);
- }
-
- high_output = 0x0;
- high_direction = 0x0f;
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) {
- high_output |= nTRSTnOE;
- high_output &= ~nTRST;
- } else {
- high_output &= ~nTRSTnOE;
- high_output |= nTRST;
- }
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL) {
- high_output &= ~nSRSTnOE;
- high_output |= nSRST;
- } else {
- high_output |= nSRSTnOE;
- high_output &= ~nSRST;
- }
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int olimex_jtag_init(void)
-{
- low_output = 0x08;
- low_direction = 0x1b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRST = 0x01;
- nTRSTnOE = 0x4;
- nSRST = 0x02;
- nSRSTnOE = 0x00;/* no output enable for nSRST */
-
- high_output = 0x0;
- high_direction = 0x0f;
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) {
- high_output |= nTRSTnOE;
- high_output &= ~nTRST;
- } else {
- high_output &= ~nTRSTnOE;
- high_output |= nTRST;
- }
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- LOG_ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD");
- else
- high_output &= ~nSRST;
-
- /* turn red LED on */
- high_output |= 0x08;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int flyswatter_init(int rev)
-{
- low_output = 0x18;
- low_direction = 0x7b;
-
- if ((rev < 0) || (rev > 3)) {
- LOG_ERROR("bogus 'flyswatter' revision supplied (%i)", rev);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (rev == 1)
- low_direction |= 1 << 7;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRST = 0x10;
- nTRSTnOE = 0x0; /* not output enable for nTRST */
- nSRST = 0x20;
- nSRSTnOE = 0x00; /* no output enable for nSRST */
-
- high_output = 0x00;
-
- if (rev == 1)
- high_direction = 0x0c;
- else
- high_direction = 0x01;
-
- /* turn red LED3 on, LED2 off */
- high_output |= 0x08;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int flyswatter1_init(void)
-{
- return flyswatter_init(1);
-}
-
-static int flyswatter2_init(void)
-{
- return flyswatter_init(2);
-}
-
-static int minimodule_init(void)
-{
- low_output = 0x18; /* check if srst should be 1 or 0 initially. (0x08) (flyswatter was
- * 0x18) */
- low_direction = 0xfb; /* 0xfb; */
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
-
- nSRST = 0x20;
-
- high_output = 0x00;
- high_direction = 0x05;
-
- /* turn red LED3 on, LED2 off */
- /* high_output |= 0x08; */
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int turtle_init(void)
-{
- low_output = 0x08;
- low_direction = 0x5b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nSRST = 0x40;
-
- high_output = 0x00;
- high_direction = 0x0C;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int comstick_init(void)
-{
- low_output = 0x08;
- low_direction = 0x0b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRST = 0x01;
- nTRSTnOE = 0x00; /* no output enable for nTRST */
- nSRST = 0x02;
- nSRSTnOE = 0x00; /* no output enable for nSRST */
-
- high_output = 0x03;
- high_direction = 0x03;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int stm32stick_init(void)
-{
- low_output = 0x88;
- low_direction = 0x8b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRST = 0x01;
- nTRSTnOE = 0x00; /* no output enable for nTRST */
- nSRST = 0x80;
- nSRSTnOE = 0x00; /* no output enable for nSRST */
-
- high_output = 0x01;
- high_direction = 0x03;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int sheevaplug_init(void)
-{
- low_output = 0x08;
- low_direction = 0x1b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRSTnOE = 0x1;
- nTRST = 0x02;
- nSRSTnOE = 0x4;
- nSRST = 0x08;
-
- high_output = 0x0;
- high_direction = 0x0f;
-
- /* nTRST is always push-pull */
- high_output &= ~nTRSTnOE;
- high_output |= nTRST;
-
- /* nSRST is always open-drain */
- high_output |= nSRSTnOE;
- high_output &= ~nSRST;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int cortino_jtag_init(void)
-{
- low_output = 0x08;
- low_direction = 0x1b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRST = 0x01;
- nTRSTnOE = 0x00; /* no output enable for nTRST */
- nSRST = 0x02;
- nSRSTnOE = 0x00; /* no output enable for nSRST */
-
- high_output = 0x03;
- high_direction = 0x03;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int lisa_l_init(void)
-{
- ftx232_dbus_init();
-
- nTRST = 0x10;
- nTRSTnOE = 0x10;
- nSRST = 0x40;
- nSRSTnOE = 0x40;
-
- high_output = 0x00;
- high_direction = 0x18;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'lisa_l' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ftx232_dbus_write();
-}
-
-static int flossjtag_init(void)
-{
- ftx232_dbus_init();
-
- nTRST = 0x10;
- nTRSTnOE = 0x10;
- nSRST = 0x40;
- nSRSTnOE = 0x40;
-
- high_output = 0x00;
- high_direction = 0x18;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'Floss-JTAG' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ftx232_dbus_write();
-}
-
-/*
- * The reference schematic from TI for the XDS100v2 has a CPLD on which opens
- * the door for a number of different configurations
- *
- * Known Implementations:
- * http://processors.wiki.ti.com/images/9/93/TMS570LS20216_USB_STICK_Schematic.pdf
- *
- * http://processors.wiki.ti.com/index.php/XDS100 (rev2)
- * * CLPD logic: Rising edge to enable outputs (XDS100_PWR_RST)
- * * ACBUS3 to transition 0->1 (OE rising edge)
- * * CPLD logic: Put the EMU0/1 pins in Hi-Z:
- * * ADBUS5/GPIOL1 = EMU_EN = 1
- * * ADBUS6/GPIOL2 = EMU0 = 0
- * * ACBUS4/SPARE0 = EMU1 = 0
- * * CPLD logic: Disable loopback
- * * ACBUS6/SPARE2 = LOOPBACK = 0
- */
-#define XDS100_nEMU_EN (1<<5)
-#define XDS100_nEMU0 (1<<6)
-
-#define XDS100_PWR_RST (1<<3)
-#define XDS100_nEMU1 (1<<4)
-#define XDS100_LOOPBACK (1<<6)
-static int xds100v2_init(void)
-{
- /* These are in the lower byte */
- nTRST = 0x10;
- nTRSTnOE = 0x10;
-
- /* These aren't actually used on 14 pin connectors
- * These are in the upper byte */
- nSRST = 0x01;
- nSRSTnOE = 0x01;
-
- low_output = 0x08 | nTRST | XDS100_nEMU_EN;
- low_direction = 0x0b | nTRSTnOE | XDS100_nEMU_EN | XDS100_nEMU0;
-
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'xds100v2' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- high_output = 0;
- high_direction = nSRSTnOE | XDS100_LOOPBACK | XDS100_PWR_RST | XDS100_nEMU1;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't put CPLD in to reset with 'xds100v2' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- high_output |= XDS100_PWR_RST;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't bring CPLD out of reset with 'xds100v2' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static void olimex_jtag_blink(void)
-{
- /* Olimex ARM-USB-OCD has a LED connected to ACBUS3
- * ACBUS3 is bit 3 of the GPIOH port
- */
- high_output ^= 0x08;
-
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
-}
-
-static void flyswatter_jtag_blink(unsigned char led)
-{
- buffer_write(0x82);
- buffer_write(high_output ^ led);
- buffer_write(high_direction);
-}
-
-static void flyswatter1_jtag_blink(void)
-{
- /*
- * Flyswatter has two LEDs connected to ACBUS2 and ACBUS3
- */
- flyswatter_jtag_blink(0xc);
-}
-
-static void flyswatter2_jtag_blink(void)
-{
- /*
- * Flyswatter2 only has one LED connected to ACBUS2
- */
- flyswatter_jtag_blink(0x4);
-}
-
-static void turtle_jtag_blink(void)
-{
- /*
- * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3
- */
- if (high_output & 0x08)
- high_output = 0x04;
- else
- high_output = 0x08;
-
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
-}
-
-static void lisa_l_blink(void)
-{
- /*
- * Lisa/L has two LEDs connected to BCBUS3 and BCBUS4
- */
- if (high_output & 0x10)
- high_output = 0x08;
- else
- high_output = 0x10;
-
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
-}
-
-static void flossjtag_blink(void)
-{
- /*
- * Floss-JTAG has two LEDs connected to ACBUS3 and ACBUS4
- */
- if (high_output & 0x10)
- high_output = 0x08;
- else
- high_output = 0x10;
-
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
-}
-
-static int ft2232_quit(void)
-{
-#if BUILD_FT2232_FTD2XX == 1
-
- FT_Close(ftdih);
-#elif BUILD_FT2232_LIBFTDI == 1
- ftdi_usb_close(&ftdic);
-
- ftdi_deinit(&ftdic);
-#endif
-
- free(ft2232_buffer);
- ft2232_buffer = NULL;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ft2232_handle_device_desc_command)
-{
- char *cp;
- char buf[200];
- if (CMD_ARGC == 1) {
- ft2232_device_desc = strdup(CMD_ARGV[0]);
- cp = strchr(ft2232_device_desc, 0);
- /* under Win32, the FTD2XX driver appends an "A" to the end
- * of the description, this examines the given desc
- * and creates the 'missing' _A or non_A variable. */
- if ((cp[-1] == 'A') && (cp[-2] == ' ')) {
- /* it was, so make this the "A" version. */
- ft2232_device_desc_A = ft2232_device_desc;
- /* and *CREATE* the non-A version. */
- strcpy(buf, ft2232_device_desc);
- cp = strchr(buf, 0);
- cp[-2] = 0;
- ft2232_device_desc = strdup(buf);
- } else {
- /* <space > A not defined
- * so create it */
- sprintf(buf, "%s A", ft2232_device_desc);
- ft2232_device_desc_A = strdup(buf);
- }
- } else
- LOG_ERROR("expected exactly one argument to ft2232_device_desc <description>");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ft2232_handle_serial_command)
-{
- if (CMD_ARGC == 1)
- ft2232_serial = strdup(CMD_ARGV[0]);
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ft2232_handle_layout_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (layout) {
- LOG_ERROR("already specified ft2232_layout %s",
- layout->name);
- return (strcmp(layout->name, CMD_ARGV[0]) != 0)
- ? ERROR_FAIL
- : ERROR_OK;
- }
-
- for (const struct ft2232_layout *l = ft2232_layouts; l->name; l++) {
- if (strcmp(l->name, CMD_ARGV[0]) == 0) {
- layout = l;
- ft2232_channel = l->channel;
- return ERROR_OK;
- }
- }
-
- LOG_ERROR("No FT2232 layout '%s' found", CMD_ARGV[0]);
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(ft2232_handle_vid_pid_command)
-{
- if (CMD_ARGC > MAX_USB_IDS * 2) {
- LOG_WARNING("ignoring extra IDs in ft2232_vid_pid "
- "(maximum is %d pairs)", MAX_USB_IDS);
- CMD_ARGC = MAX_USB_IDS * 2;
- }
- if (CMD_ARGC < 2 || (CMD_ARGC & 1)) {
- LOG_WARNING("incomplete ft2232_vid_pid configuration directive");
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- /* remove the incomplete trailing id */
- CMD_ARGC -= 1;
- }
-
- unsigned i;
- for (i = 0; i < CMD_ARGC; i += 2) {
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ft2232_vid[i >> 1]);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ft2232_pid[i >> 1]);
- }
-
- /*
- * Explicitly terminate, in case there are multiples instances of
- * ft2232_vid_pid.
- */
- ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ft2232_handle_latency_command)
-{
- if (CMD_ARGC == 1)
- ft2232_latency = atoi(CMD_ARGV[0]);
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ft2232_handle_channel_command)
-{
- if (CMD_ARGC == 1) {
- ft2232_channel = atoi(CMD_ARGV[0]);
- if (ft2232_channel < 0 || ft2232_channel > 4)
- LOG_ERROR("ft2232_channel must be in the 0 to 4 range");
- } else
- LOG_ERROR("expected exactly one argument to ft2232_channel <ch>");
-
- return ERROR_OK;
-}
-
-static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd)
-{
- int retval = 0;
-
- /* 7 bits of either ones or zeros. */
- uint8_t tms = (tap_get_state() == TAP_RESET ? 0x7F : 0x00);
-
- while (num_cycles > 0) {
- /* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles
- * at most 7 bits per invocation. Here we invoke it potentially
- * several times.
- */
- int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles;
-
- if (ft2232_buffer_size + 3 >= FT2232_BUFFER_SIZE) {
- if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
-
- first_unsent = cmd;
- }
-
- /* there are no state transitions in this code, so omit state tracking */
-
- /* command "Clock Data to TMS/CS Pin (no Read)" */
- buffer_write(0x4b);
-
- /* scan 7 bit */
- buffer_write(bitcount_per_command - 1);
-
- /* TMS data bits are either all zeros or ones to stay in the current stable state */
- buffer_write(tms);
-
- require_send = 1;
-
- num_cycles -= bitcount_per_command;
- }
-
- return retval;
-}
-
-/* ---------------------------------------------------------------------
- * Support for IceBear JTAG adapter from Section5:
- * http://section5.ch/icebear
- *
- * Author: Sten, debian@sansys-electronic.com
- */
-
-/* Icebear pin layout
- *
- * ADBUS5 (nEMU) nSRST | 2 1| GND (10k->VCC)
- * GND GND | 4 3| n.c.
- * ADBUS3 TMS | 6 5| ADBUS6 VCC
- * ADBUS0 TCK | 8 7| ADBUS7 (GND)
- * ADBUS4 nTRST |10 9| ACBUS0 (GND)
- * ADBUS1 TDI |12 11| ACBUS1 (GND)
- * ADBUS2 TDO |14 13| GND GND
- *
- * ADBUS0 O L TCK ACBUS0 GND
- * ADBUS1 O L TDI ACBUS1 GND
- * ADBUS2 I TDO ACBUS2 n.c.
- * ADBUS3 O H TMS ACBUS3 n.c.
- * ADBUS4 O H nTRST
- * ADBUS5 O H nSRST
- * ADBUS6 - VCC
- * ADBUS7 - GND
- */
-static int icebear_jtag_init(void)
-{
- low_direction = 0x0b; /* output: TCK TDI TMS; input: TDO */
- low_output = 0x08; /* high: TMS; low: TCK TDI */
- nTRST = 0x10;
- nSRST = 0x20;
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0)
- low_direction &= ~nTRST; /* nTRST high impedance */
- else {
- low_direction |= nTRST;
- low_output |= nTRST;
- }
-
- low_direction |= nSRST;
- low_output |= nSRST;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- high_output = 0x0;
- high_direction = 0x00;
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static void icebear_jtag_reset(int trst, int srst)
-{
- if (trst == 1) {
- low_direction |= nTRST;
- low_output &= ~nTRST;
- } else if (trst == 0) {
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0)
- low_direction &= ~nTRST;
- else
- low_output |= nTRST;
- }
-
- if (srst == 1)
- low_output &= ~nSRST;
- else if (srst == 0)
- low_output |= nSRST;
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
-
- LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x",
- trst,
- srst,
- low_output,
- low_direction);
-}
-
-/* ---------------------------------------------------------------------
- * Support for Signalyzer H2 and Signalyzer H4
- * JTAG adapter from Xverve Technologies Inc.
- * http://www.signalyzer.com or http://www.xverve.com
- *
- * Author: Oleg Seiljus, oleg@signalyzer.com
- */
-static unsigned char signalyzer_h_side;
-static unsigned int signalyzer_h_adapter_type;
-
-static int signalyzer_h_ctrl_write(int address, unsigned short value);
-
-#if BUILD_FT2232_FTD2XX == 1
-static int signalyzer_h_ctrl_read(int address, unsigned short *value);
-#endif
-
-#define SIGNALYZER_COMMAND_ADDR 128
-#define SIGNALYZER_DATA_BUFFER_ADDR 129
-
-#define SIGNALYZER_COMMAND_VERSION 0x41
-#define SIGNALYZER_COMMAND_RESET 0x42
-#define SIGNALYZER_COMMAND_POWERCONTROL_GET 0x50
-#define SIGNALYZER_COMMAND_POWERCONTROL_SET 0x51
-#define SIGNALYZER_COMMAND_PWM_SET 0x52
-#define SIGNALYZER_COMMAND_LED_SET 0x53
-#define SIGNALYZER_COMMAND_ADC 0x54
-#define SIGNALYZER_COMMAND_GPIO_STATE 0x55
-#define SIGNALYZER_COMMAND_GPIO_MODE 0x56
-#define SIGNALYZER_COMMAND_GPIO_PORT 0x57
-#define SIGNALYZER_COMMAND_I2C 0x58
-
-#define SIGNALYZER_CHAN_A 1
-#define SIGNALYZER_CHAN_B 2
-/* LEDS use channel C */
-#define SIGNALYZER_CHAN_C 4
-
-#define SIGNALYZER_LED_GREEN 1
-#define SIGNALYZER_LED_RED 2
-
-#define SIGNALYZER_MODULE_TYPE_EM_LT16_A 0x0301
-#define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG 0x0302
-#define SIGNALYZER_MODULE_TYPE_EM_JTAG 0x0303
-#define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P 0x0304
-#define SIGNALYZER_MODULE_TYPE_EM_JTAG_P 0x0305
-
-
-static int signalyzer_h_ctrl_write(int address, unsigned short value)
-{
-#if BUILD_FT2232_FTD2XX == 1
- return FT_WriteEE(ftdih, address, value);
-#elif BUILD_FT2232_LIBFTDI == 1
- return 0;
-#endif
-}
-
-#if BUILD_FT2232_FTD2XX == 1
-static int signalyzer_h_ctrl_read(int address, unsigned short *value)
-{
- return FT_ReadEE(ftdih, address, value);
-}
-#endif
-
-static int signalyzer_h_led_set(unsigned char channel, unsigned char led,
- int on_time_ms, int off_time_ms, unsigned char cycles)
-{
- unsigned char on_time;
- unsigned char off_time;
-
- if (on_time_ms < 0xFFFF)
- on_time = (unsigned char)(on_time_ms / 62);
- else
- on_time = 0xFF;
-
- off_time = (unsigned char)(off_time_ms / 62);
-
-#if BUILD_FT2232_FTD2XX == 1
- FT_STATUS status;
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- ((uint32_t)(channel << 8) | led));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1),
- ((uint32_t)(on_time << 8) | off_time));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2),
- ((uint32_t)cycles));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_LED_SET);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-#elif BUILD_FT2232_LIBFTDI == 1
- int retval;
-
- retval = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- ((uint32_t)(channel << 8) | led));
- if (retval < 0) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1),
- ((uint32_t)(on_time << 8) | off_time));
- if (retval < 0) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2),
- (uint32_t)cycles);
- if (retval < 0) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- retval = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_LED_SET);
- if (retval < 0) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-#endif
-}
-
-static int signalyzer_h_init(void)
-{
-#if BUILD_FT2232_FTD2XX == 1
- FT_STATUS status;
- int i;
-#endif
-
- char *end_of_desc;
-
- uint16_t read_buf[12] = { 0 };
-
- /* turn on center green led */
- signalyzer_h_led_set(SIGNALYZER_CHAN_C, SIGNALYZER_LED_GREEN,
- 0xFFFF, 0x00, 0x00);
-
- /* determine what channel config wants to open
- * TODO: change me... current implementation is made to work
- * with openocd description parsing.
- */
- end_of_desc = strrchr(ft2232_device_desc, 0x00);
-
- if (end_of_desc) {
- signalyzer_h_side = *(end_of_desc - 1);
- if (signalyzer_h_side == 'B')
- signalyzer_h_side = SIGNALYZER_CHAN_B;
- else
- signalyzer_h_side = SIGNALYZER_CHAN_A;
- } else {
- LOG_ERROR("No Channel was specified");
- return ERROR_FAIL;
- }
-
- signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_GREEN,
- 1000, 1000, 0xFF);
-
-#if BUILD_FT2232_FTD2XX == 1
- /* read signalyzer versionining information */
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_VERSION);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- for (i = 0; i < 10; i++) {
- status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i),
- &read_buf[i]);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_read returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
-
- LOG_INFO("Signalyzer: ID info: { %.4x %.4x %.4x %.4x %.4x %.4x %.4x }",
- read_buf[0], read_buf[1], read_buf[2], read_buf[3],
- read_buf[4], read_buf[5], read_buf[6]);
-
- /* set gpio register */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- (uint32_t)(signalyzer_h_side << 8));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0404);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_GPIO_STATE);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* read adapter type information */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- ((uint32_t)(signalyzer_h_side << 8) | 0x01));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(
- (SIGNALYZER_DATA_BUFFER_ADDR + 1), 0xA000);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(
- (SIGNALYZER_DATA_BUFFER_ADDR + 2), 0x0008);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_I2C);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- usleep(100000);
-
- status = signalyzer_h_ctrl_read(SIGNALYZER_COMMAND_ADDR, &read_buf[0]);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_read returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (read_buf[0] != 0x0498)
- signalyzer_h_adapter_type = 0x0000;
- else {
- for (i = 0; i < 4; i++) {
- status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i), &read_buf[i]);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_read returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
-
- signalyzer_h_adapter_type = read_buf[0];
- }
-
-#elif BUILD_FT2232_LIBFTDI == 1
- /* currently libftdi does not allow reading individual eeprom
- * locations, therefore adapter type cannot be detected.
- * override with most common type
- */
- signalyzer_h_adapter_type = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG;
-#endif
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- /* ADAPTOR: EM_LT16_A */
- if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) {
- LOG_INFO("Signalyzer: EM-LT (16-channel level translator) "
- "detected. (HW: %2x).", (read_buf[1] >> 8));
-
- nTRST = 0x10;
- nTRSTnOE = 0x10;
- nSRST = 0x20;
- nSRSTnOE = 0x20;
-
- low_output = 0x08;
- low_direction = 0x1b;
-
- high_output = 0x0;
- high_direction = 0x0;
-
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) {
- low_direction &= ~nTRSTnOE; /* nTRST input */
- low_output &= ~nTRST; /* nTRST = 0 */
- } else {
- low_direction |= nTRSTnOE; /* nTRST output */
- low_output |= nTRST; /* nTRST = 1 */
- }
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL) {
- low_direction |= nSRSTnOE; /* nSRST output */
- low_output |= nSRST; /* nSRST = 1 */
- } else {
- low_direction &= ~nSRSTnOE; /* nSRST input */
- low_output &= ~nSRST; /* nSRST = 0 */
- }
-
-#if BUILD_FT2232_FTD2XX == 1
- /* enable power to the module */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- ((uint32_t)(signalyzer_h_side << 8) | 0x01));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_POWERCONTROL_SET);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* set gpio mode register */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- (uint32_t)(signalyzer_h_side << 8));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* set gpio register */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- (uint32_t)(signalyzer_h_side << 8));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x4040);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_GPIO_STATE);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-#endif
- }
- /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */
- else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) ||
- (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) ||
- (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) ||
- (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) {
- if (signalyzer_h_adapter_type
- == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG)
- LOG_INFO("Signalyzer: EM-ARM-JTAG (ARM JTAG) "
- "detected. (HW: %2x).", (read_buf[1] >> 8));
- else if (signalyzer_h_adapter_type
- == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P)
- LOG_INFO("Signalyzer: EM-ARM-JTAG_P "
- "(ARM JTAG with PSU) detected. (HW: %2x).",
- (read_buf[1] >> 8));
- else if (signalyzer_h_adapter_type
- == SIGNALYZER_MODULE_TYPE_EM_JTAG)
- LOG_INFO("Signalyzer: EM-JTAG (Generic JTAG) "
- "detected. (HW: %2x).", (read_buf[1] >> 8));
- else if (signalyzer_h_adapter_type
- == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)
- LOG_INFO("Signalyzer: EM-JTAG-P "
- "(Generic JTAG with PSU) detected. (HW: %2x).",
- (read_buf[1] >> 8));
-
- nTRST = 0x02;
- nTRSTnOE = 0x04;
- nSRST = 0x08;
- nSRSTnOE = 0x10;
-
- low_output = 0x08;
- low_direction = 0x1b;
-
- high_output = 0x0;
- high_direction = 0x1f;
-
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) {
- high_output |= nTRSTnOE;
- high_output &= ~nTRST;
- } else {
- high_output &= ~nTRSTnOE;
- high_output |= nTRST;
- }
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL) {
- high_output &= ~nSRSTnOE;
- high_output |= nSRST;
- } else {
- high_output |= nSRSTnOE;
- high_output &= ~nSRST;
- }
-
-#if BUILD_FT2232_FTD2XX == 1
- /* enable power to the module */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- ((uint32_t)(signalyzer_h_side << 8) | 0x01));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
- SIGNALYZER_COMMAND_POWERCONTROL_SET);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* set gpio mode register (IO_16 and IO_17 set as analog
- * inputs, other is gpio)
- */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- (uint32_t)(signalyzer_h_side << 8));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0060);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* set gpio register (all inputs, for -P modules,
- * PSU will be turned off)
- */
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
- (uint32_t)(signalyzer_h_side << 8));
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE);
- if (status != FT_OK) {
- LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-#endif
- } else if (signalyzer_h_adapter_type == 0x0000) {
- LOG_INFO("Signalyzer: No external modules were detected.");
-
- nTRST = 0x10;
- nTRSTnOE = 0x10;
- nSRST = 0x20;
- nSRSTnOE = 0x20;
-
- low_output = 0x08;
- low_direction = 0x1b;
-
- high_output = 0x0;
- high_direction = 0x0;
-
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) {
- low_direction &= ~nTRSTnOE; /* nTRST input */
- low_output &= ~nTRST; /* nTRST = 0 */
- } else {
- low_direction |= nTRSTnOE; /* nTRST output */
- low_output |= nTRST; /* nTRST = 1 */
- }
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL) {
- low_direction |= nSRSTnOE; /* nSRST output */
- low_output |= nSRST; /* nSRST = 1 */
- } else {
- low_direction &= ~nSRSTnOE; /* nSRST input */
- low_output &= ~nSRST; /* nSRST = 0 */
- }
- } else {
- LOG_ERROR("Unknown module type is detected: %.4x",
- signalyzer_h_adapter_type);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* initialize low byte of controller for jtag operation */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize Signalyzer-H layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
-#if BUILD_FT2232_FTD2XX == 1
- if (ftdi_device == FT_DEVICE_2232H) {
- /* initialize high byte of controller for jtag operation */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize Signalyzer-H layout");
- return ERROR_JTAG_INIT_FAILED;
- }
- }
-#elif BUILD_FT2232_LIBFTDI == 1
- if (ftdi_device == TYPE_2232H) {
- /* initialize high byte of controller for jtag operation */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize Signalyzer-H layout");
- return ERROR_JTAG_INIT_FAILED;
- }
- }
-#endif
- return ERROR_OK;
-}
-
-static void signalyzer_h_reset(int trst, int srst)
-{
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- /* ADAPTOR: EM_LT16_A */
- if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) {
- if (trst == 1) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- /* switch to output pin (output is low) */
- low_direction |= nTRSTnOE;
- else
- /* switch output low */
- low_output &= ~nTRST;
- } else if (trst == 0) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- /* switch to input pin (high-Z + internal
- * and external pullup) */
- low_direction &= ~nTRSTnOE;
- else
- /* switch output high */
- low_output |= nTRST;
- }
-
- if (srst == 1) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- /* switch output low */
- low_output &= ~nSRST;
- else
- /* switch to output pin (output is low) */
- low_direction |= nSRSTnOE;
- } else if (srst == 0) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- /* switch output high */
- low_output |= nSRST;
- else
- /* switch to input pin (high-Z) */
- low_direction &= ~nSRSTnOE;
- }
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
- LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, "
- "low_direction: 0x%2.2x",
- trst, srst, low_output, low_direction);
- }
- /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */
- else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) ||
- (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) ||
- (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) ||
- (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) {
- if (trst == 1) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output &= ~nTRSTnOE;
- else
- high_output &= ~nTRST;
- } else if (trst == 0) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output |= nTRSTnOE;
- else
- high_output |= nTRST;
- }
-
- if (srst == 1) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- high_output &= ~nSRST;
- else
- high_output &= ~nSRSTnOE;
- } else if (srst == 0) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- high_output |= nSRST;
- else
- high_output |= nSRSTnOE;
- }
-
- /* command "set data bits high byte" */
- buffer_write(0x82);
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_INFO("trst: %i, srst: %i, high_output: 0x%2.2x, "
- "high_direction: 0x%2.2x",
- trst, srst, high_output, high_direction);
- } else if (signalyzer_h_adapter_type == 0x0000) {
- if (trst == 1) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- /* switch to output pin (output is low) */
- low_direction |= nTRSTnOE;
- else
- /* switch output low */
- low_output &= ~nTRST;
- } else if (trst == 0) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- /* switch to input pin (high-Z + internal
- * and external pullup) */
- low_direction &= ~nTRSTnOE;
- else
- /* switch output high */
- low_output |= nTRST;
- }
-
- if (srst == 1) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- /* switch output low */
- low_output &= ~nSRST;
- else
- /* switch to output pin (output is low) */
- low_direction |= nSRSTnOE;
- } else if (srst == 0) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- /* switch output high */
- low_output |= nSRST;
- else
- /* switch to input pin (high-Z) */
- low_direction &= ~nSRSTnOE;
- }
-
- /* command "set data bits low byte" */
- buffer_write(0x80);
- buffer_write(low_output);
- buffer_write(low_direction);
- LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, "
- "low_direction: 0x%2.2x",
- trst, srst, low_output, low_direction);
- }
-}
-
-static void signalyzer_h_blink(void)
-{
- signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_RED, 100, 0, 1);
-}
-
-/********************************************************************
- * Support for KT-LINK
- * JTAG adapter from KRISTECH
- * http://www.kristech.eu
- *******************************************************************/
-static int ktlink_init(void)
-{
- uint8_t swd_en = 0x20; /* 0x20 SWD disable, 0x00 SWD enable (ADBUS5) */
-
- low_output = 0x08 | swd_en; /* value; TMS=1,TCK=0,TDI=0,SWD=swd_en */
- low_direction = 0x3B; /* out=1; TCK/TDI/TMS=out,TDO=in,SWD=out,RTCK=in,SRSTIN=in */
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- nTRST = 0x01;
- nSRST = 0x02;
- nTRSTnOE = 0x04;
- nSRSTnOE = 0x08;
-
- high_output = 0x80; /* turn LED on */
- high_direction = 0xFF; /* all outputs */
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) {
- high_output |= nTRSTnOE;
- high_output &= ~nTRST;
- } else {
- high_output &= ~nTRSTnOE;
- high_output |= nTRST;
- }
-
- if (jtag_reset_config & RESET_SRST_PUSH_PULL) {
- high_output &= ~nSRSTnOE;
- high_output |= nSRST;
- } else {
- high_output |= nSRSTnOE;
- high_output &= ~nSRST;
- }
-
- /* initialize high byte for jtag */
- if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static void ktlink_reset(int trst, int srst)
-{
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if (trst == 1) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output &= ~nTRSTnOE;
- else
- high_output &= ~nTRST;
- } else if (trst == 0) {
- if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
- high_output |= nTRSTnOE;
- else
- high_output |= nTRST;
- }
-
- if (srst == 1) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- high_output &= ~nSRST;
- else
- high_output &= ~nSRSTnOE;
- } else if (srst == 0) {
- if (jtag_reset_config & RESET_SRST_PUSH_PULL)
- high_output |= nSRST;
- else
- high_output |= nSRSTnOE;
- }
-
- buffer_write(0x82); /* command "set data bits high byte" */
- buffer_write(high_output);
- buffer_write(high_direction);
- LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x",
- trst,
- srst,
- high_output,
- high_direction);
-}
-
-static void ktlink_blink(void)
-{
- /* LED connected to ACBUS7 */
- high_output ^= 0x80;
-
- buffer_write(0x82); /* command "set data bits high byte" */
- buffer_write(high_output);
- buffer_write(high_direction);
-}
-
-/********************************************************************
- * Support for Digilent HS-1
- * JTAG adapter from Digilent
- * http://www.digilent.com
- * Author: Stephane Bonnet bonnetst@hds.utc.fr
- *******************************************************************/
-
-static int digilent_hs1_init(void)
-{
- /* the adapter only supports the base JTAG signals, no nTRST
- nor nSRST */
- low_output = 0x88;
- low_direction = 0x8b;
-
- /* initialize low byte for jtag */
- if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) {
- LOG_ERROR("couldn't initialize FT2232 with 'digilent_hs1' layout");
- return ERROR_JTAG_INIT_FAILED;
- }
- return ERROR_OK;
-}
-
-static void digilent_hs1_reset(int trst, int srst)
-{
- /* Dummy function, no reset signals supported. */
-}
-
-static const struct command_registration ft2232_command_handlers[] = {
- {
- .name = "ft2232_device_desc",
- .handler = &ft2232_handle_device_desc_command,
- .mode = COMMAND_CONFIG,
- .help = "set the USB device description of the FTDI FT2232 device",
- .usage = "description_string",
- },
- {
- .name = "ft2232_serial",
- .handler = &ft2232_handle_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the FTDI FT2232 device",
- .usage = "serial_string",
- },
- {
- .name = "ft2232_layout",
- .handler = &ft2232_handle_layout_command,
- .mode = COMMAND_CONFIG,
- .help = "set the layout of the FT2232 GPIO signals used "
- "to control output-enables and reset signals",
- .usage = "layout_name",
- },
- {
- .name = "ft2232_vid_pid",
- .handler = &ft2232_handle_vid_pid_command,
- .mode = COMMAND_CONFIG,
- .help = "the vendor ID and product ID of the FTDI FT2232 device",
- .usage = "(vid pid)* ",
- },
- {
- .name = "ft2232_latency",
- .handler = &ft2232_handle_latency_command,
- .mode = COMMAND_CONFIG,
- .help = "set the FT2232 latency timer to a new value",
- .usage = "value",
- },
- {
- .name = "ft2232_channel",
- .handler = &ft2232_handle_channel_command,
- .mode = COMMAND_CONFIG,
- .help = "set the FT2232 channel to a new value",
- .usage = "value",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface ft2232_interface = {
- .name = "ft2232",
- .supported = DEBUG_CAP_TMS_SEQ,
- .commands = ft2232_command_handlers,
- .transports = jtag_only,
-
- .init = ft2232_init,
- .quit = ft2232_quit,
- .speed = ft2232_speed,
- .speed_div = ft2232_speed_div,
- .khz = ft2232_khz,
- .execute_queue = ft2232_execute_queue,
-};
diff --git a/src/jtag/drivers/ftd2xx_common.h b/src/jtag/drivers/ftd2xx_common.h
deleted file mode 100644
index 14b8455..0000000
--- a/src/jtag/drivers/ftd2xx_common.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Spencer Oliver <spen@spen-soft.co.uk> *
- * *
- * Written by Arnim Laeuger, 2008 (from urjtag) *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H
-
-#if ((BUILD_FT2232_FTD2XX == 1) || (BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1))
-#include <ftd2xx.h>
-
-static const char *ftd2xx_status_string(FT_STATUS status)
-{
- switch (status) {
- case FT_OK: return "OK";
- case FT_INVALID_HANDLE: return "invalid handle";
- case FT_DEVICE_NOT_FOUND: return "device not found";
- case FT_DEVICE_NOT_OPENED: return "device not opened";
- case FT_IO_ERROR: return "io error";
- case FT_INSUFFICIENT_RESOURCES: return "insufficient resources";
- case FT_INVALID_PARAMETER: return "invalid parameter";
- case FT_INVALID_BAUD_RATE: return "invalid baud rate";
-
- case FT_DEVICE_NOT_OPENED_FOR_ERASE: return "device not opened for erase";
- case FT_DEVICE_NOT_OPENED_FOR_WRITE: return "device not opened for write";
- case FT_FAILED_TO_WRITE_DEVICE: return "failed to write device";
- case FT_EEPROM_READ_FAILED: return "eeprom read failed";
- case FT_EEPROM_WRITE_FAILED: return "eeprom write failed";
- case FT_EEPROM_ERASE_FAILED: return "eeprom erase failed";
- case FT_EEPROM_NOT_PRESENT: return "eeprom not present";
- case FT_EEPROM_NOT_PROGRAMMED: return "eeprom not programmed";
- case FT_INVALID_ARGS: return "invalid args";
- case FT_NOT_SUPPORTED: return "not supported";
- case FT_OTHER_ERROR: return "other error";
- }
-
- return "undefined FTD2xx error";
-}
-
-#endif
-#endif /* OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H */
diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
deleted file mode 100644
index 8b78fe8..0000000
--- a/src/jtag/drivers/ftdi.c
+++ /dev/null
@@ -1,1297 +0,0 @@
-/**************************************************************************
-* Copyright (C) 2012 by Andreas Fritiofson *
-* andreas.fritiofson@gmail.com *
-* *
-* This program is free software; you can redistribute it and/or modify *
-* it under the terms of the GNU General Public License as published by *
-* the Free Software Foundation; either version 2 of the License, or *
-* (at your option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-* GNU General Public License for more details. *
-* *
-* You should have received a copy of the GNU General Public License *
-* along with this program. If not, see <http://www.gnu.org/licenses/>. *
-***************************************************************************/
-
-/**
- * @file
- * JTAG adapters based on the FT2232 full and high speed USB parts are
- * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters
- * are discrete, but development boards may integrate them as alternatives
- * to more capable (and expensive) third party JTAG pods.
- *
- * JTAG uses only one of the two communications channels ("MPSSE engines")
- * on these devices. Adapters based on FT4232 parts have four ports/channels
- * (A/B/C/D), instead of just two (A/B).
- *
- * Especially on development boards integrating one of these chips (as
- * opposed to discrete pods/dongles), the additional channels can be used
- * for a variety of purposes, but OpenOCD only uses one channel at a time.
- *
- * - As a USB-to-serial adapter for the target's console UART ...
- * which may be able to support ROM boot loaders that load initial
- * firmware images to flash (or SRAM).
- *
- * - On systems which support ARM's SWD in addition to JTAG, or instead
- * of it, that second port can be used for reading SWV/SWO trace data.
- *
- * - Additional JTAG links, e.g. to a CPLD or * FPGA.
- *
- * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG
- * request/response interactions involve round trips over the USB link.
- * A "smart" JTAG adapter has intelligence close to the scan chain, so it
- * can for example poll quickly for a status change (usually taking on the
- * order of microseconds not milliseconds) before beginning a queued
- * transaction which require the previous one to have completed.
- *
- * There are dozens of adapters of this type, differing in details which
- * this driver needs to understand. Those "layout" details are required
- * as part of FT2232 driver configuration.
- *
- * This code uses information contained in the MPSSE specification which was
- * found here:
- * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf
- * Hereafter this is called the "MPSSE Spec".
- *
- * The datasheet for the ftdichip.com's FT2232D part is here:
- * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf
- *
- * Also note the issue with code 0x4b (clock data to TMS) noted in
- * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html
- * which can affect longer JTAG state paths.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <jtag/swd.h>
-#include <transport/transport.h>
-#include <helper/time_support.h>
-
-#if IS_CYGWIN == 1
-#include <windows.h>
-#endif
-
-#include <assert.h>
-
-/* FTDI access library includes */
-#include "mpsse.h"
-
-#define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
-#define JTAG_MODE_ALT (LSB_FIRST | NEG_EDGE_IN | NEG_EDGE_OUT)
-#define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
-
-static char *ftdi_device_desc;
-static char *ftdi_serial;
-static char *ftdi_location;
-static uint8_t ftdi_channel;
-static uint8_t ftdi_jtag_mode = JTAG_MODE;
-
-static bool swd_mode;
-
-#define MAX_USB_IDS 8
-/* vid = pid = 0 marks the end of the list */
-static uint16_t ftdi_vid[MAX_USB_IDS + 1] = { 0 };
-static uint16_t ftdi_pid[MAX_USB_IDS + 1] = { 0 };
-
-static struct mpsse_ctx *mpsse_ctx;
-
-struct signal {
- const char *name;
- uint16_t data_mask;
- uint16_t input_mask;
- uint16_t oe_mask;
- bool invert_data;
- bool invert_input;
- bool invert_oe;
- struct signal *next;
-};
-
-static struct signal *signals;
-
-/* FIXME: Where to store per-instance data? We need an SWD context. */
-static struct swd_cmd_queue_entry {
- uint8_t cmd;
- uint32_t *dst;
- uint8_t trn_ack_data_parity_trn[DIV_ROUND_UP(4 + 3 + 32 + 1 + 4, 8)];
-} *swd_cmd_queue;
-static size_t swd_cmd_queue_length;
-static size_t swd_cmd_queue_alloced;
-static int queued_retval;
-static int freq;
-
-static uint16_t output;
-static uint16_t direction;
-static uint16_t jtag_output_init;
-static uint16_t jtag_direction_init;
-
-static int ftdi_swd_switch_seq(enum swd_special_seq seq);
-
-static struct signal *find_signal_by_name(const char *name)
-{
- for (struct signal *sig = signals; sig; sig = sig->next) {
- if (strcmp(name, sig->name) == 0)
- return sig;
- }
- return NULL;
-}
-
-static struct signal *create_signal(const char *name)
-{
- struct signal **psig = &signals;
- while (*psig)
- psig = &(*psig)->next;
-
- *psig = calloc(1, sizeof(**psig));
- if (*psig == NULL)
- return NULL;
-
- (*psig)->name = strdup(name);
- if ((*psig)->name == NULL) {
- free(*psig);
- *psig = NULL;
- }
- return *psig;
-}
-
-static int ftdi_set_signal(const struct signal *s, char value)
-{
- bool data;
- bool oe;
-
- if (s->data_mask == 0 && s->oe_mask == 0) {
- LOG_ERROR("interface doesn't provide signal '%s'", s->name);
- return ERROR_FAIL;
- }
- switch (value) {
- case '0':
- data = s->invert_data;
- oe = !s->invert_oe;
- break;
- case '1':
- if (s->data_mask == 0) {
- LOG_ERROR("interface can't drive '%s' high", s->name);
- return ERROR_FAIL;
- }
- data = !s->invert_data;
- oe = !s->invert_oe;
- break;
- case 'z':
- case 'Z':
- if (s->oe_mask == 0) {
- LOG_ERROR("interface can't tri-state '%s'", s->name);
- return ERROR_FAIL;
- }
- data = s->invert_data;
- oe = s->invert_oe;
- break;
- default:
- assert(0 && "invalid signal level specifier");
- return ERROR_FAIL;
- }
-
- uint16_t old_output = output;
- uint16_t old_direction = direction;
-
- output = data ? output | s->data_mask : output & ~s->data_mask;
- if (s->oe_mask == s->data_mask)
- direction = oe ? direction | s->oe_mask : direction & ~s->oe_mask;
- else
- output = oe ? output | s->oe_mask : output & ~s->oe_mask;
-
- if ((output & 0xff) != (old_output & 0xff) || (direction & 0xff) != (old_direction & 0xff))
- mpsse_set_data_bits_low_byte(mpsse_ctx, output & 0xff, direction & 0xff);
- if ((output >> 8 != old_output >> 8) || (direction >> 8 != old_direction >> 8))
- mpsse_set_data_bits_high_byte(mpsse_ctx, output >> 8, direction >> 8);
-
- return ERROR_OK;
-}
-
-static int ftdi_get_signal(const struct signal *s, uint16_t * value_out)
-{
- uint8_t data_low = 0;
- uint8_t data_high = 0;
-
- if (s->input_mask == 0) {
- LOG_ERROR("interface doesn't provide signal '%s'", s->name);
- return ERROR_FAIL;
- }
-
- if (s->input_mask & 0xff)
- mpsse_read_data_bits_low_byte(mpsse_ctx, &data_low);
- if (s->input_mask >> 8)
- mpsse_read_data_bits_high_byte(mpsse_ctx, &data_high);
-
- mpsse_flush(mpsse_ctx);
-
- *value_out = (((uint16_t)data_high) << 8) | data_low;
-
- if (s->invert_input)
- *value_out = ~(*value_out);
-
- *value_out &= s->input_mask;
-
- return ERROR_OK;
-}
-
-/**
- * Function move_to_state
- * moves the TAP controller from the current state to a
- * \a goal_state through a path given by tap_get_tms_path(). State transition
- * logging is performed by delegation to clock_tms().
- *
- * @param goal_state is the destination state for the move.
- */
-static void move_to_state(tap_state_t goal_state)
-{
- tap_state_t start_state = tap_get_state();
-
- /* goal_state is 1/2 of a tuple/pair of states which allow convenient
- lookup of the required TMS pattern to move to this state from the
- start state.
- */
-
- /* do the 2 lookups */
- uint8_t tms_bits = tap_get_tms_path(start_state, goal_state);
- int tms_count = tap_get_tms_path_len(start_state, goal_state);
- assert(tms_count <= 8);
-
- DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state));
-
- /* Track state transitions step by step */
- for (int i = 0; i < tms_count; i++)
- tap_set_state(tap_state_transition(tap_get_state(), (tms_bits >> i) & 1));
-
- mpsse_clock_tms_cs_out(mpsse_ctx,
- &tms_bits,
- 0,
- tms_count,
- false,
- ftdi_jtag_mode);
-}
-
-static int ftdi_speed(int speed)
-{
- int retval;
- retval = mpsse_set_frequency(mpsse_ctx, speed);
-
- if (retval < 0) {
- LOG_ERROR("couldn't set FTDI TCK speed");
- return retval;
- }
-
- if (!swd_mode && speed >= 10000000 && ftdi_jtag_mode != JTAG_MODE_ALT)
- LOG_INFO("ftdi: if you experience problems at higher adapter clocks, try "
- "the command \"ftdi_tdo_sample_edge falling\"");
- return ERROR_OK;
-}
-
-static int ftdi_speed_div(int speed, int *khz)
-{
- *khz = speed / 1000;
- return ERROR_OK;
-}
-
-static int ftdi_khz(int khz, int *jtag_speed)
-{
- if (khz == 0 && !mpsse_is_high_speed(mpsse_ctx)) {
- LOG_DEBUG("RCLK not supported");
- return ERROR_FAIL;
- }
-
- *jtag_speed = khz * 1000;
- return ERROR_OK;
-}
-
-static void ftdi_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %s is not a stable end state", tap_state_name(state));
- exit(-1);
- }
-}
-
-static void ftdi_execute_runtest(struct jtag_command *cmd)
-{
- int i;
- uint8_t zero = 0;
-
- DEBUG_JTAG_IO("runtest %i cycles, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
-
- if (tap_get_state() != TAP_IDLE)
- move_to_state(TAP_IDLE);
-
- /* TODO: Reuse ftdi_execute_stableclocks */
- i = cmd->cmd.runtest->num_cycles;
- while (i > 0) {
- /* there are no state transitions in this code, so omit state tracking */
- unsigned this_len = i > 7 ? 7 : i;
- mpsse_clock_tms_cs_out(mpsse_ctx, &zero, 0, this_len, false, ftdi_jtag_mode);
- i -= this_len;
- }
-
- ftdi_end_state(cmd->cmd.runtest->end_state);
-
- if (tap_get_state() != tap_get_end_state())
- move_to_state(tap_get_end_state());
-
- DEBUG_JTAG_IO("runtest: %i, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(tap_get_end_state()));
-}
-
-static void ftdi_execute_statemove(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("statemove end in %s",
- tap_state_name(cmd->cmd.statemove->end_state));
-
- ftdi_end_state(cmd->cmd.statemove->end_state);
-
- /* shortest-path move to desired end state */
- if (tap_get_state() != tap_get_end_state() || tap_get_end_state() == TAP_RESET)
- move_to_state(tap_get_end_state());
-}
-
-/**
- * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG
- * (or SWD) state machine. REVISIT: Not the best method, perhaps.
- */
-static void ftdi_execute_tms(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("TMS: %d bits", cmd->cmd.tms->num_bits);
-
- /* TODO: Missing tap state tracking, also missing from ft2232.c! */
- mpsse_clock_tms_cs_out(mpsse_ctx,
- cmd->cmd.tms->bits,
- 0,
- cmd->cmd.tms->num_bits,
- false,
- ftdi_jtag_mode);
-}
-
-static void ftdi_execute_pathmove(struct jtag_command *cmd)
-{
- tap_state_t *path = cmd->cmd.pathmove->path;
- int num_states = cmd->cmd.pathmove->num_states;
-
- DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states,
- tap_state_name(tap_get_state()),
- tap_state_name(path[num_states-1]));
-
- int state_count = 0;
- unsigned bit_count = 0;
- uint8_t tms_byte = 0;
-
- DEBUG_JTAG_IO("-");
-
- /* this loop verifies that the path is legal and logs each state in the path */
- while (num_states--) {
-
- /* either TMS=0 or TMS=1 must work ... */
- if (tap_state_transition(tap_get_state(), false)
- == path[state_count])
- buf_set_u32(&tms_byte, bit_count++, 1, 0x0);
- else if (tap_state_transition(tap_get_state(), true)
- == path[state_count]) {
- buf_set_u32(&tms_byte, bit_count++, 1, 0x1);
-
- /* ... or else the caller goofed BADLY */
- } else {
- LOG_ERROR("BUG: %s -> %s isn't a valid "
- "TAP state transition",
- tap_state_name(tap_get_state()),
- tap_state_name(path[state_count]));
- exit(-1);
- }
-
- tap_set_state(path[state_count]);
- state_count++;
-
- if (bit_count == 7 || num_states == 0) {
- mpsse_clock_tms_cs_out(mpsse_ctx,
- &tms_byte,
- 0,
- bit_count,
- false,
- ftdi_jtag_mode);
- bit_count = 0;
- }
- }
- tap_set_end_state(tap_get_state());
-}
-
-#ifdef _DEBUG_JTAG_IO_
-static void debug_jtag_io_value(const char *prefix, const uint8_t *value,
- unsigned int num_bits)
-{
- if (!value) {
- return;
- }
-
- char buf[33];
- char *bufp = buf;
- unsigned int chars = (num_bits + 3) / 4;
- for (unsigned int i = 0; i < chars; i++) {
- if (i && (i % 32) == 0) {
- DEBUG_JTAG_IO(" %s%s", prefix, buf);
- bufp = buf;
- }
- int start_bit = 4 * (chars - i - 1);
- sprintf(bufp, "%01x", buf_get_u32(value, start_bit, 4));
- bufp++;
- }
- if (bufp != buf) {
- DEBUG_JTAG_IO(" %s%s", prefix, buf);
- }
-}
-#endif
-
-static void ftdi_execute_scan(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN",
- jtag_scan_type(cmd->cmd.scan));
-#ifdef _DEBUG_JTAG_IO_
- debug_jtag_io_value(" out=", cmd->cmd.scan->fields->out_value,
- cmd->cmd.scan->fields->num_bits);
-#endif
-
- /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */
- while (cmd->cmd.scan->num_fields > 0
- && cmd->cmd.scan->fields[cmd->cmd.scan->num_fields - 1].num_bits == 0) {
- cmd->cmd.scan->num_fields--;
- LOG_DEBUG("discarding trailing empty field");
- }
-
- if (cmd->cmd.scan->num_fields == 0) {
- LOG_DEBUG("empty scan, doing nothing");
- return;
- }
-
- if (cmd->cmd.scan->ir_scan) {
- if (tap_get_state() != TAP_IRSHIFT)
- move_to_state(TAP_IRSHIFT);
- } else {
- if (tap_get_state() != TAP_DRSHIFT)
- move_to_state(TAP_DRSHIFT);
- }
-
- ftdi_end_state(cmd->cmd.scan->end_state);
-
- struct scan_field *field = cmd->cmd.scan->fields;
- unsigned scan_size = 0;
-
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
- scan_size += field->num_bits;
- DEBUG_JTAG_IO("%s%s field %d/%d %d bits",
- field->in_value ? "in" : "",
- field->out_value ? "out" : "",
- i,
- cmd->cmd.scan->num_fields,
- field->num_bits);
-
- if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) {
- /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap
- * movement. This last field can't have length zero, it was checked above. */
- mpsse_clock_data(mpsse_ctx,
- field->out_value,
- 0,
- field->in_value,
- 0,
- field->num_bits - 1,
- ftdi_jtag_mode);
- uint8_t last_bit = 0;
- if (field->out_value)
- bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1);
- uint8_t tms_bits = 0x01;
- mpsse_clock_tms_cs(mpsse_ctx,
- &tms_bits,
- 0,
- field->in_value,
- field->num_bits - 1,
- 1,
- last_bit,
- ftdi_jtag_mode);
- tap_set_state(tap_state_transition(tap_get_state(), 1));
- mpsse_clock_tms_cs_out(mpsse_ctx,
- &tms_bits,
- 1,
- 1,
- last_bit,
- ftdi_jtag_mode);
- tap_set_state(tap_state_transition(tap_get_state(), 0));
- } else
- mpsse_clock_data(mpsse_ctx,
- field->out_value,
- 0,
- field->in_value,
- 0,
- field->num_bits,
- ftdi_jtag_mode);
- }
-
- if (tap_get_state() != tap_get_end_state())
- move_to_state(tap_get_end_state());
-
- DEBUG_JTAG_IO("%s scan, %i bits, end in %s",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
- tap_state_name(tap_get_end_state()));
-
-#ifdef _DEBUG_JTAG_IO_
- debug_jtag_io_value(" in=", cmd->cmd.scan->fields->in_value,
- cmd->cmd.scan->fields->num_bits);
-#endif
-}
-
-static void ftdi_execute_reset(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-
- if (cmd->cmd.reset->trst == 1
- || (cmd->cmd.reset->srst
- && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
-
- struct signal *trst = find_signal_by_name("nTRST");
- if (cmd->cmd.reset->trst == 1) {
- if (trst)
- ftdi_set_signal(trst, '0');
- else
- LOG_ERROR("Can't assert TRST: nTRST signal is not defined");
- } else if (trst && jtag_get_reset_config() & RESET_HAS_TRST &&
- cmd->cmd.reset->trst == 0) {
- if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN)
- ftdi_set_signal(trst, 'z');
- else
- ftdi_set_signal(trst, '1');
- }
-
- struct signal *srst = find_signal_by_name("nSRST");
- if (cmd->cmd.reset->srst == 1) {
- if (srst)
- ftdi_set_signal(srst, '0');
- else
- LOG_ERROR("Can't assert SRST: nSRST signal is not defined");
- } else if (srst && jtag_get_reset_config() & RESET_HAS_SRST &&
- cmd->cmd.reset->srst == 0) {
- if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
- ftdi_set_signal(srst, '1');
- else
- ftdi_set_signal(srst, 'z');
- }
-
- DEBUG_JTAG_IO("trst: %i, srst: %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-}
-
-static void ftdi_execute_sleep(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us);
-
- mpsse_flush(mpsse_ctx);
- jtag_sleep(cmd->cmd.sleep->us);
- DEBUG_JTAG_IO("sleep %" PRIi32 " usec while in %s",
- cmd->cmd.sleep->us,
- tap_state_name(tap_get_state()));
-}
-
-static void ftdi_execute_stableclocks(struct jtag_command *cmd)
-{
- /* this is only allowed while in a stable state. A check for a stable
- * state was done in jtag_add_clocks()
- */
- int num_cycles = cmd->cmd.stableclocks->num_cycles;
-
- /* 7 bits of either ones or zeros. */
- uint8_t tms = tap_get_state() == TAP_RESET ? 0x7f : 0x00;
-
- /* TODO: Use mpsse_clock_data with in=out=0 for this, if TMS can be set to
- * the correct level and remain there during the scan */
- while (num_cycles > 0) {
- /* there are no state transitions in this code, so omit state tracking */
- unsigned this_len = num_cycles > 7 ? 7 : num_cycles;
- mpsse_clock_tms_cs_out(mpsse_ctx, &tms, 0, this_len, false, ftdi_jtag_mode);
- num_cycles -= this_len;
- }
-
- DEBUG_JTAG_IO("clocks %i while in %s",
- cmd->cmd.stableclocks->num_cycles,
- tap_state_name(tap_get_state()));
-}
-
-static void ftdi_execute_command(struct jtag_command *cmd)
-{
- switch (cmd->type) {
- case JTAG_RESET:
- ftdi_execute_reset(cmd);
- break;
- case JTAG_RUNTEST:
- ftdi_execute_runtest(cmd);
- break;
- case JTAG_TLR_RESET:
- ftdi_execute_statemove(cmd);
- break;
- case JTAG_PATHMOVE:
- ftdi_execute_pathmove(cmd);
- break;
- case JTAG_SCAN:
- ftdi_execute_scan(cmd);
- break;
- case JTAG_SLEEP:
- ftdi_execute_sleep(cmd);
- break;
- case JTAG_STABLECLOCKS:
- ftdi_execute_stableclocks(cmd);
- break;
- case JTAG_TMS:
- ftdi_execute_tms(cmd);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered: %d", cmd->type);
- break;
- }
-}
-
-static int ftdi_execute_queue(void)
-{
- /* blink, if the current layout has that feature */
- struct signal *led = find_signal_by_name("LED");
- if (led)
- ftdi_set_signal(led, '1');
-
- for (struct jtag_command *cmd = jtag_command_queue; cmd; cmd = cmd->next) {
- /* fill the write buffer with the desired command */
- ftdi_execute_command(cmd);
- }
-
- if (led)
- ftdi_set_signal(led, '0');
-
- int retval = mpsse_flush(mpsse_ctx);
- if (retval != ERROR_OK)
- LOG_ERROR("error while flushing MPSSE queue: %d", retval);
-
- return retval;
-}
-
-static int ftdi_initialize(void)
-{
- if (tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRPAUSE) == 7)
- LOG_DEBUG("ftdi interface using 7 step jtag state transitions");
- else
- LOG_DEBUG("ftdi interface using shortest path jtag state transitions");
-
- for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) {
- mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc,
- ftdi_serial, ftdi_location, ftdi_channel);
- if (mpsse_ctx)
- break;
- }
-
- if (!mpsse_ctx)
- return ERROR_JTAG_INIT_FAILED;
-
- output = jtag_output_init;
- direction = jtag_direction_init;
-
- if (swd_mode) {
- struct signal *sig = find_signal_by_name("SWD_EN");
- if (!sig) {
- LOG_ERROR("SWD mode is active but SWD_EN signal is not defined");
- return ERROR_JTAG_INIT_FAILED;
- }
- /* A dummy SWD_EN would have zero mask */
- if (sig->data_mask)
- ftdi_set_signal(sig, '1');
- }
-
- mpsse_set_data_bits_low_byte(mpsse_ctx, output & 0xff, direction & 0xff);
- mpsse_set_data_bits_high_byte(mpsse_ctx, output >> 8, direction >> 8);
-
- mpsse_loopback_config(mpsse_ctx, false);
-
- freq = mpsse_set_frequency(mpsse_ctx, jtag_get_speed_khz() * 1000);
-
- return mpsse_flush(mpsse_ctx);
-}
-
-static int ftdi_quit(void)
-{
- mpsse_close(mpsse_ctx);
-
- free(swd_cmd_queue);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ftdi_handle_device_desc_command)
-{
- if (CMD_ARGC == 1) {
- if (ftdi_device_desc)
- free(ftdi_device_desc);
- ftdi_device_desc = strdup(CMD_ARGV[0]);
- } else {
- LOG_ERROR("expected exactly one argument to ftdi_device_desc <description>");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ftdi_handle_serial_command)
-{
- if (CMD_ARGC == 1) {
- if (ftdi_serial)
- free(ftdi_serial);
- ftdi_serial = strdup(CMD_ARGV[0]);
- } else {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
-COMMAND_HANDLER(ftdi_handle_location_command)
-{
- if (CMD_ARGC == 1) {
- if (ftdi_location)
- free(ftdi_location);
- ftdi_location = strdup(CMD_ARGV[0]);
- } else {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-#endif
-
-COMMAND_HANDLER(ftdi_handle_channel_command)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], ftdi_channel);
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ftdi_handle_layout_init_command)
-{
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], jtag_output_init);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], jtag_direction_init);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ftdi_handle_layout_signal_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- bool invert_data = false;
- uint16_t data_mask = 0;
- bool invert_input = false;
- uint16_t input_mask = 0;
- bool invert_oe = false;
- uint16_t oe_mask = 0;
- for (unsigned i = 1; i < CMD_ARGC; i += 2) {
- if (strcmp("-data", CMD_ARGV[i]) == 0) {
- invert_data = false;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask);
- } else if (strcmp("-ndata", CMD_ARGV[i]) == 0) {
- invert_data = true;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask);
- } else if (strcmp("-input", CMD_ARGV[i]) == 0) {
- invert_input = false;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], input_mask);
- } else if (strcmp("-ninput", CMD_ARGV[i]) == 0) {
- invert_input = true;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], input_mask);
- } else if (strcmp("-oe", CMD_ARGV[i]) == 0) {
- invert_oe = false;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask);
- } else if (strcmp("-noe", CMD_ARGV[i]) == 0) {
- invert_oe = true;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask);
- } else if (!strcmp("-alias", CMD_ARGV[i]) ||
- !strcmp("-nalias", CMD_ARGV[i])) {
- if (!strcmp("-nalias", CMD_ARGV[i])) {
- invert_data = true;
- invert_input = true;
- }
- struct signal *sig = find_signal_by_name(CMD_ARGV[i + 1]);
- if (!sig) {
- LOG_ERROR("signal %s is not defined", CMD_ARGV[i + 1]);
- return ERROR_FAIL;
- }
- data_mask = sig->data_mask;
- input_mask = sig->input_mask;
- oe_mask = sig->oe_mask;
- invert_input ^= sig->invert_input;
- invert_oe = sig->invert_oe;
- invert_data ^= sig->invert_data;
- } else {
- LOG_ERROR("unknown option '%s'", CMD_ARGV[i]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- struct signal *sig;
- sig = find_signal_by_name(CMD_ARGV[0]);
- if (!sig)
- sig = create_signal(CMD_ARGV[0]);
- if (!sig) {
- LOG_ERROR("failed to create signal %s", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- sig->invert_data = invert_data;
- sig->data_mask = data_mask;
- sig->invert_input = invert_input;
- sig->input_mask = input_mask;
- sig->invert_oe = invert_oe;
- sig->oe_mask = oe_mask;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ftdi_handle_set_signal_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct signal *sig;
- sig = find_signal_by_name(CMD_ARGV[0]);
- if (!sig) {
- LOG_ERROR("interface configuration doesn't define signal '%s'", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- switch (*CMD_ARGV[1]) {
- case '0':
- case '1':
- case 'z':
- case 'Z':
- /* single character level specifier only */
- if (CMD_ARGV[1][1] == '\0') {
- ftdi_set_signal(sig, *CMD_ARGV[1]);
- break;
- }
- default:
- LOG_ERROR("unknown signal level '%s', use 0, 1 or z", CMD_ARGV[1]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return mpsse_flush(mpsse_ctx);
-}
-
-COMMAND_HANDLER(ftdi_handle_get_signal_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct signal *sig;
- uint16_t sig_data = 0;
- sig = find_signal_by_name(CMD_ARGV[0]);
- if (!sig) {
- LOG_ERROR("interface configuration doesn't define signal '%s'", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- int ret = ftdi_get_signal(sig, &sig_data);
- if (ret != ERROR_OK)
- return ret;
-
- LOG_USER("Signal %s = %#06x", sig->name, sig_data);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ftdi_handle_vid_pid_command)
-{
- if (CMD_ARGC > MAX_USB_IDS * 2) {
- LOG_WARNING("ignoring extra IDs in ftdi_vid_pid "
- "(maximum is %d pairs)", MAX_USB_IDS);
- CMD_ARGC = MAX_USB_IDS * 2;
- }
- if (CMD_ARGC < 2 || (CMD_ARGC & 1)) {
- LOG_WARNING("incomplete ftdi_vid_pid configuration directive");
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- /* remove the incomplete trailing id */
- CMD_ARGC -= 1;
- }
-
- unsigned i;
- for (i = 0; i < CMD_ARGC; i += 2) {
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ftdi_vid[i >> 1]);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ftdi_pid[i >> 1]);
- }
-
- /*
- * Explicitly terminate, in case there are multiples instances of
- * ftdi_vid_pid.
- */
- ftdi_vid[i >> 1] = ftdi_pid[i >> 1] = 0;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ftdi_handle_tdo_sample_edge_command)
-{
- Jim_Nvp *n;
- static const Jim_Nvp nvp_ftdi_jtag_modes[] = {
- { .name = "rising", .value = JTAG_MODE },
- { .name = "falling", .value = JTAG_MODE_ALT },
- { .name = NULL, .value = -1 },
- };
-
- if (CMD_ARGC > 0) {
- n = Jim_Nvp_name2value_simple(nvp_ftdi_jtag_modes, CMD_ARGV[0]);
- if (n->name == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
- ftdi_jtag_mode = n->value;
-
- }
-
- n = Jim_Nvp_value2name_simple(nvp_ftdi_jtag_modes, ftdi_jtag_mode);
- command_print(CMD_CTX, "ftdi samples TDO on %s edge of TCK", n->name);
-
- return ERROR_OK;
-}
-
-static const struct command_registration ftdi_command_handlers[] = {
- {
- .name = "ftdi_device_desc",
- .handler = &ftdi_handle_device_desc_command,
- .mode = COMMAND_CONFIG,
- .help = "set the USB device description of the FTDI device",
- .usage = "description_string",
- },
- {
- .name = "ftdi_serial",
- .handler = &ftdi_handle_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the FTDI device",
- .usage = "serial_string",
- },
-#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
- {
- .name = "ftdi_location",
- .handler = &ftdi_handle_location_command,
- .mode = COMMAND_CONFIG,
- .help = "set the USB bus location of the FTDI device",
- .usage = "<bus>:port[,port]...",
- },
-#endif
- {
- .name = "ftdi_channel",
- .handler = &ftdi_handle_channel_command,
- .mode = COMMAND_CONFIG,
- .help = "set the channel of the FTDI device that is used as JTAG",
- .usage = "(0-3)",
- },
- {
- .name = "ftdi_layout_init",
- .handler = &ftdi_handle_layout_init_command,
- .mode = COMMAND_CONFIG,
- .help = "initialize the FTDI GPIO signals used "
- "to control output-enables and reset signals",
- .usage = "data direction",
- },
- {
- .name = "ftdi_layout_signal",
- .handler = &ftdi_handle_layout_signal_command,
- .mode = COMMAND_ANY,
- .help = "define a signal controlled by one or more FTDI GPIO as data "
- "and/or output enable",
- .usage = "name [-data mask|-ndata mask] [-oe mask|-noe mask] [-alias|-nalias name]",
- },
- {
- .name = "ftdi_set_signal",
- .handler = &ftdi_handle_set_signal_command,
- .mode = COMMAND_EXEC,
- .help = "control a layout-specific signal",
- .usage = "name (1|0|z)",
- },
- {
- .name = "ftdi_get_signal",
- .handler = &ftdi_handle_get_signal_command,
- .mode = COMMAND_EXEC,
- .help = "read the value of a layout-specific signal",
- .usage = "name",
- },
- {
- .name = "ftdi_vid_pid",
- .handler = &ftdi_handle_vid_pid_command,
- .mode = COMMAND_CONFIG,
- .help = "the vendor ID and product ID of the FTDI device",
- .usage = "(vid pid)* ",
- },
- {
- .name = "ftdi_tdo_sample_edge",
- .handler = &ftdi_handle_tdo_sample_edge_command,
- .mode = COMMAND_ANY,
- .help = "set which TCK clock edge is used for sampling TDO "
- "- default is rising-edge (Setting to falling-edge may "
- "allow signalling speed increase)",
- .usage = "(rising|falling)",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int create_default_signal(const char *name, uint16_t data_mask)
-{
- struct signal *sig = create_signal(name);
- if (!sig) {
- LOG_ERROR("failed to create signal %s", name);
- return ERROR_FAIL;
- }
- sig->invert_data = false;
- sig->data_mask = data_mask;
- sig->invert_oe = false;
- sig->oe_mask = 0;
-
- return ERROR_OK;
-}
-
-static int create_signals(void)
-{
- if (create_default_signal("TCK", 0x01) != ERROR_OK)
- return ERROR_FAIL;
- if (create_default_signal("TDI", 0x02) != ERROR_OK)
- return ERROR_FAIL;
- if (create_default_signal("TDO", 0x04) != ERROR_OK)
- return ERROR_FAIL;
- if (create_default_signal("TMS", 0x08) != ERROR_OK)
- return ERROR_FAIL;
- return ERROR_OK;
-}
-
-static int ftdi_swd_init(void)
-{
- LOG_INFO("FTDI SWD mode enabled");
- swd_mode = true;
-
- if (create_signals() != ERROR_OK)
- return ERROR_FAIL;
-
- swd_cmd_queue_alloced = 10;
- swd_cmd_queue = malloc(swd_cmd_queue_alloced * sizeof(*swd_cmd_queue));
-
- return swd_cmd_queue != NULL ? ERROR_OK : ERROR_FAIL;
-}
-
-static void ftdi_swd_swdio_en(bool enable)
-{
- struct signal *oe = find_signal_by_name("SWDIO_OE");
- if (oe)
- ftdi_set_signal(oe, enable ? '1' : '0');
-}
-
-/**
- * Flush the MPSSE queue and process the SWD transaction queue
- * @param dap
- * @return
- */
-static int ftdi_swd_run_queue(void)
-{
- LOG_DEBUG("Executing %zu queued transactions", swd_cmd_queue_length);
- int retval;
- struct signal *led = find_signal_by_name("LED");
-
- if (queued_retval != ERROR_OK) {
- LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
- goto skip;
- }
-
- /* A transaction must be followed by another transaction or at least 8 idle cycles to
- * ensure that data is clocked through the AP. */
- mpsse_clock_data_out(mpsse_ctx, NULL, 0, 8, SWD_MODE);
-
- /* Terminate the "blink", if the current layout has that feature */
- if (led)
- ftdi_set_signal(led, '0');
-
- queued_retval = mpsse_flush(mpsse_ctx);
- if (queued_retval != ERROR_OK) {
- LOG_ERROR("MPSSE failed");
- goto skip;
- }
-
- for (size_t i = 0; i < swd_cmd_queue_length; i++) {
- int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3);
-
- LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
- ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
- swd_cmd_queue[i].cmd & SWD_CMD_APnDP ? "AP" : "DP",
- swd_cmd_queue[i].cmd & SWD_CMD_RnW ? "read" : "write",
- (swd_cmd_queue[i].cmd & SWD_CMD_A32) >> 1,
- buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn,
- 1 + 3 + (swd_cmd_queue[i].cmd & SWD_CMD_RnW ? 0 : 1), 32));
-
- if (ack != SWD_ACK_OK) {
- queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
- goto skip;
-
- } else if (swd_cmd_queue[i].cmd & SWD_CMD_RnW) {
- uint32_t data = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3, 32);
- int parity = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + 32, 1);
-
- if (parity != parity_u32(data)) {
- LOG_ERROR("SWD Read data parity mismatch");
- queued_retval = ERROR_FAIL;
- goto skip;
- }
-
- if (swd_cmd_queue[i].dst != NULL)
- *swd_cmd_queue[i].dst = data;
- }
- }
-
-skip:
- swd_cmd_queue_length = 0;
- retval = queued_retval;
- queued_retval = ERROR_OK;
-
- /* Queue a new "blink" */
- if (led && retval == ERROR_OK)
- ftdi_set_signal(led, '1');
-
- return retval;
-}
-
-static void ftdi_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk)
-{
- if (swd_cmd_queue_length >= swd_cmd_queue_alloced) {
- /* Not enough room in the queue. Run the queue and increase its size for next time.
- * Note that it's not possible to avoid running the queue here, because mpsse contains
- * pointers into the queue which may be invalid after the realloc. */
- queued_retval = ftdi_swd_run_queue();
- struct swd_cmd_queue_entry *q = realloc(swd_cmd_queue, swd_cmd_queue_alloced * 2 * sizeof(*swd_cmd_queue));
- if (q != NULL) {
- swd_cmd_queue = q;
- swd_cmd_queue_alloced *= 2;
- LOG_DEBUG("Increased SWD command queue to %zu elements", swd_cmd_queue_alloced);
- }
- }
-
- if (queued_retval != ERROR_OK)
- return;
-
- size_t i = swd_cmd_queue_length++;
- swd_cmd_queue[i].cmd = cmd | SWD_CMD_START | SWD_CMD_PARK;
-
- mpsse_clock_data_out(mpsse_ctx, &swd_cmd_queue[i].cmd, 0, 8, SWD_MODE);
-
- if (swd_cmd_queue[i].cmd & SWD_CMD_RnW) {
- /* Queue a read transaction */
- swd_cmd_queue[i].dst = dst;
-
- ftdi_swd_swdio_en(false);
- mpsse_clock_data_in(mpsse_ctx, swd_cmd_queue[i].trn_ack_data_parity_trn,
- 0, 1 + 3 + 32 + 1 + 1, SWD_MODE);
- ftdi_swd_swdio_en(true);
- } else {
- /* Queue a write transaction */
- ftdi_swd_swdio_en(false);
-
- mpsse_clock_data_in(mpsse_ctx, swd_cmd_queue[i].trn_ack_data_parity_trn,
- 0, 1 + 3 + 1, SWD_MODE);
-
- ftdi_swd_swdio_en(true);
-
- buf_set_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + 1, 32, data);
- buf_set_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1 + 3 + 1 + 32, 1, parity_u32(data));
-
- mpsse_clock_data_out(mpsse_ctx, swd_cmd_queue[i].trn_ack_data_parity_trn,
- 1 + 3 + 1, 32 + 1, SWD_MODE);
- }
-
- /* Insert idle cycles after AP accesses to avoid WAIT */
- if (cmd & SWD_CMD_APnDP)
- mpsse_clock_data_out(mpsse_ctx, NULL, 0, ap_delay_clk, SWD_MODE);
-
-}
-
-static void ftdi_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
-{
- assert(cmd & SWD_CMD_RnW);
- ftdi_swd_queue_cmd(cmd, value, 0, ap_delay_clk);
-}
-
-static void ftdi_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
-{
- assert(!(cmd & SWD_CMD_RnW));
- ftdi_swd_queue_cmd(cmd, NULL, value, ap_delay_clk);
-}
-
-static int_least32_t ftdi_swd_frequency(int_least32_t hz)
-{
- if (hz > 0)
- freq = mpsse_set_frequency(mpsse_ctx, hz);
-
- return freq;
-}
-
-static int ftdi_swd_switch_seq(enum swd_special_seq seq)
-{
- switch (seq) {
- case LINE_RESET:
- LOG_DEBUG("SWD line reset");
- mpsse_clock_data_out(mpsse_ctx, swd_seq_line_reset, 0, swd_seq_line_reset_len, SWD_MODE);
- break;
- case JTAG_TO_SWD:
- LOG_DEBUG("JTAG-to-SWD");
- mpsse_clock_data_out(mpsse_ctx, swd_seq_jtag_to_swd, 0, swd_seq_jtag_to_swd_len, SWD_MODE);
- break;
- case SWD_TO_JTAG:
- LOG_DEBUG("SWD-to-JTAG");
- mpsse_clock_data_out(mpsse_ctx, swd_seq_swd_to_jtag, 0, swd_seq_swd_to_jtag_len, SWD_MODE);
- break;
- default:
- LOG_ERROR("Sequence %d not supported", seq);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static const struct swd_driver ftdi_swd = {
- .init = ftdi_swd_init,
- .frequency = ftdi_swd_frequency,
- .switch_seq = ftdi_swd_switch_seq,
- .read_reg = ftdi_swd_read_reg,
- .write_reg = ftdi_swd_write_reg,
- .run = ftdi_swd_run_queue,
-};
-
-static const char * const ftdi_transports[] = { "jtag", "swd", NULL };
-
-struct jtag_interface ftdi_interface = {
- .name = "ftdi",
- .supported = DEBUG_CAP_TMS_SEQ,
- .commands = ftdi_command_handlers,
- .transports = ftdi_transports,
- .swd = &ftdi_swd,
-
- .init = ftdi_initialize,
- .quit = ftdi_quit,
- .speed = ftdi_speed,
- .speed_div = ftdi_speed_div,
- .khz = ftdi_khz,
- .execute_queue = ftdi_execute_queue,
-};
diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c
deleted file mode 100644
index f668996..0000000
--- a/src/jtag/drivers/gw16012.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-
-#if 1
-#define _DEBUG_GW16012_IO_
-#endif
-
-/* system includes */
-/* -ino: 060521-1036 */
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-
-#include <machine/sysarch.h>
-#include <machine/cpufunc.h>
-#define ioperm(startport, length, enable) \
- 386_set_ioperm((startport), (length), (enable))
-
-#else
-
-#endif /* __FreeBSD__, __FreeBSD_kernel__ */
-
-#if PARPORT_USE_PPDEV == 1
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <dev/ppbus/ppi.h>
-#include <dev/ppbus/ppbconf.h>
-#define PPRSTATUS PPIGSTATUS
-#define PPWDATA PPISDATA
-#else
-#include <linux/parport.h>
-#include <linux/ppdev.h>
-#endif
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#else /* not PARPORT_USE_PPDEV */
-#ifndef _WIN32
-#include <sys/io.h>
-#endif
-#endif
-
-#if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
-#include <windows.h>
-#endif
-
-/* configuration */
-uint16_t gw16012_port;
-
-/* interface variables
- */
-static uint8_t gw16012_msb;
-static uint8_t gw16012_control_value;
-
-#if PARPORT_USE_PPDEV == 1
-static int device_handle;
-#endif
-
-static void gw16012_data(uint8_t value)
-{
- value = (value & 0x7f) | gw16012_msb;
- gw16012_msb ^= 0x80; /* toggle MSB */
-
-#ifdef _DEBUG_GW16012_IO_
- LOG_DEBUG("%2.2x", value);
-#endif
-
- #if PARPORT_USE_PPDEV == 1
- ioctl(device_handle, PPWDATA, &value);
- #else
- #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- outb(gw16012_port, value);
- #else
- outb(value, gw16012_port);
- #endif
- #endif
-}
-
-static void gw16012_control(uint8_t value)
-{
- if (value != gw16012_control_value) {
- gw16012_control_value = value;
-
-#ifdef _DEBUG_GW16012_IO_
- LOG_DEBUG("%2.2x", gw16012_control_value);
-#endif
-
- #if PARPORT_USE_PPDEV == 1
- ioctl(device_handle, PPWCONTROL, &gw16012_control_value);
- #else
- #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- outb(gw16012_port + 2, gw16012_control_value);
- #else
- outb(gw16012_control_value, gw16012_port + 2);
- #endif
- #endif
- }
-}
-
-static void gw16012_input(uint8_t *value)
-{
- #if PARPORT_USE_PPDEV == 1
- ioctl(device_handle, PPRSTATUS, value);
- #else
- *value = inb(gw16012_port + 1);
- #endif
-
-#ifdef _DEBUG_GW16012_IO_
- LOG_DEBUG("%2.2x", *value);
-#endif
-}
-
-/* (1) assert or (0) deassert reset lines */
-static void gw16012_reset(int trst, int srst)
-{
- LOG_DEBUG("trst: %i, srst: %i", trst, srst);
-
- if (trst == 0)
- gw16012_control(0x0d);
- else if (trst == 1)
- gw16012_control(0x0c);
-
- if (srst == 0)
- gw16012_control(0x0a);
- else if (srst == 1)
- gw16012_control(0x0b);
-}
-
-static void gw16012_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-static void gw16012_state_move(void)
-{
- int i = 0, tms = 0;
- 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());
-
- gw16012_control(0x0); /* single-bit mode */
-
- for (i = 0; i < tms_count; i++) {
- tms = (tms_scan >> i) & 1;
- gw16012_data(tms << 1); /* output next TMS bit */
- }
-
- tap_set_state(tap_get_end_state());
-}
-
-static void gw16012_path_move(struct pathmove_command *cmd)
-{
- int num_states = cmd->num_states;
- int state_count;
-
- state_count = 0;
- while (num_states) {
- gw16012_control(0x0); /* single-bit mode */
- if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
- gw16012_data(0x0); /* TCK cycle with TMS low */
- else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
- gw16012_data(0x2); /* TCK cycle with TMS high */
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
- exit(-1);
- }
-
- tap_set_state(cmd->path[state_count]);
- state_count++;
- num_states--;
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void gw16012_runtest(int num_cycles)
-{
- tap_state_t saved_end_state = tap_get_end_state();
- int i;
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- gw16012_end_state(TAP_IDLE);
- gw16012_state_move();
- }
-
- for (i = 0; i < num_cycles; i++) {
- gw16012_control(0x0); /* single-bit mode */
- gw16012_data(0x0); /* TMS cycle with TMS low */
- }
-
- gw16012_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- gw16012_state_move();
-}
-
-static void gw16012_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
-{
- int bits_left = scan_size;
- int bit_count = 0;
- tap_state_t saved_end_state = tap_get_end_state();
- uint8_t scan_out, scan_in;
-
- /* only if we're not already in the correct Shift state */
- if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) ||
- (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) {
- if (ir_scan)
- gw16012_end_state(TAP_IRSHIFT);
- else
- gw16012_end_state(TAP_DRSHIFT);
-
- gw16012_state_move();
- gw16012_end_state(saved_end_state);
- }
-
- while (type == SCAN_OUT && ((bits_left - 1) > 7)) {
- gw16012_control(0x2); /* seven-bit mode */
- scan_out = buf_get_u32(buffer, bit_count, 7);
- gw16012_data(scan_out);
- bit_count += 7;
- bits_left -= 7;
- }
-
- gw16012_control(0x0); /* single-bit mode */
- while (bits_left-- > 0) {
- uint8_t tms = 0;
-
- scan_out = buf_get_u32(buffer, bit_count, 1);
-
- if (bits_left == 0) /* last bit */ {
- if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT))
- || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))
- tms = 0;
- else
- tms = 2;
- }
-
- gw16012_data(scan_out | tms);
-
- if (type != SCAN_OUT) {
- gw16012_input(&scan_in);
- buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
- }
-
- bit_count++;
- }
-
- if (!((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) ||
- (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))) {
- gw16012_data(0x0);
- if (ir_scan)
- tap_set_state(TAP_IRPAUSE);
- else
- tap_set_state(TAP_DRPAUSE);
-
- if (tap_get_state() != tap_get_end_state())
- gw16012_state_move();
- }
-}
-
-static int gw16012_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
- int retval;
-
- /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
- * that wasn't handled by a caller-provided error handler
- */
- retval = ERROR_OK;
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-#endif
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
-#endif
- gw16012_end_state(cmd->cmd.runtest->end_state);
- gw16012_runtest(cmd->cmd.runtest->num_cycles);
- break;
- case JTAG_TLR_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
-#endif
- gw16012_end_state(cmd->cmd.statemove->end_state);
- gw16012_state_move();
- break;
- case JTAG_PATHMOVE:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-#endif
- gw16012_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_SCAN:
- gw16012_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr",
- type, scan_size, cmd->cmd.scan->end_state);
-#endif
- gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- if (buffer)
- free(buffer);
- break;
- case JTAG_SLEEP:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
-#endif
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
- cmd = cmd->next;
- }
-
- return retval;
-}
-
-#if PARPORT_USE_GIVEIO == 1
-static int gw16012_get_giveio_access(void)
-{
- HANDLE h;
- OSVERSIONINFO version;
-
- version.dwOSVersionInfoSize = sizeof version;
- if (!GetVersionEx(&version)) {
- errno = EINVAL;
- return -1;
- }
- if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
- return 0;
-
- h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- errno = ENODEV;
- return -1;
- }
-
- CloseHandle(h);
-
- return 0;
-}
-#endif
-
-#if PARPORT_USE_PPDEV == 1
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-
-#define GW16012_PPDEV_NAME "ppi"
-
-static int gw16012_init_ioctls(void)
-{
- int temp = 0;
- temp = ioctl(device_handle, PPCLAIM);
- if (temp < 0) {
- LOG_ERROR("cannot claim device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- temp = PARPORT_MODE_COMPAT;
- temp = ioctl(device_handle, PPSETMODE, &temp);
- if (temp < 0) {
- LOG_ERROR(" cannot set compatible mode to device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- temp = IEEE1284_MODE_COMPAT;
- temp = ioctl(device_handle, PPNEGOT, &temp);
- if (temp < 0) {
- LOG_ERROR("cannot set compatible 1284 mode to device");
- return ERROR_JTAG_INIT_FAILED;
- }
- return ERROR_OK;
-}
-#else
-
-#define GW16012_PPDEV_NAME "parport"
-
-static int gw16012_init_ioctls(void)
-{
- return ERROR_OK;
-}
-
-#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
-
-static int gw16012_init_device(void)
-{
- const char *device_name = GW16012_PPDEV_NAME;
- char buffer[256];
-
- if (device_handle > 0) {
- LOG_ERROR("device is already opened");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- snprintf(buffer, 256, "/dev/%s%d", device_name, gw16012_port);
- LOG_DEBUG("opening %s...", buffer);
-
- device_handle = open(buffer, O_WRONLY);
- if (device_handle < 0) {
- LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- LOG_DEBUG("...open");
-
- if (gw16012_init_ioctls() != ERROR_OK)
- return ERROR_JTAG_INIT_FAILED;
-
- return ERROR_OK;
-}
-
-#else /* PARPORT_USE_PPDEV */
-
-static int gw16012_init_device(void)
-{
- if (gw16012_port == 0) {
- gw16012_port = 0x378;
- LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
- }
-
- LOG_DEBUG("requesting privileges for parallel port 0x%lx...", (long unsigned)(gw16012_port));
-#if PARPORT_USE_GIVEIO == 1
- if (gw16012_get_giveio_access() != 0) {
-#else /* PARPORT_USE_GIVEIO */
- if (ioperm(gw16012_port, 3, 1) != 0) {
-#endif /* PARPORT_USE_GIVEIO */
- LOG_ERROR("missing privileges for direct i/o");
- return ERROR_JTAG_INIT_FAILED;
- }
- LOG_DEBUG("...privileges granted");
-
- /* make sure parallel port is in right mode (clear tristate and interrupt */
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- outb(gw16012_port + 2, 0x0);
-#else
- outb(0x0, gw16012_port + 2);
-#endif
- return ERROR_OK;
-}
-
-#endif /* PARPORT_USE_PPDEV */
-
-static int gw16012_init(void)
-{
- uint8_t status_port;
-
- if (gw16012_init_device() != ERROR_OK)
- return ERROR_JTAG_INIT_FAILED;
-
- gw16012_input(&status_port);
- gw16012_msb = (status_port & 0x80) ^ 0x80;
-
- gw16012_reset(0, 0);
-
- return ERROR_OK;
-}
-
-static int gw16012_quit(void)
-{
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(gw16012_handle_parport_port_command)
-{
- if (CMD_ARGC == 1) {
- /* only if the port wasn't overwritten by cmdline */
- if (gw16012_port == 0)
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], gw16012_port);
- else {
- LOG_ERROR("The parport port was already configured!");
- return ERROR_FAIL;
- }
- }
-
- command_print(CMD_CTX, "parport port = %u", gw16012_port);
-
- return ERROR_OK;
-}
-
-static const struct command_registration gw16012_command_handlers[] = {
- {
- .name = "parport_port",
- .handler = gw16012_handle_parport_port_command,
- .mode = COMMAND_CONFIG,
- .help = "Display the address of the I/O port (e.g. 0x378) "
- "or the number of the '/dev/parport' device used. "
- "If a parameter is provided, first change that port.",
- .usage = "[port_number]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface gw16012_interface = {
- .name = "gw16012",
- .commands = gw16012_command_handlers,
-
- .init = gw16012_init,
- .quit = gw16012_quit,
- .execute_queue = gw16012_execute_queue,
-};
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
deleted file mode 100644
index 3009058..0000000
--- a/src/jtag/drivers/jlink.c
+++ /dev/null
@@ -1,1979 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
- * based on Dominic Rath's and Benedikt Sauter's usbprog.c *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD *
- * plagnioj@jcrosoft.com *
- * *
- * Copyright (C) 2015 by Marc Schink *
- * openocd-dev@marcschink.de *
- * *
- * Copyright (C) 2015 by Paul Fertser *
- * fercerpav@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdint.h>
-#include <math.h>
-
-#include <jtag/interface.h>
-#include <jtag/swd.h>
-#include <jtag/commands.h>
-
-#include <libjaylink/libjaylink.h>
-
-static struct jaylink_context *jayctx;
-static struct jaylink_device_handle *devh;
-static struct jaylink_connection conn;
-static struct jaylink_connection connlist[JAYLINK_MAX_CONNECTIONS];
-static enum jaylink_jtag_version jtag_command_version;
-static uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE];
-
-static uint32_t serial_number;
-static bool use_serial_number;
-static enum jaylink_usb_address usb_address;
-static bool use_usb_address;
-static enum jaylink_target_interface iface = JAYLINK_TIF_JTAG;
-static bool trace_enabled;
-
-#define JLINK_MAX_SPEED 12000
-#define JLINK_TAP_BUFFER_SIZE 2048
-
-static unsigned int swd_buffer_size = JLINK_TAP_BUFFER_SIZE;
-
-/* 256 byte non-volatile memory */
-struct device_config {
- uint8_t usb_address;
- /* 0ffset 0x01 to 0x03 */
- uint8_t reserved_1[3];
- uint32_t target_power;
- /* 0ffset 0x08 to 0x1f */
- uint8_t reserved_2[24];
- /* IP only for J-Link Pro */
- uint8_t ip_address[4];
- uint8_t subnet_mask[4];
- /* 0ffset 0x28 to 0x2f */
- uint8_t reserved_3[8];
- uint8_t mac_address[6];
- /* 0ffset 0x36 to 0xff */
- uint8_t reserved_4[202];
-} __attribute__ ((packed));
-
-static struct device_config config;
-static struct device_config tmp_config;
-
-/* Queue command functions */
-static void jlink_end_state(tap_state_t state);
-static void jlink_state_move(void);
-static void jlink_path_move(int num_states, tap_state_t *path);
-static void jlink_stableclocks(int num_cycles);
-static void jlink_runtest(int num_cycles);
-static void jlink_reset(int trst, int srst);
-static int jlink_swd_run_queue(void);
-static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk);
-static int jlink_swd_switch_seq(enum swd_special_seq seq);
-
-/* J-Link tap buffer functions */
-static void jlink_tap_init(void);
-static int jlink_flush(void);
-/**
- * Queue data to go out and in, flushing the queue as many times as
- * necessary.
- *
- * @param out A pointer to TDI data, if NULL, old stale data will be used.
- * @param out_offset A bit offset for TDI data.
- * @param tms_out A pointer to TMS data, if NULL, zeroes will be emitted.
- * @param tms_offset A bit offset for TMS data.
- * @param in A pointer to store TDO data to, if NULL the data will be discarded.
- * @param in_offset A bit offset for TDO data.
- * @param length Amount of bits to transfer out and in.
- *
- * @retval This function doesn't return any value.
- */
-static void jlink_clock_data(const uint8_t *out, unsigned out_offset,
- const uint8_t *tms_out, unsigned tms_offset,
- uint8_t *in, unsigned in_offset,
- unsigned length);
-
-static enum tap_state jlink_last_state = TAP_RESET;
-static int queued_retval;
-
-/***************************************************************************/
-/* External interface implementation */
-
-static void jlink_execute_stableclocks(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles);
- jlink_stableclocks(cmd->cmd.runtest->num_cycles);
-}
-
-static void jlink_execute_runtest(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
-
- jlink_end_state(cmd->cmd.runtest->end_state);
- jlink_runtest(cmd->cmd.runtest->num_cycles);
-}
-
-static void jlink_execute_statemove(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
-
- jlink_end_state(cmd->cmd.statemove->end_state);
- jlink_state_move();
-}
-
-static void jlink_execute_pathmove(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("pathmove: %i states, end in %i",
- cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-
- jlink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
-}
-
-static void jlink_execute_scan(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN",
- jtag_scan_type(cmd->cmd.scan));
-
- /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */
- while (cmd->cmd.scan->num_fields > 0
- && cmd->cmd.scan->fields[cmd->cmd.scan->num_fields - 1].num_bits == 0) {
- cmd->cmd.scan->num_fields--;
- LOG_DEBUG("discarding trailing empty field");
- }
-
- if (cmd->cmd.scan->num_fields == 0) {
- LOG_DEBUG("empty scan, doing nothing");
- return;
- }
-
- if (cmd->cmd.scan->ir_scan) {
- if (tap_get_state() != TAP_IRSHIFT) {
- jlink_end_state(TAP_IRSHIFT);
- jlink_state_move();
- }
- } else {
- if (tap_get_state() != TAP_DRSHIFT) {
- jlink_end_state(TAP_DRSHIFT);
- jlink_state_move();
- }
- }
-
- jlink_end_state(cmd->cmd.scan->end_state);
-
- struct scan_field *field = cmd->cmd.scan->fields;
- unsigned scan_size = 0;
-
- for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) {
- scan_size += field->num_bits;
- DEBUG_JTAG_IO("%s%s field %d/%d %d bits",
- field->in_value ? "in" : "",
- field->out_value ? "out" : "",
- i,
- cmd->cmd.scan->num_fields,
- field->num_bits);
-
- if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) {
- /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap
- * movement. This last field can't have length zero, it was checked above. */
- jlink_clock_data(field->out_value,
- 0,
- NULL,
- 0,
- field->in_value,
- 0,
- field->num_bits - 1);
- uint8_t last_bit = 0;
- if (field->out_value)
- bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1);
- uint8_t tms_bits = 0x01;
- jlink_clock_data(&last_bit,
- 0,
- &tms_bits,
- 0,
- field->in_value,
- field->num_bits - 1,
- 1);
- tap_set_state(tap_state_transition(tap_get_state(), 1));
- jlink_clock_data(NULL,
- 0,
- &tms_bits,
- 1,
- NULL,
- 0,
- 1);
- tap_set_state(tap_state_transition(tap_get_state(), 0));
- } else
- jlink_clock_data(field->out_value,
- 0,
- NULL,
- 0,
- field->in_value,
- 0,
- field->num_bits);
- }
-
- if (tap_get_state() != tap_get_end_state()) {
- jlink_end_state(tap_get_end_state());
- jlink_state_move();
- }
-
- DEBUG_JTAG_IO("%s scan, %i bits, end in %s",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
- tap_state_name(tap_get_end_state()));
-}
-
-static void jlink_execute_reset(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-
- jlink_flush();
- jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- jlink_flush();
-}
-
-static void jlink_execute_sleep(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us);
- jlink_flush();
- jtag_sleep(cmd->cmd.sleep->us);
-}
-
-static int jlink_execute_command(struct jtag_command *cmd)
-{
- switch (cmd->type) {
- case JTAG_STABLECLOCKS:
- jlink_execute_stableclocks(cmd);
- break;
- case JTAG_RUNTEST:
- jlink_execute_runtest(cmd);
- break;
- case JTAG_TLR_RESET:
- jlink_execute_statemove(cmd);
- break;
- case JTAG_PATHMOVE:
- jlink_execute_pathmove(cmd);
- break;
- case JTAG_SCAN:
- jlink_execute_scan(cmd);
- break;
- case JTAG_RESET:
- jlink_execute_reset(cmd);
- break;
- case JTAG_SLEEP:
- jlink_execute_sleep(cmd);
- break;
- default:
- LOG_ERROR("BUG: Unknown JTAG command type encountered.");
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int jlink_execute_queue(void)
-{
- int ret;
- struct jtag_command *cmd = jtag_command_queue;
-
- while (cmd != NULL) {
- ret = jlink_execute_command(cmd);
-
- if (ret != ERROR_OK)
- return ret;
-
- cmd = cmd->next;
- }
-
- return jlink_flush();
-}
-
-static int jlink_speed(int speed)
-{
- int ret;
- uint32_t freq;
- uint16_t divider;
- int max_speed;
-
- if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
- ret = jaylink_get_speeds(devh, &freq, &divider);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_speeds() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- freq = freq / 1000;
- max_speed = freq / divider;
- } else {
- max_speed = JLINK_MAX_SPEED;
- }
-
- if (!speed) {
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_ADAPTIVE_CLOCKING)) {
- LOG_ERROR("Adaptive clocking is not supported by the device.");
- return ERROR_JTAG_NOT_IMPLEMENTED;
- }
-
- speed = JAYLINK_SPEED_ADAPTIVE_CLOCKING;
- } else if (speed > max_speed) {
- LOG_INFO("Reduced speed from %d kHz to %d kHz (maximum).", speed,
- max_speed);
- speed = max_speed;
- }
-
- ret = jaylink_set_speed(devh, speed);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_set_speed() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int jlink_speed_div(int speed, int *khz)
-{
- *khz = speed;
-
- return ERROR_OK;
-}
-
-static int jlink_khz(int khz, int *jtag_speed)
-{
- *jtag_speed = khz;
-
- return ERROR_OK;
-}
-
-static bool read_device_config(struct device_config *cfg)
-{
- int ret;
-
- ret = jaylink_read_raw_config(devh, (uint8_t *)cfg);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_read_raw_config() failed: %s.",
- jaylink_strerror_name(ret));
- return false;
- }
-
- if (cfg->usb_address == 0xff)
- cfg->usb_address = 0x00;
-
- if (cfg->target_power == 0xffffffff)
- cfg->target_power = 0;
-
- return true;
-}
-
-static int select_interface(void)
-{
- int ret;
- uint32_t interfaces;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SELECT_TIF)) {
- if (iface != JAYLINK_TIF_JTAG) {
- LOG_ERROR("Device supports JTAG transport only.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
- }
-
- ret = jaylink_get_available_interfaces(devh, &interfaces);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_available_interfaces() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (!(interfaces & (1 << iface))) {
- LOG_ERROR("Selected transport is not supported by the device.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- ret = jaylink_select_interface(devh, iface, NULL);
-
- if (ret < 0) {
- LOG_ERROR("jaylink_select_interface() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- return ERROR_OK;
-}
-
-static int jlink_register(void)
-{
- int ret;
- int i;
- bool handle_found;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER))
- return ERROR_OK;
-
- ret = jaylink_register(devh, &conn, connlist, NULL, NULL);
-
- if (ret < 0) {
- LOG_ERROR("jaylink_register() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- handle_found = false;
-
- for (i = 0; i < ret; i++) {
- if (connlist[i].handle == conn.handle) {
- handle_found = true;
- break;
- }
- }
-
- if (!handle_found) {
- LOG_ERROR("Registration failed: maximum number of connections on the "
- "device reached.");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-/*
- * Adjust the SWD transaction buffer size depending on the free device internal
- * memory. This ensures that the SWD transactions sent to the device do not
- * exceed the internal memory of the device.
- */
-static bool adjust_swd_buffer_size(void)
-{
- int ret;
- uint32_t tmp;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_FREE_MEMORY))
- return true;
-
- ret = jaylink_get_free_memory(devh, &tmp);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_free_memory() failed: %s.",
- jaylink_strerror_name(ret));
- return false;
- }
-
- if (tmp < 143) {
- LOG_ERROR("Not enough free device internal memory: %u bytes.", tmp);
- return false;
- }
-
- tmp = MIN(JLINK_TAP_BUFFER_SIZE, (tmp - 16) / 2);
-
- if (tmp != swd_buffer_size) {
- swd_buffer_size = tmp;
- LOG_DEBUG("Adjusted SWD transaction buffer size to %u bytes.",
- swd_buffer_size);
- }
-
- return true;
-}
-
-static int jlink_init(void)
-{
- int ret;
- struct jaylink_device **devs;
- unsigned int i;
- bool found_device;
- uint32_t tmp;
- char *firmware_version;
- struct jaylink_hardware_version hwver;
- struct jaylink_hardware_status hwstatus;
- enum jaylink_usb_address address;
- size_t length;
-
- ret = jaylink_init(&jayctx);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_init() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- ret = jaylink_get_device_list(jayctx, &devs);
-
- if (ret < 0) {
- LOG_ERROR("jaylink_get_device_list() failed: %s.",
- jaylink_strerror_name(ret));
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- found_device = false;
-
- if (!use_serial_number && !use_usb_address)
- LOG_INFO("No device selected, using first device.");
-
- for (i = 0; devs[i]; i++) {
- if (use_serial_number) {
- ret = jaylink_device_get_serial_number(devs[i], &tmp);
-
- if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
- continue;
- } else if (ret != JAYLINK_OK) {
- LOG_WARNING("jaylink_device_get_serial_number() failed: %s.",
- jaylink_strerror_name(ret));
- continue;
- }
-
- if (serial_number != tmp)
- continue;
- }
-
- if (use_usb_address) {
- ret = jaylink_device_get_usb_address(devs[i], &address);
-
- if (ret != JAYLINK_OK) {
- LOG_WARNING("jaylink_device_get_usb_address() failed: %s.",
- jaylink_strerror_name(ret));
- continue;
- }
-
- if (usb_address != address)
- continue;
- }
-
- ret = jaylink_open(devs[i], &devh);
-
- if (ret == JAYLINK_OK) {
- found_device = true;
- break;
- }
-
- LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret));
- }
-
- jaylink_free_device_list(devs, 1);
-
- if (!found_device) {
- LOG_ERROR("No J-Link device found.");
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- /*
- * Be careful with changing the following initialization sequence because
- * some devices are known to be sensitive regarding the order.
- */
-
- ret = jaylink_get_firmware_version(devh, &firmware_version, &length);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_firmware_version() failed: %s.",
- jaylink_strerror_name(ret));
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- } else if (length > 0) {
- LOG_INFO("%s", firmware_version);
- free(firmware_version);
- } else {
- LOG_WARNING("Device responds empty firmware version string.");
- }
-
- memset(caps, 0, JAYLINK_DEV_EXT_CAPS_SIZE);
- ret = jaylink_get_caps(devh, caps);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_caps() failed: %s.", jaylink_strerror_name(ret));
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) {
- ret = jaylink_get_extended_caps(devh, caps);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_extended_caps() failed: %s.",
- jaylink_strerror_name(ret));
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
- }
-
- jtag_command_version = JAYLINK_JTAG_V2;
-
- if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) {
- ret = jaylink_get_hardware_version(devh, &hwver);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("Failed to retrieve hardware version: %s.",
- jaylink_strerror_name(ret));
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor);
-
- if (hwver.major >= 5)
- jtag_command_version = JAYLINK_JTAG_V3;
- }
-
- if (iface == JAYLINK_TIF_SWD) {
- /*
- * Adjust the SWD transaction buffer size in case there is already
- * allocated memory on the device. This happens for example if the
- * memory for SWO capturing is still allocated because the software
- * which used the device before has not been shut down properly.
- */
- if (!adjust_swd_buffer_size()) {
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
- }
-
- if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
- if (!read_device_config(&config)) {
- LOG_ERROR("Failed to read device configuration data.");
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- memcpy(&tmp_config, &config, sizeof(struct device_config));
- }
-
- ret = jaylink_get_hardware_status(devh, &hwstatus);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_hardware_status() failed: %s.",
- jaylink_strerror_name(ret));
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- LOG_INFO("VTarget = %u.%03u V", hwstatus.target_voltage / 1000,
- hwstatus.target_voltage % 1000);
-
- conn.handle = 0;
- conn.pid = 0;
- conn.hid = 0;
- conn.iid = 0;
- conn.cid = 0;
-
- ret = jlink_register();
-
- if (ret != ERROR_OK) {
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- ret = select_interface();
-
- if (ret != ERROR_OK) {
- jaylink_close(devh);
- jaylink_exit(jayctx);
- return ret;
- }
-
- jlink_reset(0, 0);
- jtag_sleep(3000);
- jlink_tap_init();
-
- jlink_speed(jtag_get_speed_khz());
-
- if (iface == JAYLINK_TIF_JTAG) {
- /*
- * J-Link devices with firmware version v5 and v6 seems to have an issue
- * if the first tap move is not divisible by 8, so we send a TLR on
- * first power up.
- */
- uint8_t tms = 0xff;
- jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 8);
-
- jlink_flush();
- }
-
- return ERROR_OK;
-}
-
-static int jlink_quit(void)
-{
- int ret;
-
- if (trace_enabled) {
- ret = jaylink_swo_stop(devh);
-
- if (ret != JAYLINK_OK)
- LOG_ERROR("jaylink_swo_stop() failed: %s.",
- jaylink_strerror_name(ret));
- }
-
- if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) {
- ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL);
-
- if (ret < 0)
- LOG_ERROR("jaylink_unregister() failed: %s.",
- jaylink_strerror_name(ret));
- }
-
- jaylink_close(devh);
- jaylink_exit(jayctx);
-
- return ERROR_OK;
-}
-
-/***************************************************************************/
-/* Queue command implementations */
-
-static void jlink_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-/* Goes to the end state. */
-static void jlink_state_move(void)
-{
- uint8_t tms_scan;
- uint8_t tms_scan_bits;
-
- tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
- tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
-
- jlink_clock_data(NULL, 0, &tms_scan, 0, NULL, 0, tms_scan_bits);
-
- tap_set_state(tap_get_end_state());
-}
-
-static void jlink_path_move(int num_states, tap_state_t *path)
-{
- int i;
- uint8_t tms = 0xff;
-
- for (i = 0; i < num_states; i++) {
- if (path[i] == tap_state_transition(tap_get_state(), false))
- jlink_clock_data(NULL, 0, NULL, 0, NULL, 0, 1);
- else if (path[i] == tap_state_transition(tap_get_state(), true))
- jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 1);
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.",
- tap_state_name(tap_get_state()), tap_state_name(path[i]));
- exit(-1);
- }
-
- tap_set_state(path[i]);
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void jlink_stableclocks(int num_cycles)
-{
- int i;
-
- uint8_t tms = tap_get_state() == TAP_RESET;
- /* Execute num_cycles. */
- for (i = 0; i < num_cycles; i++)
- jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 1);
-}
-
-static void jlink_runtest(int num_cycles)
-{
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* Only do a state_move when we're not already in IDLE. */
- if (tap_get_state() != TAP_IDLE) {
- jlink_end_state(TAP_IDLE);
- jlink_state_move();
- /* num_cycles--; */
- }
-
- jlink_stableclocks(num_cycles);
-
- /* Finish in end_state. */
- jlink_end_state(saved_end_state);
-
- if (tap_get_state() != tap_get_end_state())
- jlink_state_move();
-}
-
-static void jlink_reset(int trst, int srst)
-{
- LOG_DEBUG("TRST: %i, SRST: %i.", trst, srst);
-
- /* Signals are active low. */
- if (srst == 0)
- jaylink_set_reset(devh);
-
- if (srst == 1)
- jaylink_clear_reset(devh);
-
- if (trst == 1)
- jaylink_jtag_clear_trst(devh);
-
- if (trst == 0)
- jaylink_jtag_set_trst(devh);
-}
-
-COMMAND_HANDLER(jlink_usb_command)
-{
- int tmp;
-
- if (CMD_ARGC != 1) {
- command_print(CMD_CTX, "Need exactly one argument for jlink usb.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) {
- command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) {
- command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- usb_address = tmp;
-
- use_serial_number = false;
- use_usb_address = true;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_serial_command)
-{
- if (CMD_ARGC != 1) {
- command_print(CMD_CTX, "Need exactly one argument for jlink serial.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) {
- command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- use_serial_number = true;
- use_usb_address = false;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_hwstatus_command)
-{
- int ret;
- struct jaylink_hardware_status status;
-
- ret = jaylink_get_hardware_status(devh, &status);
-
- if (ret != JAYLINK_OK) {
- command_print(CMD_CTX, "jaylink_get_hardware_status() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- command_print(CMD_CTX, "VTarget = %u.%03u V",
- status.target_voltage / 1000, status.target_voltage % 1000);
-
- command_print(CMD_CTX, "TCK = %u TDI = %u TDO = %u TMS = %u SRST = %u "
- "TRST = %u", status.tck, status.tdi, status.tdo, status.tms,
- status.tres, status.trst);
-
- if (status.target_voltage < 1500)
- command_print(CMD_CTX, "Target voltage too low. Check target power.");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_free_memory_command)
-{
- int ret;
- uint32_t tmp;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_FREE_MEMORY)) {
- command_print(CMD_CTX, "Retrieval of free memory is not supported by "
- "the device.");
- return ERROR_OK;
- }
-
- ret = jaylink_get_free_memory(devh, &tmp);
-
- if (ret != JAYLINK_OK) {
- command_print(CMD_CTX, "jaylink_get_free_memory() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- command_print(CMD_CTX, "Device has %u bytes of free memory.", tmp);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_jlink_jtag_command)
-{
- int tmp;
- int version;
-
- if (!CMD_ARGC) {
- switch (jtag_command_version) {
- case JAYLINK_JTAG_V2:
- version = 2;
- break;
- case JAYLINK_JTAG_V3:
- version = 3;
- break;
- default:
- return ERROR_FAIL;
- }
-
- command_print(CMD_CTX, "JTAG command version: %i", version);
- } else if (CMD_ARGC == 1) {
- if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) {
- command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- switch (tmp) {
- case 2:
- jtag_command_version = JAYLINK_JTAG_V2;
- break;
- case 3:
- jtag_command_version = JAYLINK_JTAG_V3;
- break;
- default:
- command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- } else {
- command_print(CMD_CTX, "Need exactly one argument for jlink jtag.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_target_power_command)
-{
- int ret;
- int enable;
-
- if (CMD_ARGC != 1) {
- command_print(CMD_CTX, "Need exactly one argument for jlink "
- "targetpower.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) {
- command_print(CMD_CTX, "Target power supply is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!strcmp(CMD_ARGV[0], "on")) {
- enable = true;
- } else if (!strcmp(CMD_ARGV[0], "off")) {
- enable = false;
- } else {
- command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- ret = jaylink_set_target_power(devh, enable);
-
- if (ret != JAYLINK_OK) {
- command_print(CMD_CTX, "jaylink_set_target_power() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static void show_config_usb_address(struct command_context *ctx)
-{
- if (config.usb_address != tmp_config.usb_address)
- command_print(ctx, "USB address: %u [%u]", config.usb_address,
- tmp_config.usb_address);
- else
- command_print(ctx, "USB address: %u", config.usb_address);
-}
-
-static void show_config_ip_address(struct command_context *ctx)
-{
- if (!memcmp(config.ip_address, tmp_config.ip_address, 4))
- command_print(ctx, "IP address: %d.%d.%d.%d",
- config.ip_address[3], config.ip_address[2],
- config.ip_address[1], config.ip_address[0]);
- else
- command_print(ctx, "IP address: %d.%d.%d.%d [%d.%d.%d.%d]",
- config.ip_address[3], config.ip_address[2],
- config.ip_address[1], config.ip_address[0],
- tmp_config.ip_address[3], tmp_config.ip_address[2],
- tmp_config.ip_address[1], tmp_config.ip_address[0]);
-
- if (!memcmp(config.subnet_mask, tmp_config.subnet_mask, 4))
- command_print(ctx, "Subnet mask: %d.%d.%d.%d",
- config.subnet_mask[3], config.subnet_mask[2],
- config.subnet_mask[1], config.subnet_mask[0]);
- else
- command_print(ctx, "Subnet mask: %d.%d.%d.%d [%d.%d.%d.%d]",
- config.subnet_mask[3], config.subnet_mask[2],
- config.subnet_mask[1], config.subnet_mask[0],
- tmp_config.subnet_mask[3], tmp_config.subnet_mask[2],
- tmp_config.subnet_mask[1], tmp_config.subnet_mask[0]);
-}
-
-static void show_config_mac_address(struct command_context *ctx)
-{
- if (!memcmp(config.mac_address, tmp_config.mac_address, 6))
- command_print(ctx, "MAC address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x",
- config.mac_address[5], config.mac_address[4],
- config.mac_address[3], config.mac_address[2],
- config.mac_address[1], config.mac_address[0]);
- else
- command_print(ctx, "MAC address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x "
- "[%.02x:%.02x:%.02x:%.02x:%.02x:%.02x]",
- config.mac_address[5], config.mac_address[4],
- config.mac_address[3], config.mac_address[2],
- config.mac_address[1], config.mac_address[0],
- tmp_config.mac_address[5], tmp_config.mac_address[4],
- tmp_config.mac_address[3], tmp_config.mac_address[2],
- tmp_config.mac_address[1], tmp_config.mac_address[0]);
-}
-
-static void show_config_target_power(struct command_context *ctx)
-{
- const char *target_power;
- const char *current_target_power;
-
- if (!config.target_power)
- target_power = "off";
- else
- target_power = "on";
-
- if (!tmp_config.target_power)
- current_target_power = "off";
- else
- current_target_power = "on";
-
- if (config.target_power != tmp_config.target_power)
- command_print(ctx, "Target power supply: %s [%s]", target_power,
- current_target_power);
- else
- command_print(ctx, "Target power supply: %s", target_power);
-}
-
-static void show_config(struct command_context *ctx)
-{
- command_print(ctx, "J-Link device configuration:");
-
- show_config_usb_address(ctx);
-
- if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER))
- show_config_target_power(ctx);
-
- if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_ETHERNET)) {
- show_config_ip_address(ctx);
- show_config_mac_address(ctx);
- }
-}
-
-static int poll_trace(uint8_t *buf, size_t *size)
-{
- int ret;
- uint32_t length;
-
- length = *size;
-
- ret = jaylink_swo_read(devh, buf, &length);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_swo_read() failed: %s.", jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- *size = length;
-
- return ERROR_OK;
-}
-
-static uint32_t calculate_trace_buffer_size(void)
-{
- int ret;
- uint32_t tmp;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_FREE_MEMORY))
- return 0;
-
- ret = jaylink_get_free_memory(devh, &tmp);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_get_free_memory() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- if (tmp > 0x3fff || tmp <= 0x600)
- tmp = tmp >> 1;
- else
- tmp = tmp - 0x400;
-
- return tmp & 0xffffff00;
-}
-
-static bool check_trace_freq(struct jaylink_swo_speed speed,
- uint32_t trace_freq)
-{
- double min;
- double deviation;
- uint32_t divider;
-
- min = fabs(1.0 - (speed.freq / ((double)trace_freq * speed.min_div)));
-
- for (divider = speed.min_div; divider < speed.max_div; divider++) {
- deviation = fabs(1.0 - (speed.freq / ((double)trace_freq * divider)));
-
- if (deviation < 0.03) {
- LOG_DEBUG("Found suitable frequency divider %u with deviation of "
- "%.02f %%.", divider, deviation);
- return true;
- }
-
- if (deviation < min)
- min = deviation;
- }
-
- LOG_ERROR("Selected trace frequency is not supported by the device. "
- "Please choose a different trace frequency.");
- LOG_ERROR("Maximum permitted deviation is 3.00 %%, but only %.02f %% "
- "could be achieved.", min * 100);
-
- return false;
-}
-
-static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
-{
- int ret;
- uint32_t buffer_size;
- struct jaylink_swo_speed speed;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SWO)) {
- LOG_ERROR("Trace capturing is not supported by the device.");
- return ERROR_FAIL;
- }
-
- if (pin_protocol != ASYNC_UART) {
- LOG_ERROR("Selected pin protocol is not supported.");
- return ERROR_FAIL;
- }
-
- trace_enabled = enabled;
-
- ret = jaylink_swo_stop(devh);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_swo_stop() failed: %s.", jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- if (!enabled) {
- /*
- * Adjust the SWD transaction buffer size as stopping SWO capturing
- * deallocates device internal memory.
- */
- if (!adjust_swd_buffer_size())
- return ERROR_FAIL;
-
- return ERROR_OK;
- }
-
- buffer_size = calculate_trace_buffer_size();
-
- if (!buffer_size) {
- LOG_ERROR("Not enough free device memory to start trace capturing.");
- return ERROR_FAIL;
- }
-
- ret = jaylink_swo_get_speeds(devh, JAYLINK_SWO_MODE_UART, &speed);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_swo_get_speeds() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- if (!*trace_freq)
- *trace_freq = speed.freq / speed.min_div;
-
- if (!check_trace_freq(speed, *trace_freq))
- return ERROR_FAIL;
-
- LOG_DEBUG("Using %u bytes device memory for trace capturing.", buffer_size);
-
- ret = jaylink_swo_start(devh, JAYLINK_SWO_MODE_UART, *trace_freq,
- buffer_size);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_start_swo() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- /*
- * Adjust the SWD transaction buffer size as starting SWO capturing
- * allocates device internal memory.
- */
- if (!adjust_swd_buffer_size())
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_config_usb_address_command)
-{
- uint8_t tmp;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
- command_print(CMD_CTX, "Reading configuration is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!CMD_ARGC) {
- show_config_usb_address(CMD_CTX);
- } else if (CMD_ARGC == 1) {
- if (sscanf(CMD_ARGV[0], "%" SCNd8, &tmp) != 1) {
- command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- if (tmp > JAYLINK_USB_ADDRESS_3) {
- command_print(CMD_CTX, "Invalid USB address: %u.", tmp);
- return ERROR_FAIL;
- }
-
- tmp_config.usb_address = tmp;
- } else {
- command_print(CMD_CTX, "Need exactly one argument for jlink config "
- "usb.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_config_target_power_command)
-{
- int enable;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
- command_print(CMD_CTX, "Reading configuration is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) {
- command_print(CMD_CTX, "Target power supply is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!CMD_ARGC) {
- show_config_target_power(CMD_CTX);
- } else if (CMD_ARGC == 1) {
- if (!strcmp(CMD_ARGV[0], "on")) {
- enable = true;
- } else if (!strcmp(CMD_ARGV[0], "off")) {
- enable = false;
- } else {
- command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- tmp_config.target_power = enable;
- } else {
- command_print(CMD_CTX, "Need exactly one argument for jlink config "
- "targetpower.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_config_mac_address_command)
-{
- uint8_t addr[6];
- int i;
- char *e;
- const char *str;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
- command_print(CMD_CTX, "Reading configuration is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_ETHERNET)) {
- command_print(CMD_CTX, "Ethernet connectivity is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!CMD_ARGC) {
- show_config_mac_address(CMD_CTX);
- } else if (CMD_ARGC == 1) {
- str = CMD_ARGV[0];
-
- if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' || \
- str[8] != ':' || str[11] != ':' || str[14] != ':')) {
- command_print(CMD_CTX, "Invalid MAC address format.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- for (i = 5; i >= 0; i--) {
- addr[i] = strtoul(str, &e, 16);
- str = e + 1;
- }
-
- if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) {
- command_print(CMD_CTX, "Invalid MAC address: zero address.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (!(0x01 & addr[0])) {
- command_print(CMD_CTX, "Invalid MAC address: multicast address.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- memcpy(tmp_config.mac_address, addr, sizeof(addr));
- } else {
- command_print(CMD_CTX, "Need exactly one argument for jlink config "
- " mac.");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static bool string_to_ip(const char *s, uint8_t *ip, int *pos)
-{
- uint8_t lip[4];
- char *e;
- const char *s_save = s;
- int i;
-
- if (!s)
- return false;
-
- for (i = 0; i < 4; i++) {
- lip[i] = strtoul(s, &e, 10);
-
- if (*e != '.' && i != 3)
- return false;
-
- s = e + 1;
- }
-
- *pos = e - s_save;
- memcpy(ip, lip, sizeof(lip));
-
- return true;
-}
-
-static void cpy_ip(uint8_t *dst, uint8_t *src)
-{
- int i, j;
-
- for (i = 0, j = 3; i < 4; i++, j--)
- dst[i] = src[j];
-}
-
-COMMAND_HANDLER(jlink_handle_config_ip_address_command)
-{
- uint8_t ip_address[4];
- uint32_t subnet_mask = 0;
- int i, len;
- uint8_t subnet_bits = 24;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
- command_print(CMD_CTX, "Reading configuration is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_ETHERNET)) {
- command_print(CMD_CTX, "Ethernet connectivity is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!CMD_ARGC) {
- show_config_ip_address(CMD_CTX);
- } else {
- if (!string_to_ip(CMD_ARGV[0], ip_address, &i))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- len = strlen(CMD_ARGV[0]);
-
- /* Check for format A.B.C.D/E. */
- if (i < len) {
- if (CMD_ARGV[0][i] != '/')
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0] + i + 1, subnet_bits);
- } else if (CMD_ARGC > 1) {
- if (!string_to_ip(CMD_ARGV[1], (uint8_t *)&subnet_mask, &i))
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (!subnet_mask)
- subnet_mask = (uint32_t)(subnet_bits < 32 ?
- ((1ULL << subnet_bits) - 1) : 0xffffffff);
-
- cpy_ip(tmp_config.ip_address, ip_address);
- cpy_ip(tmp_config.subnet_mask, (uint8_t *)&subnet_mask);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_config_reset_command)
-{
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG))
- return ERROR_OK;
-
- memcpy(&tmp_config, &config, sizeof(struct device_config));
-
- return ERROR_OK;
-}
-
-
-COMMAND_HANDLER(jlink_handle_config_write_command)
-{
- int ret;
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
- command_print(CMD_CTX, "Reading configuration is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_WRITE_CONFIG)) {
- command_print(CMD_CTX, "Writing configuration is not supported by the "
- "device.");
- return ERROR_OK;
- }
-
- if (!memcmp(&config, &tmp_config, sizeof(struct device_config))) {
- command_print(CMD_CTX, "Operation not performed due to no changes in "
- "the configuration.");
- return ERROR_OK;
- }
-
- ret = jaylink_write_raw_config(devh, (const uint8_t *)&tmp_config);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_write_raw_config() failed: %s.",
- jaylink_strerror_name(ret));
- return ERROR_FAIL;
- }
-
- if (!read_device_config(&config)) {
- LOG_ERROR("Failed to read device configuration for verification.");
- return ERROR_FAIL;
- }
-
- if (memcmp(&config, &tmp_config, sizeof(struct device_config))) {
- LOG_ERROR("Verification of device configuration failed. Please check "
- "your device.");
- return ERROR_FAIL;
- }
-
- memcpy(&tmp_config, &config, sizeof(struct device_config));
- command_print(CMD_CTX, "The new device configuration applies after power "
- "cycling the J-Link device.");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jlink_handle_config_command)
-{
- if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
- command_print(CMD_CTX, "Device doesn't support reading configuration.");
- return ERROR_OK;
- }
-
- if (CMD_ARGC == 0)
- show_config(CMD_CTX);
-
- return ERROR_OK;
-}
-
-static const struct command_registration jlink_config_subcommand_handlers[] = {
- {
- .name = "usb",
- .handler = &jlink_handle_config_usb_address_command,
- .mode = COMMAND_EXEC,
- .help = "set the USB address",
- .usage = "[0-3]",
- },
- {
- .name = "targetpower",
- .handler = &jlink_handle_config_target_power_command,
- .mode = COMMAND_EXEC,
- .help = "set the target power supply",
- .usage = "[on|off]"
- },
- {
- .name = "mac",
- .handler = &jlink_handle_config_mac_address_command,
- .mode = COMMAND_EXEC,
- .help = "set the MAC Address",
- .usage = "[ff:ff:ff:ff:ff:ff]",
- },
- {
- .name = "ip",
- .handler = &jlink_handle_config_ip_address_command,
- .mode = COMMAND_EXEC,
- .help = "set the IP address, where A.B.C.D is the IP address, "
- "E the bit of the subnet mask, F.G.H.I the subnet mask",
- .usage = "[A.B.C.D[/E] [F.G.H.I]]",
- },
- {
- .name = "reset",
- .handler = &jlink_handle_config_reset_command,
- .mode = COMMAND_EXEC,
- .help = "undo configuration changes"
- },
- {
- .name = "write",
- .handler = &jlink_handle_config_write_command,
- .mode = COMMAND_EXEC,
- .help = "write configuration to the device"
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration jlink_subcommand_handlers[] = {
- {
- .name = "jtag",
- .handler = &jlink_handle_jlink_jtag_command,
- .mode = COMMAND_EXEC,
- .help = "select the JTAG command version",
- .usage = "[2|3]",
- },
- {
- .name = "targetpower",
- .handler = &jlink_handle_target_power_command,
- .mode = COMMAND_EXEC,
- .help = "set the target power supply",
- .usage = "<on|off>"
- },
- {
- .name = "freemem",
- .handler = &jlink_handle_free_memory_command,
- .mode = COMMAND_EXEC,
- .help = "show free device memory"
- },
- {
- .name = "hwstatus",
- .handler = &jlink_handle_hwstatus_command,
- .mode = COMMAND_EXEC,
- .help = "show the hardware status"
- },
- {
- .name = "usb",
- .handler = &jlink_usb_command,
- .mode = COMMAND_CONFIG,
- .help = "set the USB address of the device that should be used",
- .usage = "<0-3>"
- },
- {
- .name = "serial",
- .handler = &jlink_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the device that should be used",
- .usage = "<serial number>"
- },
- {
- .name = "config",
- .handler = &jlink_handle_config_command,
- .mode = COMMAND_EXEC,
- .help = "access the device configuration. If no argument is given "
- "this will show the device configuration",
- .chain = jlink_config_subcommand_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration jlink_command_handlers[] = {
- {
- .name = "jlink",
- .mode = COMMAND_ANY,
- .help = "perform jlink management",
- .chain = jlink_subcommand_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int jlink_swd_init(void)
-{
- iface = JAYLINK_TIF_SWD;
-
- return ERROR_OK;
-}
-
-static void jlink_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
-{
- assert(!(cmd & SWD_CMD_RnW));
- jlink_swd_queue_cmd(cmd, NULL, value, ap_delay_clk);
-}
-
-static void jlink_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
-{
- assert(cmd & SWD_CMD_RnW);
- jlink_swd_queue_cmd(cmd, value, 0, ap_delay_clk);
-}
-
-static int_least32_t jlink_swd_frequency(int_least32_t hz)
-{
- if (hz > 0)
- jlink_speed(hz / 1000);
-
- return hz;
-}
-
-/***************************************************************************/
-/* J-Link tap functions */
-
-static unsigned tap_length;
-/* In SWD mode use tms buffer for direction control */
-static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE];
-static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE];
-static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE];
-
-struct pending_scan_result {
- /** First bit position in tdo_buffer to read. */
- unsigned first;
- /** Number of bits to read. */
- unsigned length;
- /** Location to store the result */
- void *buffer;
- /** Offset in the destination buffer */
- unsigned buffer_offset;
-};
-
-#define MAX_PENDING_SCAN_RESULTS 256
-
-static int pending_scan_results_length;
-static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
-
-static void jlink_tap_init(void)
-{
- tap_length = 0;
- pending_scan_results_length = 0;
- memset(tms_buffer, 0, sizeof(tms_buffer));
- memset(tdi_buffer, 0, sizeof(tdi_buffer));
-}
-
-static void jlink_clock_data(const uint8_t *out, unsigned out_offset,
- const uint8_t *tms_out, unsigned tms_offset,
- uint8_t *in, unsigned in_offset,
- unsigned length)
-{
- do {
- unsigned available_length = JLINK_TAP_BUFFER_SIZE - tap_length / 8;
-
- if (!available_length ||
- (in && pending_scan_results_length == MAX_PENDING_SCAN_RESULTS)) {
- if (jlink_flush() != ERROR_OK)
- return;
- available_length = JLINK_TAP_BUFFER_SIZE;
- }
-
- struct pending_scan_result *pending_scan_result =
- &pending_scan_results_buffer[pending_scan_results_length];
-
- unsigned scan_length = length > available_length ?
- available_length : length;
-
- if (out)
- buf_set_buf(out, out_offset, tdi_buffer, tap_length, scan_length);
- if (tms_out)
- buf_set_buf(tms_out, tms_offset, tms_buffer, tap_length, scan_length);
-
- if (in) {
- pending_scan_result->first = tap_length;
- pending_scan_result->length = scan_length;
- pending_scan_result->buffer = in;
- pending_scan_result->buffer_offset = in_offset;
- pending_scan_results_length++;
- }
-
- tap_length += scan_length;
- out_offset += scan_length;
- tms_offset += scan_length;
- in_offset += scan_length;
- length -= scan_length;
- } while (length > 0);
-}
-
-static int jlink_flush(void)
-{
- int i;
- int ret;
-
- if (!tap_length)
- return ERROR_OK;
-
- jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer,
- tap_length, jlink_last_state);
-
- ret = jaylink_jtag_io(devh, tms_buffer, tdi_buffer, tdo_buffer,
- tap_length, jtag_command_version);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_jtag_io() failed: %s.", jaylink_strerror_name(ret));
- jlink_tap_init();
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- for (i = 0; i < pending_scan_results_length; i++) {
- struct pending_scan_result *p = &pending_scan_results_buffer[i];
-
- buf_set_buf(tdo_buffer, p->first, p->buffer,
- p->buffer_offset, p->length);
-
- DEBUG_JTAG_IO("Pending scan result, length = %d.", p->length);
- }
-
- jlink_tap_init();
-
- return ERROR_OK;
-}
-
-static void fill_buffer(uint8_t *buf, uint32_t val, uint32_t len)
-{
- unsigned int tap_pos = tap_length;
-
- while (len > 32) {
- buf_set_u32(buf, tap_pos, 32, val);
- len -= 32;
- tap_pos += 32;
- }
-
- if (len)
- buf_set_u32(buf, tap_pos, len, val);
-}
-
-static void jlink_queue_data_out(const uint8_t *data, uint32_t len)
-{
- const uint32_t dir_out = 0xffffffff;
-
- if (data)
- bit_copy(tdi_buffer, tap_length, data, 0, len);
- else
- fill_buffer(tdi_buffer, 0, len);
-
- fill_buffer(tms_buffer, dir_out, len);
- tap_length += len;
-}
-
-static void jlink_queue_data_in(uint32_t len)
-{
- const uint32_t dir_in = 0;
-
- fill_buffer(tms_buffer, dir_in, len);
- tap_length += len;
-}
-
-static int jlink_swd_switch_seq(enum swd_special_seq seq)
-{
- const uint8_t *s;
- unsigned int s_len;
-
- switch (seq) {
- case LINE_RESET:
- LOG_DEBUG("SWD line reset");
- s = swd_seq_line_reset;
- s_len = swd_seq_line_reset_len;
- break;
- case JTAG_TO_SWD:
- LOG_DEBUG("JTAG-to-SWD");
- s = swd_seq_jtag_to_swd;
- s_len = swd_seq_jtag_to_swd_len;
- break;
- case SWD_TO_JTAG:
- LOG_DEBUG("SWD-to-JTAG");
- s = swd_seq_swd_to_jtag;
- s_len = swd_seq_swd_to_jtag_len;
- break;
- default:
- LOG_ERROR("Sequence %d not supported.", seq);
- return ERROR_FAIL;
- }
-
- jlink_queue_data_out(s, s_len);
-
- return ERROR_OK;
-}
-
-static int jlink_swd_run_queue(void)
-{
- int i;
- int ret;
-
- LOG_DEBUG("Executing %d queued transactions.", pending_scan_results_length);
-
- if (queued_retval != ERROR_OK) {
- LOG_DEBUG("Skipping due to previous errors: %d.", queued_retval);
- goto skip;
- }
-
- /*
- * A transaction must be followed by another transaction or at least 8 idle
- * cycles to ensure that data is clocked through the AP.
- */
- jlink_queue_data_out(NULL, 8);
-
- ret = jaylink_swd_io(devh, tms_buffer, tdi_buffer, tdo_buffer, tap_length);
-
- if (ret != JAYLINK_OK) {
- LOG_ERROR("jaylink_swd_io() failed: %s.", jaylink_strerror_name(ret));
- goto skip;
- }
-
- for (i = 0; i < pending_scan_results_length; i++) {
- int ack = buf_get_u32(tdo_buffer, pending_scan_results_buffer[i].first, 3);
-
- if (ack != SWD_ACK_OK) {
- LOG_DEBUG("SWD ack not OK: %d %s", ack,
- ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
- queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
- goto skip;
- } else if (pending_scan_results_buffer[i].length) {
- uint32_t data = buf_get_u32(tdo_buffer, 3 + pending_scan_results_buffer[i].first, 32);
- int parity = buf_get_u32(tdo_buffer, 3 + 32 + pending_scan_results_buffer[i].first, 1);
-
- if (parity != parity_u32(data)) {
- LOG_ERROR("SWD: Read data parity mismatch.");
- queued_retval = ERROR_FAIL;
- goto skip;
- }
-
- if (pending_scan_results_buffer[i].buffer)
- *(uint32_t *)pending_scan_results_buffer[i].buffer = data;
- }
- }
-
-skip:
- jlink_tap_init();
- ret = queued_retval;
- queued_retval = ERROR_OK;
-
- return ret;
-}
-
-static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk)
-{
- uint8_t data_parity_trn[DIV_ROUND_UP(32 + 1, 8)];
- if (tap_length + 46 + 8 + ap_delay_clk >= sizeof(tdi_buffer) * 8 ||
- pending_scan_results_length == MAX_PENDING_SCAN_RESULTS) {
- /* Not enough room in the queue. Run the queue. */
- queued_retval = jlink_swd_run_queue();
- }
-
- if (queued_retval != ERROR_OK)
- return;
-
- cmd |= SWD_CMD_START | SWD_CMD_PARK;
-
- jlink_queue_data_out(&cmd, 8);
-
- pending_scan_results_buffer[pending_scan_results_length].first = tap_length;
-
- if (cmd & SWD_CMD_RnW) {
- /* Queue a read transaction. */
- pending_scan_results_buffer[pending_scan_results_length].length = 32;
- pending_scan_results_buffer[pending_scan_results_length].buffer = dst;
-
- jlink_queue_data_in(1 + 3 + 32 + 1 + 1);
- } else {
- /* Queue a write transaction. */
- pending_scan_results_buffer[pending_scan_results_length].length = 0;
- jlink_queue_data_in(1 + 3 + 1);
-
- buf_set_u32(data_parity_trn, 0, 32, data);
- buf_set_u32(data_parity_trn, 32, 1, parity_u32(data));
-
- jlink_queue_data_out(data_parity_trn, 32 + 1);
- }
-
- pending_scan_results_length++;
-
- /* Insert idle cycles after AP accesses to avoid WAIT. */
- if (cmd & SWD_CMD_APnDP)
- jlink_queue_data_out(NULL, ap_delay_clk);
-}
-
-static const struct swd_driver jlink_swd = {
- .init = &jlink_swd_init,
- .frequency = &jlink_swd_frequency,
- .switch_seq = &jlink_swd_switch_seq,
- .read_reg = &jlink_swd_read_reg,
- .write_reg = &jlink_swd_write_reg,
- .run = &jlink_swd_run_queue,
-};
-
-static const char * const jlink_transports[] = { "jtag", "swd", NULL };
-
-struct jtag_interface jlink_interface = {
- .name = "jlink",
- .commands = jlink_command_handlers,
- .transports = jlink_transports,
- .swd = &jlink_swd,
- .execute_queue = &jlink_execute_queue,
- .speed = &jlink_speed,
- .speed_div = &jlink_speed_div,
- .khz = &jlink_khz,
- .init = &jlink_init,
- .quit = &jlink_quit,
- .config_trace = &config_trace,
- .poll_trace = &poll_trace,
-};
diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c
deleted file mode 100644
index 1b0fcba..0000000
--- a/src/jtag/drivers/jtag_vpi.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * JTAG to VPI driver
- *
- * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#define NO_TAP_SHIFT 0
-#define TAP_SHIFT 1
-
-#define SERVER_ADDRESS "127.0.0.1"
-#define SERVER_PORT 5555
-
-#define XFERT_MAX_SIZE 512
-
-#define CMD_RESET 0
-#define CMD_TMS_SEQ 1
-#define CMD_SCAN_CHAIN 2
-#define CMD_SCAN_CHAIN_FLIP_TMS 3
-#define CMD_STOP_SIMU 4
-
-int server_port = SERVER_PORT;
-char *server_address;
-
-int sockfd;
-struct sockaddr_in serv_addr;
-
-struct vpi_cmd {
- int cmd;
- unsigned char buffer_out[XFERT_MAX_SIZE];
- unsigned char buffer_in[XFERT_MAX_SIZE];
- int length;
- int nb_bits;
-};
-
-static int jtag_vpi_send_cmd(struct vpi_cmd *vpi)
-{
- int retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
- if (retval <= 0)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
-{
- int retval = read_socket(sockfd, vpi, sizeof(struct vpi_cmd));
- if (retval < (int)sizeof(struct vpi_cmd))
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-/**
- * jtag_vpi_reset - ask to reset the JTAG device
- * @trst: 1 if TRST is to be asserted
- * @srst: 1 if SRST is to be asserted
- */
-static int jtag_vpi_reset(int trst, int srst)
-{
- struct vpi_cmd vpi;
-
- vpi.cmd = CMD_RESET;
- vpi.length = 0;
- return jtag_vpi_send_cmd(&vpi);
-}
-
-/**
- * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
- * @bits: TMS bits to be written (bit0, bit1 .. bitN)
- * @nb_bits: number of TMS bits (between 1 and 8)
- *
- * Write a serie of TMS transitions, where each transition consists in :
- * - writing out TCK=0, TMS=<new_state>, TDI=<???>
- * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
- * The function ensures that at the end of the sequence, the clock (TCK) is put
- * low.
- */
-static int jtag_vpi_tms_seq(const uint8_t *bits, int nb_bits)
-{
- struct vpi_cmd vpi;
- int nb_bytes;
-
- nb_bytes = DIV_ROUND_UP(nb_bits, 8);
-
- vpi.cmd = CMD_TMS_SEQ;
- memcpy(vpi.buffer_out, bits, nb_bytes);
- vpi.length = nb_bytes;
- vpi.nb_bits = nb_bits;
-
- return jtag_vpi_send_cmd(&vpi);
-}
-
-/**
- * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
- * @cmd: path transition
- *
- * Write a serie of TMS transitions, where each transition consists in :
- * - writing out TCK=0, TMS=<new_state>, TDI=<???>
- * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
- * The function ensures that at the end of the sequence, the clock (TCK) is put
- * low.
- */
-
-static int jtag_vpi_path_move(struct pathmove_command *cmd)
-{
- uint8_t trans[DIV_ROUND_UP(cmd->num_states, 8)];
-
- memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8));
-
- for (int i = 0; i < cmd->num_states; i++) {
- if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
- buf_set_u32(trans, i, 1, 1);
- tap_set_state(cmd->path[i]);
- }
-
- return jtag_vpi_tms_seq(trans, cmd->num_states);
-}
-
-/**
- * jtag_vpi_tms - ask a tms command
- * @cmd: tms command
- */
-static int jtag_vpi_tms(struct tms_command *cmd)
-{
- return jtag_vpi_tms_seq(cmd->bits, cmd->num_bits);
-}
-
-static int jtag_vpi_state_move(tap_state_t state)
-{
- if (tap_get_state() == state)
- return ERROR_OK;
-
- uint8_t tms_scan = tap_get_tms_path(tap_get_state(), state);
- int tms_len = tap_get_tms_path_len(tap_get_state(), state);
-
- int retval = jtag_vpi_tms_seq(&tms_scan, tms_len);
- if (retval != ERROR_OK)
- return retval;
-
- tap_set_state(state);
-
- return ERROR_OK;
-}
-
-static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
-{
- struct vpi_cmd vpi;
- int nb_bytes = DIV_ROUND_UP(nb_bits, 8);
-
- vpi.cmd = tap_shift ? CMD_SCAN_CHAIN_FLIP_TMS : CMD_SCAN_CHAIN;
-
- if (bits)
- memcpy(vpi.buffer_out, bits, nb_bytes);
- else
- memset(vpi.buffer_out, 0xff, nb_bytes);
-
- vpi.length = nb_bytes;
- vpi.nb_bits = nb_bits;
-
- int retval = jtag_vpi_send_cmd(&vpi);
- if (retval != ERROR_OK)
- return retval;
-
- retval = jtag_vpi_receive_cmd(&vpi);
- if (retval != ERROR_OK)
- return retval;
-
- if (bits)
- memcpy(bits, vpi.buffer_in, nb_bytes);
-
- return ERROR_OK;
-}
-
-/**
- * jtag_vpi_queue_tdi - short description
- * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
- * @nb_bits: number of bits
- */
-static int jtag_vpi_queue_tdi(uint8_t *bits, int nb_bits, int tap_shift)
-{
- int nb_xfer = DIV_ROUND_UP(nb_bits, XFERT_MAX_SIZE * 8);
- uint8_t *xmit_buffer = bits;
- int xmit_nb_bits = nb_bits;
- int i = 0;
- int retval;
-
- while (nb_xfer) {
-
- if (nb_xfer == 1) {
- retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], xmit_nb_bits, tap_shift);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], XFERT_MAX_SIZE * 8, NO_TAP_SHIFT);
- if (retval != ERROR_OK)
- return retval;
- xmit_nb_bits -= XFERT_MAX_SIZE * 8;
- i += XFERT_MAX_SIZE;
- }
-
- nb_xfer--;
- }
-
- return ERROR_OK;
-}
-
-/**
- * jtag_vpi_clock_tms - clock a TMS transition
- * @tms: the TMS to be sent
- *
- * Triggers a TMS transition (ie. one JTAG TAP state move).
- */
-static int jtag_vpi_clock_tms(int tms)
-{
- const uint8_t tms_0 = 0;
- const uint8_t tms_1 = 1;
-
- return jtag_vpi_tms_seq(tms ? &tms_1 : &tms_0, 1);
-}
-
-/**
- * jtag_vpi_scan - launches a DR-scan or IR-scan
- * @cmd: the command to launch
- *
- * Launch a JTAG IR-scan or DR-scan
- *
- * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
- */
-static int jtag_vpi_scan(struct scan_command *cmd)
-{
- int scan_bits;
- uint8_t *buf = NULL;
- int retval = ERROR_OK;
-
- scan_bits = jtag_build_buffer(cmd, &buf);
-
- if (cmd->ir_scan) {
- retval = jtag_vpi_state_move(TAP_IRSHIFT);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = jtag_vpi_state_move(TAP_DRSHIFT);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (cmd->end_state == TAP_DRSHIFT) {
- retval = jtag_vpi_queue_tdi(buf, scan_bits, NO_TAP_SHIFT);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = jtag_vpi_queue_tdi(buf, scan_bits, TAP_SHIFT);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (cmd->end_state != TAP_DRSHIFT) {
- /*
- * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
- * forward to a stable IRPAUSE or DRPAUSE.
- */
- retval = jtag_vpi_clock_tms(0);
- if (retval != ERROR_OK)
- return retval;
-
- if (cmd->ir_scan)
- tap_set_state(TAP_IRPAUSE);
- else
- tap_set_state(TAP_DRPAUSE);
- }
-
- retval = jtag_read_buffer(buf, cmd);
- if (retval != ERROR_OK)
- return retval;
-
- if (buf)
- free(buf);
-
- if (cmd->end_state != TAP_DRSHIFT) {
- retval = jtag_vpi_state_move(cmd->end_state);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int jtag_vpi_runtest(int cycles, tap_state_t state)
-{
- int retval;
-
- retval = jtag_vpi_state_move(TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = jtag_vpi_queue_tdi(NULL, cycles, NO_TAP_SHIFT);
- if (retval != ERROR_OK)
- return retval;
-
- return jtag_vpi_state_move(state);
-}
-
-static int jtag_vpi_stableclocks(int cycles)
-{
- return jtag_vpi_queue_tdi(NULL, cycles, TAP_SHIFT);
-}
-
-static int jtag_vpi_execute_queue(void)
-{
- struct jtag_command *cmd;
- int retval = ERROR_OK;
-
- for (cmd = jtag_command_queue; retval == ERROR_OK && cmd != NULL;
- cmd = cmd->next) {
- switch (cmd->type) {
- case JTAG_RESET:
- retval = jtag_vpi_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
- retval = jtag_vpi_runtest(cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
- break;
- case JTAG_STABLECLOCKS:
- retval = jtag_vpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
- break;
- case JTAG_TLR_RESET:
- retval = jtag_vpi_state_move(cmd->cmd.statemove->end_state);
- break;
- case JTAG_PATHMOVE:
- retval = jtag_vpi_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_TMS:
- retval = jtag_vpi_tms(cmd->cmd.tms);
- break;
- case JTAG_SLEEP:
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- case JTAG_SCAN:
- retval = jtag_vpi_scan(cmd->cmd.scan);
- break;
- }
- }
-
- return retval;
-}
-
-static int jtag_vpi_init(void)
-{
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd < 0) {
- LOG_ERROR("Could not create socket");
- return ERROR_FAIL;
- }
-
- memset(&serv_addr, 0, sizeof(serv_addr));
-
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(server_port);
-
- if (!server_address)
- server_address = strdup(SERVER_ADDRESS);
-
- serv_addr.sin_addr.s_addr = inet_addr(server_address);
-
- if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
- LOG_ERROR("inet_addr error occured");
- return ERROR_FAIL;
- }
-
- if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
- close(sockfd);
- LOG_ERROR("Can't connect to %s : %u", server_address, server_port);
- return ERROR_COMMAND_CLOSE_CONNECTION;
- }
-
- LOG_INFO("Connection to %s : %u succeed", server_address, server_port);
-
- return ERROR_OK;
-}
-
-static int jtag_vpi_quit(void)
-{
- free(server_address);
- return close(sockfd);
-}
-
-COMMAND_HANDLER(jtag_vpi_set_port)
-{
- if (CMD_ARGC == 0)
- LOG_WARNING("You need to set a port number");
- else
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port);
-
- LOG_INFO("Set server port to %u", server_port);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(jtag_vpi_set_address)
-{
- free(server_address);
-
- if (CMD_ARGC == 0) {
- LOG_WARNING("You need to set an address");
- server_address = strdup(SERVER_ADDRESS);
- } else
- server_address = strdup(CMD_ARGV[0]);
-
- LOG_INFO("Set server address to %s", server_address);
-
- return ERROR_OK;
-}
-
-static const struct command_registration jtag_vpi_command_handlers[] = {
- {
- .name = "jtag_vpi_set_port",
- .handler = &jtag_vpi_set_port,
- .mode = COMMAND_CONFIG,
- .help = "set the port of the VPI server",
- .usage = "description_string",
- },
- {
- .name = "jtag_vpi_set_address",
- .handler = &jtag_vpi_set_address,
- .mode = COMMAND_CONFIG,
- .help = "set the address of the VPI server",
- .usage = "description_string",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface jtag_vpi_interface = {
- .name = "jtag_vpi",
- .supported = DEBUG_CAP_TMS_SEQ,
- .commands = jtag_vpi_command_handlers,
- .transports = jtag_only,
-
- .init = jtag_vpi_init,
- .quit = jtag_vpi_quit,
- .execute_queue = jtag_vpi_execute_queue,
-};
diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink
deleted file mode 160000
-Subproject d57dee67bc756291b7d8b51d350d1c6213e514f
diff --git a/src/jtag/drivers/libusb0_common.c b/src/jtag/drivers/libusb0_common.c
deleted file mode 100644
index e319751..0000000
--- a/src/jtag/drivers/libusb0_common.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "log.h"
-#include "libusb0_common.h"
-
-static bool jtag_libusb_match(struct jtag_libusb_device *dev,
- const uint16_t vids[], const uint16_t pids[])
-{
- for (unsigned i = 0; vids[i]; i++) {
- if (dev->descriptor.idVendor == vids[i] &&
- dev->descriptor.idProduct == pids[i]) {
- return true;
- }
- }
- return false;
-}
-
-/* Returns true if the string descriptor indexed by str_index in device matches string */
-static bool string_descriptor_equal(usb_dev_handle *device, uint8_t str_index,
- const char *string)
-{
- int retval;
- bool matched;
- char desc_string[256+1]; /* Max size of string descriptor */
-
- if (str_index == 0)
- return false;
-
- retval = usb_get_string_simple(device, str_index,
- desc_string, sizeof(desc_string)-1);
- if (retval < 0) {
- LOG_ERROR("usb_get_string_simple() failed with %d", retval);
- return false;
- }
-
- /* Null terminate descriptor string in case it needs to be logged. */
- desc_string[sizeof(desc_string)-1] = '\0';
-
- matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
- if (!matched)
- LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
- desc_string, string);
- return matched;
-}
-
-int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
- const char *serial,
- struct jtag_libusb_device_handle **out)
-{
- int retval = -ENODEV;
- struct jtag_libusb_device_handle *libusb_handle;
- usb_init();
-
- usb_find_busses();
- usb_find_devices();
-
- struct usb_bus *busses = usb_get_busses();
- for (struct usb_bus *bus = busses; bus; bus = bus->next) {
- for (struct usb_device *dev = bus->devices;
- dev; dev = dev->next) {
- if (!jtag_libusb_match(dev, vids, pids))
- continue;
-
- libusb_handle = usb_open(dev);
- if (NULL == libusb_handle) {
- retval = -errno;
- continue;
- }
-
- /* Device must be open to use libusb_get_string_descriptor_ascii. */
- if (serial != NULL &&
- !string_descriptor_equal(libusb_handle, dev->descriptor.iSerialNumber, serial)) {
- usb_close(libusb_handle);
- continue;
- }
- *out = libusb_handle;
- retval = 0;
- break;
- }
- }
- return retval;
-}
-
-void jtag_libusb_close(jtag_libusb_device_handle *dev)
-{
- /* Close device */
- usb_close(dev);
-}
-
-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 transferred = 0;
-
- transferred = usb_control_msg(dev, requestType, request, wValue, wIndex,
- bytes, size, timeout);
-
- if (transferred < 0)
- transferred = 0;
-
- return transferred;
-}
-
-int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
-{
- return usb_bulk_write(dev, ep, bytes, size, timeout);
-}
-
-int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
-{
- return usb_bulk_read(dev, ep, bytes, size, timeout);
-}
-
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
- int configuration)
-{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
-
- return usb_set_configuration(devh,
- udev->config[configuration].bConfigurationValue);
-}
-
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
- unsigned int *usb_read_ep,
- unsigned int *usb_write_ep,
- int bclass, int subclass, int protocol)
-{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
- struct usb_interface *iface = udev->config->interface;
- struct usb_interface_descriptor *desc = iface->altsetting;
-
- *usb_read_ep = *usb_write_ep = 0;
-
- for (int i = 0; i < desc->bNumEndpoints; i++) {
- if ((bclass > 0 && desc->bInterfaceClass != bclass) ||
- (subclass > 0 && desc->bInterfaceSubClass != subclass) ||
- (protocol > 0 && desc->bInterfaceProtocol != protocol))
- continue;
-
- uint8_t epnum = desc->endpoint[i].bEndpointAddress;
- bool is_input = epnum & 0x80;
- LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
- if (is_input)
- *usb_read_ep = epnum;
- else
- *usb_write_ep = epnum;
-
- if (*usb_read_ep && *usb_write_ep) {
- LOG_DEBUG("Claiming interface %d", (int)desc->bInterfaceNumber);
- usb_claim_interface(devh, (int)desc->bInterfaceNumber);
- return ERROR_OK;
- }
- }
-
- return ERROR_FAIL;
-}
-
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid)
-{
- if (!dev)
- return ERROR_FAIL;
-
- *pid = dev->descriptor.idProduct;
- return ERROR_OK;
-}
diff --git a/src/jtag/drivers/libusb0_common.h b/src/jtag/drivers/libusb0_common.h
deleted file mode 100644
index 7163b43..0000000
--- a/src/jtag/drivers/libusb0_common.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H
-
-#include <usb.h>
-
-#define jtag_libusb_device usb_device
-#define jtag_libusb_device_handle usb_dev_handle
-#define jtag_libusb_device_descriptor usb_device_descriptor
-#define jtag_libusb_interface usb_interface
-#define jtag_libusb_interface_descriptor usb_interface_descriptor
-#define jtag_libusb_endpoint_descriptor usb_endpoint_descriptor
-#define jtag_libusb_config_descriptor usb_config_descriptor
-
-#define jtag_libusb_reset_device(dev) usb_reset(dev)
-#define jtag_libusb_get_device(devh) usb_device(devh)
-
-/* make some defines compatible to libusb1 */
-#define LIBUSB_REQUEST_TYPE_VENDOR USB_TYPE_VENDOR
-#define LIBUSB_RECIPIENT_DEVICE USB_RECIP_DEVICE
-#define LIBUSB_ENDPOINT_OUT USB_ENDPOINT_OUT
-#define LIBUSB_ENDPOINT_IN USB_ENDPOINT_IN
-
-static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return usb_claim_interface(devh, iface);
-};
-
-static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return usb_release_interface(devh, iface);
-}
-
-int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
- const char *serial,
- struct jtag_libusb_device_handle **out);
-void jtag_libusb_close(jtag_libusb_device_handle *dev);
-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);
-int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout);
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
- int configuration);
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
- unsigned int *usb_read_ep,
- unsigned int *usb_write_ep,
- int bclass, int subclass, int protocol);
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
-
-#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */
diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb1_common.c
deleted file mode 100644
index f8b7c75..0000000
--- a/src/jtag/drivers/libusb1_common.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "log.h"
-#include "libusb1_common.h"
-
-static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
-static libusb_device **devs; /**< The usb device list **/
-
-static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
- const uint16_t vids[], const uint16_t pids[])
-{
- for (unsigned i = 0; vids[i]; i++) {
- if (dev_desc->idVendor == vids[i] &&
- dev_desc->idProduct == pids[i]) {
- return true;
- }
- }
- return false;
-}
-
-/* Returns true if the string descriptor indexed by str_index in device matches string */
-static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index,
- const char *string)
-{
- int retval;
- bool matched;
- char desc_string[256+1]; /* Max size of string descriptor */
-
- if (str_index == 0)
- return false;
-
- retval = libusb_get_string_descriptor_ascii(device, str_index,
- (unsigned char *)desc_string, sizeof(desc_string)-1);
- if (retval < 0) {
- LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval);
- return false;
- }
-
- /* Null terminate descriptor string in case it needs to be logged. */
- desc_string[sizeof(desc_string)-1] = '\0';
-
- matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
- if (!matched)
- LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
- desc_string, string);
- return matched;
-}
-
-int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
- const char *serial,
- struct jtag_libusb_device_handle **out)
-{
- int cnt, idx, errCode;
- int retval = -ENODEV;
- struct jtag_libusb_device_handle *libusb_handle = NULL;
-
- if (libusb_init(&jtag_libusb_context) < 0)
- return -ENODEV;
-
- cnt = libusb_get_device_list(jtag_libusb_context, &devs);
-
- for (idx = 0; idx < cnt; idx++) {
- struct libusb_device_descriptor dev_desc;
-
- if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0)
- continue;
-
- if (!jtag_libusb_match(&dev_desc, vids, pids))
- continue;
-
- errCode = libusb_open(devs[idx], &libusb_handle);
-
- if (errCode) {
- LOG_ERROR("libusb_open() failed with %s",
- libusb_error_name(errCode));
- continue;
- }
-
- /* Device must be open to use libusb_get_string_descriptor_ascii. */
- if (serial != NULL &&
- !string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) {
- libusb_close(libusb_handle);
- continue;
- }
-
- /* Success. */
- *out = libusb_handle;
- retval = 0;
- break;
- }
- if (cnt >= 0)
- libusb_free_device_list(devs, 1);
- return retval;
-}
-
-void jtag_libusb_close(jtag_libusb_device_handle *dev)
-{
- /* Close device */
- libusb_close(dev);
-
- libusb_exit(jtag_libusb_context);
-}
-
-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 transferred = 0;
-
- transferred = libusb_control_transfer(dev, requestType, request, wValue, wIndex,
- (unsigned char *)bytes, size, timeout);
-
- if (transferred < 0)
- transferred = 0;
-
- return transferred;
-}
-
-int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
-{
- int transferred = 0;
-
- libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
- &transferred, timeout);
- return transferred;
-}
-
-int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
- int size, int timeout)
-{
- int transferred = 0;
-
- libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
- &transferred, timeout);
- return transferred;
-}
-
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
- int configuration)
-{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
- int retCode = -99;
-
- struct libusb_config_descriptor *config = NULL;
- int current_config = -1;
-
- retCode = libusb_get_configuration(devh, &current_config);
- if (retCode != 0)
- return retCode;
-
- retCode = libusb_get_config_descriptor(udev, configuration, &config);
- if (retCode != 0 || config == NULL)
- return retCode;
-
- /* Only change the configuration if it is not already set to the
- same one. Otherwise this issues a lightweight reset and hangs
- LPC-Link2 with JLink firmware. */
- if (current_config != config->bConfigurationValue)
- retCode = libusb_set_configuration(devh, config->bConfigurationValue);
-
- libusb_free_config_descriptor(config);
-
- return retCode;
-}
-
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
- unsigned int *usb_read_ep,
- unsigned int *usb_write_ep,
- int bclass, int subclass, int protocol)
-{
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
- const struct libusb_interface *inter;
- const struct libusb_interface_descriptor *interdesc;
- const struct libusb_endpoint_descriptor *epdesc;
- struct libusb_config_descriptor *config;
-
- *usb_read_ep = *usb_write_ep = 0;
-
- libusb_get_config_descriptor(udev, 0, &config);
- for (int i = 0; i < (int)config->bNumInterfaces; i++) {
- inter = &config->interface[i];
-
- interdesc = &inter->altsetting[0];
- for (int k = 0;
- k < (int)interdesc->bNumEndpoints; k++) {
- if ((bclass > 0 && interdesc->bInterfaceClass != bclass) ||
- (subclass > 0 && interdesc->bInterfaceSubClass != subclass) ||
- (protocol > 0 && interdesc->bInterfaceProtocol != protocol))
- continue;
-
- epdesc = &interdesc->endpoint[k];
-
- uint8_t epnum = epdesc->bEndpointAddress;
- bool is_input = epnum & 0x80;
- LOG_DEBUG("usb ep %s %02x",
- is_input ? "in" : "out", epnum);
-
- if (is_input)
- *usb_read_ep = epnum;
- else
- *usb_write_ep = epnum;
-
- if (*usb_read_ep && *usb_write_ep) {
- LOG_DEBUG("Claiming interface %d", (int)interdesc->bInterfaceNumber);
- libusb_claim_interface(devh, (int)interdesc->bInterfaceNumber);
- libusb_free_config_descriptor(config);
- return ERROR_OK;
- }
- }
- }
- libusb_free_config_descriptor(config);
-
- return ERROR_FAIL;
-}
-
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid)
-{
- struct libusb_device_descriptor dev_desc;
-
- if (libusb_get_device_descriptor(dev, &dev_desc) == 0) {
- *pid = dev_desc.idProduct;
-
- return ERROR_OK;
- }
-
- return ERROR_FAIL;
-}
diff --git a/src/jtag/drivers/libusb1_common.h b/src/jtag/drivers/libusb1_common.h
deleted file mode 100644
index fc6526a..0000000
--- a/src/jtag/drivers/libusb1_common.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H
-
-#include <libusb.h>
-
-#define jtag_libusb_device libusb_device
-#define jtag_libusb_device_handle libusb_device_handle
-#define jtag_libusb_device_descriptor libusb_device_descriptor
-#define jtag_libusb_interface libusb_interface
-#define jtag_libusb_interface_descriptor libusb_interface_descriptor
-#define jtag_libusb_endpoint_descriptor libusb_endpoint_descriptor
-#define jtag_libusb_config_descriptor libusb_config_descriptor
-
-#define jtag_libusb_reset_device(dev) libusb_reset_device(dev)
-#define jtag_libusb_get_device(devh) libusb_get_device(devh)
-
-static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return libusb_claim_interface(devh, iface);
-};
-
-static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
- int iface)
-{
- return libusb_release_interface(devh, iface);
-}
-
-int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
- const char *serial,
- struct jtag_libusb_device_handle **out);
-void jtag_libusb_close(jtag_libusb_device_handle *dev);
-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);
-int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
- char *bytes, int size, int timeout);
-int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
- int configuration);
-/**
- * Find the first interface optionally matching class, subclass and
- * protocol and claim it.
- * @param devh _libusb_ device handle.
- * @param usb_read_ep A pointer to a variable where the _IN_ endpoint
- * number will be stored.
- * @param usb_write_ep A pointer to a variable where the _OUT_ endpoint
- * number will be stored.
- * @param bclass `bInterfaceClass` to match, or -1 to ignore this field.
- * @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field.
- * @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field.
- * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise.
- */
-int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
- unsigned int *usb_read_ep,
- unsigned int *usb_write_ep,
- int bclass, int subclass, int protocol);
-int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
-
-#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */
diff --git a/src/jtag/drivers/libusb_common.h b/src/jtag/drivers/libusb_common.h
deleted file mode 100644
index 563af10..0000000
--- a/src/jtag/drivers/libusb_common.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
-
-#ifdef HAVE_LIBUSB1
-#include <libusb1_common.h>
-#else
-#include <libusb0_common.h>
-#endif
-
-#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */
diff --git a/src/jtag/drivers/minidriver_imp.h b/src/jtag/drivers/minidriver_imp.h
deleted file mode 100644
index cd59a74..0000000
--- a/src/jtag/drivers/minidriver_imp.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007-2009 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_MINIDRIVER_IMP_H
-#define OPENOCD_JTAG_DRIVERS_MINIDRIVER_IMP_H
-
-#include <jtag/commands.h>
-
-static inline void interface_jtag_add_scan_check_alloc(struct scan_field *field)
-{
- unsigned num_bytes = DIV_ROUND_UP(field->num_bits, 8);
- field->in_value = cmd_queue_alloc(num_bytes);
-}
-
-void interface_jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0);
-
-void interface_jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
- jtag_callback_data_t data1, jtag_callback_data_t data2,
- jtag_callback_data_t data3);
-
-void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
- jtag_callback_data_t data1, jtag_callback_data_t data2,
- jtag_callback_data_t data3);
-
-#endif /* OPENOCD_JTAG_DRIVERS_MINIDRIVER_IMP_H */
diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c
deleted file mode 100644
index 0ef88ba..0000000
--- a/src/jtag/drivers/mpsse.c
+++ /dev/null
@@ -1,930 +0,0 @@
-/**************************************************************************
- * Copyright (C) 2012 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mpsse.h"
-#include "helper/log.h"
-#include <libusb.h>
-
-/* Compatibility define for older libusb-1.0 */
-#ifndef LIBUSB_CALL
-#define LIBUSB_CALL
-#endif
-
-#ifdef _DEBUG_JTAG_IO_
-#define DEBUG_IO(expr...) LOG_DEBUG(expr)
-#define DEBUG_PRINT_BUF(buf, len) \
- do { \
- char buf_string[32 * 3 + 1]; \
- int buf_string_pos = 0; \
- for (int i = 0; i < len; i++) { \
- buf_string_pos += sprintf(buf_string + buf_string_pos, " %02x", buf[i]); \
- if (i % 32 == 32 - 1) { \
- LOG_DEBUG("%s", buf_string); \
- buf_string_pos = 0; \
- } \
- } \
- if (buf_string_pos > 0) \
- LOG_DEBUG("%s", buf_string);\
- } while (0)
-#else
-#define DEBUG_IO(expr...) do {} while (0)
-#define DEBUG_PRINT_BUF(buf, len) do {} while (0)
-#endif
-
-#define FTDI_DEVICE_OUT_REQTYPE (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE)
-#define FTDI_DEVICE_IN_REQTYPE (0x80 | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE)
-
-#define BITMODE_MPSSE 0x02
-
-#define SIO_RESET_REQUEST 0x00
-#define SIO_SET_LATENCY_TIMER_REQUEST 0x09
-#define SIO_GET_LATENCY_TIMER_REQUEST 0x0A
-#define SIO_SET_BITMODE_REQUEST 0x0B
-
-#define SIO_RESET_SIO 0
-#define SIO_RESET_PURGE_RX 1
-#define SIO_RESET_PURGE_TX 2
-
-struct mpsse_ctx {
- libusb_context *usb_ctx;
- libusb_device_handle *usb_dev;
- unsigned int usb_write_timeout;
- unsigned int usb_read_timeout;
- uint8_t in_ep;
- uint8_t out_ep;
- uint16_t max_packet_size;
- uint16_t index;
- uint8_t interface;
- enum ftdi_chip_type type;
- uint8_t *write_buffer;
- unsigned write_size;
- unsigned write_count;
- uint8_t *read_buffer;
- unsigned read_size;
- unsigned read_count;
- uint8_t *read_chunk;
- unsigned read_chunk_size;
- struct bit_copy_queue read_queue;
- int retval;
-};
-
-/* Returns true if the string descriptor indexed by str_index in device matches string */
-static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index,
- const char *string)
-{
- int retval;
- char desc_string[256]; /* Max size of string descriptor */
- retval = libusb_get_string_descriptor_ascii(device, str_index, (unsigned char *)desc_string,
- sizeof(desc_string));
- if (retval < 0) {
- LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %s", libusb_error_name(retval));
- return false;
- }
- return strncmp(string, desc_string, sizeof(desc_string)) == 0;
-}
-
-static bool device_location_equal(libusb_device *device, const char *location)
-{
- bool result = false;
-#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
- char *loc = strdup(location);
- uint8_t port_path[7];
- int path_step, path_len;
- uint8_t dev_bus = libusb_get_bus_number(device);
- char *ptr;
-
- path_len = libusb_get_port_numbers(device, port_path, 7);
- if (path_len == LIBUSB_ERROR_OVERFLOW) {
- LOG_ERROR("cannot determine path to usb device! (more than 7 ports in path)");
- goto done;
- }
-
- LOG_DEBUG("device path has %i steps", path_len);
-
- ptr = strtok(loc, ":");
- if (ptr == NULL) {
- LOG_DEBUG("no ':' in path");
- goto done;
- }
- if (atoi(ptr) != dev_bus) {
- LOG_DEBUG("bus mismatch");
- goto done;
- }
-
- path_step = 0;
- while (path_step < 7) {
- ptr = strtok(NULL, ",");
- if (ptr == NULL) {
- LOG_DEBUG("no more tokens in path at step %i", path_step);
- break;
- }
-
- if (path_step < path_len
- && atoi(ptr) != port_path[path_step]) {
- LOG_DEBUG("path mismatch at step %i", path_step);
- break;
- }
-
- path_step++;
- };
-
- /* walked the full path, all elements match */
- if (path_step == path_len)
- result = true;
-
- done:
- free(loc);
-#endif
- return result;
-}
-
-/* Helper to open a libusb device that matches vid, pid, product string and/or serial string.
- * Set any field to 0 as a wildcard. If the device is found true is returned, with ctx containing
- * the already opened handle. ctx->interface must be set to the desired interface (channel) number
- * prior to calling this function. */
-static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid,
- const char *product, const char *serial, const char *location)
-{
- libusb_device **list;
- struct libusb_device_descriptor desc;
- struct libusb_config_descriptor *config0;
- int err;
- bool found = false;
- ssize_t cnt = libusb_get_device_list(ctx->usb_ctx, &list);
- if (cnt < 0)
- LOG_ERROR("libusb_get_device_list() failed with %s", libusb_error_name(cnt));
-
- for (ssize_t i = 0; i < cnt; i++) {
- libusb_device *device = list[i];
-
- err = libusb_get_device_descriptor(device, &desc);
- if (err != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_get_device_descriptor() failed with %s", libusb_error_name(err));
- continue;
- }
-
- if (vid && *vid != desc.idVendor)
- continue;
- if (pid && *pid != desc.idProduct)
- continue;
-
- err = libusb_open(device, &ctx->usb_dev);
- if (err != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_open() failed with %s",
- libusb_error_name(err));
- continue;
- }
-
- if (location && !device_location_equal(device, location)) {
- libusb_close(ctx->usb_dev);
- continue;
- }
-
- if (product && !string_descriptor_equal(ctx->usb_dev, desc.iProduct, product)) {
- libusb_close(ctx->usb_dev);
- continue;
- }
-
- if (serial && !string_descriptor_equal(ctx->usb_dev, desc.iSerialNumber, serial)) {
- libusb_close(ctx->usb_dev);
- continue;
- }
-
- found = true;
- break;
- }
-
- libusb_free_device_list(list, 1);
-
- if (!found) {
- LOG_ERROR("no device found");
- return false;
- }
-
- err = libusb_get_config_descriptor(libusb_get_device(ctx->usb_dev), 0, &config0);
- if (err != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_get_config_descriptor() failed with %s", libusb_error_name(err));
- libusb_close(ctx->usb_dev);
- return false;
- }
-
- /* Make sure the first configuration is selected */
- int cfg;
- err = libusb_get_configuration(ctx->usb_dev, &cfg);
- if (err != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_get_configuration() failed with %s", libusb_error_name(err));
- goto error;
- }
-
- if (desc.bNumConfigurations > 0 && cfg != config0->bConfigurationValue) {
- err = libusb_set_configuration(ctx->usb_dev, config0->bConfigurationValue);
- if (err != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_set_configuration() failed with %s", libusb_error_name(err));
- goto error;
- }
- }
-
- /* Try to detach ftdi_sio kernel module */
- err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface);
- if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND
- && err != LIBUSB_ERROR_NOT_SUPPORTED) {
- LOG_ERROR("libusb_detach_kernel_driver() failed with %s", libusb_error_name(err));
- goto error;
- }
-
- err = libusb_claim_interface(ctx->usb_dev, ctx->interface);
- if (err != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_claim_interface() failed with %s", libusb_error_name(err));
- goto error;
- }
-
- /* Reset FTDI device */
- err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
- SIO_RESET_REQUEST, SIO_RESET_SIO,
- ctx->index, NULL, 0, ctx->usb_write_timeout);
- if (err < 0) {
- LOG_ERROR("failed to reset FTDI device: %s", libusb_error_name(err));
- goto error;
- }
-
- switch (desc.bcdDevice) {
- case 0x500:
- ctx->type = TYPE_FT2232C;
- break;
- case 0x700:
- ctx->type = TYPE_FT2232H;
- break;
- case 0x800:
- ctx->type = TYPE_FT4232H;
- break;
- case 0x900:
- ctx->type = TYPE_FT232H;
- break;
- default:
- LOG_ERROR("unsupported FTDI chip type: 0x%04x", desc.bcdDevice);
- goto error;
- }
-
- /* Determine maximum packet size and endpoint addresses */
- if (!(desc.bNumConfigurations > 0 && ctx->interface < config0->bNumInterfaces
- && config0->interface[ctx->interface].num_altsetting > 0))
- goto desc_error;
-
- const struct libusb_interface_descriptor *descriptor;
- descriptor = &config0->interface[ctx->interface].altsetting[0];
- if (descriptor->bNumEndpoints != 2)
- goto desc_error;
-
- ctx->in_ep = 0;
- ctx->out_ep = 0;
- for (int i = 0; i < descriptor->bNumEndpoints; i++) {
- if (descriptor->endpoint[i].bEndpointAddress & 0x80) {
- ctx->in_ep = descriptor->endpoint[i].bEndpointAddress;
- ctx->max_packet_size =
- descriptor->endpoint[i].wMaxPacketSize;
- } else {
- ctx->out_ep = descriptor->endpoint[i].bEndpointAddress;
- }
- }
-
- if (ctx->in_ep == 0 || ctx->out_ep == 0)
- goto desc_error;
-
- libusb_free_config_descriptor(config0);
- return true;
-
-desc_error:
- LOG_ERROR("unrecognized USB device descriptor");
-error:
- libusb_free_config_descriptor(config0);
- libusb_close(ctx->usb_dev);
- return false;
-}
-
-struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description,
- const char *serial, const char *location, int channel)
-{
- struct mpsse_ctx *ctx = calloc(1, sizeof(*ctx));
- int err;
-
- if (!ctx)
- return 0;
-
- bit_copy_queue_init(&ctx->read_queue);
- ctx->read_chunk_size = 16384;
- ctx->read_size = 16384;
- ctx->write_size = 16384;
- ctx->read_chunk = malloc(ctx->read_chunk_size);
- ctx->read_buffer = malloc(ctx->read_size);
- ctx->write_buffer = malloc(ctx->write_size);
- if (!ctx->read_chunk || !ctx->read_buffer || !ctx->write_buffer)
- goto error;
-
- ctx->interface = channel;
- ctx->index = channel + 1;
- ctx->usb_read_timeout = 5000;
- ctx->usb_write_timeout = 5000;
-
- err = libusb_init(&ctx->usb_ctx);
- if (err != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_init() failed with %s", libusb_error_name(err));
- goto error;
- }
-
- if (!open_matching_device(ctx, vid, pid, description, serial, location)) {
- /* Four hex digits plus terminating zero each */
- char vidstr[5];
- char pidstr[5];
- LOG_ERROR("unable to open ftdi device with vid %s, pid %s, description '%s', "
- "serial '%s' at bus location '%s'",
- vid ? sprintf(vidstr, "%04x", *vid), vidstr : "*",
- pid ? sprintf(pidstr, "%04x", *pid), pidstr : "*",
- description ? description : "*",
- serial ? serial : "*",
- location ? location : "*");
- ctx->usb_dev = 0;
- goto error;
- }
-
- err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
- SIO_SET_LATENCY_TIMER_REQUEST, 255, ctx->index, NULL, 0,
- ctx->usb_write_timeout);
- if (err < 0) {
- LOG_ERROR("unable to set latency timer: %s", libusb_error_name(err));
- goto error;
- }
-
- err = libusb_control_transfer(ctx->usb_dev,
- FTDI_DEVICE_OUT_REQTYPE,
- SIO_SET_BITMODE_REQUEST,
- 0x0b | (BITMODE_MPSSE << 8),
- ctx->index,
- NULL,
- 0,
- ctx->usb_write_timeout);
- if (err < 0) {
- LOG_ERROR("unable to set MPSSE bitmode: %s", libusb_error_name(err));
- goto error;
- }
-
- mpsse_purge(ctx);
-
- return ctx;
-error:
- mpsse_close(ctx);
- return 0;
-}
-
-void mpsse_close(struct mpsse_ctx *ctx)
-{
- if (ctx->usb_dev)
- libusb_close(ctx->usb_dev);
- if (ctx->usb_ctx)
- libusb_exit(ctx->usb_ctx);
- bit_copy_discard(&ctx->read_queue);
- if (ctx->write_buffer)
- free(ctx->write_buffer);
- if (ctx->read_buffer)
- free(ctx->read_buffer);
- if (ctx->read_chunk)
- free(ctx->read_chunk);
-
- free(ctx);
-}
-
-bool mpsse_is_high_speed(struct mpsse_ctx *ctx)
-{
- return ctx->type != TYPE_FT2232C;
-}
-
-void mpsse_purge(struct mpsse_ctx *ctx)
-{
- int err;
- LOG_DEBUG("-");
- ctx->write_count = 0;
- ctx->read_count = 0;
- ctx->retval = ERROR_OK;
- bit_copy_discard(&ctx->read_queue);
- err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_PURGE_RX, ctx->index, NULL, 0, ctx->usb_write_timeout);
- if (err < 0) {
- LOG_ERROR("unable to purge ftdi rx buffers: %s", libusb_error_name(err));
- return;
- }
-
- err = libusb_control_transfer(ctx->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_PURGE_TX, ctx->index, NULL, 0, ctx->usb_write_timeout);
- if (err < 0) {
- LOG_ERROR("unable to purge ftdi tx buffers: %s", libusb_error_name(err));
- return;
- }
-}
-
-static unsigned buffer_write_space(struct mpsse_ctx *ctx)
-{
- /* Reserve one byte for SEND_IMMEDIATE */
- return ctx->write_size - ctx->write_count - 1;
-}
-
-static unsigned buffer_read_space(struct mpsse_ctx *ctx)
-{
- return ctx->read_size - ctx->read_count;
-}
-
-static void buffer_write_byte(struct mpsse_ctx *ctx, uint8_t data)
-{
- DEBUG_IO("%02x", data);
- assert(ctx->write_count < ctx->write_size);
- ctx->write_buffer[ctx->write_count++] = data;
-}
-
-static unsigned buffer_write(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset,
- unsigned bit_count)
-{
- DEBUG_IO("%d bits", bit_count);
- assert(ctx->write_count + DIV_ROUND_UP(bit_count, 8) <= ctx->write_size);
- bit_copy(ctx->write_buffer + ctx->write_count, 0, out, out_offset, bit_count);
- ctx->write_count += DIV_ROUND_UP(bit_count, 8);
- return bit_count;
-}
-
-static unsigned buffer_add_read(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset,
- unsigned bit_count, unsigned offset)
-{
- DEBUG_IO("%d bits, offset %d", bit_count, offset);
- assert(ctx->read_count + DIV_ROUND_UP(bit_count, 8) <= ctx->read_size);
- bit_copy_queued(&ctx->read_queue, in, in_offset, ctx->read_buffer + ctx->read_count, offset,
- bit_count);
- ctx->read_count += DIV_ROUND_UP(bit_count, 8);
- return bit_count;
-}
-
-void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset,
- unsigned length, uint8_t mode)
-{
- mpsse_clock_data(ctx, out, out_offset, 0, 0, length, mode);
-}
-
-void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length,
- uint8_t mode)
-{
- mpsse_clock_data(ctx, 0, 0, in, in_offset, length, mode);
-}
-
-void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
- unsigned in_offset, unsigned length, uint8_t mode)
-{
- /* TODO: Fix MSB first modes */
- DEBUG_IO("%s%s %d bits", in ? "in" : "", out ? "out" : "", length);
-
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- /* TODO: On H chips, use command 0x8E/0x8F if in and out are both 0 */
- if (out || (!out && !in))
- mode |= 0x10;
- if (in)
- mode |= 0x20;
-
- while (length > 0) {
- /* Guarantee buffer space enough for a minimum size transfer */
- if (buffer_write_space(ctx) + (length < 8) < (out || (!out && !in) ? 4 : 3)
- || (in && buffer_read_space(ctx) < 1))
- ctx->retval = mpsse_flush(ctx);
-
- if (length < 8) {
- /* Transfer remaining bits in bit mode */
- buffer_write_byte(ctx, 0x02 | mode);
- buffer_write_byte(ctx, length - 1);
- if (out)
- out_offset += buffer_write(ctx, out, out_offset, length);
- if (in)
- in_offset += buffer_add_read(ctx, in, in_offset, length, 8 - length);
- if (!out && !in)
- buffer_write_byte(ctx, 0x00);
- length = 0;
- } else {
- /* Byte transfer */
- unsigned this_bytes = length / 8;
- /* MPSSE command limit */
- if (this_bytes > 65536)
- this_bytes = 65536;
- /* Buffer space limit. We already made sure there's space for the minimum
- * transfer. */
- if ((out || (!out && !in)) && this_bytes + 3 > buffer_write_space(ctx))
- this_bytes = buffer_write_space(ctx) - 3;
- if (in && this_bytes > buffer_read_space(ctx))
- this_bytes = buffer_read_space(ctx);
-
- if (this_bytes > 0) {
- buffer_write_byte(ctx, mode);
- buffer_write_byte(ctx, (this_bytes - 1) & 0xff);
- buffer_write_byte(ctx, (this_bytes - 1) >> 8);
- if (out)
- out_offset += buffer_write(ctx,
- out,
- out_offset,
- this_bytes * 8);
- if (in)
- in_offset += buffer_add_read(ctx,
- in,
- in_offset,
- this_bytes * 8,
- 0);
- if (!out && !in)
- for (unsigned n = 0; n < this_bytes; n++)
- buffer_write_byte(ctx, 0x00);
- length -= this_bytes * 8;
- }
- }
- }
-}
-
-void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset,
- unsigned length, bool tdi, uint8_t mode)
-{
- mpsse_clock_tms_cs(ctx, out, out_offset, 0, 0, length, tdi, mode);
-}
-
-void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
- unsigned in_offset, unsigned length, bool tdi, uint8_t mode)
-{
- DEBUG_IO("%sout %d bits, tdi=%d", in ? "in" : "", length, tdi);
- assert(out);
-
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- mode |= 0x42;
- if (in)
- mode |= 0x20;
-
- while (length > 0) {
- /* Guarantee buffer space enough for a minimum size transfer */
- if (buffer_write_space(ctx) < 3 || (in && buffer_read_space(ctx) < 1))
- ctx->retval = mpsse_flush(ctx);
-
- /* Byte transfer */
- unsigned this_bits = length;
- /* MPSSE command limit */
- /* NOTE: there's a report of an FT2232 bug in this area, where shifting
- * exactly 7 bits can make problems with TMS signaling for the last
- * clock cycle:
- *
- * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html
- */
- if (this_bits > 7)
- this_bits = 7;
-
- if (this_bits > 0) {
- buffer_write_byte(ctx, mode);
- buffer_write_byte(ctx, this_bits - 1);
- uint8_t data = 0;
- /* TODO: Fix MSB first, if allowed in MPSSE */
- bit_copy(&data, 0, out, out_offset, this_bits);
- out_offset += this_bits;
- buffer_write_byte(ctx, data | (tdi ? 0x80 : 0x00));
- if (in)
- in_offset += buffer_add_read(ctx,
- in,
- in_offset,
- this_bits,
- 8 - this_bits);
- length -= this_bits;
- }
- }
-}
-
-void mpsse_set_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir)
-{
- DEBUG_IO("-");
-
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- if (buffer_write_space(ctx) < 3)
- ctx->retval = mpsse_flush(ctx);
-
- buffer_write_byte(ctx, 0x80);
- buffer_write_byte(ctx, data);
- buffer_write_byte(ctx, dir);
-}
-
-void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir)
-{
- DEBUG_IO("-");
-
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- if (buffer_write_space(ctx) < 3)
- ctx->retval = mpsse_flush(ctx);
-
- buffer_write_byte(ctx, 0x82);
- buffer_write_byte(ctx, data);
- buffer_write_byte(ctx, dir);
-}
-
-void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data)
-{
- DEBUG_IO("-");
-
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- if (buffer_write_space(ctx) < 1 || buffer_read_space(ctx) < 1)
- ctx->retval = mpsse_flush(ctx);
-
- buffer_write_byte(ctx, 0x81);
- buffer_add_read(ctx, data, 0, 8, 0);
-}
-
-void mpsse_read_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t *data)
-{
- DEBUG_IO("-");
-
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- if (buffer_write_space(ctx) < 1 || buffer_read_space(ctx) < 1)
- ctx->retval = mpsse_flush(ctx);
-
- buffer_write_byte(ctx, 0x83);
- buffer_add_read(ctx, data, 0, 8, 0);
-}
-
-static void single_byte_boolean_helper(struct mpsse_ctx *ctx, bool var, uint8_t val_if_true,
- uint8_t val_if_false)
-{
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- if (buffer_write_space(ctx) < 1)
- ctx->retval = mpsse_flush(ctx);
-
- buffer_write_byte(ctx, var ? val_if_true : val_if_false);
-}
-
-void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable)
-{
- LOG_DEBUG("%s", enable ? "on" : "off");
- single_byte_boolean_helper(ctx, enable, 0x84, 0x85);
-}
-
-void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor)
-{
- LOG_DEBUG("%d", divisor);
-
- if (ctx->retval != ERROR_OK) {
- DEBUG_IO("Ignoring command due to previous error");
- return;
- }
-
- if (buffer_write_space(ctx) < 3)
- ctx->retval = mpsse_flush(ctx);
-
- buffer_write_byte(ctx, 0x86);
- buffer_write_byte(ctx, divisor & 0xff);
- buffer_write_byte(ctx, divisor >> 8);
-}
-
-int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable)
-{
- if (!mpsse_is_high_speed(ctx))
- return ERROR_FAIL;
-
- LOG_DEBUG("%s", enable ? "on" : "off");
- single_byte_boolean_helper(ctx, enable, 0x8b, 0x8a);
-
- return ERROR_OK;
-}
-
-int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable)
-{
- if (!mpsse_is_high_speed(ctx))
- return ERROR_FAIL;
-
- LOG_DEBUG("%s", enable ? "on" : "off");
- single_byte_boolean_helper(ctx, enable, 0x96, 0x97);
-
- return ERROR_OK;
-}
-
-int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency)
-{
- LOG_DEBUG("target %d Hz", frequency);
- assert(frequency >= 0);
- int base_clock;
-
- if (frequency == 0)
- return mpsse_rtck_config(ctx, true);
-
- mpsse_rtck_config(ctx, false); /* just try */
-
- if (frequency > 60000000 / 2 / 65536 && mpsse_divide_by_5_config(ctx, false) == ERROR_OK) {
- base_clock = 60000000;
- } else {
- mpsse_divide_by_5_config(ctx, true); /* just try */
- base_clock = 12000000;
- }
-
- int divisor = (base_clock / 2 + frequency - 1) / frequency - 1;
- if (divisor > 65535)
- divisor = 65535;
- assert(divisor >= 0);
-
- mpsse_set_divisor(ctx, divisor);
-
- frequency = base_clock / 2 / (1 + divisor);
- LOG_DEBUG("actually %d Hz", frequency);
-
- return frequency;
-}
-
-/* Context needed by the callbacks */
-struct transfer_result {
- struct mpsse_ctx *ctx;
- bool done;
- unsigned transferred;
-};
-
-static LIBUSB_CALL void read_cb(struct libusb_transfer *transfer)
-{
- struct transfer_result *res = transfer->user_data;
- struct mpsse_ctx *ctx = res->ctx;
-
- unsigned packet_size = ctx->max_packet_size;
-
- DEBUG_PRINT_BUF(transfer->buffer, transfer->actual_length);
-
- /* Strip the two status bytes sent at the beginning of each USB packet
- * while copying the chunk buffer to the read buffer */
- unsigned num_packets = DIV_ROUND_UP(transfer->actual_length, packet_size);
- unsigned chunk_remains = transfer->actual_length;
- for (unsigned i = 0; i < num_packets && chunk_remains > 2; i++) {
- unsigned this_size = packet_size - 2;
- if (this_size > chunk_remains - 2)
- this_size = chunk_remains - 2;
- if (this_size > ctx->read_count - res->transferred)
- this_size = ctx->read_count - res->transferred;
- memcpy(ctx->read_buffer + res->transferred,
- ctx->read_chunk + packet_size * i + 2,
- this_size);
- res->transferred += this_size;
- chunk_remains -= this_size + 2;
- if (res->transferred == ctx->read_count) {
- res->done = true;
- break;
- }
- }
-
- DEBUG_IO("raw chunk %d, transferred %d of %d", transfer->actual_length, res->transferred,
- ctx->read_count);
-
- if (!res->done)
- if (libusb_submit_transfer(transfer) != LIBUSB_SUCCESS)
- res->done = true;
-}
-
-static LIBUSB_CALL void write_cb(struct libusb_transfer *transfer)
-{
- struct transfer_result *res = transfer->user_data;
- struct mpsse_ctx *ctx = res->ctx;
-
- res->transferred += transfer->actual_length;
-
- DEBUG_IO("transferred %d of %d", res->transferred, ctx->write_count);
-
- DEBUG_PRINT_BUF(transfer->buffer, transfer->actual_length);
-
- if (res->transferred == ctx->write_count)
- res->done = true;
- else {
- transfer->length = ctx->write_count - res->transferred;
- transfer->buffer = ctx->write_buffer + res->transferred;
- if (libusb_submit_transfer(transfer) != LIBUSB_SUCCESS)
- res->done = true;
- }
-}
-
-int mpsse_flush(struct mpsse_ctx *ctx)
-{
- int retval = ctx->retval;
-
- if (retval != ERROR_OK) {
- DEBUG_IO("Ignoring flush due to previous error");
- assert(ctx->write_count == 0 && ctx->read_count == 0);
- ctx->retval = ERROR_OK;
- return retval;
- }
-
- DEBUG_IO("write %d%s, read %d", ctx->write_count, ctx->read_count ? "+1" : "",
- ctx->read_count);
- assert(ctx->write_count > 0 || ctx->read_count == 0); /* No read data without write data */
-
- if (ctx->write_count == 0)
- return retval;
-
- struct libusb_transfer *read_transfer = 0;
- struct transfer_result read_result = { .ctx = ctx, .done = true };
- if (ctx->read_count) {
- buffer_write_byte(ctx, 0x87); /* SEND_IMMEDIATE */
- read_result.done = false;
- /* delay read transaction to ensure the FTDI chip can support us with data
- immediately after processing the MPSSE commands in the write transaction */
- }
-
- struct transfer_result write_result = { .ctx = ctx, .done = false };
- struct libusb_transfer *write_transfer = libusb_alloc_transfer(0);
- libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer,
- ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout);
- retval = libusb_submit_transfer(write_transfer);
-
- if (ctx->read_count) {
- read_transfer = libusb_alloc_transfer(0);
- libusb_fill_bulk_transfer(read_transfer, ctx->usb_dev, ctx->in_ep, ctx->read_chunk,
- ctx->read_chunk_size, read_cb, &read_result,
- ctx->usb_read_timeout);
- retval = libusb_submit_transfer(read_transfer);
- }
-
- /* Polling loop, more or less taken from libftdi */
- while (!write_result.done || !read_result.done) {
- retval = libusb_handle_events(ctx->usb_ctx);
- keep_alive();
- if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) {
- libusb_cancel_transfer(write_transfer);
- if (read_transfer)
- libusb_cancel_transfer(read_transfer);
- while (!write_result.done || !read_result.done)
- if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS)
- break;
- }
- }
-
- if (retval != LIBUSB_SUCCESS) {
- LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval));
- retval = ERROR_FAIL;
- } else if (write_result.transferred < ctx->write_count) {
- LOG_ERROR("ftdi device did not accept all data: %d, tried %d",
- write_result.transferred,
- ctx->write_count);
- retval = ERROR_FAIL;
- } else if (read_result.transferred < ctx->read_count) {
- LOG_ERROR("ftdi device did not return all data: %d, expected %d",
- read_result.transferred,
- ctx->read_count);
- retval = ERROR_FAIL;
- } else if (ctx->read_count) {
- ctx->write_count = 0;
- ctx->read_count = 0;
- bit_copy_execute(&ctx->read_queue);
- retval = ERROR_OK;
- } else {
- ctx->write_count = 0;
- bit_copy_discard(&ctx->read_queue);
- retval = ERROR_OK;
- }
-
- libusb_free_transfer(write_transfer);
- if (read_transfer)
- libusb_free_transfer(read_transfer);
-
- if (retval != ERROR_OK)
- mpsse_purge(ctx);
-
- return retval;
-}
diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h
deleted file mode 100644
index 651eef9..0000000
--- a/src/jtag/drivers/mpsse.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/**************************************************************************
- * Copyright (C) 2012 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_MPSSE_H
-#define OPENOCD_JTAG_DRIVERS_MPSSE_H
-
-#include <stdbool.h>
-#include "helper/binarybuffer.h"
-
-/* Mode flags */
-#define POS_EDGE_OUT 0x00
-#define NEG_EDGE_OUT 0x01
-#define POS_EDGE_IN 0x00
-#define NEG_EDGE_IN 0x04
-#define MSB_FIRST 0x00
-#define LSB_FIRST 0x08
-
-enum ftdi_chip_type {
- TYPE_FT2232C,
- TYPE_FT2232H,
- TYPE_FT4232H,
- TYPE_FT232H,
-};
-
-struct mpsse_ctx;
-
-/* Device handling */
-struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description,
- const char *serial, const char *location, int channel);
-void mpsse_close(struct mpsse_ctx *ctx);
-bool mpsse_is_high_speed(struct mpsse_ctx *ctx);
-
-/* Command queuing. These correspond to the MPSSE commands with the same names, but no need to care
- * about bit/byte transfer or data length limitation. Read data is guaranteed to be available only
- * after the following mpsse_flush(). */
-void mpsse_clock_data_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset,
- unsigned length, uint8_t mode);
-void mpsse_clock_data_in(struct mpsse_ctx *ctx, uint8_t *in, unsigned in_offset, unsigned length,
- uint8_t mode);
-void mpsse_clock_data(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
- unsigned in_offset, unsigned length, uint8_t mode);
-void mpsse_clock_tms_cs_out(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset,
- unsigned length, bool tdi, uint8_t mode);
-void mpsse_clock_tms_cs(struct mpsse_ctx *ctx, const uint8_t *out, unsigned out_offset, uint8_t *in,
- unsigned in_offset, unsigned length, bool tdi, uint8_t mode);
-void mpsse_set_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir);
-void mpsse_set_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t data, uint8_t dir);
-void mpsse_read_data_bits_low_byte(struct mpsse_ctx *ctx, uint8_t *data);
-void mpsse_read_data_bits_high_byte(struct mpsse_ctx *ctx, uint8_t *data);
-void mpsse_loopback_config(struct mpsse_ctx *ctx, bool enable);
-void mpsse_set_divisor(struct mpsse_ctx *ctx, uint16_t divisor);
-int mpsse_divide_by_5_config(struct mpsse_ctx *ctx, bool enable);
-int mpsse_rtck_config(struct mpsse_ctx *ctx, bool enable);
-
-/* Helper to set frequency in Hertz. Returns actual realizable frequency or negative error.
- * Frequency 0 means RTCK. */
-int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency);
-
-/* Queue handling */
-int mpsse_flush(struct mpsse_ctx *ctx);
-void mpsse_purge(struct mpsse_ctx *ctx);
-
-#endif /* OPENOCD_JTAG_DRIVERS_MPSSE_H */
diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c
deleted file mode 100644
index 458df34..0000000
--- a/src/jtag/drivers/opendous.c
+++ /dev/null
@@ -1,825 +0,0 @@
-/***************************************************************************
- * *
- * Copyright (C) 2009 by Cahya Wirawan <cahya@gmx.at> *
- * Based on opendous driver by Vladimir Fonov *
- * *
- * Copyright (C) 2009 by Vladimir Fonov <vladimir.fonov@gmai.com> *
- * Based on J-link driver by Juergen Stuber *
- * *
- * Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
- * based on Dominic Rath's and Benedikt Sauter's usbprog.c *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include "libusb_common.h"
-#include <string.h>
-#include <time.h>
-
-#define OPENDOUS_MAX_VIDS_PIDS 4
-/* define some probes with similar interface */
-struct opendous_probe {
- const char *name;
- uint16_t VID[OPENDOUS_MAX_VIDS_PIDS];
- uint16_t PID[OPENDOUS_MAX_VIDS_PIDS];
- uint8_t READ_EP;
- uint8_t WRITE_EP;
- uint8_t CONTROL_TRANSFER;
- int BUFFERSIZE;
-};
-
-static const struct opendous_probe opendous_probes[] = {
- {"usbprog-jtag", {0x1781, 0}, {0x0C63, 0}, 0x82, 0x02, 0x00, 510 },
- {"opendous", {0x1781, 0x03EB, 0}, {0xC0C0, 0x204F, 0}, 0x81, 0x02, 0x00, 360 },
- {"usbvlab", {0x16C0, 0}, {0x05DC, 0}, 0x81, 0x02, 0x01, 360 },
- {NULL, {0x0000}, {0x0000}, 0x00, 0x00, 0x00, 0 }
-};
-
-#define OPENDOUS_WRITE_ENDPOINT (opendous_probe->WRITE_EP)
-#define OPENDOUS_READ_ENDPOINT (opendous_probe->READ_EP)
-
-static unsigned int opendous_hw_jtag_version = 1;
-
-#define OPENDOUS_USB_TIMEOUT 1000
-
-#define OPENDOUS_USB_BUFFER_SIZE (opendous_probe->BUFFERSIZE)
-#define OPENDOUS_IN_BUFFER_SIZE (OPENDOUS_USB_BUFFER_SIZE)
-#define OPENDOUS_OUT_BUFFER_SIZE (OPENDOUS_USB_BUFFER_SIZE)
-
-/* Global USB buffers */
-static uint8_t *usb_in_buffer;
-static uint8_t *usb_out_buffer;
-
-/* Constants for OPENDOUS command */
-
-#define OPENDOUS_MAX_SPEED 66
-#define OPENDOUS_MAX_TAP_TRANSMIT ((opendous_probe->BUFFERSIZE)-10)
-#define OPENDOUS_MAX_INPUT_DATA (OPENDOUS_MAX_TAP_TRANSMIT*4)
-
-/* TAP */
-#define OPENDOUS_TAP_BUFFER_SIZE 65536
-
-struct pending_scan_result {
- int first; /* First bit position in tdo_buffer to read */
- int length; /* Number of bits to read */
- struct scan_command *command; /* Corresponding scan command */
- uint8_t *buffer;
-};
-
-static int pending_scan_results_length;
-static struct pending_scan_result *pending_scan_results_buffer;
-
-#define MAX_PENDING_SCAN_RESULTS (OPENDOUS_MAX_INPUT_DATA)
-
-/* JTAG usb commands */
-#define JTAG_CMD_TAP_OUTPUT 0x0
-#define JTAG_CMD_SET_TRST 0x1
-#define JTAG_CMD_SET_SRST 0x2
-#define JTAG_CMD_READ_INPUT 0x3
-#define JTAG_CMD_TAP_OUTPUT_EMU 0x4
-#define JTAG_CMD_SET_DELAY 0x5
-#define JTAG_CMD_SET_SRST_TRST 0x6
-#define JTAG_CMD_READ_CONFIG 0x7
-
-/* usbvlab control transfer */
-#define FUNC_START_BOOTLOADER 30
-#define FUNC_WRITE_DATA 0x50
-#define FUNC_READ_DATA 0x51
-
-static char *opendous_type;
-static const struct opendous_probe *opendous_probe;
-
-/* External interface functions */
-static int opendous_execute_queue(void);
-static int opendous_init(void);
-static int opendous_quit(void);
-
-/* Queue command functions */
-static void opendous_end_state(tap_state_t state);
-static void opendous_state_move(void);
-static void opendous_path_move(int num_states, tap_state_t *path);
-static void opendous_runtest(int num_cycles);
-static void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer,
- int scan_size, struct scan_command *command);
-static void opendous_reset(int trst, int srst);
-static void opendous_simple_command(uint8_t command, uint8_t _data);
-static int opendous_get_status(void);
-
-/* opendous tap buffer functions */
-static void opendous_tap_init(void);
-static int opendous_tap_execute(void);
-static void opendous_tap_ensure_space(int scans, int bits);
-static void opendous_tap_append_step(int tms, int tdi);
-static void opendous_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command);
-
-/* opendous lowlevel functions */
-struct opendous_jtag {
- struct jtag_libusb_device_handle *usb_handle;
-};
-
-static struct opendous_jtag *opendous_usb_open(void);
-static void opendous_usb_close(struct opendous_jtag *opendous_jtag);
-static int opendous_usb_message(struct opendous_jtag *opendous_jtag, int out_length, int in_length);
-static int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length);
-static int opendous_usb_read(struct opendous_jtag *opendous_jtag);
-
-/* helper functions */
-int opendous_get_version_info(void);
-
-#ifdef _DEBUG_USB_COMMS_
-static void opendous_debug_buffer(uint8_t *buffer, int length);
-#endif
-
-static struct opendous_jtag *opendous_jtag_handle;
-
-/***************************************************************************/
-/* External interface implementation */
-
-COMMAND_HANDLER(opendous_handle_opendous_type_command)
-{
- if (CMD_ARGC == 0)
- return ERROR_OK;
-
- /* only if the cable name wasn't overwritten by cmdline */
- if (opendous_type == NULL) {
- /* REVISIT first verify that it's listed in cables[] ... */
- opendous_type = strdup(CMD_ARGV[0]);
- }
-
- /* REVISIT it's probably worth returning the current value ... */
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(opendous_handle_opendous_info_command)
-{
- if (opendous_get_version_info() == ERROR_OK) {
- /* attempt to get status */
- opendous_get_status();
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(opendous_handle_opendous_hw_jtag_command)
-{
- switch (CMD_ARGC) {
- case 0:
- command_print(CMD_CTX, "opendous hw jtag %i", opendous_hw_jtag_version);
- break;
-
- case 1: {
- int request_version = atoi(CMD_ARGV[0]);
- switch (request_version) {
- case 2:
- case 3:
- opendous_hw_jtag_version = request_version;
- break;
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- break;
- }
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration opendous_command_handlers[] = {
- {
- .name = "opendous_info",
- .handler = &opendous_handle_opendous_info_command,
- .mode = COMMAND_EXEC,
- .help = "show opendous info",
- },
- {
- .name = "opendous_hw_jtag",
- .handler = &opendous_handle_opendous_hw_jtag_command,
- .mode = COMMAND_EXEC,
- .help = "access opendous HW JTAG command version",
- .usage = "[2|3]",
- },
- {
- .name = "opendous_type",
- .handler = &opendous_handle_opendous_type_command,
- .mode = COMMAND_CONFIG,
- .help = "set opendous type",
- .usage = "[usbvlab|usbprog-jtag|opendous]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface opendous_interface = {
- .name = "opendous",
- .commands = opendous_command_handlers,
- .execute_queue = opendous_execute_queue,
- .init = opendous_init,
- .quit = opendous_quit,
-};
-
-static int opendous_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue;
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
-
- while (cmd != NULL) {
- switch (cmd->type) {
- case JTAG_RUNTEST:
- DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \
- cmd->cmd.runtest->end_state);
-
- if (cmd->cmd.runtest->end_state != -1)
- opendous_end_state(cmd->cmd.runtest->end_state);
- opendous_runtest(cmd->cmd.runtest->num_cycles);
- break;
-
- case JTAG_TLR_RESET:
- DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
-
- if (cmd->cmd.statemove->end_state != -1)
- opendous_end_state(cmd->cmd.statemove->end_state);
- opendous_state_move();
- break;
-
- case JTAG_PATHMOVE:
- DEBUG_JTAG_IO("pathmove: %i states, end in %i", \
- cmd->cmd.pathmove->num_states, \
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-
- opendous_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
- break;
-
- case JTAG_SCAN:
- DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state);
-
- if (cmd->cmd.scan->end_state != -1)
- opendous_end_state(cmd->cmd.scan->end_state);
-
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- DEBUG_JTAG_IO("scan input, length = %d", scan_size);
-
-#ifdef _DEBUG_USB_COMMS_
- opendous_debug_buffer(buffer, (scan_size + 7) / 8);
-#endif
- type = jtag_scan_type(cmd->cmd.scan);
- opendous_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
- break;
-
- case JTAG_RESET:
- DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-
- opendous_tap_execute();
-
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- opendous_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
-
- case JTAG_SLEEP:
- DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us);
- opendous_tap_execute();
- jtag_sleep(cmd->cmd.sleep->us);
- break;
-
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
- cmd = cmd->next;
- }
- return opendous_tap_execute();
-}
-
-static int opendous_init(void)
-{
- int check_cnt;
- const struct opendous_probe *cur_opendous_probe;
-
- cur_opendous_probe = opendous_probes;
-
- if (opendous_type == NULL) {
- opendous_type = strdup("opendous");
- LOG_WARNING("No opendous_type specified, using default 'opendous'");
- }
-
- while (cur_opendous_probe->name) {
- if (strcmp(cur_opendous_probe->name, opendous_type) == 0) {
- opendous_probe = cur_opendous_probe;
- break;
- }
- cur_opendous_probe++;
- }
-
- if (!opendous_probe) {
- LOG_ERROR("No matching cable found for %s", opendous_type);
- return ERROR_JTAG_INIT_FAILED;
- }
-
-
- usb_in_buffer = malloc(opendous_probe->BUFFERSIZE);
- usb_out_buffer = malloc(opendous_probe->BUFFERSIZE);
-
- pending_scan_results_buffer = malloc(
- MAX_PENDING_SCAN_RESULTS * sizeof(*pending_scan_results_buffer));
-
- opendous_jtag_handle = opendous_usb_open();
-
- if (opendous_jtag_handle == 0) {
- LOG_ERROR("Cannot find opendous Interface! Please check connection and permissions.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- check_cnt = 0;
- while (check_cnt < 3) {
- if (opendous_get_version_info() == ERROR_OK) {
- /* attempt to get status */
- opendous_get_status();
- break;
- }
-
- check_cnt++;
- }
-
- LOG_INFO("opendous JTAG Interface ready");
-
- opendous_reset(0, 0);
- opendous_tap_init();
-
- return ERROR_OK;
-}
-
-static int opendous_quit(void)
-{
- opendous_usb_close(opendous_jtag_handle);
-
- if (usb_out_buffer) {
- free(usb_out_buffer);
- usb_out_buffer = NULL;
- }
-
- if (usb_in_buffer) {
- free(usb_in_buffer);
- usb_in_buffer = NULL;
- }
-
- if (pending_scan_results_buffer) {
- free(pending_scan_results_buffer);
- pending_scan_results_buffer = NULL;
- }
-
- if (opendous_type) {
- free(opendous_type);
- opendous_type = NULL;
- }
-
- return ERROR_OK;
-}
-
-/***************************************************************************/
-/* Queue command implementations */
-
-void opendous_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-/* Goes to the end state. */
-void opendous_state_move(void)
-{
- int i;
- int tms = 0;
- uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
- uint8_t tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
-
- for (i = 0; i < tms_scan_bits; i++) {
- tms = (tms_scan >> i) & 1;
- opendous_tap_append_step(tms, 0);
- }
-
- tap_set_state(tap_get_end_state());
-}
-
-void opendous_path_move(int num_states, tap_state_t *path)
-{
- int i;
-
- for (i = 0; i < num_states; i++) {
- if (path[i] == tap_state_transition(tap_get_state(), false))
- opendous_tap_append_step(0, 0);
- else if (path[i] == tap_state_transition(tap_get_state(), true))
- opendous_tap_append_step(1, 0);
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(tap_get_state()), tap_state_name(path[i]));
- exit(-1);
- }
-
- tap_set_state(path[i]);
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-void opendous_runtest(int num_cycles)
-{
- int i;
-
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- opendous_end_state(TAP_IDLE);
- opendous_state_move();
- }
-
- /* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
- opendous_tap_append_step(0, 0);
-
- /* finish in end_state */
- opendous_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- opendous_state_move();
-}
-
-void opendous_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command)
-{
- tap_state_t saved_end_state;
-
- opendous_tap_ensure_space(1, scan_size + 8);
-
- saved_end_state = tap_get_end_state();
-
- /* Move to appropriate scan state */
- opendous_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
-
- if (tap_get_state() != tap_get_end_state())
- opendous_state_move();
-
- opendous_end_state(saved_end_state);
-
- /* Scan */
- opendous_tap_append_scan(scan_size, buffer, command);
-
- /* We are in Exit1, go to Pause */
- opendous_tap_append_step(0, 0);
-
- tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
-
- if (tap_get_state() != tap_get_end_state())
- opendous_state_move();
-}
-
-void opendous_reset(int trst, int srst)
-{
- LOG_DEBUG("trst: %i, srst: %i", trst, srst);
-
- /* Signals are active low */
-#if 0
- if (srst == 0)
- opendous_simple_command(JTAG_CMD_SET_SRST, 1);
- else if (srst == 1)
- opendous_simple_command(JTAG_CMD_SET_SRST, 0);
-
- if (trst == 0)
- opendous_simple_command(JTAG_CMD_SET_TRST, 1);
- else if (trst == 1)
- opendous_simple_command(JTAG_CMD_SET_TRST, 0);
-#endif
-
- srst = srst ? 0 : 1;
- trst = trst ? 0 : 2;
- opendous_simple_command(JTAG_CMD_SET_SRST_TRST, srst | trst);
-}
-
-void opendous_simple_command(uint8_t command, uint8_t _data)
-{
- int result;
-
- DEBUG_JTAG_IO("0x%02x 0x%02x", command, _data);
-
- usb_out_buffer[0] = 2;
- usb_out_buffer[1] = 0;
- usb_out_buffer[2] = command;
- usb_out_buffer[3] = _data;
-
- result = opendous_usb_message(opendous_jtag_handle, 4, 1);
- if (result != 1)
- LOG_ERROR("opendous command 0x%02x failed (%d)", command, result);
-}
-
-int opendous_get_status(void)
-{
- return ERROR_OK;
-}
-
-int opendous_get_version_info(void)
-{
- return ERROR_OK;
-}
-
-/***************************************************************************/
-/* Estick tap functions */
-
-static int tap_length;
-static uint8_t tms_buffer[OPENDOUS_TAP_BUFFER_SIZE];
-static uint8_t tdo_buffer[OPENDOUS_TAP_BUFFER_SIZE];
-
-static int last_tms;
-
-void opendous_tap_init(void)
-{
- tap_length = 0;
- pending_scan_results_length = 0;
-}
-
-void opendous_tap_ensure_space(int scans, int bits)
-{
- int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length;
- int available_bits = OPENDOUS_TAP_BUFFER_SIZE / 2 - tap_length;
-
- if ((scans > available_scans) || (bits > available_bits))
- opendous_tap_execute();
-}
-
-void opendous_tap_append_step(int tms, int tdi)
-{
- last_tms = tms;
- unsigned char _tms = tms ? 1 : 0;
- unsigned char _tdi = tdi ? 1 : 0;
-
- opendous_tap_ensure_space(0, 1);
-
- int tap_index = tap_length / 4;
- int bits = (tap_length % 4) * 2;
-
- if (tap_length < OPENDOUS_TAP_BUFFER_SIZE) {
- if (!bits)
- tms_buffer[tap_index] = 0;
-
- tms_buffer[tap_index] |= (_tdi << bits)|(_tms << (bits + 1)) ;
- tap_length++;
- } else
- LOG_ERROR("opendous_tap_append_step, overflow");
-}
-
-void opendous_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command)
-{
- DEBUG_JTAG_IO("append scan, length = %d", length);
-
- struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length];
- int i;
-
- pending_scan_result->first = tap_length;
- pending_scan_result->length = length;
- pending_scan_result->command = command;
- pending_scan_result->buffer = buffer;
-
- for (i = 0; i < length; i++)
- opendous_tap_append_step((i < length-1 ? 0 : 1), (buffer[i / 8] >> (i % 8)) & 1);
- pending_scan_results_length++;
-}
-
-/* Pad and send a tap sequence to the device, and receive the answer.
- * For the purpose of padding we assume that we are in idle or pause state. */
-int opendous_tap_execute(void)
-{
- int byte_length;
- int i, j;
- int result;
-
-#ifdef _DEBUG_USB_COMMS_
- int byte_length_out;
-#endif
-
- if (tap_length > 0) {
-
- /* memset(tdo_buffer,0,OPENDOUS_TAP_BUFFER_SIZE); */
- /* LOG_INFO("OPENDOUS tap execute %d",tap_length); */
- byte_length = (tap_length + 3) / 4;
-
-#ifdef _DEBUG_USB_COMMS_
- byte_length_out = (tap_length + 7) / 8;
- LOG_DEBUG("opendous is sending %d bytes", byte_length);
-#endif
-
- for (j = 0, i = 0; j < byte_length;) {
-
- int receive;
- int transmit = byte_length - j;
- if (transmit > OPENDOUS_MAX_TAP_TRANSMIT) {
- transmit = OPENDOUS_MAX_TAP_TRANSMIT;
- receive = (OPENDOUS_MAX_TAP_TRANSMIT) / 2;
- usb_out_buffer[2] = JTAG_CMD_TAP_OUTPUT;
- } else {
- usb_out_buffer[2] = JTAG_CMD_TAP_OUTPUT | ((tap_length % 4) << 4);
- receive = (transmit + 1) / 2;
- }
- usb_out_buffer[0] = (transmit + 1) & 0xff;
- usb_out_buffer[1] = ((transmit + 1) >> 8) & 0xff;
-
- memmove(usb_out_buffer + 3, tms_buffer + j, transmit);
- result = opendous_usb_message(opendous_jtag_handle, 3 + transmit, receive);
- if (result != receive) {
- LOG_ERROR("opendous_tap_execute, wrong result %d, expected %d", result, receive);
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- memmove(tdo_buffer + i, usb_in_buffer, receive);
- i += receive;
- j += transmit;
- }
-
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("opendous tap result %d", byte_length_out);
- opendous_debug_buffer(tdo_buffer, byte_length_out);
-#endif
-
- /* LOG_INFO("eStick tap execute %d",tap_length); */
- for (i = 0; i < pending_scan_results_length; i++) {
-
- struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i];
- uint8_t *buffer = pending_scan_result->buffer;
- int length = pending_scan_result->length;
- int first = pending_scan_result->first;
- struct scan_command *command = pending_scan_result->command;
-
- /* Copy to buffer */
- buf_set_buf(tdo_buffer, first, buffer, 0, length);
-
- DEBUG_JTAG_IO("pending scan result, length = %d", length);
-
-#ifdef _DEBUG_USB_COMMS_
- opendous_debug_buffer(buffer, byte_length_out);
-#endif
-
- if (jtag_read_buffer(buffer, command) != ERROR_OK) {
- opendous_tap_init();
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- if (pending_scan_result->buffer != NULL)
- free(pending_scan_result->buffer);
- }
-
- opendous_tap_init();
- }
-
- return ERROR_OK;
-}
-
-/*****************************************************************************/
-/* Estick USB low-level functions */
-
-struct opendous_jtag *opendous_usb_open(void)
-{
- struct opendous_jtag *result;
-
- struct jtag_libusb_device_handle *devh;
- if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh) != ERROR_OK)
- return NULL;
-
- jtag_libusb_set_configuration(devh, 0);
- jtag_libusb_claim_interface(devh, 0);
-
- result = malloc(sizeof(*result));
- result->usb_handle = devh;
- return result;
-}
-
-void opendous_usb_close(struct opendous_jtag *opendous_jtag)
-{
- jtag_libusb_close(opendous_jtag->usb_handle);
- free(opendous_jtag);
-}
-
-/* Send a message and receive the reply. */
-int opendous_usb_message(struct opendous_jtag *opendous_jtag, int out_length, int in_length)
-{
- int result;
-
- result = opendous_usb_write(opendous_jtag, out_length);
- if (result == out_length) {
- result = opendous_usb_read(opendous_jtag);
- if (result == in_length)
- return result;
- else {
- LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result);
- return -1;
- }
- } else {
- LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result);
- return -1;
- }
-}
-
-/* Write data from out_buffer to USB. */
-int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
-{
- int result;
-
- if (out_length > OPENDOUS_OUT_BUFFER_SIZE) {
- LOG_ERROR("opendous_jtag_write illegal out_length=%d (max=%d)", out_length, OPENDOUS_OUT_BUFFER_SIZE);
- return -1;
- }
-
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("USB write begin");
-#endif
- if (opendous_probe->CONTROL_TRANSFER) {
- result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
- 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);
- }
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("USB write end: %d bytes", result);
-#endif
-
- DEBUG_JTAG_IO("opendous_usb_write, out_length = %d, result = %d", out_length, result);
-
-#ifdef _DEBUG_USB_COMMS_
- opendous_debug_buffer(usb_out_buffer, out_length);
-#endif
- return result;
-}
-
-/* Read data from USB into in_buffer. */
-int opendous_usb_read(struct opendous_jtag *opendous_jtag)
-{
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("USB read begin");
-#endif
- int result;
- if (opendous_probe->CONTROL_TRANSFER) {
- result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
- 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);
- }
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("USB read end: %d bytes", result);
-#endif
- DEBUG_JTAG_IO("opendous_usb_read, result = %d", result);
-
-#ifdef _DEBUG_USB_COMMS_
- opendous_debug_buffer(usb_in_buffer, result);
-#endif
- return result;
-}
-
-#ifdef _DEBUG_USB_COMMS_
-#define BYTES_PER_LINE 16
-
-void opendous_debug_buffer(uint8_t *buffer, int length)
-{
- char line[81];
- char s[4];
- int i;
- int j;
-
- for (i = 0; i < length; i += BYTES_PER_LINE) {
- snprintf(line, 5, "%04x", i);
- for (j = i; j < i + BYTES_PER_LINE && j < length; j++) {
- snprintf(s, 4, " %02x", buffer[j]);
- strcat(line, s);
- }
- LOG_DEBUG("%s", line);
- }
-}
-#endif
diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c
deleted file mode 100644
index 157020e..0000000
--- a/src/jtag/drivers/openjtag.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/*******************************************************************************
- * Driver for OpenJTAG Project (www.openjtag.org) *
- * Compatible with libftdi and ftd2xx drivers. *
- * *
- * Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com> *
- * *
- * Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. <corbin.ryan@gmail.com> *
- * Updated to work with OpenOCD v0.7.0. Fixed libftdi read speed issue. *
- * *
- * Based on usb_blaster.c *
- * Copyright (C) 2009 Catalin Patulea *
- * Copyright (C) 2006 Kolja Waschk *
- * *
- * And jlink.c *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/***************************************************************************
- * Version 1.0 Tested on a MCBSTM32 board using a Cortex-M3 (stm32f103x), *
- * GDB and Eclipse under Linux (Ubuntu 10.04) *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include "usb_common.h"
-
-/*
- * OpenJTAG-OpenOCD state conversion
- */
-typedef enum openjtag_tap_state {
- OPENJTAG_TAP_INVALID = -1,
- OPENJTAG_TAP_RESET = 0,
- OPENJTAG_TAP_IDLE = 1,
- OPENJTAG_TAP_SELECT_DR = 2,
- OPENJTAG_TAP_CAPTURE_DR = 3,
- OPENJTAG_TAP_SHIFT_DR = 4,
- OPENJTAG_TAP_EXIT1_DR = 5,
- OPENJTAG_TAP_PAUSE_DR = 6,
- OPENJTAG_TAP_EXIT2_DR = 7,
- OPENJTAG_TAP_UPDATE_DR = 8,
- OPENJTAG_TAP_SELECT_IR = 9,
- OPENJTAG_TAP_CAPURE_IR = 10,
- OPENJTAG_TAP_SHIFT_IR = 11,
- OPENJTAG_TAP_EXIT1_IR = 12,
- OPENJTAG_TAP_PAUSE_IR = 13,
- OPENJTAG_TAP_EXIT2_IR = 14,
- OPENJTAG_TAP_UPDATE_IR = 15,
-} openjtag_tap_state_t;
-
-#if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1)
-#error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI "
- "are mutually exclusive"
-#elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1)
-#error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen"
-#endif
-
-/* OPENJTAG access library includes */
-#if BUILD_OPENJTAG_FTD2XX == 1
-#include <ftd2xx.h>
-#elif BUILD_OPENJTAG_LIBFTDI == 1
-#include <ftdi.h>
-#endif
-
-/* OpenJTAG vid/pid */
-static uint16_t openjtag_vid = 0x0403;
-static uint16_t openjtag_pid = 0x6001;
-
-static char *openjtag_device_desc;
-
-#if BUILD_OPENJTAG_FTD2XX == 1
-static FT_HANDLE ftdih;
-
-#elif BUILD_OPENJTAG_LIBFTDI == 1
-static struct ftdi_context ftdic;
-#endif
-
-#define OPENJTAG_BUFFER_SIZE 504
-#define OPENJTAG_MAX_PENDING_RESULTS 256
-
-struct openjtag_scan_result {
- uint32_t bits; /* Length in bits*/
- struct scan_command *command; /* Corresponding scan command */
- uint8_t *buffer;
-};
-
-/* USB RX/TX buffers */
-static int usb_tx_buf_offs;
-static uint8_t usb_tx_buf[OPENJTAG_BUFFER_SIZE];
-static uint32_t usb_rx_buf_len;
-static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
-
-/* Pending readings */
-static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
-static int openjtag_scan_result_count;
-
-/* Openocd usb handler */
-struct openocd {
- struct usb_dev_handle *usb_handle;
-};
-
-#ifdef _DEBUG_USB_COMMS_
-
-#define DEBUG_TYPE_READ 0
-#define DEBUG_TYPE_WRITE 1
-#define DEBUG_TYPE_OCD_READ 2
-#define DEBUG_TYPE_BUFFER 3
-
-#define LINE_LEN 16
-static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type)
-{
- char line[128];
- char s[4];
- int i;
- int j;
-
- switch (type) {
- case DEBUG_TYPE_READ:
- sprintf(line, "USB READ %d bytes", length);
- break;
- case DEBUG_TYPE_WRITE:
- sprintf(line, "USB WRITE %d bytes", length);
- break;
- case DEBUG_TYPE_OCD_READ:
- sprintf(line, "TO OpenOCD %d bytes", length);
- break;
- case DEBUG_TYPE_BUFFER:
- sprintf(line, "Buffer %d bytes", length);
- break;
- }
-
- LOG_DEBUG("%s", line);
-
- for (i = 0; i < length; i += LINE_LEN) {
- switch (type) {
- case DEBUG_TYPE_READ:
- sprintf(line, "USB READ: %04x", i);
- break;
- case DEBUG_TYPE_WRITE:
- sprintf(line, "USB WRITE: %04x", i);
- break;
- case DEBUG_TYPE_OCD_READ:
- sprintf(line, "TO OpenOCD: %04x", i);
- break;
- case DEBUG_TYPE_BUFFER:
- sprintf(line, "BUFFER: %04x", i);
- break;
- }
-
- for (j = i; j < i + LINE_LEN && j < length; j++) {
- sprintf(s, " %02x", buffer[j]);
- strcat(line, s);
- }
- LOG_DEBUG("%s", line);
- }
-
-}
-
-#endif
-
-static int8_t openjtag_get_tap_state(int8_t state)
-{
-
- switch (state) {
- case TAP_DREXIT2: return OPENJTAG_TAP_EXIT2_DR;
- case TAP_DREXIT1: return OPENJTAG_TAP_EXIT1_DR;
- case TAP_DRSHIFT: return OPENJTAG_TAP_SHIFT_DR;
- case TAP_DRPAUSE: return OPENJTAG_TAP_PAUSE_DR;
- case TAP_IRSELECT: return OPENJTAG_TAP_SELECT_IR;
- case TAP_DRUPDATE: return OPENJTAG_TAP_UPDATE_DR;
- case TAP_DRCAPTURE: return OPENJTAG_TAP_CAPTURE_DR;
- case TAP_DRSELECT: return OPENJTAG_TAP_SELECT_DR;
- case TAP_IREXIT2: return OPENJTAG_TAP_EXIT2_IR;
- case TAP_IREXIT1: return OPENJTAG_TAP_EXIT1_IR;
- case TAP_IRSHIFT: return OPENJTAG_TAP_SHIFT_IR;
- case TAP_IRPAUSE: return OPENJTAG_TAP_PAUSE_IR;
- case TAP_IDLE: return OPENJTAG_TAP_IDLE;
- case TAP_IRUPDATE: return OPENJTAG_TAP_UPDATE_IR;
- case TAP_IRCAPTURE: return OPENJTAG_TAP_CAPURE_IR;
- case TAP_RESET: return OPENJTAG_TAP_RESET;
- case TAP_INVALID:
- default: return OPENJTAG_TAP_INVALID;
- }
-}
-
-static int openjtag_buf_write(
- uint8_t *buf, int size, uint32_t *bytes_written)
-{
-#if BUILD_OPENJTAG_FTD2XX == 1
- FT_STATUS status;
- DWORD dw_bytes_written;
-
-#ifdef _DEBUG_USB_COMMS_
- openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
-#endif
-
- status = FT_Write(ftdih, buf, size, &dw_bytes_written);
- if (status != FT_OK) {
- *bytes_written = dw_bytes_written;
- LOG_ERROR("FT_Write returned: %u", status);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_written = dw_bytes_written;
- return ERROR_OK;
-#elif BUILD_OPENJTAG_LIBFTDI == 1
- int retval;
-#ifdef _DEBUG_USB_COMMS_
- openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
-#endif
-
- retval = ftdi_write_data(&ftdic, buf, size);
- if (retval < 0) {
- *bytes_written = 0;
- LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- *bytes_written += retval;
-
- return ERROR_OK;
-#endif
-}
-
-static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
-{
-
-#if BUILD_OPENJTAG_FTD2XX == 1
- DWORD dw_bytes_read;
- FT_STATUS status;
- int timeout = 50;
-
- *bytes_read = 0;
- while (qty && (*bytes_read < qty) && timeout--) {
-
- status = FT_Read(ftdih, buf + *bytes_read,
- qty - *bytes_read, &dw_bytes_read);
- if (status != FT_OK) {
- *bytes_read = dw_bytes_read;
- LOG_ERROR("FT_Read returned: %u", status);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_read += dw_bytes_read;
- }
-
-#ifdef _DEBUG_USB_COMMS_
- openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
-#endif
-
- return ERROR_OK;
-#elif BUILD_OPENJTAG_LIBFTDI == 1
- int retval;
- int timeout = 5;
-
- *bytes_read = 0;
-
- while ((*bytes_read < qty) && timeout--) {
- retval = ftdi_read_data(&ftdic, buf + *bytes_read,
- qty - *bytes_read);
- if (retval < 0) {
- *bytes_read = 0;
- DEBUG_JTAG_IO("ftdi_read_data: %s",
- ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_read += retval;
- }
-
-#ifdef _DEBUG_USB_COMMS_
- openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
-#endif
-
-#endif
- return ERROR_OK;
-}
-
-static int openjtag_sendcommand(uint8_t cmd)
-{
- uint32_t written;
- return openjtag_buf_write(&cmd, 1, &written);
-}
-
-static int openjtag_speed(int speed)
-{
- int clockcmd;
- switch (speed) {
- case 48000:
- clockcmd = 0x00;
- break;
- case 24000:
- clockcmd = 0x20;
- break;
- case 12000:
- clockcmd = 0x40;
- break;
- case 6000:
- clockcmd = 0x60;
- break;
- case 3000:
- clockcmd = 0x80;
- break;
- case 1500:
- clockcmd = 0xA0;
- break;
- case 750:
- clockcmd = 0xC0;
- break;
- case 375:
- clockcmd = 0xE0;
- break;
- default:
- clockcmd = 0xE0;
- LOG_WARNING("adapter speed not recognized, reverting to 375 kHz");
- break;
- }
- openjtag_sendcommand(clockcmd);
-
- return ERROR_OK;
-}
-
-static int openjtag_init(void)
-{
- uint8_t latency_timer;
-
-#if BUILD_OPENJTAG_FTD2XX == 1
- FT_STATUS status;
-#endif
-
-usb_tx_buf_offs = 0;
-usb_rx_buf_len = 0;
-openjtag_scan_result_count = 0;
-
-#if BUILD_OPENJTAG_FTD2XX == 1
- LOG_DEBUG("'openjtag' interface using FTD2XX");
-#elif BUILD_OPENJTAG_LIBFTDI == 1
- LOG_DEBUG("'openjtag' interface using libftdi");
-#endif
-
-/* Open by device description */
-if (openjtag_device_desc == NULL) {
- LOG_WARNING("no openjtag device description specified, "
- "using default 'Open JTAG Project'");
- openjtag_device_desc = "Open JTAG Project";
-}
-
-#if BUILD_OPENJTAG_FTD2XX == 1
-
-#if IS_WIN32 == 0
- /* Add non-standard Vid/Pid to the linux driver */
- status = FT_SetVIDPID(openjtag_vid, openjtag_pid);
- if (status != FT_OK) {
- LOG_WARNING("couldn't add %4.4x:%4.4x",
- openjtag_vid, openjtag_pid);
- }
-#endif
-
- status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION,
- &ftdih);
- if (status != FT_OK) {
- DWORD num_devices;
-
- LOG_ERROR("unable to open ftdi device: %u", status);
- status = FT_ListDevices(&num_devices, NULL,
- FT_LIST_NUMBER_ONLY);
- if (status == FT_OK) {
- char **desc_array = malloc(sizeof(char *)
- * (num_devices + 1));
- unsigned int i;
-
- for (i = 0; i < num_devices; i++)
- desc_array[i] = malloc(64);
- desc_array[num_devices] = NULL;
-
- status = FT_ListDevices(desc_array, &num_devices,
- FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
-
- if (status == FT_OK) {
- LOG_ERROR("ListDevices: %u\n", num_devices);
- for (i = 0; i < num_devices; i++)
- LOG_ERROR("%i: %s", i, desc_array[i]);
- }
-
- for (i = 0; i < num_devices; i++)
- free(desc_array[i]);
- free(desc_array);
- } else {
- LOG_ERROR("ListDevices: NONE\n");
- }
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_SetLatencyTimer(ftdih, 2);
- if (status != FT_OK) {
- LOG_ERROR("unable to set latency timer: %u", status);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_GetLatencyTimer(ftdih, &latency_timer);
- if (status != FT_OK) {
- LOG_ERROR("unable to get latency timer: %u", status);
- return ERROR_JTAG_INIT_FAILED;
- }
- LOG_DEBUG("current latency timer: %i", latency_timer);
-
- status = FT_SetBitMode(ftdih, 0x00, 0x40);
- if (status != FT_OK) {
- LOG_ERROR("unable to disable bit i/o mode: %u", status);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_SetTimeouts(ftdih, 50, 0);
- if (status != FT_OK) {
- LOG_ERROR("unable to set timeouts: %u", status);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
- if (status != FT_OK) {
- LOG_ERROR("unable to FT_Purge() %u", status);
- return ERROR_JTAG_INIT_FAILED;
- }
-
-#elif BUILD_OPENJTAG_LIBFTDI == 1
- if (ftdi_init(&ftdic) < 0)
- return ERROR_JTAG_INIT_FAILED;
-
- /* context, vendor id, product id, description, serial id */
- if (ftdi_usb_open_desc(&ftdic, openjtag_vid, openjtag_pid, openjtag_device_desc, NULL) < 0) {
- LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_usb_reset(&ftdic) < 0) {
- LOG_ERROR("unable to reset ftdi device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_set_latency_timer(&ftdic, 2) < 0) {
- LOG_ERROR("unable to set latency timer");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) {
- LOG_ERROR("unable to get latency timer");
- return ERROR_JTAG_INIT_FAILED;
- }
- LOG_DEBUG("current latency timer: %u", latency_timer);
-
- ftdi_disable_bitbang(&ftdic);
- /* was (3000000 / 4) with a comment about a bug in libftdi when using high baudrate */
- if (ftdi_set_baudrate(&ftdic, 3000000) < 0) {
- LOG_ERROR("Can't set baud rate to max: %s",
- ftdi_get_error_string(&ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-#endif
-
-#if BUILD_OPENJTAG_FTD2XX == 1
- status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
- if (status != FT_OK)
- return ERROR_JTAG_INIT_FAILED;
-#elif BUILD_OPENJTAG_LIBFTDI == 1
- if (ftdi_usb_purge_buffers(&ftdic) < 0) {
- LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
- return ERROR_JTAG_INIT_FAILED;
- }
-#endif
-
- /* OpenJTAG speed */
- openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/
-
- /* MSB */
- openjtag_sendcommand(0x75);
-
- return ERROR_OK;
-}
-
-static int openjtag_quit(void)
-{
-#if BUILD_OPENJTAG_FTD2XX == 1
- FT_Close(ftdih);
-#elif BUILD_OPENJTAG_LIBFTDI == 1
- ftdi_usb_close(&ftdic);
- ftdi_deinit(&ftdic);
-#endif
-
- return ERROR_OK;
-}
-
-static void openjtag_write_tap_buffer(void)
-{
- uint32_t written;
-
- openjtag_buf_write(usb_tx_buf, usb_tx_buf_offs, &written);
- openjtag_buf_read(usb_rx_buf, usb_tx_buf_offs, &usb_rx_buf_len);
-
- usb_tx_buf_offs = 0;
-}
-
-static int openjtag_execute_tap_queue(void)
-{
- openjtag_write_tap_buffer();
-
- int res_count = 0;
-
- if (openjtag_scan_result_count && usb_rx_buf_len) {
-
- int count;
- int rx_offs = 0;
- int len;
-
- /* for every pending result */
- while (res_count < openjtag_scan_result_count) {
-
- /* get sent bits */
- len = openjtag_scan_result_buffer[res_count].bits;
-
- count = 0;
-
- uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer;
-
- while (len) {
- if (len <= 8) {
- DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X",
- usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len));
- buffer[count] = usb_rx_buf[rx_offs] >> (8 - len);
- len = 0;
- } else {
- buffer[count] = usb_rx_buf[rx_offs];
- len -= 8;
- }
-
- rx_offs++;
- count++;
- }
-
-#ifdef _DEBUG_USB_COMMS_
- openjtag_debug_buffer(buffer,
- DIV_ROUND_UP(openjtag_scan_result_buffer[res_count].bits, 8), DEBUG_TYPE_OCD_READ);
-#endif
- jtag_read_buffer(buffer, openjtag_scan_result_buffer[res_count].command);
-
- if (openjtag_scan_result_buffer[res_count].buffer)
- free(openjtag_scan_result_buffer[res_count].buffer);
-
- res_count++;
- }
- }
-
- openjtag_scan_result_count = 0;
-
- return ERROR_OK;
-}
-
-static void openjtag_add_byte(char buf)
-{
-
- if (usb_tx_buf_offs == OPENJTAG_BUFFER_SIZE) {
- DEBUG_JTAG_IO("Forcing execute_tap_queue");
- DEBUG_JTAG_IO("TX Buff offs=%d", usb_tx_buf_offs);
- openjtag_execute_tap_queue();
- }
-
- usb_tx_buf[usb_tx_buf_offs] = buf;
- usb_tx_buf_offs++;
-}
-
-static void openjtag_add_scan(uint8_t *buffer, int length, struct scan_command *scan_cmd)
-{
-
- /* Ensure space to send long chains */
- /* We add two byte for each eight (or less) bits, one for command, one for data */
- if (usb_tx_buf_offs + (DIV_ROUND_UP(length, 8) * 2) >= OPENJTAG_BUFFER_SIZE) {
- DEBUG_JTAG_IO("Forcing execute_tap_queue from scan");
- DEBUG_JTAG_IO("TX Buff offs=%d len=%d", usb_tx_buf_offs, DIV_ROUND_UP(length, 8) * 2);
- openjtag_execute_tap_queue();
- }
-
- openjtag_scan_result_buffer[openjtag_scan_result_count].bits = length;
- openjtag_scan_result_buffer[openjtag_scan_result_count].command = scan_cmd;
- openjtag_scan_result_buffer[openjtag_scan_result_count].buffer = buffer;
-
- uint8_t command;
- uint8_t bits;
- int count = 0;
- while (length) {
-
- /* write command */
- command = 6;
-
- /* last bits? */
- if (length <= 8) {
- /* tms high */
- command |= (1 << 4);
-
- /* bits to transfer */
- bits = (length - 1);
- command |= bits << 5;
- length = 0;
- } else {
- /* whole byte */
-
- /* bits to transfer */
- bits = 7;
- command |= (7 << 5);
- length -= 8;
- }
-
- openjtag_add_byte(command);
- openjtag_add_byte(buffer[count]);
- count++;
- }
-
- openjtag_scan_result_count++;
-}
-
-static void openjtag_execute_reset(struct jtag_command *cmd)
-{
-
- DEBUG_JTAG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-
- uint8_t buf = 0x00;
-
- if (cmd->cmd.reset->trst) {
- buf = 0x03;
- } else {
- buf |= 0x04;
- buf |= 0x05 << 4;
- }
-
- openjtag_add_byte(buf);
-}
-
-static void openjtag_execute_sleep(struct jtag_command *cmd)
-{
- jtag_sleep(cmd->cmd.sleep->us);
-}
-
-static void openjtag_set_state(uint8_t openocd_state)
-{
- int8_t state = openjtag_get_tap_state(openocd_state);
-
- uint8_t buf = 0;
- buf = 0x01;
- buf |= state << 4;
-
- openjtag_add_byte(buf);
-}
-
-static void openjtag_execute_statemove(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("state move to %i", cmd->cmd.statemove->end_state);
-
- tap_set_end_state(cmd->cmd.statemove->end_state);
-
- openjtag_set_state(cmd->cmd.statemove->end_state);
-
- tap_set_state(tap_get_end_state());
-}
-
-
-static void openjtag_execute_scan(struct jtag_command *cmd)
-{
-
- int scan_size, old_state;
- uint8_t *buffer;
-
- DEBUG_JTAG_IO("scan ends in %s", tap_state_name(cmd->cmd.scan->end_state));
-
- /* get scan info */
- tap_set_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
-
-#ifdef _DEBUG_USB_COMMS_
- openjtag_debug_buffer(buffer, (scan_size + 7) / 8, DEBUG_TYPE_BUFFER);
-#endif
- /* set state */
- old_state = tap_get_end_state();
- openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
- tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
- tap_set_end_state(old_state);
-
- openjtag_add_scan(buffer, scan_size, cmd->cmd.scan);
-
- openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
- tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
-
- if (tap_get_state() != tap_get_end_state()) {
- openjtag_set_state(tap_get_end_state());
- tap_set_state(tap_get_end_state());
- }
-}
-
-static void openjtag_execute_runtest(struct jtag_command *cmd)
-{
-
- tap_state_t end_state = cmd->cmd.runtest->end_state;
- tap_set_end_state(end_state);
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- openjtag_set_state(TAP_IDLE);
- tap_set_state(TAP_IDLE);
- }
-
- if (cmd->cmd.runtest->num_cycles > 16)
- LOG_WARNING("num_cycles > 16 on run test");
-
- uint8_t command;
- command = 7;
- command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
-
- openjtag_add_byte(command);
-
- tap_set_end_state(end_state);
- if (tap_get_end_state() != tap_get_state()) {
- openjtag_set_state(end_state);
- tap_set_state(end_state);
- }
-}
-
-static void openjtag_execute_command(struct jtag_command *cmd)
-{
- DEBUG_JTAG_IO("openjtag_execute_command %i", cmd->type);
- switch (cmd->type) {
- case JTAG_RESET:
- openjtag_execute_reset(cmd);
- break;
- case JTAG_SLEEP:
- openjtag_execute_sleep(cmd);
- break;
- case JTAG_TLR_RESET:
- openjtag_execute_statemove(cmd);
- break;
- case JTAG_SCAN:
- openjtag_execute_scan(cmd);
- break;
- case JTAG_RUNTEST:
- openjtag_execute_runtest(cmd);
- break;
- case JTAG_PATHMOVE:
- /* jlink_execute_pathmove(cmd); break; */
- default:
- LOG_ERROR("BUG: unknown Open JTAG command type encountered");
- exit(-1);
- }
-}
-
-static int openjtag_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue;
-
- while (cmd != NULL) {
- openjtag_execute_command(cmd);
- cmd = cmd->next;
- }
-
- return openjtag_execute_tap_queue();
-}
-
-static int openjtag_speed_div(int speed, int *khz)
-{
- *khz = speed;
-
- return ERROR_OK;
-}
-
-static int openjtag_khz(int khz, int *jtag_speed)
-{
-
- if (khz >= 48000)
- *jtag_speed = 48000;
- else if (khz >= 24000)
- *jtag_speed = 24000;
- else if (khz >= 12000)
- *jtag_speed = 12000;
- else if (khz >= 6000)
- *jtag_speed = 6000;
- else if (khz >= 3000)
- *jtag_speed = 3000;
- else if (khz >= 1500)
- *jtag_speed = 1500;
- else if (khz >= 750)
- *jtag_speed = 750;
- else
- *jtag_speed = 375;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(openjtag_handle_device_desc_command)
-{
- if (CMD_ARGC == 1)
- openjtag_device_desc = strdup(CMD_ARGV[0]);
- else
- LOG_ERROR("require exactly one argument to "
- "openjtag_device_desc <description>");
- return ERROR_OK;
-}
-
-
-static const struct command_registration openjtag_command_handlers[] = {
- {
- .name = "openjtag_device_desc",
- .handler = openjtag_handle_device_desc_command,
- .mode = COMMAND_CONFIG,
- .help = "set the USB device description of the OpenJTAG",
- .usage = "description-string",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface openjtag_interface = {
- .name = "openjtag",
- .commands = openjtag_command_handlers,
-
- .execute_queue = openjtag_execute_queue,
- .speed = openjtag_speed,
- .speed_div = openjtag_speed_div,
- .khz = openjtag_khz,
- .init = openjtag_init,
- .quit = openjtag_quit,
-};
-
-
diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c
deleted file mode 100644
index 5db36a1..0000000
--- a/src/jtag/drivers/osbdm.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by Jan Dakinevich *
- * jan.dakinevich@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <helper/log.h>
-#include <helper/binarybuffer.h>
-#include <helper/command.h>
-#include <jtag/interface.h>
-#include "libusb_common.h"
-
-struct sequence {
- int len;
- void *tms;
- void *tdo;
- const void *tdi;
- struct sequence *next;
-};
-
-struct queue {
- struct sequence *head;
- struct sequence *tail;
-};
-
-static struct sequence *queue_add_tail(struct queue *queue, int len)
-{
- if (len <= 0) {
- LOG_ERROR("BUG: sequences with zero length are not allowed");
- return NULL;
- }
-
- struct sequence *next;
- next = malloc(sizeof(*next));
- if (next) {
- next->tms = calloc(1, DIV_ROUND_UP(len, 8));
- if (next->tms) {
- next->len = len;
- next->tdo = NULL;
- next->tdi = NULL;
- next->next = NULL;
-
- if (!queue->head) {
- /* Queue is empty at the moment */
- queue->head = next;
- } else {
- /* Queue already contains at least one sequence */
- queue->tail->next = next;
- }
-
- queue->tail = next;
- } else {
- free(next);
- next = NULL;
- }
- }
-
- if (!next)
- LOG_ERROR("Not enough memory");
-
- return next;
-}
-
-static void queue_drop_head(struct queue *queue)
-{
- struct sequence *head = queue->head->next; /* New head */
- free(queue->head->tms);
- free(queue->head);
- queue->head = head;
-}
-
-static void queue_free(struct queue *queue)
-{
- if (queue) {
- while (queue->head)
- queue_drop_head(queue);
-
- free(queue);
- }
-}
-
-static struct queue *queue_alloc(void)
-{
- struct queue *queue = malloc(sizeof(*queue));
- if (queue)
- queue->head = NULL;
- else
- LOG_ERROR("Not enough memory");
-
- return queue;
-}
-
-/* Size of usb communication buffer */
-#define OSBDM_USB_BUFSIZE 64
-/* Timeout for USB transfer, ms */
-#define OSBDM_USB_TIMEOUT 1000
-/* Write end point */
-#define OSBDM_USB_EP_WRITE 0x01
-/* Read end point */
-#define OSBDM_USB_EP_READ 0x82
-
-/* Initialize OSBDM device */
-#define OSBDM_CMD_INIT 0x11
-/* Execute special, not-BDM command. But only this
- * command is used for JTAG operation */
-#define OSBDM_CMD_SPECIAL 0x27
-/* Execute JTAG swap (tms/tdi -> tdo) */
-#define OSBDM_CMD_SPECIAL_SWAP 0x05
-/* Reset control */
-#define OSBDM_CMD_SPECIAL_SRST 0x01
-/* Maximum bit-length in one swap */
-#define OSBDM_SWAP_MAX (((OSBDM_USB_BUFSIZE - 6) / 5) * 16)
-
-/* Lists of valid VID/PID pairs
- */
-static const uint16_t osbdm_vid[] = { 0x15a2, 0x15a2, 0x15a2, 0 };
-static const uint16_t osbdm_pid[] = { 0x0042, 0x0058, 0x005e, 0 };
-
-struct osbdm {
- struct jtag_libusb_device_handle *devh; /* USB handle */
- uint8_t buffer[OSBDM_USB_BUFSIZE]; /* Data to send and receive */
- int count; /* Count data to send and to read */
-};
-
-/* osbdm instance
- */
-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);
-
- if (count != osbdm->count) {
- LOG_ERROR("OSBDM communication error: can't write");
- return ERROR_FAIL;
- }
-
- /* Save command code for next checking */
- 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);
-
- /* Now perform basic checks for data sent by BDM device
- */
-
- if (osbdm->count < 0) {
- LOG_ERROR("OSBDM communication error: can't read");
- return ERROR_FAIL;
- }
-
- if (osbdm->count < 2) {
- LOG_ERROR("OSBDM communication error: reply too small");
- return ERROR_FAIL;
- }
-
- if (osbdm->count != osbdm->buffer[1]) {
- LOG_ERROR("OSBDM communication error: reply size mismatch");
- return ERROR_FAIL;
- }
-
- if (cmd_saved != osbdm->buffer[0]) {
- LOG_ERROR("OSBDM communication error: reply command mismatch");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int osbdm_srst(struct osbdm *osbdm, int srst)
-{
- osbdm->count = 0;
- (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
-
- /* Composing request
- */
- osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
- osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SRST; /* Subcommand */
- /* Length in bytes - not used */
- osbdm->buffer[osbdm->count++] = 0;
- osbdm->buffer[osbdm->count++] = 0;
- /* SRST state */
- osbdm->buffer[osbdm->count++] = (srst ? 0 : 0x08);
-
- /* Sending data
- */
- if (osbdm_send_and_recv(osbdm) != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi,
- void *tdo, int length)
-{
- if (length > OSBDM_SWAP_MAX) {
- LOG_ERROR("BUG: bit sequence too long");
- return ERROR_FAIL;
- }
-
- if (length <= 0) {
- LOG_ERROR("BUG: bit sequence equal or less than 0");
- return ERROR_FAIL;
- }
-
- int swap_count = DIV_ROUND_UP(length, 16);
-
- /* cleanup */
- osbdm->count = 0;
- (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
-
- /* Composing request
- */
-
- osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
- osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SWAP; /* Subcommand */
- /* Length in bytes - not used */
- osbdm->buffer[osbdm->count++] = 0;
- osbdm->buffer[osbdm->count++] = 0;
- /* Swap count */
- osbdm->buffer[osbdm->count++] = 0;
- osbdm->buffer[osbdm->count++] = (uint8_t)swap_count;
-
- for (int bit_idx = 0; bit_idx < length; ) {
- /* Bit count in swap */
- int bit_count = length - bit_idx;
- if (bit_count > 16)
- bit_count = 16;
-
- osbdm->buffer[osbdm->count++] = (uint8_t)bit_count;
-
- /* Copying TMS and TDI data to output buffer */
- uint32_t tms_data = buf_get_u32(tms, bit_idx, bit_count);
- uint32_t tdi_data = buf_get_u32(tdi, bit_idx, bit_count);
- osbdm->buffer[osbdm->count++] = (uint8_t)(tdi_data >> 8);
- osbdm->buffer[osbdm->count++] = (uint8_t)tdi_data;
- osbdm->buffer[osbdm->count++] = (uint8_t)(tms_data >> 8);
- osbdm->buffer[osbdm->count++] = (uint8_t)tms_data;
-
- /* Next bit offset */
- bit_idx += bit_count;
- }
-
- assert(osbdm->count <= OSBDM_USB_BUFSIZE);
-
- /* Sending data
- */
- if (osbdm_send_and_recv(osbdm) != ERROR_OK)
- return ERROR_FAIL;
-
- /* Extra check
- */
- if (((osbdm->buffer[2] << 8) | osbdm->buffer[3]) != 2 * swap_count) {
- LOG_ERROR("OSBDM communication error: invalid swap command reply");
- return ERROR_FAIL;
- }
-
- /* Copy TDO responce
- */
- uint8_t *buffer = osbdm->buffer + 4;
- for (int bit_idx = 0; bit_idx < length; ) {
- int bit_count = length - bit_idx;
- if (bit_count > 16)
- bit_count = 16;
-
- /* Prepare data */
- uint32_t tdo_data = 0;
- tdo_data |= (*buffer++) << 8;
- tdo_data |= (*buffer++);
- tdo_data >>= (16 - bit_count);
-
- /* Copy TDO to return */
- buf_set_u32(tdo, bit_idx, bit_count, tdo_data);
-
- bit_idx += bit_count;
- }
-
- return ERROR_OK;
-}
-
-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)];
- uint8_t tdo[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
-
- int seq_back_len = 0;
-
- while (queue->head) {
- (void)memset(tms, 0, sizeof(tms));
- (void)memset(tdi, 0, sizeof(tdi));
- (void)memset(tdo, 0, sizeof(tdo));
-
- int seq_len;
- int swap_len;
- struct sequence *seq;
-
- /* Copy from queue to tms/tdi streams
- */
- seq = queue->head;
- seq_len = seq_back_len;
- swap_len = 0;
-
- while (seq && swap_len != OSBDM_SWAP_MAX) {
- /* Count bit for copy at this iteration.
- * len should fit into remaining space
- * in tms/tdo bitstreams
- */
- int len = seq->len - seq_len;
- if (len > OSBDM_SWAP_MAX - swap_len)
- len = OSBDM_SWAP_MAX - swap_len;
-
- /* Set tms data */
- buf_set_buf(seq->tms, seq_len, tms, swap_len, len);
-
- /* Set tdi data if they exists */
- if (seq->tdi)
- buf_set_buf(seq->tdi, seq_len, tdi, swap_len, len);
-
- swap_len += len;
- seq_len += len;
- if (seq_len == seq->len) {
- seq = seq->next; /* Move to next sequence */
- seq_len = 0;
- }
- }
-
- if (osbdm_swap(osbdm, tms, tdi, tdo, swap_len))
- return ERROR_FAIL;
-
- /* Copy from tdo stream to queue
- */
-
- for (int swap_back_len = 0; swap_back_len < swap_len; ) {
- int len = queue->head->len - seq_back_len;
- if (len > swap_len - swap_back_len)
- len = swap_len - swap_back_len;
-
- if (queue->head->tdo)
- buf_set_buf(tdo, swap_back_len, queue->head->tdo, seq_back_len, len);
-
- swap_back_len += len;
- seq_back_len += len;
- if (seq_back_len == queue->head->len) {
- queue_drop_head(queue);
- seq_back_len = 0;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-/* Basic operation for opening USB device */
-static int osbdm_open(struct osbdm *osbdm)
-{
- (void)memset(osbdm, 0, sizeof(*osbdm));
- if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK)
- return ERROR_FAIL;
-
- if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int osbdm_quit(void)
-{
- jtag_libusb_close(osbdm_context.devh);
- return ERROR_OK;
-}
-
-static int osbdm_add_pathmove(
- struct queue *queue,
- tap_state_t *path,
- int num_states)
-{
- assert(num_states <= 32);
-
- struct sequence *next = queue_add_tail(queue, num_states);
- if (!next) {
- LOG_ERROR("BUG: can't allocate bit sequence");
- return ERROR_FAIL;
- }
-
- uint32_t tms = 0;
- for (int i = 0; i < num_states; i++) {
- if (tap_state_transition(tap_get_state(), 1) == path[i]) {
- tms |= (1 << i);
- } else if (tap_state_transition(tap_get_state(), 0) == path[i]) {
- tms &= ~(1 << i); /* This line not so needed */
- } else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
- tap_state_name(tap_get_state()),
- tap_state_name(path[i]));
- return ERROR_FAIL;
- }
-
- tap_set_state(path[i]);
- }
-
- buf_set_u32(next->tms, 0, num_states, tms);
- tap_set_end_state(tap_get_state());
-
- return ERROR_OK;
-}
-
-static int osbdm_add_statemove(
- struct queue *queue,
- tap_state_t new_state,
- int skip_first)
-{
- int len = 0;
- int tms = 0;
-
- tap_set_end_state(new_state);
- if (tap_get_end_state() == TAP_RESET) {
- /* Ignore current state */
- tms = 0xff;
- len = 5;
- } else if (tap_get_state() != tap_get_end_state()) {
- tms = tap_get_tms_path(tap_get_state(), new_state);
- len = tap_get_tms_path_len(tap_get_state(), new_state);
- }
-
- if (len && skip_first) {
- len--;
- tms >>= 1;
- }
-
- if (len) {
- struct sequence *next = queue_add_tail(queue, len);
- if (!next) {
- LOG_ERROR("BUG: can't allocate bit sequence");
- return ERROR_FAIL;
- }
- buf_set_u32(next->tms, 0, len, tms);
- }
-
- tap_set_state(tap_get_end_state());
- return ERROR_OK;
-}
-
-static int osbdm_add_stableclocks(
- struct queue *queue,
- int count)
-{
- if (!tap_is_state_stable(tap_get_state())) {
- LOG_ERROR("BUG: current state (%s) is not stable",
- tap_state_name(tap_get_state()));
- return ERROR_FAIL;
- }
-
- struct sequence *next = queue_add_tail(queue, count);
- if (!next) {
- LOG_ERROR("BUG: can't allocate bit sequence");
- return ERROR_FAIL;
- }
-
- if (tap_get_state() == TAP_RESET)
- (void)memset(next->tms, 0xff, DIV_ROUND_UP(count, 8));
-
- return ERROR_OK;
-}
-
-static int osbdm_add_tms(
- struct queue *queue,
- const uint8_t *tms,
- int num_bits)
-{
- struct sequence *next = queue_add_tail(queue, num_bits);
- if (!next) {
- LOG_ERROR("BUG: can't allocate bit sequence");
- return ERROR_FAIL;
- }
- buf_set_buf(tms, 0, next->tms, 0, num_bits);
-
- return ERROR_OK;
-}
-
-static int osbdm_add_scan(
- struct queue *queue,
- struct scan_field *fields,
- int num_fields,
- tap_state_t end_state,
- bool ir_scan)
-{
- /* Move to desired shift state */
- if (ir_scan) {
- if (tap_get_state() != TAP_IRSHIFT) {
- if (osbdm_add_statemove(queue, TAP_IRSHIFT, 0) != ERROR_OK)
- return ERROR_FAIL;
- }
- } else {
- if (tap_get_state() != TAP_DRSHIFT) {
- if (osbdm_add_statemove(queue, TAP_DRSHIFT, 0) != ERROR_OK)
- return ERROR_FAIL;
- }
- }
-
- /* Add scan */
- tap_set_end_state(end_state);
- for (int idx = 0; idx < num_fields; idx++) {
- struct sequence *next = queue_add_tail(queue, fields[idx].num_bits);
- if (!next) {
- LOG_ERROR("Can't allocate bit sequence");
- return ERROR_FAIL;
- }
-
- (void)memset(next->tms, 0, DIV_ROUND_UP(fields[idx].num_bits, 8));
- next->tdi = fields[idx].out_value;
- next->tdo = fields[idx].in_value;
- }
-
- /* Move to end state
- */
- if (tap_get_state() != tap_get_end_state()) {
- /* Exit from IRSHIFT/DRSHIFT */
- buf_set_u32(queue->tail->tms, queue->tail->len - 1, 1, 1);
-
- /* Move with skip_first flag */
- if (osbdm_add_statemove(queue, tap_get_end_state(), 1) != ERROR_OK)
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int osbdm_add_runtest(
- struct queue *queue,
- int num_cycles,
- tap_state_t end_state)
-{
- if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK)
- return ERROR_FAIL;
-
- if (osbdm_add_stableclocks(queue, num_cycles) != ERROR_OK)
- return ERROR_FAIL;
-
- if (osbdm_add_statemove(queue, end_state, 0) != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int osbdm_execute_command(
- struct osbdm *osbdm,
- struct queue *queue,
- struct jtag_command *cmd)
-{
- int retval = ERROR_OK;
-
- switch (cmd->type) {
- case JTAG_RESET:
- if (cmd->cmd.reset->trst) {
- LOG_ERROR("BUG: nTRST signal is not supported");
- retval = ERROR_FAIL;
- } else {
- retval = osbdm_flush(osbdm, queue);
- if (retval == ERROR_OK)
- retval = osbdm_srst(osbdm, cmd->cmd.reset->srst);
- }
- break;
-
- case JTAG_PATHMOVE:
- retval = osbdm_add_pathmove(
- queue,
- cmd->cmd.pathmove->path,
- cmd->cmd.pathmove->num_states);
- break;
-
- case JTAG_TLR_RESET:
- retval = osbdm_add_statemove(
- queue,
- cmd->cmd.statemove->end_state,
- 0);
- break;
-
- case JTAG_STABLECLOCKS:
- retval = osbdm_add_stableclocks(
- queue,
- cmd->cmd.stableclocks->num_cycles);
- break;
-
- case JTAG_TMS:
- retval = osbdm_add_tms(
- queue,
- cmd->cmd.tms->bits,
- cmd->cmd.tms->num_bits);
- break;
-
- case JTAG_SCAN:
- retval = osbdm_add_scan(
- queue,
- cmd->cmd.scan->fields,
- cmd->cmd.scan->num_fields,
- cmd->cmd.scan->end_state,
- cmd->cmd.scan->ir_scan);
- break;
-
- case JTAG_SLEEP:
- retval = osbdm_flush(osbdm, queue);
- if (retval == ERROR_OK)
- jtag_sleep(cmd->cmd.sleep->us);
- break;
-
- case JTAG_RUNTEST:
- retval = osbdm_add_runtest(
- queue,
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
- break;
-
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- retval = ERROR_FAIL;
- break;
- }
-
- return retval;
-}
-
-static int osbdm_execute_queue(void)
-{
- int retval = ERROR_OK;
-
- struct queue *queue = queue_alloc();
- if (!queue) {
- LOG_ERROR("BUG: can't allocate bit queue");
- retval = ERROR_FAIL;
- } else {
- struct jtag_command *cmd = jtag_command_queue;
-
- while (retval == ERROR_OK && cmd) {
- retval = osbdm_execute_command(&osbdm_context, queue, cmd);
- cmd = cmd->next;
- }
-
- if (retval == ERROR_OK)
- retval = osbdm_flush(&osbdm_context, queue);
-
- queue_free(queue);
- }
-
- if (retval != ERROR_OK) {
- LOG_ERROR("FATAL: can't execute jtag command");
- exit(-1);
- }
-
- return retval;
-}
-
-static int osbdm_init(void)
-{
- /* Open device */
- if (osbdm_open(&osbdm_context) != ERROR_OK) {
- LOG_ERROR("Can't open OSBDM device");
- return ERROR_FAIL;
- } else {
- /* Device successfully opened */
- LOG_DEBUG("OSBDM init");
- }
-
- /* Perform initialize command */
- osbdm_context.count = 0;
- osbdm_context.buffer[osbdm_context.count++] = OSBDM_CMD_INIT;
- if (osbdm_send_and_recv(&osbdm_context) != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-struct jtag_interface osbdm_interface = {
- .name = "osbdm",
-
- .transports = jtag_only,
- .execute_queue = osbdm_execute_queue,
-
- .init = osbdm_init,
- .quit = osbdm_quit
-};
diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c
deleted file mode 100644
index c9e3316..0000000
--- a/src/jtag/drivers/parport.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include "bitbang.h"
-
-/* -ino: 060521-1036 */
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <machine/sysarch.h>
-#include <machine/cpufunc.h>
-#define ioperm(startport, length, enable)\
- i386_set_ioperm((startport), (length), (enable))
-#endif /* __FreeBSD__ */
-
-#if PARPORT_USE_PPDEV == 1
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <dev/ppbus/ppi.h>
-#include <dev/ppbus/ppbconf.h>
-#define PPRSTATUS PPIGSTATUS
-#define PPWDATA PPISDATA
-#else
-#include <linux/parport.h>
-#include <linux/ppdev.h>
-#endif
-#include <sys/ioctl.h>
-#else /* not PARPORT_USE_PPDEV */
-#ifndef _WIN32
-#include <sys/io.h>
-#endif
-#endif
-
-#if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
-#include <windows.h>
-#endif
-
-/* parallel port cable description
- */
-struct cable {
- const char *name;
- uint8_t TDO_MASK; /* status port bit containing current TDO value */
- uint8_t TRST_MASK; /* data port bit for TRST */
- uint8_t TMS_MASK; /* data port bit for TMS */
- uint8_t TCK_MASK; /* data port bit for TCK */
- uint8_t TDI_MASK; /* data port bit for TDI */
- uint8_t SRST_MASK; /* data port bit for SRST */
- uint8_t OUTPUT_INVERT; /* data port bits that should be inverted */
- uint8_t INPUT_INVERT; /* status port that should be inverted */
- uint8_t PORT_INIT; /* initialize data port with this value */
- uint8_t PORT_EXIT; /* de-initialize data port with this value */
- uint8_t LED_MASK; /* data port bit for LED */
-};
-
-static const struct cable cables[] = {
- /* name tdo trst tms tck tdi srst o_inv i_inv init exit led */
- { "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 },
- { "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 },
- { "wiggler_ntrst_inverted", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
- { "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
- { "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 },
- { "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
- { "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 },
- { "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
- { "lattice", 0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00 },
- { "flashlink", 0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00, 0x00, 0x00 },
-/* Altium Universal JTAG cable. Set the cable to Xilinx Mode and wire to target as follows:
- HARD TCK - Target TCK
- HARD TMS - Target TMS
- HARD TDI - Target TDI
- HARD TDO - Target TDO
- SOFT TCK - Target TRST
- SOFT TDI - Target SRST
-*/
- { "altium", 0x10, 0x20, 0x04, 0x02, 0x01, 0x80, 0x00, 0x00, 0x10, 0x00, 0x08 },
- { "aspo", 0x10, 0x01, 0x04, 0x08, 0x02, 0x10, 0x17, 0x00, 0x17, 0x17, 0x00 },
- { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
-
-/* configuration */
-static char *parport_cable;
-static uint16_t parport_port;
-static bool parport_exit;
-static uint32_t parport_toggling_time_ns = 1000;
-static int wait_states;
-
-/* interface variables
- */
-static const struct cable *cable;
-static uint8_t dataport_value;
-
-#if PARPORT_USE_PPDEV == 1
-static int device_handle;
-#else
-static unsigned long dataport;
-static unsigned long statusport;
-#endif
-
-static int parport_read(void)
-{
- int data = 0;
-
-#if PARPORT_USE_PPDEV == 1
- ioctl(device_handle, PPRSTATUS, &data);
-#else
- data = inb(statusport);
-#endif
-
- if ((data ^ cable->INPUT_INVERT) & cable->TDO_MASK)
- return 1;
- else
- return 0;
-}
-
-static inline void parport_write_data(void)
-{
- uint8_t output;
- output = dataport_value ^ cable->OUTPUT_INVERT;
-
-#if PARPORT_USE_PPDEV == 1
- ioctl(device_handle, PPWDATA, &output);
-#else
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- outb(dataport, output);
-#else
- outb(output, dataport);
-#endif
-#endif
-}
-
-static void parport_write(int tck, int tms, int tdi)
-{
- int i = wait_states + 1;
-
- if (tck)
- dataport_value |= cable->TCK_MASK;
- else
- dataport_value &= ~cable->TCK_MASK;
-
- if (tms)
- dataport_value |= cable->TMS_MASK;
- else
- dataport_value &= ~cable->TMS_MASK;
-
- if (tdi)
- dataport_value |= cable->TDI_MASK;
- else
- dataport_value &= ~cable->TDI_MASK;
-
- while (i-- > 0)
- parport_write_data();
-}
-
-/* (1) assert or (0) deassert reset lines */
-static void parport_reset(int trst, int srst)
-{
- LOG_DEBUG("trst: %i, srst: %i", trst, srst);
-
- if (trst == 0)
- dataport_value |= cable->TRST_MASK;
- else if (trst == 1)
- dataport_value &= ~cable->TRST_MASK;
-
- if (srst == 0)
- dataport_value |= cable->SRST_MASK;
- else if (srst == 1)
- dataport_value &= ~cable->SRST_MASK;
-
- parport_write_data();
-}
-
-/* turn LED on parport adapter on (1) or off (0) */
-static void parport_led(int on)
-{
- if (on)
- dataport_value |= cable->LED_MASK;
- else
- dataport_value &= ~cable->LED_MASK;
-
- parport_write_data();
-}
-
-static int parport_speed(int speed)
-{
- wait_states = speed;
- return ERROR_OK;
-}
-
-static int parport_khz(int khz, int *jtag_speed)
-{
- if (khz == 0) {
- LOG_DEBUG("RCLK not supported");
- return ERROR_FAIL;
- }
-
- *jtag_speed = 499999 / (khz * parport_toggling_time_ns);
- return ERROR_OK;
-}
-
-static int parport_speed_div(int speed, int *khz)
-{
- uint32_t denominator = (speed + 1) * parport_toggling_time_ns;
-
- *khz = (499999 + denominator) / denominator;
- return ERROR_OK;
-}
-
-#if PARPORT_USE_GIVEIO == 1
-static int parport_get_giveio_access(void)
-{
- HANDLE h;
- OSVERSIONINFO version;
-
- version.dwOSVersionInfoSize = sizeof version;
- if (!GetVersionEx(&version)) {
- errno = EINVAL;
- return -1;
- }
- if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
- return 0;
-
- h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (h == INVALID_HANDLE_VALUE) {
- errno = ENODEV;
- return -1;
- }
-
- CloseHandle(h);
-
- return 0;
-}
-#endif
-
-static struct bitbang_interface parport_bitbang = {
- .read = &parport_read,
- .write = &parport_write,
- .reset = &parport_reset,
- .blink = &parport_led,
- };
-
-static int parport_init(void)
-{
- const struct cable *cur_cable;
-#if PARPORT_USE_PPDEV == 1
- char buffer[256];
-#endif
-
- cur_cable = cables;
-
- if (parport_cable == NULL) {
- parport_cable = strdup("wiggler");
- LOG_WARNING("No parport cable specified, using default 'wiggler'");
- }
-
- while (cur_cable->name) {
- if (strcmp(cur_cable->name, parport_cable) == 0) {
- cable = cur_cable;
- break;
- }
- cur_cable++;
- }
-
- if (!cable) {
- LOG_ERROR("No matching cable found for %s", parport_cable);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- dataport_value = cable->PORT_INIT;
-
-#if PARPORT_USE_PPDEV == 1
- if (device_handle > 0) {
- LOG_ERROR("device is already opened");
- return ERROR_JTAG_INIT_FAILED;
- }
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- LOG_DEBUG("opening /dev/ppi%d...", parport_port);
-
- snprintf(buffer, 256, "/dev/ppi%d", parport_port);
- device_handle = open(buffer, O_WRONLY);
-#else /* not __FreeBSD__, __FreeBSD_kernel__ */
- LOG_DEBUG("opening /dev/parport%d...", parport_port);
-
- snprintf(buffer, 256, "/dev/parport%d", parport_port);
- device_handle = open(buffer, O_WRONLY);
-#endif /* __FreeBSD__, __FreeBSD_kernel__ */
-
- if (device_handle < 0) {
- int err = errno;
- LOG_ERROR("cannot open device. check it exists and that user read and write rights are set. errno=%d", err);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- LOG_DEBUG("...open");
-
-#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
- int i = ioctl(device_handle, PPCLAIM);
-
- if (i < 0) {
- LOG_ERROR("cannot claim device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- i = PARPORT_MODE_COMPAT;
- i = ioctl(device_handle, PPSETMODE, &i);
- if (i < 0) {
- LOG_ERROR(" cannot set compatible mode to device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- i = IEEE1284_MODE_COMPAT;
- i = ioctl(device_handle, PPNEGOT, &i);
- if (i < 0) {
- LOG_ERROR("cannot set compatible 1284 mode to device");
- return ERROR_JTAG_INIT_FAILED;
- }
-#endif /* not __FreeBSD__, __FreeBSD_kernel__ */
-
-#else /* not PARPORT_USE_PPDEV */
- if (parport_port == 0) {
- parport_port = 0x378;
- LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
- }
-
- dataport = parport_port;
- statusport = parport_port + 1;
-
- LOG_DEBUG("requesting privileges for parallel port 0x%lx...", dataport);
-#if PARPORT_USE_GIVEIO == 1
- if (parport_get_giveio_access() != 0) {
-#else /* PARPORT_USE_GIVEIO */
- if (ioperm(dataport, 3, 1) != 0) {
-#endif /* PARPORT_USE_GIVEIO */
- LOG_ERROR("missing privileges for direct i/o");
- return ERROR_JTAG_INIT_FAILED;
- }
- LOG_DEBUG("...privileges granted");
-
- /* make sure parallel port is in right mode (clear tristate and interrupt */
- #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- outb(parport_port + 2, 0x0);
- #else
- outb(0x0, parport_port + 2);
- #endif
-
-#endif /* PARPORT_USE_PPDEV */
-
- parport_reset(0, 0);
- parport_write(0, 0, 0);
- parport_led(1);
-
- bitbang_interface = &parport_bitbang;
-
- return ERROR_OK;
-}
-
-static int parport_quit(void)
-{
- parport_led(0);
-
- if (parport_exit) {
- dataport_value = cable->PORT_EXIT;
- parport_write_data();
- }
-
- if (parport_cable) {
- free(parport_cable);
- parport_cable = NULL;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(parport_handle_parport_port_command)
-{
- if (CMD_ARGC == 1) {
- /* only if the port wasn't overwritten by cmdline */
- if (parport_port == 0)
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], parport_port);
- else {
- LOG_ERROR("The parport port was already configured!");
- return ERROR_FAIL;
- }
- }
-
- command_print(CMD_CTX, "parport port = 0x%" PRIx16 "", parport_port);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(parport_handle_parport_cable_command)
-{
- if (CMD_ARGC == 0)
- return ERROR_OK;
-
- /* only if the cable name wasn't overwritten by cmdline */
- if (parport_cable == 0) {
- /* REVISIT first verify that it's listed in cables[] ... */
- parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
- strcpy(parport_cable, CMD_ARGV[0]);
- }
-
- /* REVISIT it's probably worth returning the current value ... */
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(parport_handle_write_on_exit_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_ON_OFF(CMD_ARGV[0], parport_exit);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(parport_handle_parport_toggling_time_command)
-{
- if (CMD_ARGC == 1) {
- uint32_t ns;
- int retval = parse_u32(CMD_ARGV[0], &ns);
-
- if (ERROR_OK != retval)
- return retval;
-
- if (ns == 0) {
- LOG_ERROR("0 ns is not a valid parport toggling time");
- return ERROR_FAIL;
- }
-
- parport_toggling_time_ns = ns;
- retval = jtag_get_speed(&wait_states);
- if (retval != ERROR_OK) {
- /* if jtag_get_speed fails then the clock_mode
- * has not been configured, this happens if parport_toggling_time is
- * called before the adapter speed is set */
- LOG_INFO("no parport speed set - defaulting to zero wait states");
- wait_states = 0;
- }
- }
-
- command_print(CMD_CTX, "parport toggling time = %" PRIu32 " ns",
- parport_toggling_time_ns);
-
- return ERROR_OK;
-}
-
-static const struct command_registration parport_command_handlers[] = {
- {
- .name = "parport_port",
- .handler = parport_handle_parport_port_command,
- .mode = COMMAND_CONFIG,
- .help = "Display the address of the I/O port (e.g. 0x378) "
- "or the number of the '/dev/parport' device used. "
- "If a parameter is provided, first change that port.",
- .usage = "[port_number]",
- },
- {
- .name = "parport_cable",
- .handler = parport_handle_parport_cable_command,
- .mode = COMMAND_CONFIG,
- .help = "Set the layout of the parallel port cable "
- "used to connect to the target.",
- /* REVISIT there's no way to list layouts we know ... */
- .usage = "[layout]",
- },
- {
- .name = "parport_write_on_exit",
- .handler = parport_handle_write_on_exit_command,
- .mode = COMMAND_CONFIG,
- .help = "Configure the parallel driver to write "
- "a known value to the parallel interface on exit.",
- .usage = "('on'|'off')",
- },
- {
- .name = "parport_toggling_time",
- .handler = parport_handle_parport_toggling_time_command,
- .mode = COMMAND_CONFIG,
- .help = "Displays or assigns how many nanoseconds it "
- "takes for the hardware to toggle TCK.",
- .usage = "[nanoseconds]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface parport_interface = {
- .name = "parport",
- .supported = DEBUG_CAP_TMS_SEQ,
- .commands = parport_command_handlers,
-
- .init = parport_init,
- .quit = parport_quit,
- .khz = parport_khz,
- .speed_div = parport_speed_div,
- .speed = parport_speed,
- .execute_queue = bitbang_execute_queue,
-};
diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c
deleted file mode 100644
index 0a18dc9..0000000
--- a/src/jtag/drivers/presto.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Pavel Chromy *
- * chromy@asix.cz *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/**
- * @file
- * Holds driver for PRESTO programmer from ASIX.
- * http://tools.asix.net/prg_presto.htm
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if IS_CYGWIN == 1
-#include "windows.h"
-#endif
-
-#include <jtag/interface.h>
-#include <helper/time_support.h>
-#include "bitq.h"
-
-/* PRESTO access library includes */
-#if BUILD_PRESTO_FTD2XX == 1
-#include <ftd2xx.h>
-#include "ftd2xx_common.h"
-#elif BUILD_PRESTO_LIBFTDI == 1
-#include <ftdi.h>
-#else
-#error "BUG: either FTD2XX and LIBFTDI has to be used"
-#endif
-
-/* -------------------------------------------------------------------------- */
-
-#define FT_DEVICE_NAME_LEN 64
-#define FT_DEVICE_SERNUM_LEN 64
-
-#define PRESTO_VID_PID 0x0403f1a0
-#define PRESTO_VID (0x0403)
-#define PRESTO_PID (0xf1a0)
-
-#define BUFFER_SIZE (64*62)
-
-struct presto {
-#if BUILD_PRESTO_FTD2XX == 1
- FT_HANDLE handle;
- FT_STATUS status;
-#elif BUILD_PRESTO_LIBFTDI == 1
- struct ftdi_context ftdic;
- int retval;
-#endif
-
- char serial[FT_DEVICE_SERNUM_LEN];
-
- uint8_t buff_out[BUFFER_SIZE];
- int buff_out_pos;
-
- uint8_t buff_in[BUFFER_SIZE];
- int buff_in_exp;/* expected in buffer length */
- int buff_in_len;/* length of data received */
- int buff_in_pos;
-
- unsigned long total_out;
- unsigned long total_in;
-
- int jtag_tms; /* last tms state */
- int jtag_tck; /* last tck state */
- int jtag_rst; /* last trst state */
-
- int jtag_tdi_data;
- int jtag_tdi_count;
-
- int jtag_speed;
-};
-
-static struct presto presto_state;
-static struct presto *presto = &presto_state;
-
-static uint8_t presto_init_seq[] = {
- 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
-};
-
-static int presto_write(uint8_t *buf, uint32_t size)
-{
-#if BUILD_PRESTO_FTD2XX == 1
- DWORD ftbytes;
- presto->status = FT_Write(presto->handle, buf, size, &ftbytes);
- if (presto->status != FT_OK) {
- LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
-#elif BUILD_PRESTO_LIBFTDI == 1
- uint32_t ftbytes;
- presto->retval = ftdi_write_data(&presto->ftdic, buf, size);
- if (presto->retval < 0) {
- LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto->ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- ftbytes = presto->retval;
-#endif
-
- if (ftbytes != size) {
- LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)",
- (unsigned)ftbytes, (unsigned)size);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int presto_read(uint8_t *buf, uint32_t size)
-{
-#if BUILD_PRESTO_FTD2XX == 1
- DWORD ftbytes;
- presto->status = FT_Read(presto->handle, buf, size, &ftbytes);
- if (presto->status != FT_OK) {
- LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
-#elif BUILD_PRESTO_LIBFTDI == 1
- uint32_t ftbytes = 0;
-
- struct timeval timeout, now;
- gettimeofday(&timeout, NULL);
- timeval_add_time(&timeout, 1, 0); /* one second timeout */
-
- while (ftbytes < size) {
- presto->retval = ftdi_read_data(&presto->ftdic, buf + ftbytes, size - ftbytes);
- if (presto->retval < 0) {
- LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto->ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- ftbytes += presto->retval;
-
- gettimeofday(&now, NULL);
- if ((now.tv_sec > timeout.tv_sec) ||
- ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec)))
- break;
- }
-#endif
-
- if (ftbytes != size) {
- /* this is just a warning, there might have been timeout when detecting PRESTO,
- *which is not fatal */
- LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%u < %u)",
- (unsigned)ftbytes, (unsigned)size);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-#if BUILD_PRESTO_FTD2XX == 1
-static int presto_open_ftd2xx(char *req_serial)
-{
- uint32_t i;
- DWORD numdevs;
- DWORD vidpid;
- char devname[FT_DEVICE_NAME_LEN];
- FT_DEVICE device;
-
- BYTE presto_data;
- DWORD ftbytes;
-
- presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
-
-#if IS_WIN32 == 0
- /* Add non-standard Vid/Pid to the linux driver */
- presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID);
- if (presto->status != FT_OK) {
- LOG_ERROR("couldn't add PRESTO VID/PID");
- exit(-1);
- }
-#endif
-
- presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY);
- if (presto->status != FT_OK) {
- LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs);
- for (i = 0; i < numdevs; i++) {
- presto->status = FT_Open(i, &(presto->handle));
- if (presto->status != FT_OK) {
- /* this is not fatal, the device may be legitimately open by other process,
- *hence debug message only */
- LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status));
- continue;
- }
- LOG_DEBUG("FTDI device %i open", (int)i);
-
- presto->status = FT_GetDeviceInfo(presto->handle, &device,
- &vidpid, presto->serial, devname, NULL);
- if (presto->status == FT_OK) {
- if (vidpid == PRESTO_VID_PID && (req_serial == NULL ||
- !strcmp(presto->serial, req_serial)))
- break;
- } else
- LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string(
- presto->status));
-
- LOG_DEBUG("FTDI device %i does not match, closing", (int)i);
- FT_Close(presto->handle);
- presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
- }
-
- if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
- return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */
-
- presto->status = FT_SetLatencyTimer(presto->handle, 1);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto->status = FT_SetTimeouts(presto->handle, 100, 0);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto_data = 0xD0;
- presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- /* delay between first write/read turnaround (after purge?) necessary
- * under Linux for unknown reason,
- * probably a bug in library threading */
- usleep(100000);
- presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- if (ftbytes != 1) {
- LOG_DEBUG("PRESTO reset");
-
- presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
- presto->status = FT_SetBitMode(presto->handle, 0x80, 1);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
- presto->status = FT_SetBaudRate(presto->handle, 9600);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto_data = 0;
- for (i = 0; i < 4 * 62; i++) {
- presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
- }
- usleep(100000);
-
- presto->status = FT_SetBitMode(presto->handle, 0x00, 0);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto_data = 0xD0;
- presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
- probably a bug in library threading */
- usleep(100000);
- presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- if (ftbytes != 1) {
- LOG_DEBUG("PRESTO not responding");
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
-
- presto->status = FT_SetTimeouts(presto->handle, 0, 0);
- if (presto->status != FT_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto->status = FT_Write(presto->handle, &presto_init_seq,
- sizeof(presto_init_seq), &ftbytes);
-
- if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
- return ERROR_JTAG_DEVICE_ERROR;
-
- return ERROR_OK;
-}
-
-#elif BUILD_PRESTO_LIBFTDI == 1
-static int presto_open_libftdi(char *req_serial)
-{
- uint8_t presto_data;
-
- LOG_DEBUG("searching for PRESTO using libftdi");
-
- /* initialize FTDI context structure */
- if (ftdi_init(&presto->ftdic) < 0) {
- LOG_ERROR("unable to init libftdi: %s", presto->ftdic.error_str);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* context, vendor id, product id */
- if (ftdi_usb_open_desc(&presto->ftdic, PRESTO_VID, PRESTO_PID, NULL, req_serial) < 0) {
- LOG_ERROR("unable to open PRESTO: %s", presto->ftdic.error_str);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (ftdi_usb_reset(&presto->ftdic) < 0) {
- LOG_ERROR("unable to reset PRESTO device");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (ftdi_set_latency_timer(&presto->ftdic, 1) < 0) {
- LOG_ERROR("unable to set latency timer");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (ftdi_usb_purge_buffers(&presto->ftdic) < 0) {
- LOG_ERROR("unable to purge PRESTO buffers");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- presto_data = 0xD0;
- if (presto_write(&presto_data, 1) != ERROR_OK) {
- LOG_ERROR("error writing to PRESTO");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (presto_read(&presto_data, 1) != ERROR_OK) {
- LOG_DEBUG("no response from PRESTO, retrying");
-
- if (ftdi_usb_purge_buffers(&presto->ftdic) < 0)
- return ERROR_JTAG_DEVICE_ERROR;
-
- presto_data = 0xD0;
- if (presto_write(&presto_data, 1) != ERROR_OK)
- return ERROR_JTAG_DEVICE_ERROR;
-
- if (presto_read(&presto_data, 1) != ERROR_OK) {
- LOG_ERROR("no response from PRESTO, giving up");
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
-
- if (presto_write(presto_init_seq, sizeof(presto_init_seq)) != ERROR_OK) {
- LOG_ERROR("error writing PRESTO init sequence");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-#endif /* BUILD_PRESTO_LIBFTDI == 1 */
-
-static int presto_open(char *req_serial)
-{
- presto->buff_out_pos = 0;
- presto->buff_in_pos = 0;
- presto->buff_in_len = 0;
- presto->buff_in_exp = 0;
-
- presto->total_out = 0;
- presto->total_in = 0;
-
- presto->jtag_tms = 0;
- presto->jtag_tck = 0;
- presto->jtag_rst = 0;
- presto->jtag_tdi_data = 0;
- presto->jtag_tdi_count = 0;
-
- presto->jtag_speed = 0;
-
-#if BUILD_PRESTO_FTD2XX == 1
- return presto_open_ftd2xx(req_serial);
-#elif BUILD_PRESTO_LIBFTDI == 1
- return presto_open_libftdi(req_serial);
-#endif
-}
-
-static int presto_close(void)
-{
-
- int result = ERROR_OK;
-
-#if BUILD_PRESTO_FTD2XX == 1
- DWORD ftbytes;
-
- if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE)
- return result;
-
- presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX);
- if (presto->status != FT_OK)
- result = ERROR_JTAG_DEVICE_ERROR;
-
- presto->status = FT_Write(presto->handle,
- &presto_init_seq,
- sizeof(presto_init_seq),
- &ftbytes);
- if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq))
- result = ERROR_JTAG_DEVICE_ERROR;
-
- presto->status = FT_SetLatencyTimer(presto->handle, 16);
- if (presto->status != FT_OK)
- result = ERROR_JTAG_DEVICE_ERROR;
-
- presto->status = FT_Close(presto->handle);
- if (presto->status != FT_OK)
- result = ERROR_JTAG_DEVICE_ERROR;
- else
- presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE;
-
-#elif BUILD_PRESTO_LIBFTDI == 1
-
- presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq));
- if (presto->retval != sizeof(presto_init_seq))
- result = ERROR_JTAG_DEVICE_ERROR;
-
- presto->retval = ftdi_set_latency_timer(&presto->ftdic, 16);
- if (presto->retval < 0)
- result = ERROR_JTAG_DEVICE_ERROR;
-
- presto->retval = ftdi_usb_close(&presto->ftdic);
- if (presto->retval < 0)
- result = ERROR_JTAG_DEVICE_ERROR;
- else
- ftdi_deinit(&presto->ftdic);
-#endif
-
- return result;
-}
-
-static int presto_flush(void)
-{
- if (presto->buff_out_pos == 0)
- return ERROR_OK;
-
-#if BUILD_PRESTO_FTD2XX == 1
- if (presto->status != FT_OK) {
-#elif BUILD_PRESTO_LIBFTDI == 1
- if (presto->retval < 0) {
-#endif
- LOG_DEBUG("error in previous communication, canceling I/O operation");
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- if (presto_write(presto->buff_out, presto->buff_out_pos) != ERROR_OK) {
- presto->buff_out_pos = 0;
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- presto->total_out += presto->buff_out_pos;
- presto->buff_out_pos = 0;
-
- if (presto->buff_in_exp == 0)
- return ERROR_OK;
-
- presto->buff_in_pos = 0;
- presto->buff_in_len = 0;
-
- if (presto_read(presto->buff_in, presto->buff_in_exp) != ERROR_OK) {
- presto->buff_in_exp = 0;
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- presto->total_in += presto->buff_in_exp;
- presto->buff_in_len = presto->buff_in_exp;
- presto->buff_in_exp = 0;
-
- return ERROR_OK;
-}
-
-static int presto_sendbyte(int data)
-{
- if (data == EOF)
- return presto_flush();
-
- if (presto->buff_out_pos < BUFFER_SIZE) {
- presto->buff_out[presto->buff_out_pos++] = (uint8_t)data;
- if (((data & 0xC0) == 0x40) || ((data & 0xD0) == 0xD0))
- presto->buff_in_exp++;
- } else
- return ERROR_JTAG_DEVICE_ERROR;
-
-#if BUILD_PRESTO_FTD2XX == 1
- if (presto->buff_out_pos >= BUFFER_SIZE)
-#elif BUILD_PRESTO_LIBFTDI == 1
- /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128
- *bytes only!) */
- if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128)
-#endif
- return presto_flush();
-
- return ERROR_OK;
-}
-
-#if 0
-static int presto_getbyte(void)
-{
- if (presto->buff_in_pos < presto->buff_in_len)
- return presto->buff_in[presto->buff_in_pos++];
-
- if (presto->buff_in_exp == 0)
- return -1;
-
- if (presto_flush() != ERROR_OK)
- return -1;
-
- if (presto->buff_in_pos < presto->buff_in_len)
- return presto->buff_in[presto->buff_in_pos++];
-
- return -1;
-}
-#endif
-
-/* -------------------------------------------------------------------------- */
-
-static int presto_tdi_flush(void)
-{
- if (presto->jtag_tdi_count == 0)
- return 0;
-
- if (presto->jtag_tck == 0) {
- LOG_ERROR("BUG: unexpected TAP condition, TCK low");
- return -1;
- }
-
- presto->jtag_tdi_data |= (presto->jtag_tdi_count - 1) << 4;
- presto_sendbyte(presto->jtag_tdi_data);
- presto->jtag_tdi_count = 0;
- presto->jtag_tdi_data = 0;
-
- return 0;
-}
-
-static int presto_tck_idle(void)
-{
- if (presto->jtag_tck == 1) {
- presto_sendbyte(0xCA);
- presto->jtag_tck = 0;
- }
-
- return 0;
-}
-
-/* -------------------------------------------------------------------------- */
-
-static int presto_bitq_out(int tms, int tdi, int tdo_req)
-{
- int i;
- unsigned char cmd;
-
- if (presto->jtag_tck == 0)
- presto_sendbyte(0xA4); /* LED idicator - JTAG active */
- else if (presto->jtag_speed == 0 && !tdo_req && tms == presto->jtag_tms) {
- presto->jtag_tdi_data |= (tdi != 0) << presto->jtag_tdi_count;
-
- if (++presto->jtag_tdi_count == 4)
- presto_tdi_flush();
-
- return 0;
- }
-
- presto_tdi_flush();
-
- cmd = tdi ? 0xCB : 0xCA;
- presto_sendbyte(cmd);
-
- if (tms != presto->jtag_tms) {
- presto_sendbyte((tms ? 0xEC : 0xE8) | (presto->jtag_rst ? 0x02 : 0));
- presto->jtag_tms = tms;
- }
-
- /* delay with TCK low */
- for (i = presto->jtag_speed; i > 1; i--)
- presto_sendbyte(cmd);
-
- cmd |= 0x04;
- presto_sendbyte(cmd | (tdo_req ? 0x10 : 0));
-
- /* delay with TCK high */
- for (i = presto->jtag_speed; i > 1; i--)
- presto_sendbyte(cmd);
-
- presto->jtag_tck = 1;
-
- return 0;
-}
-
-static int presto_bitq_flush(void)
-{
- presto_tdi_flush();
- presto_tck_idle();
-
- presto_sendbyte(0xA0); /* LED idicator - JTAG idle */
-
- return presto_flush();
-}
-
-static int presto_bitq_in_rdy(void)
-{
- if (presto->buff_in_pos >= presto->buff_in_len)
- return 0;
- return presto->buff_in_len-presto->buff_in_pos;
-}
-
-static int presto_bitq_in(void)
-{
- if (presto->buff_in_pos >= presto->buff_in_len)
- return -1;
- if (presto->buff_in[presto->buff_in_pos++]&0x08)
- return 1;
- return 0;
-}
-
-static int presto_bitq_sleep(unsigned long us)
-{
- long waits;
-
- presto_tdi_flush();
- presto_tck_idle();
-
- if (us > 100000) {
- presto_bitq_flush();
- jtag_sleep(us);
- return 0;
- }
-
- waits = us / 170 + 2;
- while (waits--)
- presto_sendbyte(0x80);
-
- return 0;
-}
-
-static int presto_bitq_reset(int trst, int srst)
-{
- presto_tdi_flush();
- presto_tck_idle();
-
- /* add a delay after possible TCK transition */
- presto_sendbyte(0x80);
- presto_sendbyte(0x80);
-
- presto->jtag_rst = trst || srst;
- presto_sendbyte((presto->jtag_rst ? 0xEA : 0xE8) | (presto->jtag_tms ? 0x04 : 0));
-
- return 0;
-}
-
-static struct bitq_interface presto_bitq = {
- .out = &presto_bitq_out,
- .flush = &presto_bitq_flush,
- .sleep = &presto_bitq_sleep,
- .reset = &presto_bitq_reset,
- .in_rdy = &presto_bitq_in_rdy,
- .in = &presto_bitq_in,
-};
-
-/* -------------------------------------------------------------------------- */
-
-static int presto_adapter_khz(int khz, int *jtag_speed)
-{
- if (khz < 0) {
- *jtag_speed = 0;
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (khz >= 3000)
- *jtag_speed = 0;
- else
- *jtag_speed = (1000 + khz-1)/khz;
-
- return 0;
-}
-
-static int presto_jtag_speed_div(int speed, int *khz)
-{
- if ((speed < 0) || (speed > 1000)) {
- *khz = 0;
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (speed == 0)
- *khz = 3000;
- else
- *khz = 1000/speed;
-
- return 0;
-}
-
-static int presto_jtag_speed(int speed)
-{
- int khz;
-
- if (presto_jtag_speed_div(speed, &khz))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- presto->jtag_speed = speed;
-
- if (khz%1000 == 0)
- LOG_INFO("setting speed to %d, max. TCK freq. is %d MHz", speed, khz/1000);
- else
- LOG_INFO("setting speed to %d, max. TCK freq. is %d kHz", speed, khz);
-
- return 0;
-}
-
-static char *presto_serial;
-
-COMMAND_HANDLER(presto_handle_serial_command)
-{
- if (CMD_ARGC == 1) {
- if (presto_serial)
- free(presto_serial);
- presto_serial = strdup(CMD_ARGV[0]);
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-static const struct command_registration presto_command_handlers[] = {
- {
- .name = "presto_serial",
- .handler = presto_handle_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "Configure USB serial number of Presto device.",
- .usage = "serial_string",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int presto_jtag_init(void)
-{
- if (presto_open(presto_serial) != ERROR_OK) {
- presto_close();
- if (presto_serial != NULL)
- LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial);
- else
- LOG_ERROR("Cannot open PRESTO");
- return ERROR_JTAG_INIT_FAILED;
- }
- LOG_INFO("PRESTO open, serial number '%s'", presto->serial);
-
- bitq_interface = &presto_bitq;
- return ERROR_OK;
-}
-
-static int presto_jtag_quit(void)
-{
- bitq_cleanup();
- presto_close();
- LOG_INFO("PRESTO closed");
-
- if (presto_serial) {
- free(presto_serial);
- presto_serial = NULL;
- }
-
- return ERROR_OK;
-}
-
-struct jtag_interface presto_interface = {
- .name = "presto",
- .commands = presto_command_handlers,
-
- .execute_queue = bitq_execute_queue,
- .speed = presto_jtag_speed,
- .khz = presto_adapter_khz,
- .speed_div = presto_jtag_speed_div,
- .init = presto_jtag_init,
- .quit = presto_jtag_quit,
-};
diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c
deleted file mode 100644
index c8d0136..0000000
--- a/src/jtag/drivers/remote_bitbang.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Richard Uhler *
- * ruhler@mit.edu *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef _WIN32
-#include <sys/un.h>
-#include <netdb.h>
-#endif
-#include <jtag/interface.h>
-#include "bitbang.h"
-
-/* arbitrary limit on host name length: */
-#define REMOTE_BITBANG_HOST_MAX 255
-
-#define REMOTE_BITBANG_RAISE_ERROR(expr ...) \
- do { \
- LOG_ERROR(expr); \
- LOG_ERROR("Terminating openocd."); \
- exit(-1); \
- } while (0)
-
-static char *remote_bitbang_host;
-static char *remote_bitbang_port;
-
-FILE *remote_bitbang_in;
-FILE *remote_bitbang_out;
-
-static void remote_bitbang_putc(int c)
-{
- if (EOF == fputc(c, remote_bitbang_out))
- REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno));
-}
-
-static int remote_bitbang_quit(void)
-{
- if (EOF == fputc('Q', remote_bitbang_out)) {
- LOG_ERROR("fputs: %s", strerror(errno));
- return ERROR_FAIL;
- }
-
- if (EOF == fflush(remote_bitbang_out)) {
- LOG_ERROR("fflush: %s", strerror(errno));
- return ERROR_FAIL;
- }
-
- /* We only need to close one of the FILE*s, because they both use the same */
- /* underlying file descriptor. */
- if (EOF == fclose(remote_bitbang_out)) {
- LOG_ERROR("fclose: %s", strerror(errno));
- return ERROR_FAIL;
- }
-
- free(remote_bitbang_host);
- free(remote_bitbang_port);
-
- LOG_INFO("remote_bitbang interface quit");
- return ERROR_OK;
-}
-
-/* Get the next read response. */
-static int remote_bitbang_rread(void)
-{
- if (EOF == fflush(remote_bitbang_out)) {
- remote_bitbang_quit();
- REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno));
- }
-
- int c = fgetc(remote_bitbang_in);
- switch (c) {
- case '0':
- return 0;
- case '1':
- return 1;
- default:
- remote_bitbang_quit();
- REMOTE_BITBANG_RAISE_ERROR(
- "remote_bitbang: invalid read response: %c(%i)", c, c);
- }
-}
-
-static int remote_bitbang_read(void)
-{
- remote_bitbang_putc('R');
- return remote_bitbang_rread();
-}
-
-static void remote_bitbang_write(int tck, int tms, int tdi)
-{
- char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
- remote_bitbang_putc(c);
-}
-
-static void remote_bitbang_reset(int trst, int srst)
-{
- char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
- remote_bitbang_putc(c);
-}
-
-static void remote_bitbang_blink(int on)
-{
- char c = on ? 'B' : 'b';
- remote_bitbang_putc(c);
-}
-
-static struct bitbang_interface remote_bitbang_bitbang = {
- .read = &remote_bitbang_read,
- .write = &remote_bitbang_write,
- .reset = &remote_bitbang_reset,
- .blink = &remote_bitbang_blink,
-};
-
-static int remote_bitbang_init_tcp(void)
-{
- struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
- struct addrinfo *result, *rp;
- int fd;
-
- LOG_INFO("Connecting to %s:%s",
- remote_bitbang_host ? remote_bitbang_host : "localhost",
- remote_bitbang_port);
-
- /* Obtain address(es) matching host/port */
- int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
- if (s != 0) {
- LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
- return ERROR_FAIL;
- }
-
- /* getaddrinfo() returns a list of address structures.
- Try each address until we successfully connect(2).
- If socket(2) (or connect(2)) fails, we (close the socket
- and) try the next address. */
-
- for (rp = result; rp != NULL ; rp = rp->ai_next) {
- fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if (fd == -1)
- continue;
-
- if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
- break; /* Success */
-
- close(fd);
- }
-
- freeaddrinfo(result); /* No longer needed */
-
- if (rp == NULL) { /* No address succeeded */
- LOG_ERROR("Failed to connect: %s", strerror(errno));
- return ERROR_FAIL;
- }
-
- return fd;
-}
-
-static int remote_bitbang_init_unix(void)
-{
- if (remote_bitbang_host == NULL) {
- LOG_ERROR("host/socket not specified");
- return ERROR_FAIL;
- }
-
- LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
- int fd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) {
- LOG_ERROR("socket: %s", strerror(errno));
- return ERROR_FAIL;
- }
-
- struct sockaddr_un addr;
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path));
- addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
-
- if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
- LOG_ERROR("connect: %s", strerror(errno));
- return ERROR_FAIL;
- }
-
- return fd;
-}
-
-static int remote_bitbang_init(void)
-{
- int fd;
- bitbang_interface = &remote_bitbang_bitbang;
-
- LOG_INFO("Initializing remote_bitbang driver");
- if (remote_bitbang_port == NULL)
- fd = remote_bitbang_init_unix();
- else
- fd = remote_bitbang_init_tcp();
-
- if (fd < 0)
- return fd;
-
- remote_bitbang_in = fdopen(fd, "r");
- if (remote_bitbang_in == NULL) {
- LOG_ERROR("fdopen: failed to open read stream");
- close(fd);
- return ERROR_FAIL;
- }
-
- remote_bitbang_out = fdopen(fd, "w");
- if (remote_bitbang_out == NULL) {
- LOG_ERROR("fdopen: failed to open write stream");
- fclose(remote_bitbang_in);
- return ERROR_FAIL;
- }
-
- LOG_INFO("remote_bitbang driver initialized");
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
-{
- if (CMD_ARGC == 1) {
- uint16_t port;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
- free(remote_bitbang_port);
- remote_bitbang_port = port == 0 ? NULL : strdup(CMD_ARGV[0]);
- return ERROR_OK;
- }
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
-{
- if (CMD_ARGC == 1) {
- free(remote_bitbang_host);
- remote_bitbang_host = strdup(CMD_ARGV[0]);
- return ERROR_OK;
- }
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static const struct command_registration remote_bitbang_command_handlers[] = {
- {
- .name = "remote_bitbang_port",
- .handler = remote_bitbang_handle_remote_bitbang_port_command,
- .mode = COMMAND_CONFIG,
- .help = "Set the port to use to connect to the remote jtag.\n"
- " if 0 or unset, use unix sockets to connect to the remote jtag.",
- .usage = "port_number",
- },
- {
- .name = "remote_bitbang_host",
- .handler = remote_bitbang_handle_remote_bitbang_host_command,
- .mode = COMMAND_CONFIG,
- .help = "Set the host to use to connect to the remote jtag.\n"
- " if port is 0 or unset, this is the name of the unix socket to use.",
- .usage = "host_name",
- },
- COMMAND_REGISTRATION_DONE,
-};
-
-struct jtag_interface remote_bitbang_interface = {
- .name = "remote_bitbang",
- .execute_queue = &bitbang_execute_queue,
- .commands = remote_bitbang_command_handlers,
- .init = &remote_bitbang_init,
- .quit = &remote_bitbang_quit,
-};
diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c
deleted file mode 100644
index 3f9e332..0000000
--- a/src/jtag/drivers/rlink.c
+++ /dev/null
@@ -1,1683 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 Rob Brown, Lou Deluxe *
- * rob@cobbleware.com, lou.openocd012@fixit.nospammail.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include "rlink.h"
-#include "rlink_st7.h"
-#include "rlink_ep1_cmd.h"
-#include "rlink_dtc_cmd.h"
-#include "usb_common.h"
-
-/* This feature is made useless by running the DTC all the time. When automatic, the LED is on
- *whenever the DTC is running. Otherwise, USB messages are sent to turn it on and off. */
-#undef AUTOMATIC_BUSY_LED
-
-/* This feature may require derating the speed due to reduced hold time. */
-#undef USE_HARDWARE_SHIFTER_FOR_TMS
-
-#define INTERFACE_NAME "RLink"
-
-#define USB_IDVENDOR (0x138e)
-#define USB_IDPRODUCT (0x9000)
-
-#define USB_EP1OUT_ADDR (0x01)
-#define USB_EP1OUT_SIZE (16)
-#define USB_EP1IN_ADDR (USB_EP1OUT_ADDR | 0x80)
-#define USB_EP1IN_SIZE (USB_EP1OUT_SIZE)
-
-#define USB_EP2OUT_ADDR (0x02)
-#define USB_EP2OUT_SIZE (64)
-#define USB_EP2IN_ADDR (USB_EP2OUT_ADDR | 0x80)
-#define USB_EP2IN_SIZE (USB_EP2OUT_SIZE)
-#define USB_EP2BANK_SIZE (512)
-
-#define USB_TIMEOUT_MS (3 * 1000)
-
-#define DTC_STATUS_POLL_BYTE (ST7_USB_BUF_EP0OUT + 0xff)
-
-#define ST7_PD_NBUSY_LED ST7_PD0
-#define ST7_PD_NRUN_LED ST7_PD1
-/* low enables VPP at adapter header, high connects it to GND instead */
-#define ST7_PD_VPP_SEL ST7_PD6
-/* low: VPP = 12v, high: VPP <= 5v */
-#define ST7_PD_VPP_SHDN ST7_PD7
-
-/* These pins are connected together */
-#define ST7_PE_ADAPTER_SENSE_IN ST7_PE3
-#define ST7_PE_ADAPTER_SENSE_OUT ST7_PE4
-
-/* Symbolic mapping between port pins and numbered IO lines */
-#define ST7_PA_IO1 ST7_PA1
-#define ST7_PA_IO2 ST7_PA2
-#define ST7_PA_IO4 ST7_PA4
-#define ST7_PA_IO8 ST7_PA6
-#define ST7_PA_IO10 ST7_PA7
-#define ST7_PB_IO5 ST7_PB5
-#define ST7_PC_IO9 ST7_PC1
-#define ST7_PC_IO3 ST7_PC2
-#define ST7_PC_IO7 ST7_PC3
-#define ST7_PE_IO6 ST7_PE5
-
-/* Symbolic mapping between numbered IO lines and adapter signals */
-#define ST7_PA_RTCK ST7_PA_IO0
-#define ST7_PA_NTRST ST7_PA_IO1
-#define ST7_PC_TDI ST7_PC_IO3
-#define ST7_PA_DBGRQ ST7_PA_IO4
-#define ST7_PB_NSRST ST7_PB_IO5
-#define ST7_PE_TMS ST7_PE_IO6
-#define ST7_PC_TCK ST7_PC_IO7
-#define ST7_PC_TDO ST7_PC_IO9
-#define ST7_PA_DBGACK ST7_PA_IO10
-
-static usb_dev_handle *pHDev;
-
-/*
- * ep1 commands are up to USB_EP1OUT_SIZE bytes in length.
- * This function takes care of zeroing the unused bytes before sending the packet.
- * Any reply packet is not handled by this function.
- */
-static int ep1_generic_commandl(usb_dev_handle *pHDev_param, size_t length, ...)
-{
- uint8_t usb_buffer[USB_EP1OUT_SIZE];
- uint8_t *usb_buffer_p;
- va_list ap;
- int usb_ret;
-
- if (length > sizeof(usb_buffer))
- length = sizeof(usb_buffer);
-
- usb_buffer_p = usb_buffer;
-
- va_start(ap, length);
- while (length > 0) {
- *usb_buffer_p++ = va_arg(ap, int);
- length--;
- }
-
- memset(
- usb_buffer_p,
- 0,
- sizeof(usb_buffer) - (usb_buffer_p - usb_buffer)
- );
-
- usb_ret = usb_bulk_write(
- pHDev_param,
- USB_EP1OUT_ADDR,
- (char *)usb_buffer, sizeof(usb_buffer),
- USB_TIMEOUT_MS
- );
-
- return usb_ret;
-}
-
-#if 0
-static ssize_t ep1_memory_read(
- usb_dev_handle *pHDev, uint16_t addr,
- size_t length, uint8_t *buffer)
-{
- uint8_t usb_buffer[USB_EP1OUT_SIZE];
- int usb_ret;
- size_t remain;
- ssize_t count;
-
- usb_buffer[0] = EP1_CMD_MEMORY_READ;
- memset(
- usb_buffer + 4,
- 0,
- sizeof(usb_buffer) - 4
- );
-
- remain = length;
- count = 0;
-
- while (remain) {
- if (remain > sizeof(usb_buffer))
- length = sizeof(usb_buffer);
- else
- length = remain;
-
- usb_buffer[1] = addr >> 8;
- usb_buffer[2] = addr;
- usb_buffer[3] = length;
-
- usb_ret = usb_bulk_write(
- pHDev, USB_EP1OUT_ADDR,
- usb_buffer, sizeof(usb_buffer),
- USB_TIMEOUT_MS
- );
-
- if (usb_ret < sizeof(usb_buffer))
- break;
-
- usb_ret = usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- buffer, length,
- USB_TIMEOUT_MS
- );
-
- if (usb_ret < length)
- break;
-
- addr += length;
- buffer += length;
- count += length;
- remain -= length;
- }
-
- return count;
-}
-#endif
-
-static ssize_t ep1_memory_write(usb_dev_handle *pHDev_param, uint16_t addr,
- size_t length, uint8_t const *buffer)
-{
- uint8_t usb_buffer[USB_EP1OUT_SIZE];
- int usb_ret;
- size_t remain;
- ssize_t count;
-
- usb_buffer[0] = EP1_CMD_MEMORY_WRITE;
-
- remain = length;
- count = 0;
-
- while (remain) {
- if (remain > (sizeof(usb_buffer) - 4))
- length = (sizeof(usb_buffer) - 4);
- else
- length = remain;
-
- usb_buffer[1] = addr >> 8;
- usb_buffer[2] = addr;
- usb_buffer[3] = length;
- memcpy(
- usb_buffer + 4,
- buffer,
- length
- );
- memset(
- usb_buffer + 4 + length,
- 0,
- sizeof(usb_buffer) - 4 - length
- );
-
- usb_ret = usb_bulk_write(
- pHDev_param, USB_EP1OUT_ADDR,
- (char *)usb_buffer, sizeof(usb_buffer),
- USB_TIMEOUT_MS
- );
-
- if ((size_t)usb_ret < sizeof(usb_buffer))
- break;
-
- addr += length;
- buffer += length;
- count += length;
- remain -= length;
- }
-
- return count;
-}
-
-
-#if 0
-static ssize_t ep1_memory_writel(usb_dev_handle *pHDev, uint16_t addr,
- size_t length, ...)
-{
- uint8_t buffer[USB_EP1OUT_SIZE - 4];
- uint8_t *buffer_p;
- va_list ap;
- size_t remain;
-
- if (length > sizeof(buffer))
- length = sizeof(buffer);
-
- remain = length;
- buffer_p = buffer;
-
- va_start(ap, length);
- while (remain > 0) {
- *buffer_p++ = va_arg(ap, int);
- remain--;
- }
-
- return ep1_memory_write(pHDev, addr, length, buffer);
-}
-#endif
-
-#define DTCLOAD_COMMENT (0)
-#define DTCLOAD_ENTRY (1)
-#define DTCLOAD_LOAD (2)
-#define DTCLOAD_RUN (3)
-#define DTCLOAD_LUT_START (4)
-#define DTCLOAD_LUT (5)
-
-#define DTC_LOAD_BUFFER ST7_USB_BUF_EP2UIDO
-
-/* This gets set by the DTC loader */
-static uint8_t dtc_entry_download;
-
-/* The buffer is specially formatted to represent a valid image to load into the DTC. */
-static int dtc_load_from_buffer(usb_dev_handle *pHDev_param, const uint8_t *buffer,
- size_t length)
-{
- struct header_s {
- uint8_t type;
- uint8_t length;
- };
-
- int usb_err;
- struct header_s *header;
- uint8_t lut_start = 0xc0;
-
- dtc_entry_download = 0;
-
- /* Stop the DTC before loading anything. */
- usb_err = ep1_generic_commandl(
- pHDev_param, 1,
- EP1_CMD_DTC_STOP
- );
- if (usb_err < 0)
- return usb_err;
-
- while (length) {
- if (length < sizeof(*header)) {
- LOG_ERROR("Malformed DTC image");
- exit(1);
- }
-
- header = (struct header_s *)buffer;
- buffer += sizeof(*header);
- length -= sizeof(*header);
-
- if (length < (size_t)header->length + 1) {
- LOG_ERROR("Malformed DTC image");
- exit(1);
- }
-
- switch (header->type) {
- case DTCLOAD_COMMENT:
- break;
-
- case DTCLOAD_ENTRY:
- /* store entry addresses somewhere */
- if (!strncmp("download", (char *)buffer + 1, 8))
- dtc_entry_download = buffer[0];
- break;
-
- case DTCLOAD_LOAD:
- /* Send the DTC program to ST7 RAM. */
- usb_err = ep1_memory_write(
- pHDev_param,
- DTC_LOAD_BUFFER,
- header->length + 1, buffer
- );
- if (usb_err < 0)
- return usb_err;
-
- /* Load it into the DTC. */
- usb_err = ep1_generic_commandl(
- pHDev_param, 3,
- EP1_CMD_DTC_LOAD,
- (DTC_LOAD_BUFFER >> 8),
- DTC_LOAD_BUFFER
- );
- if (usb_err < 0)
- return usb_err;
-
- break;
-
- case DTCLOAD_RUN:
- usb_err = ep1_generic_commandl(
- pHDev_param, 3,
- EP1_CMD_DTC_CALL,
- buffer[0],
- EP1_CMD_DTC_WAIT
- );
- if (usb_err < 0)
- return usb_err;
-
- break;
-
- case DTCLOAD_LUT_START:
- lut_start = buffer[0];
- break;
-
- case DTCLOAD_LUT:
- usb_err = ep1_memory_write(
- pHDev_param,
- ST7_USB_BUF_EP0OUT + lut_start,
- header->length + 1, buffer
- );
- if (usb_err < 0)
- return usb_err;
- break;
-
- default:
- LOG_ERROR("Invalid DTC image record type: 0x%02x", header->type);
- exit(1);
- break;
- }
-
- buffer += (header->length + 1);
- length -= (header->length + 1);
- }
-
- return 0;
-}
-
-/*
- * Start the DTC running in download mode (waiting for 512 byte command packets on ep2).
- */
-static int dtc_start_download(void)
-{
- int usb_err;
- uint8_t ep2txr;
-
- /* set up for download mode and make sure EP2 is set up to transmit */
- usb_err = ep1_generic_commandl(
- pHDev, 7,
-
- EP1_CMD_DTC_STOP,
- EP1_CMD_SET_UPLOAD,
- EP1_CMD_SET_DOWNLOAD,
- EP1_CMD_MEMORY_READ, /* read EP2TXR for its data toggle */
- ST7_EP2TXR >> 8,
- ST7_EP2TXR,
- 1
- );
- if (usb_err < 0)
- return usb_err;
-
- /* read back ep2txr */
- usb_err = usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)&ep2txr, 1,
- USB_TIMEOUT_MS
- );
- if (usb_err < 0)
- return usb_err;
-
- usb_err = ep1_generic_commandl(
- pHDev, 13,
-
- EP1_CMD_MEMORY_WRITE, /* preinitialize poll byte */
- DTC_STATUS_POLL_BYTE >> 8,
- DTC_STATUS_POLL_BYTE,
- 1,
- 0x00,
- EP1_CMD_MEMORY_WRITE, /* set EP2IN to return data */
- ST7_EP2TXR >> 8,
- ST7_EP2TXR,
- 1,
- (ep2txr & ST7_EP2TXR_DTOG_TX) | ST7_EP2TXR_STAT_VALID,
- EP1_CMD_DTC_CALL, /* start running the DTC */
- dtc_entry_download,
- EP1_CMD_DTC_GET_CACHED_STATUS
- );
- if (usb_err < 0)
- return usb_err;
-
- /* wait for completion */
- usb_err = usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)&ep2txr, 1,
- USB_TIMEOUT_MS
- );
-
- return usb_err;
-}
-
-static int dtc_run_download(
- usb_dev_handle *pHDev_param,
- uint8_t *command_buffer,
- int command_buffer_size,
- uint8_t *reply_buffer,
- int reply_buffer_size
- )
-{
- char dtc_status;
- int usb_err;
- int i;
-
- LOG_DEBUG("%d/%d", command_buffer_size, reply_buffer_size);
-
- usb_err = usb_bulk_write(
- pHDev_param,
- USB_EP2OUT_ADDR,
- (char *)command_buffer, USB_EP2BANK_SIZE,
- USB_TIMEOUT_MS
- );
- if (usb_err < 0)
- return usb_err;
-
-
- /* Wait for DTC to finish running command buffer */
- for (i = 50;; ) {
- usb_err = ep1_generic_commandl(
- pHDev_param, 4,
-
- EP1_CMD_MEMORY_READ,
- DTC_STATUS_POLL_BYTE >> 8,
- DTC_STATUS_POLL_BYTE,
- 1
- );
- if (usb_err < 0)
- return usb_err;
-
- usb_err = usb_bulk_read(
- pHDev_param,
- USB_EP1IN_ADDR,
- &dtc_status, 1,
- USB_TIMEOUT_MS
- );
- if (usb_err < 0)
- return usb_err;
-
- if (dtc_status & 0x01)
- break;
-
- if (!--i) {
- LOG_ERROR("too many retries waiting for DTC status");
- return -ETIMEDOUT;
- }
- }
-
-
- if (reply_buffer && reply_buffer_size) {
- usb_err = usb_bulk_read(
- pHDev_param,
- USB_EP2IN_ADDR,
- (char *)reply_buffer, reply_buffer_size,
- USB_TIMEOUT_MS
- );
-
- if (usb_err < reply_buffer_size) {
- LOG_ERROR("Read of endpoint 2 returned %d, expected %d",
- usb_err, reply_buffer_size
- );
- return usb_err;
- }
- }
-
- return usb_err;
-}
-
-/*
- * The dtc reply queue is a singly linked list that describes what to do
- * with the reply packet that comes from the DTC. Only SCAN_IN and SCAN_IO generate
- * these entries.
- */
-
-struct dtc_reply_queue_entry {
- struct dtc_reply_queue_entry *next;
- struct jtag_command *cmd; /* the command that resulted in this entry */
-
- struct {
- uint8_t *buffer; /* the scan buffer */
- int size; /* size of the scan buffer in bits */
- int offset; /* how many bits were already done before this? */
- int length; /* how many bits are processed in this operation? */
- enum scan_type type; /* SCAN_IN/SCAN_OUT/SCAN_IO */
- } scan;
-};
-
-
-/*
- * The dtc_queue consists of a buffer of pending commands and a reply queue.
- * rlink_scan and tap_state_run add to the command buffer and maybe to the reply queue.
- */
-
-static struct {
- struct dtc_reply_queue_entry *rq_head;
- struct dtc_reply_queue_entry *rq_tail;
- uint32_t cmd_index;
- uint32_t reply_index;
- uint8_t cmd_buffer[USB_EP2BANK_SIZE];
-} dtc_queue;
-
-/*
- * The tap state queue is for accumulating TAP state changes wiithout needlessly
- * flushing the dtc_queue. When it fills or is run, it adds the accumulated bytes to
- * the dtc_queue.
- */
-
-static struct {
- uint32_t length;
- uint32_t buffer;
-} tap_state_queue;
-
-static int dtc_queue_init(void)
-{
- dtc_queue.rq_head = NULL;
- dtc_queue.rq_tail = NULL;
- dtc_queue.cmd_index = 0;
- dtc_queue.reply_index = 0;
- return 0;
-}
-
-static inline struct dtc_reply_queue_entry *dtc_queue_enqueue_reply(
- enum scan_type type, uint8_t *buffer, int size, int offset,
- int length, struct jtag_command *cmd)
-{
- struct dtc_reply_queue_entry *rq_entry;
-
- rq_entry = malloc(sizeof(struct dtc_reply_queue_entry));
- if (rq_entry != NULL) {
- rq_entry->scan.type = type;
- rq_entry->scan.buffer = buffer;
- rq_entry->scan.size = size;
- rq_entry->scan.offset = offset;
- rq_entry->scan.length = length;
- rq_entry->cmd = cmd;
- rq_entry->next = NULL;
-
- if (dtc_queue.rq_head == NULL)
- dtc_queue.rq_head = rq_entry;
- else
- dtc_queue.rq_tail->next = rq_entry;
-
- dtc_queue.rq_tail = rq_entry;
- }
-
- return rq_entry;
-}
-
-/*
- * Running the queue means that any pending command buffer is run
- * and any reply data dealt with. The command buffer is then cleared for subsequent processing.
- * The queue is automatically run by append when it is necessary to get space for the append.
- */
-
-static int dtc_queue_run(void)
-{
- struct dtc_reply_queue_entry *rq_p, *rq_next;
- int retval;
- int usb_err;
- int bit_cnt;
- int x;
- uint8_t *dtc_p, *tdo_p;
- uint8_t dtc_mask, tdo_mask;
- uint8_t reply_buffer[USB_EP2IN_SIZE];
-
- assert((dtc_queue.rq_head != 0) == (dtc_queue.reply_index > 0));
- assert(dtc_queue.cmd_index < USB_EP2BANK_SIZE);
- assert(dtc_queue.reply_index <= USB_EP2IN_SIZE);
-
- retval = ERROR_OK;
-
- if (dtc_queue.cmd_index < 1)
- return retval;
-
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_STOP;
-
- usb_err = dtc_run_download(pHDev,
- dtc_queue.cmd_buffer, dtc_queue.cmd_index,
- reply_buffer, sizeof(reply_buffer)
- );
- if (usb_err < 0) {
- LOG_ERROR("dtc_run_download: %s", usb_strerror());
- exit(1);
- }
-
- if (dtc_queue.rq_head != NULL) {
- /* process the reply, which empties the reply queue and frees its entries */
- dtc_p = reply_buffer;
-
- /* The rigamarole with the masks and doing it bit-by-bit is due to the fact that the
- *scan buffer is LSb-first and the DTC code is MSb-first for hardware reasons. It
- *was that or craft a function to do the reversal, and that wouldn't work with
- *bit-stuffing (supplying extra bits to use mostly byte operations), or any other
- *scheme which would throw the byte alignment off. */
-
- for (
- rq_p = dtc_queue.rq_head;
- rq_p != NULL;
- rq_p = rq_next
- ) {
- tdo_p = rq_p->scan.buffer + (rq_p->scan.offset / 8);
- tdo_mask = 1 << (rq_p->scan.offset % 8);
-
-
- bit_cnt = rq_p->scan.length;
- if (bit_cnt >= 8) {
- /* bytes */
-
- dtc_mask = 1 << (8 - 1);
-
- for (
- ;
- bit_cnt;
- bit_cnt--
- ) {
- if (*dtc_p & dtc_mask)
- *tdo_p |= tdo_mask;
- else
- *tdo_p &= ~tdo_mask;
-
- dtc_mask >>= 1;
- if (dtc_mask == 0) {
- dtc_p++;
- dtc_mask = 1 << (8 - 1);
- }
-
- tdo_mask <<= 1;
- if (tdo_mask == 0) {
- tdo_p++;
- tdo_mask = 1;
- }
- }
- } else {
- /* extra bits or last bit */
-
- x = *dtc_p++;
- if ((rq_p->scan.type == SCAN_IN) && (
- rq_p->scan.offset != rq_p->scan.size - 1
- )) {
- /* extra bits were sent as a full byte with padding on the
- *end */
- dtc_mask = 1 << (8 - 1);
- } else
- dtc_mask = 1 << (bit_cnt - 1);
-
- for (
- ;
- bit_cnt;
- bit_cnt--
- ) {
- if (x & dtc_mask)
- *tdo_p |= tdo_mask;
- else
- *tdo_p &= ~tdo_mask;
-
- dtc_mask >>= 1;
-
- tdo_mask <<= 1;
- if (tdo_mask == 0) {
- tdo_p++;
- tdo_mask = 1;
- }
-
- }
- }
-
- if ((rq_p->scan.offset + rq_p->scan.length) >= rq_p->scan.size) {
- /* feed scan buffer back into openocd and free it */
- if (jtag_read_buffer(rq_p->scan.buffer,
- rq_p->cmd->cmd.scan) != ERROR_OK)
- retval = ERROR_JTAG_QUEUE_FAILED;
- free(rq_p->scan.buffer);
- }
-
- rq_next = rq_p->next;
- free(rq_p);
- }
- dtc_queue.rq_head = NULL;
- dtc_queue.rq_tail = NULL;
- }
-
- /* reset state for new appends */
- dtc_queue.cmd_index = 0;
- dtc_queue.reply_index = 0;
-
- return retval;
-}
-
-/* runs the queue if it cannot take reserved_cmd bytes of command data
- * or reserved_reply bytes of reply data */
-static int dtc_queue_run_if_full(int reserved_cmd, int reserved_reply)
-{
- /* reserve one additional byte for the STOP cmd appended during run */
- if (dtc_queue.cmd_index + reserved_cmd + 1 > USB_EP2BANK_SIZE)
- return dtc_queue_run();
-
- if (dtc_queue.reply_index + reserved_reply > USB_EP2IN_SIZE)
- return dtc_queue_run();
-
- return ERROR_OK;
-}
-
-static int tap_state_queue_init(void)
-{
- tap_state_queue.length = 0;
- tap_state_queue.buffer = 0;
- return 0;
-}
-
-static int tap_state_queue_run(void)
-{
- int i;
- int bits;
- uint8_t byte_param;
- int retval;
-
- retval = 0;
- if (!tap_state_queue.length)
- return retval;
- bits = 1;
- byte_param = 0;
- for (i = tap_state_queue.length; i--; ) {
-
- byte_param <<= 1;
- if (tap_state_queue.buffer & 1)
- byte_param |= 1;
- if ((bits >= 8) || !i) {
- byte_param <<= (8 - bits);
-
- /* make sure there's room for two cmd bytes */
- dtc_queue_run_if_full(2, 0);
-
-#ifdef USE_HARDWARE_SHIFTER_FOR_TMS
- if (bits == 8) {
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TMS_BYTES(1);
- } else {
-#endif
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TMS_BITS(bits);
-#ifdef USE_HARDWARE_SHIFTER_FOR_TMS
- }
-#endif
-
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- byte_param;
-
- byte_param = 0;
- bits = 1;
- } else
- bits++;
-
- tap_state_queue.buffer >>= 1;
- }
- retval = tap_state_queue_init();
- return retval;
-}
-
-static int tap_state_queue_append(uint8_t tms)
-{
- int retval;
-
- if (tap_state_queue.length >= sizeof(tap_state_queue.buffer) * 8) {
- retval = tap_state_queue_run();
- if (retval != 0)
- return retval;
- }
-
- if (tms)
- tap_state_queue.buffer |= (1 << tap_state_queue.length);
- tap_state_queue.length++;
-
- return 0;
-}
-
-static void rlink_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-static void rlink_state_move(void)
-{
-
- int i = 0, tms = 0;
- 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());
-
- for (i = 0; i < tms_count; i++) {
- tms = (tms_scan >> i) & 1;
- tap_state_queue_append(tms);
- }
-
- tap_set_state(tap_get_end_state());
-}
-
-static void rlink_path_move(struct pathmove_command *cmd)
-{
- int num_states = cmd->num_states;
- int state_count;
- int tms = 0;
-
- state_count = 0;
- while (num_states) {
- if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
- tms = 0;
- else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
- tms = 1;
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(tap_get_state()),
- tap_state_name(cmd->path[state_count]));
- exit(-1);
- }
-
- tap_state_queue_append(tms);
-
- tap_set_state(cmd->path[state_count]);
- state_count++;
- num_states--;
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void rlink_runtest(int num_cycles)
-{
- int i;
-
- tap_state_t saved_end_state = tap_get_end_state();
-
- /* only do a state_move when we're not already in RTI */
- if (tap_get_state() != TAP_IDLE) {
- rlink_end_state(TAP_IDLE);
- rlink_state_move();
- }
-
- /* execute num_cycles */
- for (i = 0; i < num_cycles; i++)
- tap_state_queue_append(0);
-
- /* finish in end_state */
- rlink_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- rlink_state_move();
-}
-
-/* (1) assert or (0) deassert reset lines */
-static void rlink_reset(int trst, int srst)
-{
- uint8_t bitmap;
- int usb_err;
-
- /* Read port A for bit op */
- usb_err = ep1_generic_commandl(
- pHDev, 4,
- EP1_CMD_MEMORY_READ,
- ST7_PADR >> 8,
- ST7_PADR,
- 1
- );
- if (usb_err < 0) {
- LOG_ERROR("%s", usb_strerror());
- exit(1);
- }
-
- usb_err = usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)&bitmap, 1,
- USB_TIMEOUT_MS
- );
- if (usb_err < 1) {
- LOG_ERROR("%s", usb_strerror());
- exit(1);
- }
-
- if (trst)
- bitmap &= ~ST7_PA_NTRST;
- else
- bitmap |= ST7_PA_NTRST;
-
- /* Write port A and read port B for bit op
- * port B has no OR, and we want to emulate open drain on NSRST, so we initialize DR to 0
- *and assert NSRST by setting DDR to 1. */
- usb_err = ep1_generic_commandl(
- pHDev, 9,
- EP1_CMD_MEMORY_WRITE,
- ST7_PADR >> 8,
- ST7_PADR,
- 1,
- bitmap,
- EP1_CMD_MEMORY_READ,
- ST7_PBDDR >> 8,
- ST7_PBDDR,
- 1
- );
- if (usb_err < 0) {
- LOG_ERROR("%s", usb_strerror());
- exit(1);
- }
-
- usb_err = usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)&bitmap, 1,
- USB_TIMEOUT_MS
- );
- if (usb_err < 1) {
- LOG_ERROR("%s", usb_strerror());
- exit(1);
- }
-
- if (srst)
- bitmap |= ST7_PB_NSRST;
- else
- bitmap &= ~ST7_PB_NSRST;
-
- /* write port B and read dummy to ensure completion before returning */
- usb_err = ep1_generic_commandl(
- pHDev, 6,
- EP1_CMD_MEMORY_WRITE,
- ST7_PBDDR >> 8,
- ST7_PBDDR,
- 1,
- bitmap,
- EP1_CMD_DTC_GET_CACHED_STATUS
- );
- if (usb_err < 0) {
- LOG_ERROR("%s", usb_strerror());
- exit(1);
- }
-
- usb_err = usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)&bitmap, 1,
- USB_TIMEOUT_MS
- );
- if (usb_err < 1) {
- LOG_ERROR("%s", usb_strerror());
- exit(1);
- }
-}
-
-static int rlink_scan(struct jtag_command *cmd, enum scan_type type,
- uint8_t *buffer, int scan_size)
-{
- bool ir_scan;
- tap_state_t saved_end_state;
- int byte_bits;
- int extra_bits;
- int chunk_bits;
- int chunk_bytes;
- int x;
-
- int tdi_bit_offset;
- uint8_t tdi_mask, *tdi_p;
- uint8_t dtc_mask;
-
- if (scan_size < 1) {
- LOG_ERROR("scan_size cannot be less than 1 bit");
- exit(1);
- }
-
- ir_scan = cmd->cmd.scan->ir_scan;
-
- /* Move to the proper state before starting to shift TDI/TDO. */
- if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) ||
- (ir_scan && (tap_get_state() == TAP_IRSHIFT)))) {
- saved_end_state = tap_get_end_state();
- rlink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
- rlink_state_move();
- rlink_end_state(saved_end_state);
- }
-
- tap_state_queue_run();
-
-
-#if 0
- printf("scan_size = %d, type = 0x%x\n", scan_size, type);
- {
- int i;
-
- /* clear unused bits in scan buffer for ease of debugging
- * (it makes diffing output easier) */
- buffer[scan_size / 8] &= ((1 << ((scan_size - 1) % 8) + 1) - 1);
-
- printf("before scan:");
- for (i = 0; i < (scan_size + 7) / 8; i++)
- printf(" %02x", buffer[i]);
- printf("\n");
- }
-#endif
-
- /* The number of bits that can be shifted as complete bytes */
- byte_bits = (int)(scan_size - 1) / 8 * 8;
- /* The number of bits left over, not counting the last bit */
- extra_bits = (scan_size - 1) - byte_bits;
-
- tdi_bit_offset = 0;
- tdi_p = buffer;
- tdi_mask = 1;
-
- if (extra_bits && (type == SCAN_OUT)) {
- /* Schedule any extra bits into the DTC command buffer, padding as needed
- * For SCAN_OUT, this comes before the full bytes so the (leading) padding bits will
- *fall off the end */
-
- /* make sure there's room for two cmd bytes */
- dtc_queue_run_if_full(2, 0);
-
- x = 0;
- dtc_mask = 1 << (extra_bits - 1);
-
- while (extra_bits--) {
- if (*tdi_p & tdi_mask)
- x |= dtc_mask;
-
- dtc_mask >>= 1;
-
- tdi_mask <<= 1;
- if (tdi_mask == 0) {
- tdi_p++;
- tdi_mask = 1;
- }
- }
-
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TDI_BYTES(1);
-
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
- }
-
- /* Loop scheduling full bytes into the DTC command buffer */
- while (byte_bits) {
- /* make sure there's room for one (for in scans) or two cmd bytes and
- * at least one reply byte for in or inout scans*/
- dtc_queue_run_if_full(type == SCAN_IN ? 1 : 2, type != SCAN_OUT ? 1 : 0);
-
- chunk_bits = byte_bits;
- /* we can only use up to 16 bytes at a time */
- if (chunk_bits > (16 * 8))
- chunk_bits = (16 * 8);
-
- if (type != SCAN_IN) {
- /* how much is there room for, considering stop and byte op? */
- x = (sizeof(dtc_queue.cmd_buffer) - (dtc_queue.cmd_index + 1 + 1)) * 8;
- if (chunk_bits > x)
- chunk_bits = x;
- }
-
- if (type != SCAN_OUT) {
- /* how much is there room for in the reply buffer? */
- x = (USB_EP2IN_SIZE - dtc_queue.reply_index) * 8;
- if (chunk_bits > x)
- chunk_bits = x;
- }
-
- /* so the loop will end */
- byte_bits -= chunk_bits;
-
- if (type != SCAN_OUT) {
- if (dtc_queue_enqueue_reply(
- type, buffer, scan_size, tdi_bit_offset,
- chunk_bits,
- cmd
- ) == NULL) {
- LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno));
- exit(1);
- }
- dtc_queue.reply_index += (chunk_bits + 7) / 8;
-
- tdi_bit_offset += chunk_bits;
- }
-
- /* chunk_bits is a multiple of 8, so there are no rounding issues. */
- chunk_bytes = chunk_bits / 8;
-
- switch (type) {
- case SCAN_IN:
- x = DTC_CMD_SHIFT_TDO_BYTES(chunk_bytes);
- break;
- case SCAN_OUT:
- x = DTC_CMD_SHIFT_TDI_BYTES(chunk_bytes);
- break;
- default:
- x = DTC_CMD_SHIFT_TDIO_BYTES(chunk_bytes);
- break;
- }
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
-
- if (type != SCAN_IN) {
- x = 0;
- dtc_mask = 1 << (8 - 1);
-
- while (chunk_bits--) {
- if (*tdi_p & tdi_mask)
- x |= dtc_mask;
-
- dtc_mask >>= 1;
- if (dtc_mask == 0) {
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
- x = 0;
- dtc_mask = 1 << (8 - 1);
- }
-
- tdi_mask <<= 1;
- if (tdi_mask == 0) {
- tdi_p++;
- tdi_mask = 1;
- }
- }
- }
- }
-
- if (extra_bits && (type != SCAN_OUT)) {
- /* Schedule any extra bits into the DTC command buffer */
-
- /* make sure there's room for one (for in scans) or two cmd bytes
- * and one reply byte */
- dtc_queue_run_if_full(type == SCAN_IN ? 1 : 2, 1);
-
- if (dtc_queue_enqueue_reply(
- type, buffer, scan_size, tdi_bit_offset,
- extra_bits,
- cmd
- ) == NULL) {
- LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno));
- exit(1);
- }
-
- dtc_queue.reply_index++;
-
- tdi_bit_offset += extra_bits;
-
- if (type == SCAN_IN) {
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TDO_BYTES(1);
-
- } else {
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TDIO_BITS(extra_bits);
-
- x = 0;
- dtc_mask = 1 << (8 - 1);
-
- while (extra_bits--) {
- if (*tdi_p & tdi_mask)
- x |= dtc_mask;
-
- dtc_mask >>= 1;
-
- tdi_mask <<= 1;
- if (tdi_mask == 0) {
- tdi_p++;
- tdi_mask = 1;
- }
- }
-
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
- }
- }
-
- /* Schedule the last bit into the DTC command buffer */
-
- /* make sure there's room for one cmd byte and one reply byte
- * for in or inout scans*/
- dtc_queue_run_if_full(1, type == SCAN_OUT ? 0 : 1);
-
- if (type == SCAN_OUT) {
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 0);
-
- } else {
- if (dtc_queue_enqueue_reply(
- type, buffer, scan_size, tdi_bit_offset,
- 1,
- cmd
- ) == NULL) {
- LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno));
- exit(1);
- }
-
- dtc_queue.reply_index++;
-
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 1);
- }
-
- /* Move to pause state */
- tap_state_queue_append(0);
- tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
- if (tap_get_state() != tap_get_end_state())
- rlink_state_move();
-
- return 0;
-}
-
-static int rlink_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
- int retval, tmp_retval;
-
- /* return ERROR_OK, unless something goes wrong */
- retval = ERROR_OK;
-
-#ifndef AUTOMATIC_BUSY_LED
- /* turn LED on */
- ep1_generic_commandl(pHDev, 2,
- EP1_CMD_SET_PORTD_LEDS,
- ~(ST7_PD_NBUSY_LED)
- );
-#endif
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_RUNTEST:
- case JTAG_TLR_RESET:
- case JTAG_PATHMOVE:
- case JTAG_SCAN:
- break;
-
- default:
- /* some events, such as resets, need a queue flush to ensure
- *consistency */
- tap_state_queue_run();
- dtc_queue_run();
- break;
- }
-
- switch (cmd->type) {
- case JTAG_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-#endif
- if ((cmd->cmd.reset->trst == 1) ||
- (cmd->cmd.reset->srst &&
- (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
- tap_set_state(TAP_RESET);
- rlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
-#endif
- if (cmd->cmd.runtest->end_state != -1)
- rlink_end_state(cmd->cmd.runtest->end_state);
- rlink_runtest(cmd->cmd.runtest->num_cycles);
- break;
- case JTAG_TLR_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
-#endif
- if (cmd->cmd.statemove->end_state != -1)
- rlink_end_state(cmd->cmd.statemove->end_state);
- rlink_state_move();
- break;
- case JTAG_PATHMOVE:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("pathmove: %i states, end in %i",
- cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-#endif
- rlink_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_SCAN:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("%s scan end in %i",
- (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
- cmd->cmd.scan->end_state);
-#endif
- if (cmd->cmd.scan->end_state != -1)
- rlink_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- if (rlink_scan(cmd, type, buffer, scan_size) != ERROR_OK)
- retval = ERROR_FAIL;
- break;
- case JTAG_SLEEP:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
-#endif
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
- cmd = cmd->next;
- }
-
- /* Flush the DTC queue to make sure any pending reads have been done before exiting this
- *function */
- tap_state_queue_run();
- tmp_retval = dtc_queue_run();
- if (tmp_retval != ERROR_OK)
- retval = tmp_retval;
-
-#ifndef AUTOMATIC_BUSY_LED
- /* turn LED onff */
- ep1_generic_commandl(pHDev, 2,
- EP1_CMD_SET_PORTD_LEDS,
- ~0
- );
-#endif
-
- return retval;
-}
-
-/* Using an unindexed table because it is infrequently accessed and it is short. The table must be
- *in order of ascending speed (and descending prescaler), as it is scanned in reverse. */
-
-static int rlink_speed(int speed)
-{
- int i;
-
- if (speed == 0) {
- /* fastest speed */
- speed = rlink_speed_table[rlink_speed_table_size - 1].prescaler;
- }
-
- for (i = rlink_speed_table_size; i--; ) {
- if (rlink_speed_table[i].prescaler == speed) {
- if (dtc_load_from_buffer(pHDev, rlink_speed_table[i].dtc,
- rlink_speed_table[i].dtc_size) != 0) {
- LOG_ERROR(
- "An error occurred while trying to load DTC code for speed \"%d\".",
- speed);
- exit(1);
- }
-
- if (dtc_start_download() < 0) {
- LOG_ERROR("starting DTC: %s", usb_strerror());
- exit(1);
- }
-
- return ERROR_OK;
- }
- }
-
- LOG_ERROR("%d is not a supported speed", speed);
- return ERROR_FAIL;
-}
-
-static int rlink_speed_div(int speed, int *khz)
-{
- int i;
-
- for (i = rlink_speed_table_size; i--; ) {
- if (rlink_speed_table[i].prescaler == speed) {
- *khz = rlink_speed_table[i].khz;
- return ERROR_OK;
- }
- }
-
- LOG_ERROR("%d is not a supported speed", speed);
- return ERROR_FAIL;
-}
-
-static int rlink_khz(int khz, int *speed)
-{
- int i;
-
- if (khz == 0) {
- LOG_ERROR("RCLK not supported");
- return ERROR_FAIL;
- }
-
- for (i = rlink_speed_table_size; i--; ) {
- if (rlink_speed_table[i].khz <= khz) {
- *speed = rlink_speed_table[i].prescaler;
- return ERROR_OK;
- }
- }
-
- LOG_WARNING("The lowest supported JTAG speed is %d KHz", rlink_speed_table[0].khz);
- *speed = rlink_speed_table[0].prescaler;
- return ERROR_OK;
-}
-
-static int rlink_init(void)
-{
- int i, j, retries;
- uint8_t reply_buffer[USB_EP1IN_SIZE];
-
- usb_init();
- const uint16_t vids[] = { USB_IDVENDOR, 0 };
- const uint16_t pids[] = { USB_IDPRODUCT, 0 };
- if (jtag_usb_open(vids, pids, &pHDev) != ERROR_OK)
- return ERROR_FAIL;
-
- struct usb_device *dev = usb_device(pHDev);
- if (dev->descriptor.bNumConfigurations > 1) {
- LOG_ERROR("Whoops! NumConfigurations is not 1, don't know what to do...");
- return ERROR_FAIL;
- }
- if (dev->config->bNumInterfaces > 1) {
- LOG_ERROR("Whoops! NumInterfaces is not 1, don't know what to do...");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("Opened device, pHDev = %p", pHDev);
-
- /* usb_set_configuration required under win32 */
- usb_set_configuration(pHDev, dev->config[0].bConfigurationValue);
-
- retries = 3;
- do {
- i = usb_claim_interface(pHDev, 0);
- if (i) {
- LOG_ERROR("usb_claim_interface: %s", usb_strerror());
-#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
- j = usb_detach_kernel_driver_np(pHDev, 0);
- if (j)
- LOG_ERROR("detach kernel driver: %s", usb_strerror());
-#endif
- } else {
- LOG_DEBUG("interface claimed!");
- break;
- }
- } while (--retries);
-
- if (i) {
- LOG_ERROR("Initialisation failed.");
- return ERROR_FAIL;
- }
- if (usb_set_altinterface(pHDev, 0) != 0) {
- LOG_ERROR("Failed to set interface.");
- return ERROR_FAIL;
- }
-
- /* The device starts out in an unknown state on open. As such,
- * result reads time out, and it's not even known whether the
- * command was accepted. So, for this first command, we issue
- * it repeatedly until its response doesn't time out. Also, if
- * sending a command is going to time out, we find that out here.
- *
- * It must be possible to open the device in such a way that
- * this special magic isn't needed, but, so far, it escapes us.
- */
- for (i = 0; i < 5; i++) {
- j = ep1_generic_commandl(
- pHDev, 1,
- EP1_CMD_GET_FWREV
- );
- if (j < USB_EP1OUT_SIZE) {
- LOG_ERROR("USB write error: %s", usb_strerror());
- return ERROR_FAIL;
- }
- j = usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)reply_buffer, sizeof(reply_buffer),
- 200
- );
- if (j != -ETIMEDOUT)
- break;
- }
-
- if (j < (int)sizeof(reply_buffer)) {
- LOG_ERROR("USB read error: %s", usb_strerror());
- return ERROR_FAIL;
- }
- LOG_DEBUG(INTERFACE_NAME " firmware version: %d.%d.%d",
- reply_buffer[0],
- reply_buffer[1],
- reply_buffer[2]);
-
- if ((reply_buffer[0] != 0) || (reply_buffer[1] != 0) || (reply_buffer[2] != 3))
- LOG_WARNING(
- "The rlink device is not of the version that the developers have played with. It may or may not work.");
-
- /* Probe port E for adapter presence */
- ep1_generic_commandl(
- pHDev, 16,
- EP1_CMD_MEMORY_WRITE, /* Drive sense pin with 0 */
- ST7_PEDR >> 8,
- ST7_PEDR,
- 3,
- 0x00, /* DR */
- ST7_PE_ADAPTER_SENSE_OUT, /* DDR */
- ST7_PE_ADAPTER_SENSE_OUT, /* OR */
- EP1_CMD_MEMORY_READ, /* Read back */
- ST7_PEDR >> 8,
- ST7_PEDR,
- 1,
- EP1_CMD_MEMORY_WRITE, /* Drive sense pin with 1 */
- ST7_PEDR >> 8,
- ST7_PEDR,
- 1,
- ST7_PE_ADAPTER_SENSE_OUT
- );
-
- usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)reply_buffer, 1,
- USB_TIMEOUT_MS
- );
-
- if ((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) != 0)
- LOG_WARNING("target detection problem");
-
- ep1_generic_commandl(
- pHDev, 11,
- EP1_CMD_MEMORY_READ, /* Read back */
- ST7_PEDR >> 8,
- ST7_PEDR,
- 1,
- EP1_CMD_MEMORY_WRITE, /* float port E */
- ST7_PEDR >> 8,
- ST7_PEDR,
- 3,
- 0x00, /* DR */
- 0x00, /* DDR */
- 0x00 /* OR */
- );
-
- usb_bulk_read(
- pHDev, USB_EP1IN_ADDR,
- (char *)reply_buffer, 1,
- USB_TIMEOUT_MS
- );
-
-
- if ((reply_buffer[0] & ST7_PE_ADAPTER_SENSE_IN) == 0)
- LOG_WARNING("target not plugged in");
-
- /* float ports A and B */
- ep1_generic_commandl(
- pHDev, 11,
- EP1_CMD_MEMORY_WRITE,
- ST7_PADDR >> 8,
- ST7_PADDR,
- 2,
- 0x00,
- 0x00,
- EP1_CMD_MEMORY_WRITE,
- ST7_PBDDR >> 8,
- ST7_PBDDR,
- 1,
- 0x00
- );
-
- /* make sure DTC is stopped, set VPP control, set up ports A and B */
- ep1_generic_commandl(
- pHDev, 14,
- EP1_CMD_DTC_STOP,
- EP1_CMD_SET_PORTD_VPP,
- ~(ST7_PD_VPP_SHDN),
- EP1_CMD_MEMORY_WRITE,
- ST7_PADR >> 8,
- ST7_PADR,
- 2,
- ((~(0)) & (ST7_PA_NTRST)),
- (ST7_PA_NTRST),
- /* port B has no OR, and we want to emulate open drain on NSRST, so we set DR to 0
- *here and later assert NSRST by setting DDR bit to 1. */
- EP1_CMD_MEMORY_WRITE,
- ST7_PBDR >> 8,
- ST7_PBDR,
- 1,
- 0x00
- );
-
- /* set LED updating mode and make sure they're unlit */
- ep1_generic_commandl(
- pHDev, 3,
-#ifdef AUTOMATIC_BUSY_LED
- EP1_CMD_LEDUE_BUSY,
-#else
- EP1_CMD_LEDUE_NONE,
-#endif
- EP1_CMD_SET_PORTD_LEDS,
- ~0
- );
-
- tap_state_queue_init();
- dtc_queue_init();
- rlink_reset(0, 0);
-
- return ERROR_OK;
-}
-
-static int rlink_quit(void)
-{
- /* stop DTC and make sure LEDs are off */
- ep1_generic_commandl(
- pHDev, 6,
- EP1_CMD_DTC_STOP,
- EP1_CMD_LEDUE_NONE,
- EP1_CMD_SET_PORTD_LEDS,
- ~0,
- EP1_CMD_SET_PORTD_VPP,
- ~0
- );
-
- usb_release_interface(pHDev, 0);
- usb_close(pHDev);
-
- return ERROR_OK;
-}
-
-struct jtag_interface rlink_interface = {
- .name = "rlink",
- .init = rlink_init,
- .quit = rlink_quit,
- .speed = rlink_speed,
- .speed_div = rlink_speed_div,
- .khz = rlink_khz,
- .execute_queue = rlink_execute_queue,
-};
diff --git a/src/jtag/drivers/rlink.h b/src/jtag/drivers/rlink.h
deleted file mode 100644
index 74b6258..0000000
--- a/src/jtag/drivers/rlink.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 Lou Deluxe *
- * lou.openocd012@fixit.nospammail.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_RLINK_H
-#define OPENOCD_JTAG_DRIVERS_RLINK_H
-
-struct rlink_speed_table {
- uint8_t const *dtc;
- uint16_t dtc_size;
- uint16_t khz;
- uint8_t prescaler;
-};
-
-extern const struct rlink_speed_table rlink_speed_table[];
-extern const size_t rlink_speed_table_size;
-
-#endif /* OPENOCD_JTAG_DRIVERS_RLINK_H */
diff --git a/src/jtag/drivers/rlink_call.m4 b/src/jtag/drivers/rlink_call.m4
deleted file mode 100644
index b27f392..0000000
--- a/src/jtag/drivers/rlink_call.m4
+++ /dev/null
@@ -1,483 +0,0 @@
-m4_divert(`-1')
-/***************************************************************************
- * Copyright (C) 2008 Lou Deluxe *
- * lou.openocd012@fixit.nospammail.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-m4_dnl Setup and hold times depend on SHIFTER_PRESCALER
-m4_define(`SETUP_DELAY_CYCLES', m4_eval(`('SHIFTER_PRESCALER` + 1) / 2'))
-m4_define(`HOLD_DELAY_CYCLES', m4_eval(`'SHIFTER_PRESCALER` / 2'))
-
-m4_dnl Some macros to make nybble handling a little easier
-m4_define(`m4_high_nybble', `m4_eval(`(($1) >> 4) & 0xf')')
-m4_define(`m4_low_nybble', `m4_eval(`($1) & 0xf')')
-
-m4_dnl A macro to generate a number of NOPs depending on the argument
-m4_define(`m4_0_to_5_nops', `m4_ifelse(m4_eval(`($1) >= 1'), 1, ` NOP
-'m4_ifelse(m4_eval(`($1) >= 2'), 1, ` NOP
-'m4_ifelse(m4_eval(`($1) >= 3'), 1, ` NOP
-'m4_ifelse(m4_eval(`($1) >= 4'), 1, ` NOP
-'m4_ifelse(m4_eval(`($1) >= 5'), 1, ` NOP
-')))))')
-
-
-m4_dnl Some macros to facilitate bit-banging delays.
-m4_dnl There are 3 of them. One for self-contained delays, and two for those which must be split between setup and loop to keep from disturbing A at delay time.
-m4_dnl The argument passed to any of them is the number of cycles which the delay should consume.
-
-m4_dnl This one is self-contained.
-
-m4_define(`m4_delay',
-`; delay (m4_eval($1) cycles)'
-`m4_ifelse(m4_eval(`('$1`) < 6'), 1,
- m4_0_to_5_nops($1)
-,
- m4_ifelse(m4_eval(`(('$1`) - 3) % 2'), 1, ` NOP')
- A.H = m4_high_nybble(`(('$1`) - 3) / 2')
- A.L = m4_low_nybble(`(('$1`) - 3) / 2')
- Y = A
- DECY
- JP -1
-)')
-
-
-m4_dnl These are the setup and loop parts of the split delay.
-m4_dnl The argument passed to both must match for the result to make sense.
-m4_dnl The setup does not figure into the delay. It takes 3 cycles when a loop is used and none if nops are used.
-
-m4_define(`m4_delay_setup',
-`; delay setup (m4_eval($1) cycles)'
-`m4_ifelse(m4_eval(`('$1`) < 6'), 0, ` '
- A.H = m4_high_nybble(`('$1`) / 2')
- A.L = m4_low_nybble(`('$1`) / 2')
- Y = A
-)')
-
-m4_define(`m4_delay_loop',
-`; delay loop (m4_eval($1) cycles)'
-`m4_ifelse(m4_eval(`('$1`) < 6'), 1,
- m4_0_to_5_nops($1)
-,
- m4_ifelse(m4_eval(`('$1`) % 2'), 1, ` NOP')
- DECY
- JP -1
-)')
-
-m4_dnl These are utility macros for use with delays. Specifically, there is code below which needs some predictability in code size for relative jumps to reach. The m4_delay macro generates an extra NOP when an even delay is needed, and the m4_delay_loop macro generates an extra NOP when an odd delay is needed. Using this for the argument to the respective macro rounds up the argument so that the extra NOP will not be generated. There is also logic built in to cancel the rounding when the result is small enough that a loop would not be generated.
-
-m4_define(`m4_delay_loop_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) + 1) / 2 * 2'))')
-m4_define(`m4_delay_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) / 2 * 2) + 1'))')
-
-
-m4_divert(`0')m4_dnl
-
-;------------------------------------------------------------------------------
-:opcode_error
-; This is at address 0x00 in case of empty LUT entries
- STATUS STOP ERROR
-
-;------------------------------------------------------------------------------
-; Command interpreter at address 0x01 because it is branched to a lot and having it be 0x01 means we can use X for it, which is already used for other purposes which want it to be 1.
-; Assumes X is 1
-; Assumes ADR_BUFFER0 points to the next command byte
-; Stores the current command byte in CMP01
-
-:command_interpreter
- A = DATA_BUFFER0
- ADR_BUFFER0 += X
- CMP01 = A ; store the current command for later
-
- EXCHANGE ; put MSN into LSN
- A.H = 0xc ; lookup table at 0x1550 + 0xc0 = 0x1610
-
- ; branch to address in lookup table
- Y = A
- A = <Y>
- BRANCH
-
-;------------------------------------------------------------------------------
-; LUT for high nybble
-
-;LUT; c0 opcode_error
-;LUT; c1 opcode_shift_tdi_andor_tms_bytes
-;LUT; c2 opcode_shift_tdi_andor_tms_bytes
-;LUT; c3 opcode_shift_tdi_andor_tms_bytes
-;LUT; c4 opcode_shift_tdo_bytes
-;LUT; c5 opcode_error
-;LUT; c6 opcode_shift_tdio_bytes
-;LUT; c7 opcode_error
-;LUT; c8 opcode_shift_tms_tdi_bit_pair
-;LUT; c9 opcode_shift_tms_bits
-;LUT; ca opcode_error
-;LUT; cb opcode_error
-;LUT; cc opcode_error
-;LUT; cd opcode_error
-;LUT; ce opcode_shift_tdio_bits
-;LUT; cf opcode_stop
-
-
-;------------------------------------------------------------------------------
-; USB/buffer handling
-;
-
-;ENTRY; download entry_download
-
-opcode_stop:
-opcode_next_buffer:
- ; pointer to completion flag
- A.H = 0xf
- A.L = 0xf
- Y = A
-
- A = OR_MPEG ; buffer indicator from previous iteration
- <Y> = A ; either indicator will have bit 0 set
- BSET 1 ; was buffer 1 previously current?
-; A.H = 0 ; already zero from OR_MPEG
- JP opcode_next_buffer_0
-
-opcode_next_buffer_1:
- A.L = 0x1 ; ack buffer 0
- BUFFER_MNGT = A
-; A.H = 0x0 ; already zero from BUFFER_MNGT
- A.L = 0x3 ; Input buffer 1 = 0x1850 (0x0300)
- JP +4
-
-opcode_next_buffer_0:
- A.L = 0x2 ; ack buffer 1
- BUFFER_MNGT = A
-entry_download:
- A = X ; Input buffer 0 = 0x1650 (0x0100)
-
- ADR_BUFFER01 = A
- OR_MPEG = A ; store for next iteration
-
- A.L = 0x0
- BUFFER_MNGT = A ; finish acking previous buffer
- Y = A
- ADR_BUFFER00 = A
- ADR_BUFFER11 = A
-
- A.H = 0x4 ; Output buffer = 0x1590 (0x0040)
- ADR_BUFFER10 = A
-
- EXCHANGE ; 0x04
- X = A ; for the spin loop below
-
- ; pointer to status in shared memory
- DECY ; setting to 0 above and decrementing here saves a byte
-
- ; wait until a command buffer is available
- A = BUFFER_MNGT ; spin while neither of bits 2 or 3 are set
- CP A<X ; this is slightly faster and smaller than trying to AND and compare the result, and it lets us just use the nybble-swapped 0x40 from the output buffer setup.
- JP -2
- <Y> = A ; update status once done spinning
-
- ; restore X, since we used it
-; A.H = 0 ; high nybble of BUFFER_MNGT will always be 0 the way we use it
- A.L = 1
- X = A
-
- ; go to command interpreter
- BRANCH
-
-
-;;------------------------------------------------------------------------------
-;:opcode_stop
-;;
-;
-; ; Ack buffer 0 in download mode
-; A.L = 0x1
-; BUFFER_MNGT = A
-;
-; STATUS STOP
-
-
-;------------------------------------------------------------------------------
-:opcode_shift_tdi_andor_tms_bytes
-;
-
- A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
- A.H = 0
- Y = A ; loop counter
-
- A = CMP01
- EXCHANGE
- CMP01 = A ; we're interested in bits in the high nybble
-
-opcode_shift_tdi_andor_tms_bytes__loop:
-
-; set tdi to supplied byte or zero
- A = CMP01
- BSET 1
- JP +4
- A.H = 0
- A.L = 0
- JP +3
- A = DATA_BUFFER0
- ADR_BUFFER0 += X
- SHIFT_MPEG = A
-
-; set tms to supplied byte or zero
- A = CMP01
- BCLR 0
- JP +5
- A = DATA_BUFFER0
- ADR_BUFFER0 += X
- SHIFT_CARD = A
- SHIFT CARD OUT=>PIN0
-
-; run both shifters as nearly simultaneously as possible
- SHIFT MPEG OUT=>PIN1
-
- A = CTRL_FCI
- EXCHANGE
- BCLR 3
- JP -3
-
- DECY
- JP opcode_shift_tdi_andor_tms_bytes__loop
-
- A = X
- BRANCH
-
-
-;------------------------------------------------------------------------------
-:opcode_shift_tdo_bytes
-;
-
- A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
- A.H = 0
- Y = A ; loop counter
-
-opcode_shift_tdo_bytes__loop:
- SHIFT MPEG PIN0=>IN
-
- A = CTRL_FCI
- EXCHANGE
- BCLR 3
- JP -3
-
- ; put shifted byte into output buffer
- A = SHIFT_MPEG
- DATA_BUFFER1 = A
- ADR_BUFFER1 += X
-
- DECY
- JP opcode_shift_tdo_bytes__loop
-
- A = X
- BRANCH
-
-
-;------------------------------------------------------------------------------
-:opcode_shift_tdio_bytes
-;
-
- A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
- A.H = 0
- CMP10 = A ; byte loop counter
-
- A.H = opcode_shift_tdio_bytes__sub_return
- A.L = opcode_shift_tdio_bytes__sub_return
- CMP00 = A ; return address
-
-opcode_shift_tdio_bytes__loop:
- A.H = 0
- A.L = 7
- CMP11 = A ; always use 8 bits
-
- JP sub_shift_tdio_bits
-opcode_shift_tdio_bytes__sub_return:
-
- A = CMP10 ; byte loop counter
- CP A=>X
- CLC
- A -= X
- CMP10 = A
- JP opcode_shift_tdio_bytes__loop
-
- A = X
-;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
- BRANCH
-
-
-;------------------------------------------------------------------------------
-:opcode_shift_tdio_bits
-;
-
- A = CMP01 ; bits 2..0 contain the number of bits to shift - 1
- A.H = 0
- BCLR 3 ; set TMS=1 if bit 3 was set
- CMP11 = A ; bit loop counter
-
- A.H = opcode_shift_tdio_bits__sub_return
- A.L = opcode_shift_tdio_bits__sub_return
- CMP00 = A ; return address
-
- JP sub_shift_tdio_bits
- A.L = 0x1 ; TMS=1
- DR_CARD = A
- JP sub_shift_tdio_bits
-opcode_shift_tdio_bits__sub_return:
-
- A = X
-;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
- BRANCH
-
-
-;------------------------------------------------------------------------------
-:sub_shift_tdio_bits
-;
-
- A = DATA_BUFFER0 ; get byte from input buffer
- ADR_BUFFER0 += X
- MASK = A ; put it in MASK where bit routine will use it
-
-:sub_shift_tdio_bits__loop
-m4_delay_setup(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1))
-
- A = MASK ; shift TDO into and TDI out of MASK via carry
- A += MASK
- MASK = A
-
- ; shifting out TDI
- A.L = 0x2 ; TCK=0, TDI=1
- CP CARRY
- JP +2
- A.L = 0x0 ; TCK=0, TDI=0
- DR_MPEG = A
-
-m4_delay_loop(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1))
-
- BSET 2 ; TCK high
- DR_MPEG = A
-
- A = DR_MPEG ; set carry bit to TDO
- CLC
- BCLR 0
- JP +2
- SEC
-
-m4_delay(HOLD_DELAY_CYCLES - 10)
-
- A = CMP11 ; bit loop counter
- Y = A ; use Y to avoid corrupting carry bit with subtract
- DECY
- A = Y
- CMP11 = A
- JP :sub_shift_tdio_bits__loop
-
- ; shift last TDO bit into result
- A = MASK
- A += MASK
- DATA_BUFFER1 = A
- ADR_BUFFER1 += X
-
- A = CMP00 ; return to caller
- BRANCH
-
-
-;------------------------------------------------------------------------------
-:opcode_shift_tms_tdi_bit_pair
-;
-
-; set TMS line manually
- A = CMP01 ; bits 3..0 contain TDI and TMS bits and whether to return TDO
- BSET 0 ; TMS bit
- A.L = 0x1 ; TMS=1
- JP +2
- A.L = 0x0 ; TMS=0
- DR_CARD = A
-
-; stuff command buffer with bitmap of single TDI bit
- A = CMP01
- BSET 1 ; TDI bit
- A.H = 0x8 ; TDI=1
- JP +2
- A.H = 0x0 ; TDI=0
- ADR_BUFFER0 -= X
- DATA_BUFFER0 = A
-
- A.H = 0
- A.L = 0
- CMP11 = A ; bit loop counter (only doing one bit)
-
- A.H = opcode_shift_tms_tdi_bit_pair__sub_return
- A.L = opcode_shift_tms_tdi_bit_pair__sub_return
- CMP00 = A ; return address
-
-; jump this way due to relative jump range issues
- A.H = sub_shift_tdio_bits
- A.L = sub_shift_tdio_bits
- BRANCH
-opcode_shift_tms_tdi_bit_pair__sub_return:
-
- A = CMP01
- BSET 3 ; bit says whether to return TDO
- JP +2
- ADR_BUFFER1 -= X ; subroutine returns it, so undo that
-
- A = X
- DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
- BRANCH
-
-
-;------------------------------------------------------------------------------
-:opcode_shift_tms_bits
-;
-
- A = CMP01 ; bits 3..0 contain the number of bits to shift - 1 (only 1-8 bits is valid... no checking, just improper operation)
- A.H = 0
- CMP11 = A ; bit loop counter
-
- A = DATA_BUFFER0 ; get byte from input buffer
- ADR_BUFFER0 += X
- MASK = A ; The byte we'll be shifting
-
-:opcode_shift_tms_bits__loop
-m4_delay_setup(SETUP_DELAY_CYCLES - 1)
-
- A = MASK ; shift TMS out of MASK via carry
- A += MASK
- MASK = A
-
- ; shifting out TMS
- A.L = 0x1 ; TCK=0, TDI=0, TMS=1
- CP CARRY
- JP +2
- A.L = 0x0 ; TCK=0, TDI=0, TMS=0
- DR_CARD = A
- DR_MPEG = A
-
-m4_delay_loop(SETUP_DELAY_CYCLES - 1)
-
- BSET 2 ; TCK high
- DR_MPEG = A
-
-m4_delay(HOLD_DELAY_CYCLES - 10)
-
- A = CMP11 ; bit loop counter
- CP A=>X
- CLC
- A -= X
- CMP11 = A
- JP :opcode_shift_tms_bits__loop
-
- A = X
- DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
- BRANCH
-
-
diff --git a/src/jtag/drivers/rlink_dtc_cmd.h b/src/jtag/drivers/rlink_dtc_cmd.h
deleted file mode 100644
index ff9e8b2..0000000
--- a/src/jtag/drivers/rlink_dtc_cmd.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 Lou Deluxe *
- * lou.openocd012@fixit.nospammail.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_RLINK_DTC_CMD_H
-#define OPENOCD_JTAG_DRIVERS_RLINK_DTC_CMD_H
-
-/* A command position with the high nybble of 0x0 is reserved for an error condition.
- * If executed, it stops the DTC and raises the ERROR flag */
-
-#define DTC_CMD_SHIFT_TMS_BYTES(bytes) ((0x1 << 4) | ((bytes) - 1))
-/* Shift 1-16 bytes out TMS. TDI is 0. */
-/* Bytes to shift follow. */
-
-#define DTC_CMD_SHIFT_TDI_BYTES(bytes) ((0x2 << 4) | ((bytes) - 1))
-/* Shift 1-16 bytes out TDI. TMS is 0. */
-/* Bytes to shift follow. */
-
-#define DTC_CMD_SHIFT_TDI_AND_TMS_BYTES(bytes) ((0x3 << 4) | ((bytes) - 1))
-/* Shift 1-16 byte pairs out TDI and TMS. */
-/* Byte pairs to shift follow in TDI, TMS order. */
-
-#define DTC_CMD_SHIFT_TDO_BYTES(bytes) ((0x4 << 4) | ((bytes) - 1))
-/* Shift 1-16 bytes in TDO. TMS is unaffected. */
-/* Reply buffer contains bytes shifted in. */
-
-#define DTC_CMD_SHIFT_TDIO_BYTES(bytes) ((0x6 << 4) | ((bytes) - 1))
-/* Shift 1-16 bytes out TDI and in TDO. TMS is unaffected. */
-
-#define DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(tms, tdi, tdo) ((0x8 << 4) | (\
- (tms) ? (1 << 0) : 0 \
-) | (\
- (tdi) ? (1 << 1) : 0 \
-) | (\
- (tdo) ? (1 << 3) : 0 \
-))
-/* Single bit shift.
- * tms and tdi are the levels shifted out on TMS and TDI, respectively.
- * tdo indicates whether a byte will be returned in the reply buffer with its
- * least significant bit set to reflect TDO
- * Care should be taken when tdo is zero, as the underlying code actually does put
- * that byte in the reply buffer. Setting tdo to zero just moves the pointer back.
- * The result is that if this command is executed when the reply buffer is already full,
- * a byte will be written erroneously to memory not belonging to the reply buffer.
- * This could be worked around at the expense of DTC code space and speed. */
-
-#define DTC_CMD_SHIFT_TMS_BITS(bits) ((0x9 << 4) | ((bits) - 1))
-/* Shift 1-8 bits out TMS. */
-/* Bits to be shifted out are left justified in the following byte. */
-
-#define DTC_CMD_SHIFT_TDIO_BITS(bits) ((0xe << 4) | ((bits) - 1))
-/* Shift 1-8 bits out TDI and in TDO, TMS is unaffected. */
-/* Bits to be shifted out are left justified in the following byte. */
-/* Bits shifted in are right justified in the byte placed in the reply buffer. */
-
-#define DTC_CMD_STOP (0xf << 4)
-/* Stop processing the command buffer and wait for the next one. */
-/* A shared status byte is updated with bit 0 set when this has happened,
- * and it is cleared when a new command buffer becomes ready.
- * The host can poll that byte to see when it is safe to read a reply. */
-
-#endif /* OPENOCD_JTAG_DRIVERS_RLINK_DTC_CMD_H */
diff --git a/src/jtag/drivers/rlink_ep1_cmd.h b/src/jtag/drivers/rlink_ep1_cmd.h
deleted file mode 100644
index 3f9f2b3..0000000
--- a/src/jtag/drivers/rlink_ep1_cmd.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 Lou Deluxe *
- * lou.openocd012@fixit.nospammail.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_RLINK_EP1_CMD_H
-#define OPENOCD_JTAG_DRIVERS_RLINK_EP1_CMD_H
-
-/*
- * Command opcodes that can be sent over endpoint 1.
- * This codifies information provided by Rob Brown <rob@cobbleware.com>.
- * The buffer can contain several of these, but only one which returns data.
- * Some of these opcodes have arguments, which follow immediately.
- * If shorter than the packet size, trailing positions should be zero-filled.
- */
-
-/* LED update enables:
- * When enabled, each LED is updated automatically.
- * When not enabled, each LED can be controlled manually with EP1_CMD_SET_PORTD_LEDS.
- */
-#define EP1_CMD_LEDUE_BOTH (0x05)
-/* EP1_CMD_LEDUE_NONE has the side effect of turning the LEDs on */
-#define EP1_CMD_LEDUE_NONE (0x06)
-#define EP1_CMD_LEDUE_ERROR (0x17)
-#define EP1_CMD_LEDUE_BUSY (0x18)
-
-#define EP1_CMD_DTC_STOP (0x0b)
-#define EP1_CMD_DTC_LOAD (0x0c)
-#define EP1_CMD_DTC_CALL (0x0d)
-#define EP1_CMD_SET_UPLOAD (0x0f)
-#define EP1_CMD_SET_DOWNLOAD (0x10)
-#define EP1_CMD_DTC_WAIT (0x12)
-#define EP1_CMD_DTC_GET_STATUS (0x15)
-/* a quick way to just read back one byte */
-#define EP1_CMD_DTC_GET_CACHED_STATUS (0x16)
-
-/* Writes upper 2 bits (SHDN and SEL) of port D with argument */
-#define EP1_CMD_SET_PORTD_VPP (0x19)
-/* Writes lower 2 bits (BUSY and ERROR) of port D with argument */
-#define EP1_CMD_SET_PORTD_LEDS (0x1a)
-
-#define EP1_CMD_MEMORY_READ (0x28)
-#define EP1_CMD_MEMORY_WRITE (0x29)
-#define EP1_CMD_GET_FWREV (0xfe)
-#define EP1_CMD_GET_SERIAL (0xff)
-
-#endif /* OPENOCD_JTAG_DRIVERS_RLINK_EP1_CMD_H */
diff --git a/src/jtag/drivers/rlink_init.m4 b/src/jtag/drivers/rlink_init.m4
deleted file mode 100644
index 8ad2f51..0000000
--- a/src/jtag/drivers/rlink_init.m4
+++ /dev/null
@@ -1,72 +0,0 @@
-m4_divert(`-1')
-/***************************************************************************
- * Copyright (C) 2008 Lou Deluxe *
- * lou.openocd012@fixit.nospammail.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-m4_undefine(`CTRL_MPEG_L')
-m4_undefine(`CTRL_CARD_L')
-
-m4_ifelse(SHIFTER_PRESCALER, 1, `
- m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x0')')
-')
-m4_ifelse(SHIFTER_PRESCALER, 2, `
- m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x2')')
- m4_define(`CTRL_CARD_L', `m4_eval(`0x8 | 0x1')')
-')
-m4_ifelse(SHIFTER_PRESCALER, 8, `
- m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x3')')
-')
-m4_ifelse(SHIFTER_PRESCALER, 11, `
- m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x4')')
-')
-m4_ifelse(SHIFTER_PRESCALER, 64, `
- m4_define(`CTRL_MPEG_L', `m4_eval(`0x8 | 0x7')')
-')
-
-m4_ifdef(`CTRL_MPEG_L',,`
- m4_errprint(`SHIFTER_PRESCALER was not defined with a supported value
-') m4_m4exit(`1')
-')
-
-m4_divert(`0')m4_dnl
-
-init:
- A.H = 0
-
- A.L = 0
-
- DR_MPEG = A ; TDI and TCK start out low
- DR_CARD = A ; TMS starts out low
-
- A.L = 0x6
-
- CTRL_FCI = A ; MPEG and CARD driven by FCI
- DDR_MPEG = A ; TDI and TCK are outputs
-
- A.L = 0x1
-
- X = A ; X == 1
- DDR_CARD = A ; TMS is output
-
- A.L = CTRL_MPEG_L
- CTRL_MPEG = A
-m4_ifdef(`CTRL_CARD_L',
-` A.L = 'CTRL_CARD_L`
-')m4_dnl
- CTRL_CARD = A
-
- STATUS STOP
diff --git a/src/jtag/drivers/rlink_speed_table.c b/src/jtag/drivers/rlink_speed_table.c
deleted file mode 100644
index b843577..0000000
--- a/src/jtag/drivers/rlink_speed_table.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* This file was created automatically by ../../../tools/rlink_make_speed_table/rlink_make_speed_table.pl. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rlink.h"
-#include "rlink_st7.h"
-
-static const uint8_t dtc_64[] = {
- 0, 2, 68, 84, 67, 2, 13, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148,
- 191, 143, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0, 42, 42,
- 42, 73, 0, 88, 0, 160, 189, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100, 111, 119,
- 110, 108, 111, 97, 100, 2, 226, 7, 219, 39, 137, 51, 172, 130, 192, 96,
- 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159, 193, 133,
- 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9, 98, 128, 177,
- 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176, 67, 219, 39,
- 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60, 118, 193,
- 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105, 193, 96,
- 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36, 138, 105,
- 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67, 193, 96, 219,
- 39, 131, 161, 176, 130, 195, 53, 131, 178, 10, 66, 176, 151, 60, 97, 58,
- 151, 215, 2, 40, 66, 1, 0, 160, 185, 130, 60, 97, 203, 130, 60, 194, 139,
- 127, 195, 53, 156, 47, 200, 96, 201, 56, 177, 66, 176, 147, 201, 57, 168,
- 66, 160, 38, 155, 160, 176, 139, 171, 182, 136, 167, 183, 96, 201, 59,
- 66, 46, 193, 151, 96, 201, 160, 139, 219, 39, 131, 160, 191, 130, 195,
- 53, 131, 177, 10, 66, 176, 147, 151, 0, 60, 97, 58, 151, 0, 160, 185, 130,
- 60, 97, 203, 8, 2, 36, 139, 124, 193, 151, 96
-};
-
-static const uint8_t dtc_11[] = {
- 0, 2, 68, 84, 67, 2, 13, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148,
- 188, 143, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0, 42, 42,
- 42, 73, 0, 88, 0, 154, 183, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100, 111, 119,
- 110, 108, 111, 97, 100, 2, 213, 7, 219, 39, 137, 51, 172, 130, 192, 96,
- 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159, 193, 133,
- 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9, 98, 128, 177,
- 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176, 67, 219, 39,
- 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60, 118, 193,
- 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105, 193, 96,
- 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36, 138, 105,
- 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67, 193, 96, 219,
- 39, 131, 195, 53, 131, 178, 10, 66, 176, 151, 0, 0, 0, 0, 0, 58, 151, 215,
- 2, 40, 66, 1, 203, 130, 60, 194, 139, 121, 195, 53, 156, 47, 200, 96, 201,
- 56, 177, 66, 176, 147, 201, 57, 168, 66, 160, 38, 155, 160, 176, 139, 171,
- 176, 136, 167, 183, 96, 201, 59, 66, 46, 193, 151, 96, 201, 160, 139, 219,
- 39, 131, 195, 53, 131, 177, 10, 66, 176, 147, 151, 0, 0, 0, 0, 0, 58, 151,
- 203, 8, 2, 36, 139, 117, 193, 151, 96
-};
-
-static const uint8_t dtc_8[] = {
- 0, 2, 68, 84, 67, 2, 13, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148,
- 187, 143, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0, 42, 42,
- 42, 73, 0, 88, 0, 152, 181, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100, 111, 119,
- 110, 108, 111, 97, 100, 2, 209, 7, 219, 39, 137, 51, 172, 130, 192, 96,
- 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159, 193, 133,
- 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9, 98, 128, 177,
- 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176, 67, 219, 39,
- 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60, 118, 193,
- 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105, 193, 96,
- 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36, 138, 105,
- 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67, 193, 96, 219,
- 39, 131, 195, 53, 131, 178, 10, 66, 176, 151, 0, 0, 0, 58, 151, 215, 2,
- 40, 66, 1, 203, 130, 60, 194, 139, 119, 195, 53, 156, 47, 200, 96, 201,
- 56, 177, 66, 176, 147, 201, 57, 168, 66, 160, 38, 155, 160, 176, 139, 170,
- 190, 136, 167, 183, 96, 201, 59, 66, 46, 193, 151, 96, 201, 160, 139, 219,
- 39, 131, 195, 53, 131, 177, 10, 66, 176, 147, 151, 0, 0, 0, 58, 151, 203,
- 8, 2, 36, 139, 115, 193, 151, 96
-};
-
-static const uint8_t dtc_2[] = {
- 0, 2, 68, 84, 67, 2, 14, 160, 176, 151, 147, 182, 141, 152, 177, 129, 148,
- 186, 143, 185, 142, 5, 3, 0, 0, 0, 2, 68, 84, 67, 4, 0, 192, 5, 15, 0,
- 42, 42, 42, 73, 0, 88, 0, 149, 178, 0, 0, 0, 0, 106, 9, 1, 8, 22, 100,
- 111, 119, 110, 108, 111, 97, 100, 2, 203, 7, 219, 39, 137, 51, 172, 130,
- 192, 96, 175, 191, 130, 217, 128, 57, 69, 177, 159, 179, 68, 178, 159,
- 193, 133, 153, 176, 159, 130, 132, 135, 164, 134, 51, 129, 60, 223, 9,
- 98, 128, 177, 129, 96, 201, 160, 130, 201, 51, 137, 201, 57, 68, 160, 176,
- 67, 219, 39, 154, 201, 40, 69, 219, 39, 150, 17, 27, 205, 51, 43, 99, 60,
- 118, 193, 96, 201, 160, 130, 24, 205, 51, 43, 99, 218, 156, 47, 60, 105,
- 193, 96, 201, 160, 138, 166, 178, 136, 160, 183, 139, 86, 202, 8, 2, 36,
- 138, 105, 193, 96, 201, 160, 43, 139, 167, 181, 136, 70, 177, 147, 67,
- 193, 96, 219, 39, 131, 195, 53, 131, 178, 10, 66, 176, 151, 58, 151, 215,
- 2, 40, 66, 1, 203, 130, 60, 194, 139, 116, 195, 53, 156, 47, 200, 96, 201,
- 56, 177, 66, 176, 147, 201, 57, 168, 66, 160, 38, 155, 160, 176, 139, 170,
- 187, 136, 167, 183, 96, 201, 59, 66, 46, 193, 151, 96, 201, 160, 139, 219,
- 39, 131, 195, 53, 131, 177, 10, 66, 176, 147, 151, 58, 151, 203, 8, 2,
- 36, 139, 112, 193, 151, 96
-};
-
-const struct rlink_speed_table rlink_speed_table[] = {{
- dtc_64, sizeof(dtc_64), (ST7_FOSC * 2) / (1000 * 64), 64
-}, {
- dtc_11, sizeof(dtc_11), (ST7_FOSC * 2) / (1000 * 11), 11
-}, {
- dtc_8, sizeof(dtc_8), (ST7_FOSC * 2) / (1000 * 8), 8
-}, {
- dtc_2, sizeof(dtc_2), (ST7_FOSC * 2) / (1000 * 2), 2
-} };
-
-const size_t rlink_speed_table_size = ARRAY_SIZE(rlink_speed_table);
-
diff --git a/src/jtag/drivers/rlink_st7.h b/src/jtag/drivers/rlink_st7.h
deleted file mode 100644
index 3d573e7..0000000
--- a/src/jtag/drivers/rlink_st7.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 Lou Deluxe *
- * lou.openocd012@fixit.nospammail.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_RLINK_ST7_H
-#define OPENOCD_JTAG_DRIVERS_RLINK_ST7_H
-
-#define ST7_FOSC (12 * 1000000)
-
-/* This is not a complete enumeration of ST7 registers, but it is sufficient for this interface driver. */
-
-#define ST7_PADR (0x0000)
-#define ST7_PADDR (ST7_PADR + 1)
-#define ST7_PAOR (ST7_PADR + 2)
-#define ST7_PBDR (0x0003)
-#define ST7_PBDDR (ST7_PBDR + 1)
-#define ST7_PCDR (0x0006)
-#define ST7_PCDDR (ST7_PCDR + 1)
-#define ST7_PCOR (ST7_PCDR + 2)
-#define ST7_PDDR (0x0009)
-#define ST7_PDDDR (ST7_PDDR + 1)
-#define ST7_PDOR (ST7_PDDR + 2)
-#define ST7_PEDR (0x000c)
-#define ST7_PEDDR (ST7_PEDR + 1)
-#define ST7_PEOR (ST7_PEDR + 2)
-#define ST7_PFDR (0x000f)
-#define ST7_PFDDR (ST7_PFDR + 1)
-
-#define ST7_ADCDR (0x0012)
-#define ST7_ADCCSR (ST7_ADCDR + 1)
-
-#define ST7_EP2TXR (0x003e)
-#define ST7_EP2TXR_STAT_TX0 (1 << 0)
-#define ST7_EP2TXR_STAT_TX1 (1 << 1)
-#define ST7_EP2TXR_STAT_DISABLED (0)
-#define ST7_EP2TXR_STAT_STALL (ST7_EP2TXR_STAT_TX0)
-#define ST7_EP2TXR_STAT_VALID (ST7_EP2TXR_STAT_TX1 | ST7_EP2TXR_STAT_TX0)
-#define ST7_EP2TXR_STAT_NAK (ST7_EP2TXR_STAT_TX1)
-#define ST7_EP2TXR_DTOG_TX (1 << 2)
-#define ST7_EP2TXR_CTR_TX (1 << 3)
-
-#define ST7_USB_BUF_EP0OUT (0x1550)
-#define ST7_USB_BUF_EP0IN (0x1560)
-#define ST7_USB_BUF_EP1OUT (0x1570)
-#define ST7_USB_BUF_EP1IN (0x1580)
-#define ST7_USB_BUF_EP2UODI (0x1590)
-#define ST7_USB_BUF_EP2UIDO (0x1650)
-
-#define ST7_PA0 (1 << 0)
-#define ST7_PA1 (1 << 1)
-#define ST7_PA2 (1 << 2)
-#define ST7_PA3 (1 << 3)
-#define ST7_PA4 (1 << 4)
-#define ST7_PA5 (1 << 5)
-#define ST7_PA6 (1 << 6)
-#define ST7_PA7 (1 << 7)
-
-#define ST7_PB0 (1 << 0)
-#define ST7_PB1 (1 << 1)
-#define ST7_PB2 (1 << 2)
-#define ST7_PB3 (1 << 3)
-#define ST7_PB4 (1 << 4)
-#define ST7_PB5 (1 << 5)
-#define ST7_PB6 (1 << 6)
-#define ST7_PB7 (1 << 7)
-
-#define ST7_PC0 (1 << 0)
-#define ST7_PC1 (1 << 1)
-#define ST7_PC2 (1 << 2)
-#define ST7_PC3 (1 << 3)
-#define ST7_PC4 (1 << 4)
-#define ST7_PC5 (1 << 5)
-#define ST7_PC6 (1 << 6)
-#define ST7_PC7 (1 << 7)
-
-#define ST7_PD0 (1 << 0)
-#define ST7_PD1 (1 << 1)
-#define ST7_PD2 (1 << 2)
-#define ST7_PD3 (1 << 3)
-#define ST7_PD4 (1 << 4)
-#define ST7_PD5 (1 << 5)
-#define ST7_PD6 (1 << 6)
-#define ST7_PD7 (1 << 7)
-
-#define ST7_PE0 (1 << 0)
-#define ST7_PE1 (1 << 1)
-#define ST7_PE2 (1 << 2)
-#define ST7_PE3 (1 << 3)
-#define ST7_PE4 (1 << 4)
-#define ST7_PE5 (1 << 5)
-#define ST7_PE6 (1 << 6)
-#define ST7_PE7 (1 << 7)
-
-#define ST7_PF0 (1 << 0)
-#define ST7_PF1 (1 << 1)
-#define ST7_PF2 (1 << 2)
-#define ST7_PF3 (1 << 3)
-#define ST7_PF4 (1 << 4)
-#define ST7_PF5 (1 << 5)
-#define ST7_PF6 (1 << 6)
-#define ST7_PF7 (1 << 7)
-
-#endif /* OPENOCD_JTAG_DRIVERS_RLINK_ST7_H */
diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c
deleted file mode 100644
index 699c41f..0000000
--- a/src/jtag/drivers/stlink_usb.c
+++ /dev/null
@@ -1,1890 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011-2012 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This code is based on https://github.com/texane/stlink *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <helper/binarybuffer.h>
-#include <jtag/interface.h>
-#include <jtag/hla/hla_layout.h>
-#include <jtag/hla/hla_transport.h>
-#include <jtag/hla/hla_interface.h>
-#include <target/target.h>
-
-#include <target/cortex_m.h>
-
-#include "libusb_common.h"
-
-#define ENDPOINT_IN 0x80
-#define ENDPOINT_OUT 0x00
-
-#define STLINK_WRITE_TIMEOUT 1000
-#define STLINK_READ_TIMEOUT 1000
-
-#define STLINK_NULL_EP 0
-#define STLINK_RX_EP (1|ENDPOINT_IN)
-#define STLINK_TX_EP (2|ENDPOINT_OUT)
-#define STLINK_TRACE_EP (3|ENDPOINT_IN)
-
-#define STLINK_V2_1_TX_EP (1|ENDPOINT_OUT)
-#define STLINK_V2_1_TRACE_EP (2|ENDPOINT_IN)
-
-#define STLINK_SG_SIZE (31)
-#define STLINK_DATA_SIZE (4096)
-#define STLINK_CMD_SIZE_V2 (16)
-#define STLINK_CMD_SIZE_V1 (10)
-
-#define STLINK_V1_PID (0x3744)
-#define STLINK_V2_PID (0x3748)
-#define STLINK_V2_1_PID (0x374B)
-
-/* the current implementation of the stlink limits
- * 8bit read/writes to max 64 bytes. */
-#define STLINK_MAX_RW8 (64)
-
-/* "WAIT" responses will be retried (with exponential backoff) at
- * most this many times before failing to caller.
- */
-#define MAX_WAIT_RETRIES 8
-
-enum stlink_jtag_api_version {
- STLINK_JTAG_API_V1 = 1,
- STLINK_JTAG_API_V2,
-};
-
-/** */
-struct stlink_usb_version {
- /** */
- int stlink;
- /** */
- int jtag;
- /** */
- int swim;
- /** highest supported jtag api version */
- enum stlink_jtag_api_version jtag_api_max;
-};
-
-/** */
-struct stlink_usb_handle_s {
- /** */
- struct jtag_libusb_device_handle *fd;
- /** */
- struct libusb_transfer *trans;
- /** */
- uint8_t rx_ep;
- /** */
- uint8_t tx_ep;
- /** */
- uint8_t trace_ep;
- /** */
- uint8_t cmdbuf[STLINK_SG_SIZE];
- /** */
- uint8_t cmdidx;
- /** */
- uint8_t direction;
- /** */
- uint8_t databuf[STLINK_DATA_SIZE];
- /** */
- uint32_t max_mem_packet;
- /** */
- enum hl_transports transport;
- /** */
- struct stlink_usb_version version;
- /** */
- uint16_t vid;
- /** */
- uint16_t pid;
- /** this is the currently used jtag api */
- enum stlink_jtag_api_version jtag_api;
- /** */
- struct {
- /** whether SWO tracing is enabled or not */
- bool enabled;
- /** trace module source clock */
- uint32_t source_hz;
- } trace;
- /** reconnect is needed next time we try to query the
- * status */
- bool reconnect_pending;
-};
-
-#define STLINK_DEBUG_ERR_OK 0x80
-#define STLINK_DEBUG_ERR_FAULT 0x81
-#define STLINK_SWD_AP_WAIT 0x10
-#define STLINK_SWD_AP_FAULT 0x11
-#define STLINK_SWD_AP_ERROR 0x12
-#define STLINK_SWD_AP_PARITY_ERROR 0x13
-#define STLINK_JTAG_WRITE_ERROR 0x0c
-#define STLINK_JTAG_WRITE_VERIF_ERROR 0x0d
-#define STLINK_SWD_DP_WAIT 0x14
-#define STLINK_SWD_DP_FAULT 0x15
-#define STLINK_SWD_DP_ERROR 0x16
-#define STLINK_SWD_DP_PARITY_ERROR 0x17
-
-#define STLINK_SWD_AP_WDATA_ERROR 0x18
-#define STLINK_SWD_AP_STICKY_ERROR 0x19
-#define STLINK_SWD_AP_STICKYORUN_ERROR 0x1a
-
-#define STLINK_CORE_RUNNING 0x80
-#define STLINK_CORE_HALTED 0x81
-#define STLINK_CORE_STAT_UNKNOWN -1
-
-#define STLINK_GET_VERSION 0xF1
-#define STLINK_DEBUG_COMMAND 0xF2
-#define STLINK_DFU_COMMAND 0xF3
-#define STLINK_SWIM_COMMAND 0xF4
-#define STLINK_GET_CURRENT_MODE 0xF5
-#define STLINK_GET_TARGET_VOLTAGE 0xF7
-
-#define STLINK_DEV_DFU_MODE 0x00
-#define STLINK_DEV_MASS_MODE 0x01
-#define STLINK_DEV_DEBUG_MODE 0x02
-#define STLINK_DEV_SWIM_MODE 0x03
-#define STLINK_DEV_BOOTLOADER_MODE 0x04
-#define STLINK_DEV_UNKNOWN_MODE -1
-
-#define STLINK_DFU_EXIT 0x07
-
-#define STLINK_SWIM_ENTER 0x00
-#define STLINK_SWIM_EXIT 0x01
-
-#define STLINK_DEBUG_ENTER_JTAG 0x00
-#define STLINK_DEBUG_GETSTATUS 0x01
-#define STLINK_DEBUG_FORCEDEBUG 0x02
-#define STLINK_DEBUG_APIV1_RESETSYS 0x03
-#define STLINK_DEBUG_APIV1_READALLREGS 0x04
-#define STLINK_DEBUG_APIV1_READREG 0x05
-#define STLINK_DEBUG_APIV1_WRITEREG 0x06
-#define STLINK_DEBUG_READMEM_32BIT 0x07
-#define STLINK_DEBUG_WRITEMEM_32BIT 0x08
-#define STLINK_DEBUG_RUNCORE 0x09
-#define STLINK_DEBUG_STEPCORE 0x0a
-#define STLINK_DEBUG_APIV1_SETFP 0x0b
-#define STLINK_DEBUG_READMEM_8BIT 0x0c
-#define STLINK_DEBUG_WRITEMEM_8BIT 0x0d
-#define STLINK_DEBUG_APIV1_CLEARFP 0x0e
-#define STLINK_DEBUG_APIV1_WRITEDEBUGREG 0x0f
-#define STLINK_DEBUG_APIV1_SETWATCHPOINT 0x10
-
-#define STLINK_DEBUG_ENTER_JTAG 0x00
-#define STLINK_DEBUG_ENTER_SWD 0xa3
-
-#define STLINK_DEBUG_APIV1_ENTER 0x20
-#define STLINK_DEBUG_EXIT 0x21
-#define STLINK_DEBUG_READCOREID 0x22
-
-#define STLINK_DEBUG_APIV2_ENTER 0x30
-#define STLINK_DEBUG_APIV2_READ_IDCODES 0x31
-#define STLINK_DEBUG_APIV2_RESETSYS 0x32
-#define STLINK_DEBUG_APIV2_READREG 0x33
-#define STLINK_DEBUG_APIV2_WRITEREG 0x34
-#define STLINK_DEBUG_APIV2_WRITEDEBUGREG 0x35
-#define STLINK_DEBUG_APIV2_READDEBUGREG 0x36
-
-#define STLINK_DEBUG_APIV2_READALLREGS 0x3A
-#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS 0x3B
-#define STLINK_DEBUG_APIV2_DRIVE_NRST 0x3C
-
-#define STLINK_DEBUG_APIV2_START_TRACE_RX 0x40
-#define STLINK_DEBUG_APIV2_STOP_TRACE_RX 0x41
-#define STLINK_DEBUG_APIV2_GET_TRACE_NB 0x42
-#define STLINK_DEBUG_APIV2_SWD_SET_FREQ 0x43
-
-#define STLINK_DEBUG_APIV2_DRIVE_NRST_LOW 0x00
-#define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01
-#define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02
-
-#define STLINK_TRACE_SIZE 1024
-#define STLINK_TRACE_MAX_HZ 2000000
-#define STLINK_TRACE_MIN_VERSION 13
-
-/** */
-enum stlink_mode {
- STLINK_MODE_UNKNOWN = 0,
- STLINK_MODE_DFU,
- STLINK_MODE_MASS,
- STLINK_MODE_DEBUG_JTAG,
- STLINK_MODE_DEBUG_SWD,
- STLINK_MODE_DEBUG_SWIM
-};
-
-#define REQUEST_SENSE 0x03
-#define REQUEST_SENSE_LENGTH 18
-
-static const struct {
- int speed;
- int speed_divisor;
-} stlink_khz_to_speed_map[] = {
- {4000, 0},
- {1800, 1}, /* default */
- {1200, 2},
- {950, 3},
- {480, 7},
- {240, 15},
- {125, 31},
- {100, 40},
- {50, 79},
- {25, 158},
- {15, 265},
- {5, 798}
-};
-
-static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size);
-
-/** */
-static int stlink_usb_xfer_v1_get_status(void *handle)
-{
- struct stlink_usb_handle_s *h = handle;
-
- 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)
- return ERROR_FAIL;
-
- uint32_t t1;
-
- t1 = buf_get_u32(h->cmdbuf, 0, 32);
-
- /* check for USBS */
- if (t1 != 0x53425355)
- return ERROR_FAIL;
- /*
- * CSW status:
- * 0 success
- * 1 command failure
- * 2 phase error
- */
- if (h->cmdbuf[12] != 0)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_xfer_rw(void *handle, int cmdsize, const uint8_t *buf, int size)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (jtag_libusb_bulk_write(h->fd, h->tx_ep, (char *)h->cmdbuf, cmdsize,
- STLINK_WRITE_TIMEOUT) != 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) {
- 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) {
- LOG_DEBUG("bulk read failed");
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_xfer_v1_get_sense(void *handle)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 16);
-
- h->cmdbuf[h->cmdidx++] = REQUEST_SENSE;
- h->cmdbuf[h->cmdidx++] = 0;
- h->cmdbuf[h->cmdidx++] = 0;
- h->cmdbuf[h->cmdidx++] = 0;
- h->cmdbuf[h->cmdidx++] = REQUEST_SENSE_LENGTH;
-
- res = stlink_usb_xfer_rw(handle, REQUEST_SENSE_LENGTH, h->databuf, 16);
-
- if (res != ERROR_OK)
- return res;
-
- if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_xfer(void *handle, const uint8_t *buf, int size)
-{
- int err, cmdsize = STLINK_CMD_SIZE_V2;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->version.stlink == 1)
- cmdsize = STLINK_SG_SIZE;
-
- err = stlink_usb_xfer_rw(handle, cmdsize, buf, size);
-
- if (err != ERROR_OK)
- return err;
-
- if (h->version.stlink == 1) {
- if (stlink_usb_xfer_v1_get_status(handle) != ERROR_OK) {
- /* check csw status */
- if (h->cmdbuf[12] == 1) {
- LOG_DEBUG("get sense");
- if (stlink_usb_xfer_v1_get_sense(handle) != ERROR_OK)
- return ERROR_FAIL;
- }
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-
-/**
- Converts an STLINK status code held in the first byte of a response
- to an openocd error, logs any error/wait status as debug output.
-*/
-static int stlink_usb_error_check(void *handle)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- /* TODO: no error checking yet on api V1 */
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->databuf[0] = STLINK_DEBUG_ERR_OK;
-
- switch (h->databuf[0]) {
- case STLINK_DEBUG_ERR_OK:
- return ERROR_OK;
- case STLINK_DEBUG_ERR_FAULT:
- LOG_DEBUG("SWD fault response (0x%x)", STLINK_DEBUG_ERR_FAULT);
- return ERROR_FAIL;
- case STLINK_SWD_AP_WAIT:
- LOG_DEBUG("wait status SWD_AP_WAIT (0x%x)", STLINK_SWD_AP_WAIT);
- return ERROR_WAIT;
- case STLINK_SWD_DP_WAIT:
- LOG_DEBUG("wait status SWD_DP_WAIT (0x%x)", STLINK_SWD_DP_WAIT);
- return ERROR_WAIT;
- case STLINK_JTAG_WRITE_ERROR:
- LOG_DEBUG("Write error");
- return ERROR_FAIL;
- case STLINK_JTAG_WRITE_VERIF_ERROR:
- LOG_DEBUG("Verify error");
- return ERROR_FAIL;
- case STLINK_SWD_AP_FAULT:
- /* git://git.ac6.fr/openocd commit 657e3e885b9ee10
- * returns ERROR_OK with the comment:
- * Change in error status when reading outside RAM.
- * This fix allows CDT plugin to visualize memory.
- */
- LOG_DEBUG("STLINK_SWD_AP_FAULT");
- return ERROR_FAIL;
- case STLINK_SWD_AP_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_PARITY_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_PARITY_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_DP_FAULT:
- LOG_DEBUG("STLINK_SWD_DP_FAULT");
- return ERROR_FAIL;
- case STLINK_SWD_DP_ERROR:
- LOG_DEBUG("STLINK_SWD_DP_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_DP_PARITY_ERROR:
- LOG_DEBUG("STLINK_SWD_DP_PARITY_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_WDATA_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_WDATA_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_STICKY_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_STICKY_ERROR");
- return ERROR_FAIL;
- case STLINK_SWD_AP_STICKYORUN_ERROR:
- LOG_DEBUG("STLINK_SWD_AP_STICKYORUN_ERROR");
- return ERROR_FAIL;
- default:
- LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]);
- return ERROR_FAIL;
- }
-}
-
-
-/** Issue an STLINK command via USB transfer, with retries on any wait status responses.
-
- Works for commands where the STLINK_DEBUG status is returned in the first
- byte of the response packet.
-
- Returns an openocd result code.
-*/
-static int stlink_cmd_allow_retry(void *handle, const uint8_t *buf, int size)
-{
- int retries = 0;
- int res;
- while (1) {
- res = stlink_usb_xfer(handle, buf, size);
- if (res != ERROR_OK)
- return res;
- res = stlink_usb_error_check(handle);
- if (res == ERROR_WAIT && retries < MAX_WAIT_RETRIES) {
- usleep((1<<retries++) * 1000);
- continue;
- }
- return res;
- }
-}
-
-/** */
-static int stlink_usb_read_trace(void *handle, const uint8_t *buf, int size)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- assert(h->version.stlink >= 2);
-
- if (jtag_libusb_bulk_read(h->fd, h->trace_ep, (char *)buf,
- size, STLINK_READ_TIMEOUT) != size) {
- LOG_ERROR("bulk trace read failed");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-/** */
-static void stlink_usb_xfer_v1_create_cmd(void *handle, uint8_t direction, uint32_t size)
-{
- struct stlink_usb_handle_s *h = handle;
-
- /* fill the send buffer */
- strcpy((char *)h->cmdbuf, "USBC");
- h->cmdidx += 4;
- /* csw tag not used */
- h->cmdidx += 4;
- buf_set_u32(h->cmdbuf+h->cmdidx, 0, 32, size);
- h->cmdidx += 4;
- h->cmdbuf[h->cmdidx++] = (direction == h->rx_ep ? ENDPOINT_IN : ENDPOINT_OUT);
- h->cmdbuf[h->cmdidx++] = 0; /* lun */
- h->cmdbuf[h->cmdidx++] = STLINK_CMD_SIZE_V1;
-}
-
-/** */
-static void stlink_usb_init_buffer(void *handle, uint8_t direction, uint32_t size)
-{
- struct stlink_usb_handle_s *h = handle;
-
- h->direction = direction;
-
- h->cmdidx = 0;
-
- memset(h->cmdbuf, 0, STLINK_SG_SIZE);
- memset(h->databuf, 0, STLINK_DATA_SIZE);
-
- if (h->version.stlink == 1)
- stlink_usb_xfer_v1_create_cmd(handle, direction, size);
-}
-
-/** */
-static int stlink_usb_version(void *handle)
-{
- int res;
- uint16_t v;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 6);
-
- h->cmdbuf[h->cmdidx++] = STLINK_GET_VERSION;
-
- res = stlink_usb_xfer(handle, h->databuf, 6);
-
- if (res != ERROR_OK)
- return res;
-
- v = (h->databuf[0] << 8) | h->databuf[1];
-
- h->version.stlink = (v >> 12) & 0x0f;
- h->version.jtag = (v >> 6) & 0x3f;
- h->version.swim = v & 0x3f;
- h->vid = buf_get_u32(h->databuf, 16, 16);
- h->pid = buf_get_u32(h->databuf, 32, 16);
-
- /* set the supported jtag api version
- * API V2 is supported since JTAG V11
- */
- if (h->version.jtag >= 11)
- h->version.jtag_api_max = STLINK_JTAG_API_V2;
- else
- h->version.jtag_api_max = STLINK_JTAG_API_V1;
-
- LOG_INFO("STLINK v%d JTAG v%d API v%d SWIM v%d VID 0x%04X PID 0x%04X",
- h->version.stlink,
- h->version.jtag,
- (h->version.jtag_api_max == STLINK_JTAG_API_V1) ? 1 : 2,
- h->version.swim,
- h->vid,
- h->pid);
-
- return ERROR_OK;
-}
-
-static int stlink_usb_check_voltage(void *handle, float *target_voltage)
-{
- struct stlink_usb_handle_s *h = handle;
- uint32_t adc_results[2];
-
- /* only supported by stlink/v2 and for firmware >= 13 */
- if (h->version.stlink == 1 || h->version.jtag < 13)
- return ERROR_COMMAND_NOTFOUND;
-
- stlink_usb_init_buffer(handle, h->rx_ep, 8);
-
- h->cmdbuf[h->cmdidx++] = STLINK_GET_TARGET_VOLTAGE;
-
- int result = stlink_usb_xfer(handle, h->databuf, 8);
-
- if (result != ERROR_OK)
- return result;
-
- /* convert result */
- adc_results[0] = le_to_h_u32(h->databuf);
- adc_results[1] = le_to_h_u32(h->databuf + 4);
-
- *target_voltage = 0;
-
- if (adc_results[0])
- *target_voltage = 2 * ((float)adc_results[1]) * (float)(1.2 / adc_results[0]);
-
- LOG_INFO("Target voltage: %f", (double)*target_voltage);
-
- return ERROR_OK;
-}
-
-static int stlink_usb_set_swdclk(void *handle, uint16_t clk_divisor)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- /* only supported by stlink/v2 and for firmware >= 22 */
- if (h->version.stlink == 1 || h->version.jtag < 22)
- return ERROR_COMMAND_NOTFOUND;
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_SWD_SET_FREQ;
- h_u16_to_le(h->cmdbuf+h->cmdidx, clk_divisor);
- h->cmdidx += 2;
-
- int result = stlink_cmd_allow_retry(handle, h->databuf, 2);
-
- if (result != ERROR_OK)
- return result;
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_current_mode(void *handle, uint8_t *mode)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_GET_CURRENT_MODE;
-
- res = stlink_usb_xfer(handle, h->databuf, 2);
-
- if (res != ERROR_OK)
- return res;
-
- *mode = h->databuf[0];
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_mode_enter(void *handle, enum stlink_mode type)
-{
- int rx_size = 0;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- /* on api V2 we are able the read the latest command
- * status
- * TODO: we need the test on api V1 too
- */
- if (h->jtag_api == STLINK_JTAG_API_V2)
- rx_size = 2;
-
- stlink_usb_init_buffer(handle, h->rx_ep, rx_size);
-
- switch (type) {
- case STLINK_MODE_DEBUG_JTAG:
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_JTAG;
- break;
- case STLINK_MODE_DEBUG_SWD:
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_ENTER;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_ENTER;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_ENTER_SWD;
- break;
- case STLINK_MODE_DEBUG_SWIM:
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_ENTER;
- break;
- case STLINK_MODE_DFU:
- case STLINK_MODE_MASS:
- default:
- return ERROR_FAIL;
- }
-
- return stlink_cmd_allow_retry(handle, h->databuf, rx_size);
-}
-
-/** */
-static int stlink_usb_mode_leave(void *handle, enum stlink_mode type)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, STLINK_NULL_EP, 0);
-
- switch (type) {
- case STLINK_MODE_DEBUG_JTAG:
- case STLINK_MODE_DEBUG_SWD:
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_EXIT;
- break;
- case STLINK_MODE_DEBUG_SWIM:
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_SWIM_EXIT;
- break;
- case STLINK_MODE_DFU:
- h->cmdbuf[h->cmdidx++] = STLINK_DFU_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DFU_EXIT;
- break;
- case STLINK_MODE_MASS:
- default:
- return ERROR_FAIL;
- }
-
- res = stlink_usb_xfer(handle, 0, 0);
-
- if (res != ERROR_OK)
- return res;
-
- return ERROR_OK;
-}
-
-static int stlink_usb_assert_srst(void *handle, int srst);
-
-static enum stlink_mode stlink_get_mode(enum hl_transports t)
-{
- switch (t) {
- case HL_TRANSPORT_SWD:
- return STLINK_MODE_DEBUG_SWD;
- case HL_TRANSPORT_JTAG:
- return STLINK_MODE_DEBUG_JTAG;
- case HL_TRANSPORT_SWIM:
- return STLINK_MODE_DEBUG_SWIM;
- default:
- return STLINK_MODE_UNKNOWN;
- }
-}
-
-/** */
-static int stlink_usb_init_mode(void *handle, bool connect_under_reset)
-{
- int res;
- uint8_t mode;
- enum stlink_mode emode;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- res = stlink_usb_current_mode(handle, &mode);
-
- if (res != ERROR_OK)
- return res;
-
- LOG_DEBUG("MODE: 0x%02X", mode);
-
- /* try to exit current mode */
- switch (mode) {
- case STLINK_DEV_DFU_MODE:
- emode = STLINK_MODE_DFU;
- break;
- case STLINK_DEV_DEBUG_MODE:
- emode = STLINK_MODE_DEBUG_SWD;
- break;
- case STLINK_DEV_SWIM_MODE:
- emode = STLINK_MODE_DEBUG_SWIM;
- break;
- case STLINK_DEV_BOOTLOADER_MODE:
- case STLINK_DEV_MASS_MODE:
- default:
- emode = STLINK_MODE_UNKNOWN;
- break;
- }
-
- if (emode != STLINK_MODE_UNKNOWN) {
- res = stlink_usb_mode_leave(handle, emode);
-
- if (res != ERROR_OK)
- return res;
- }
-
- res = stlink_usb_current_mode(handle, &mode);
-
- if (res != ERROR_OK)
- return res;
-
- /* we check the target voltage here as an aid to debugging connection problems.
- * the stlink requires the target Vdd to be connected for reliable debugging.
- * this cmd is supported in all modes except DFU
- */
- if (mode != STLINK_DEV_DFU_MODE) {
-
- float target_voltage;
-
- /* check target voltage (if supported) */
- res = stlink_usb_check_voltage(h, &target_voltage);
-
- if (res != ERROR_OK) {
- if (res != ERROR_COMMAND_NOTFOUND)
- LOG_ERROR("voltage check failed");
- /* attempt to continue as it is not a catastrophic failure */
- } else {
- /* check for a sensible target voltage, operating range is 1.65-5.5v
- * according to datasheet */
- if (target_voltage < 1.5)
- LOG_ERROR("target voltage may be too low for reliable debugging");
- }
- }
-
- LOG_DEBUG("MODE: 0x%02X", mode);
-
- /* set selected mode */
- emode = stlink_get_mode(h->transport);
-
- if (emode == STLINK_MODE_UNKNOWN) {
- LOG_ERROR("selected mode (transport) not supported");
- return ERROR_FAIL;
- }
-
- if (connect_under_reset) {
- res = stlink_usb_assert_srst(handle, 0);
- if (res != ERROR_OK)
- return res;
- }
-
- res = stlink_usb_mode_enter(handle, emode);
-
- if (res != ERROR_OK)
- return res;
-
- res = stlink_usb_current_mode(handle, &mode);
-
- if (res != ERROR_OK)
- return res;
-
- LOG_DEBUG("MODE: 0x%02X", mode);
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_idcode(void *handle, uint32_t *idcode)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 4);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READCOREID;
-
- res = stlink_usb_xfer(handle, h->databuf, 4);
-
- if (res != ERROR_OK)
- return res;
-
- *idcode = le_to_h_u32(h->databuf);
-
- LOG_DEBUG("IDCODE: 0x%08" PRIX32, *idcode);
-
- return ERROR_OK;
-}
-
-static int stlink_usb_v2_read_debug_reg(void *handle, uint32_t addr, uint32_t *val)
-{
- struct stlink_usb_handle_s *h = handle;
- int res;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 8);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READDEBUGREG;
- h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
- h->cmdidx += 4;
-
- res = stlink_cmd_allow_retry(handle, h->databuf, 8);
- if (res != ERROR_OK)
- return res;
-
- *val = le_to_h_u32(h->databuf + 4);
- return ERROR_OK;
-}
-
-static int stlink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEDEBUGREG;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEDEBUGREG;
- h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
- h->cmdidx += 4;
- h_u32_to_le(h->cmdbuf+h->cmdidx, val);
- h->cmdidx += 4;
-
- return stlink_cmd_allow_retry(handle, h->databuf, 2);
-}
-
-/** */
-static int stlink_usb_trace_read(void *handle, uint8_t *buf, size_t *size)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->trace.enabled && h->version.jtag >= STLINK_TRACE_MIN_VERSION) {
- int res;
-
- stlink_usb_init_buffer(handle, h->rx_ep, 10);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GET_TRACE_NB;
-
- res = stlink_usb_xfer(handle, h->databuf, 2);
- if (res != ERROR_OK)
- return res;
-
- size_t bytes_avail = le_to_h_u16(h->databuf);
- *size = bytes_avail < *size ? bytes_avail : *size - 1;
-
- if (*size > 0) {
- res = stlink_usb_read_trace(handle, buf, *size);
- if (res != ERROR_OK)
- return res;
- return ERROR_OK;
- }
- }
- *size = 0;
- return ERROR_OK;
-}
-
-static enum target_state stlink_usb_v2_get_status(void *handle)
-{
- int result;
- uint32_t status;
-
- result = stlink_usb_v2_read_debug_reg(handle, DCB_DHCSR, &status);
- if (result != ERROR_OK)
- return TARGET_UNKNOWN;
-
- if (status & S_HALT)
- return TARGET_HALTED;
- else if (status & S_RESET_ST)
- return TARGET_RESET;
-
- return TARGET_RUNNING;
-}
-
-/** */
-static enum target_state stlink_usb_state(void *handle)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->reconnect_pending) {
- LOG_INFO("Previous state query failed, trying to reconnect");
- res = stlink_usb_mode_enter(handle, stlink_get_mode(h->transport));
-
- if (res != ERROR_OK)
- return TARGET_UNKNOWN;
-
- h->reconnect_pending = false;
- }
-
- if (h->jtag_api == STLINK_JTAG_API_V2) {
- res = stlink_usb_v2_get_status(handle);
- if (res == TARGET_UNKNOWN)
- h->reconnect_pending = true;
- return res;
- }
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_GETSTATUS;
-
- res = stlink_usb_xfer(handle, h->databuf, 2);
-
- if (res != ERROR_OK)
- return TARGET_UNKNOWN;
-
- if (h->databuf[0] == STLINK_CORE_RUNNING)
- return TARGET_RUNNING;
- if (h->databuf[0] == STLINK_CORE_HALTED)
- return TARGET_HALTED;
-
- h->reconnect_pending = true;
-
- return TARGET_UNKNOWN;
-}
-
-static int stlink_usb_assert_srst(void *handle, int srst)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->version.stlink == 1)
- return ERROR_COMMAND_NOTFOUND;
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_DRIVE_NRST;
- h->cmdbuf[h->cmdidx++] = srst;
-
- return stlink_cmd_allow_retry(handle, h->databuf, 2);
-}
-
-/** */
-static void stlink_usb_trace_disable(void *handle)
-{
- int res = ERROR_OK;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- assert(h->version.jtag >= STLINK_TRACE_MIN_VERSION);
-
- LOG_DEBUG("Tracing: disable");
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_STOP_TRACE_RX;
- res = stlink_usb_xfer(handle, h->databuf, 2);
-
- if (res == ERROR_OK)
- h->trace.enabled = false;
-}
-
-
-/** */
-static int stlink_usb_trace_enable(void *handle)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->version.jtag >= STLINK_TRACE_MIN_VERSION) {
- stlink_usb_init_buffer(handle, h->rx_ep, 10);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_START_TRACE_RX;
- h_u16_to_le(h->cmdbuf+h->cmdidx, (uint16_t)STLINK_TRACE_SIZE);
- h->cmdidx += 2;
- h_u32_to_le(h->cmdbuf+h->cmdidx, h->trace.source_hz);
- h->cmdidx += 4;
-
- res = stlink_usb_xfer(handle, h->databuf, 2);
-
- if (res == ERROR_OK) {
- h->trace.enabled = true;
- LOG_DEBUG("Tracing: recording at %" PRIu32 "Hz", h->trace.source_hz);
- }
- } else {
- LOG_ERROR("Tracing is not supported by this version.");
- res = ERROR_FAIL;
- }
-
- return res;
-}
-
-/** */
-static int stlink_usb_reset(void *handle)
-{
- struct stlink_usb_handle_s *h = handle;
- int retval;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
-
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_RESETSYS;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_RESETSYS;
-
- retval = stlink_cmd_allow_retry(handle, h->databuf, 2);
- if (retval != ERROR_OK)
- return retval;
-
- if (h->trace.enabled) {
- stlink_usb_trace_disable(h);
- return stlink_usb_trace_enable(h);
- }
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_run(void *handle)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->jtag_api == STLINK_JTAG_API_V2) {
- res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_DEBUGEN);
-
- return res;
- }
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_RUNCORE;
-
- return stlink_cmd_allow_retry(handle, h->databuf, 2);
-}
-
-/** */
-static int stlink_usb_halt(void *handle)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->jtag_api == STLINK_JTAG_API_V2) {
- res = stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN);
-
- return res;
- }
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_FORCEDEBUG;
-
- return stlink_cmd_allow_retry(handle, h->databuf, 2);
-}
-
-/** */
-static int stlink_usb_step(void *handle)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->jtag_api == STLINK_JTAG_API_V2) {
- /* TODO: this emulates the v1 api, it should really use a similar auto mask isr
- * that the Cortex-M3 currently does. */
- stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_MASKINTS|C_DEBUGEN);
- stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_STEP|C_MASKINTS|C_DEBUGEN);
- return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN);
- }
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_STEPCORE;
-
- return stlink_cmd_allow_retry(handle, h->databuf, 2);
-}
-
-/** */
-static int stlink_usb_read_regs(void *handle)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 84);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READALLREGS;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READALLREGS;
-
- res = stlink_usb_xfer(handle, h->databuf, 84);
-
- if (res != ERROR_OK)
- return res;
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_read_reg(void *handle, int num, uint32_t *val)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, h->jtag_api == STLINK_JTAG_API_V1 ? 4 : 8);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READREG;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READREG;
- h->cmdbuf[h->cmdidx++] = num;
-
- if (h->jtag_api == STLINK_JTAG_API_V1) {
- res = stlink_usb_xfer(handle, h->databuf, 4);
- if (res != ERROR_OK)
- return res;
- *val = le_to_h_u32(h->databuf);
- return ERROR_OK;
- } else {
- res = stlink_cmd_allow_retry(handle, h->databuf, 8);
- if (res != ERROR_OK)
- return res;
- *val = le_to_h_u32(h->databuf + 4);
- return ERROR_OK;
- }
-}
-
-/** */
-static int stlink_usb_write_reg(void *handle, int num, uint32_t val)
-{
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- if (h->jtag_api == STLINK_JTAG_API_V1)
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEREG;
- else
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEREG;
- h->cmdbuf[h->cmdidx++] = num;
- h_u32_to_le(h->cmdbuf+h->cmdidx, val);
- h->cmdidx += 4;
-
- return stlink_cmd_allow_retry(handle, h->databuf, 2);
-}
-
-static int stlink_usb_get_rw_status(void *handle)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- if (h->jtag_api == STLINK_JTAG_API_V1)
- return ERROR_OK;
-
- stlink_usb_init_buffer(handle, h->rx_ep, 2);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS;
-
- res = stlink_usb_xfer(handle, h->databuf, 2);
-
- if (res != ERROR_OK)
- return res;
-
- return stlink_usb_error_check(h);
-}
-
-/** */
-static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len,
- uint8_t *buffer)
-{
- int res;
- uint16_t read_len = len;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- /* max 8bit read/write is 64bytes */
- if (len > STLINK_MAX_RW8) {
- LOG_DEBUG("max buffer length exceeded");
- return ERROR_FAIL;
- }
-
- stlink_usb_init_buffer(handle, h->rx_ep, read_len);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_8BIT;
- h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
- h->cmdidx += 4;
- h_u16_to_le(h->cmdbuf+h->cmdidx, len);
- h->cmdidx += 2;
-
- /* we need to fix read length for single bytes */
- if (read_len == 1)
- read_len++;
-
- res = stlink_usb_xfer(handle, h->databuf, read_len);
-
- if (res != ERROR_OK)
- return res;
-
- memcpy(buffer, h->databuf, len);
-
- return stlink_usb_get_rw_status(handle);
-}
-
-/** */
-static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len,
- const uint8_t *buffer)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- /* max 8bit read/write is 64bytes */
- if (len > STLINK_MAX_RW8) {
- LOG_DEBUG("max buffer length exceeded");
- return ERROR_FAIL;
- }
-
- stlink_usb_init_buffer(handle, h->tx_ep, len);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_8BIT;
- h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
- h->cmdidx += 4;
- h_u16_to_le(h->cmdbuf+h->cmdidx, len);
- h->cmdidx += 2;
-
- res = stlink_usb_xfer(handle, buffer, len);
-
- if (res != ERROR_OK)
- return res;
-
- return stlink_usb_get_rw_status(handle);
-}
-
-/** */
-static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
- uint8_t *buffer)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- /* data must be a multiple of 4 and word aligned */
- if (len % 4 || addr % 4) {
- LOG_DEBUG("Invalid data alignment");
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- stlink_usb_init_buffer(handle, h->rx_ep, len);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_READMEM_32BIT;
- h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
- h->cmdidx += 4;
- h_u16_to_le(h->cmdbuf+h->cmdidx, len);
- h->cmdidx += 2;
-
- res = stlink_usb_xfer(handle, h->databuf, len);
-
- if (res != ERROR_OK)
- return res;
-
- memcpy(buffer, h->databuf, len);
-
- return stlink_usb_get_rw_status(handle);
-}
-
-/** */
-static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
- const uint8_t *buffer)
-{
- int res;
- struct stlink_usb_handle_s *h = handle;
-
- assert(handle != NULL);
-
- /* data must be a multiple of 4 and word aligned */
- if (len % 4 || addr % 4) {
- LOG_DEBUG("Invalid data alignment");
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- stlink_usb_init_buffer(handle, h->tx_ep, len);
-
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND;
- h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_WRITEMEM_32BIT;
- h_u32_to_le(h->cmdbuf+h->cmdidx, addr);
- h->cmdidx += 4;
- h_u16_to_le(h->cmdbuf+h->cmdidx, len);
- h->cmdidx += 2;
-
- res = stlink_usb_xfer(handle, buffer, len);
-
- if (res != ERROR_OK)
- return res;
-
- return stlink_usb_get_rw_status(handle);
-}
-
-static uint32_t stlink_max_block_size(uint32_t tar_autoincr_block, uint32_t address)
-{
- uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address));
- if (max_tar_block == 0)
- max_tar_block = 4;
- return max_tar_block;
-}
-
-static int stlink_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- int retval = ERROR_OK;
- uint32_t bytes_remaining;
- int retries = 0;
- struct stlink_usb_handle_s *h = handle;
-
- /* calculate byte count */
- count *= size;
-
- while (count) {
-
- bytes_remaining = (size == 4) ? \
- stlink_max_block_size(h->max_mem_packet, addr) : STLINK_MAX_RW8;
-
- if (count < bytes_remaining)
- bytes_remaining = count;
-
- /* the stlink only supports 8/32bit memory read/writes
- * honour 32bit, all others will be handled as 8bit access */
- if (size == 4) {
-
- /* When in jtag mode the stlink uses the auto-increment functinality.
- * However it expects us to pass the data correctly, this includes
- * alignment and any page boundaries. We already do this as part of the
- * adi_v5 implementation, but the stlink is a hla adapter and so this
- * needs implementiong manually.
- * currently this only affects jtag mode, according to ST they do single
- * access in SWD mode - but this may change and so we do it for both modes */
-
- /* we first need to check for any unaligned bytes */
- if (addr % 4) {
-
- uint32_t head_bytes = 4 - (addr % 4);
- retval = stlink_usb_read_mem8(handle, addr, head_bytes, buffer);
- if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) {
- usleep((1<<retries++) * 1000);
- continue;
- }
- if (retval != ERROR_OK)
- return retval;
- buffer += head_bytes;
- addr += head_bytes;
- count -= head_bytes;
- bytes_remaining -= head_bytes;
- }
-
- if (bytes_remaining % 4)
- retval = stlink_usb_read_mem(handle, addr, 1, bytes_remaining, buffer);
- else
- retval = stlink_usb_read_mem32(handle, addr, bytes_remaining, buffer);
- } else
- retval = stlink_usb_read_mem8(handle, addr, bytes_remaining, buffer);
-
- if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) {
- usleep((1<<retries++) * 1000);
- continue;
- }
- if (retval != ERROR_OK)
- return retval;
-
- buffer += bytes_remaining;
- addr += bytes_remaining;
- count -= bytes_remaining;
- }
-
- return retval;
-}
-
-static int stlink_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- int retval = ERROR_OK;
- uint32_t bytes_remaining;
- int retries = 0;
- struct stlink_usb_handle_s *h = handle;
-
- /* calculate byte count */
- count *= size;
-
- while (count) {
-
- bytes_remaining = (size == 4) ? \
- stlink_max_block_size(h->max_mem_packet, addr) : STLINK_MAX_RW8;
-
- if (count < bytes_remaining)
- bytes_remaining = count;
-
- /* the stlink only supports 8/32bit memory read/writes
- * honour 32bit, all others will be handled as 8bit access */
- if (size == 4) {
-
- /* When in jtag mode the stlink uses the auto-increment functinality.
- * However it expects us to pass the data correctly, this includes
- * alignment and any page boundaries. We already do this as part of the
- * adi_v5 implementation, but the stlink is a hla adapter and so this
- * needs implementiong manually.
- * currently this only affects jtag mode, according to ST they do single
- * access in SWD mode - but this may change and so we do it for both modes */
-
- /* we first need to check for any unaligned bytes */
- if (addr % 4) {
-
- uint32_t head_bytes = 4 - (addr % 4);
- retval = stlink_usb_write_mem8(handle, addr, head_bytes, buffer);
- if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) {
- usleep((1<<retries++) * 1000);
- continue;
- }
- if (retval != ERROR_OK)
- return retval;
- buffer += head_bytes;
- addr += head_bytes;
- count -= head_bytes;
- bytes_remaining -= head_bytes;
- }
-
- if (bytes_remaining % 4)
- retval = stlink_usb_write_mem(handle, addr, 1, bytes_remaining, buffer);
- else
- retval = stlink_usb_write_mem32(handle, addr, bytes_remaining, buffer);
-
- } else
- retval = stlink_usb_write_mem8(handle, addr, bytes_remaining, buffer);
- if (retval == ERROR_WAIT && retries < MAX_WAIT_RETRIES) {
- usleep((1<<retries++) * 1000);
- continue;
- }
- if (retval != ERROR_OK)
- return retval;
-
- buffer += bytes_remaining;
- addr += bytes_remaining;
- count -= bytes_remaining;
- }
-
- return retval;
-}
-
-/** */
-static int stlink_usb_override_target(const char *targetname)
-{
- return !strcmp(targetname, "cortex_m");
-}
-
-static int stlink_speed(void *handle, int khz, bool query)
-{
- unsigned i;
- int speed_index = -1;
- int speed_diff = INT_MAX;
- struct stlink_usb_handle_s *h = handle;
-
- /* only supported by stlink/v2 and for firmware >= 22 */
- if (h && (h->version.stlink == 1 || h->version.jtag < 22))
- return khz;
-
- for (i = 0; i < ARRAY_SIZE(stlink_khz_to_speed_map); i++) {
- if (khz == stlink_khz_to_speed_map[i].speed) {
- speed_index = i;
- break;
- } else {
- int current_diff = khz - stlink_khz_to_speed_map[i].speed;
- /* get abs value for comparison */
- current_diff = (current_diff > 0) ? current_diff : -current_diff;
- if ((current_diff < speed_diff) && khz >= stlink_khz_to_speed_map[i].speed) {
- speed_diff = current_diff;
- speed_index = i;
- }
- }
- }
-
- bool match = true;
-
- if (speed_index == -1) {
- /* this will only be here if we cannot match the slow speed.
- * use the slowest speed we support.*/
- speed_index = ARRAY_SIZE(stlink_khz_to_speed_map) - 1;
- match = false;
- } else if (i == ARRAY_SIZE(stlink_khz_to_speed_map))
- match = false;
-
- if (!match && query) {
- LOG_INFO("Unable to match requested speed %d kHz, using %d kHz", \
- khz, stlink_khz_to_speed_map[speed_index].speed);
- }
-
- if (h && !query) {
- int result = stlink_usb_set_swdclk(h, stlink_khz_to_speed_map[speed_index].speed_divisor);
- if (result != ERROR_OK) {
- LOG_ERROR("Unable to set adapter speed");
- return khz;
- }
- }
-
- return stlink_khz_to_speed_map[speed_index].speed;
-}
-
-/** */
-static int stlink_usb_close(void *handle)
-{
- struct stlink_usb_handle_s *h = handle;
-
- if (h && h->fd)
- jtag_libusb_close(h->fd);
-
- free(h);
-
- return ERROR_OK;
-}
-
-/** */
-static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
-{
- int err, retry_count = 1;
- struct stlink_usb_handle_s *h;
- enum stlink_jtag_api_version api;
-
- LOG_DEBUG("stlink_usb_open");
-
- h = calloc(1, sizeof(struct stlink_usb_handle_s));
-
- if (h == 0) {
- LOG_DEBUG("malloc failed");
- return ERROR_FAIL;
- }
-
- h->transport = param->transport;
-
- const uint16_t vids[] = { param->vid, 0 };
- const uint16_t pids[] = { param->pid, 0 };
- const char *serial = param->serial;
-
- LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
- param->transport, param->vid, param->pid,
- param->serial ? param->serial : "");
-
- /*
- On certain host USB configurations(e.g. MacBook Air)
- STLINKv2 dongle seems to have its FW in a funky state if,
- after plugging it in, you try to use openocd with it more
- then once (by launching and closing openocd). In cases like
- that initial attempt to read the FW info via
- stlink_usb_version will fail and the device has to be reset
- in order to become operational.
- */
- do {
- if (jtag_libusb_open(vids, pids, serial, &h->fd) != ERROR_OK) {
- LOG_ERROR("open failed");
- goto error_open;
- }
-
- jtag_libusb_set_configuration(h->fd, 0);
-
- if (jtag_libusb_claim_interface(h->fd, 0) != ERROR_OK) {
- LOG_DEBUG("claim interface failed");
- goto error_open;
- }
-
- /* RX EP is common for all versions */
- h->rx_ep = STLINK_RX_EP;
-
- /* wrap version for first read */
- switch (param->pid) {
- case STLINK_V1_PID:
- h->version.stlink = 1;
- h->tx_ep = STLINK_TX_EP;
- h->trace_ep = STLINK_TRACE_EP;
- break;
- case STLINK_V2_1_PID:
- h->version.stlink = 2;
- h->tx_ep = STLINK_V2_1_TX_EP;
- h->trace_ep = STLINK_V2_1_TRACE_EP;
- break;
- default:
- /* fall through - we assume V2 to be the default version*/
- case STLINK_V2_PID:
- h->version.stlink = 2;
- h->tx_ep = STLINK_TX_EP;
- h->trace_ep = STLINK_TRACE_EP;
- break;
- }
-
- /* get the device version */
- err = stlink_usb_version(h);
-
- if (err == ERROR_OK) {
- break;
- } else if (h->version.stlink == 1 ||
- retry_count == 0) {
- LOG_ERROR("read version failed");
- goto error_open;
- } else {
- err = jtag_libusb_release_interface(h->fd, 0);
- if (err != ERROR_OK) {
- LOG_ERROR("release interface failed");
- goto error_open;
- }
-
- err = jtag_libusb_reset_device(h->fd);
- if (err != ERROR_OK) {
- LOG_ERROR("reset device failed");
- goto error_open;
- }
-
- jtag_libusb_close(h->fd);
- /*
- Give the device one second to settle down and
- reenumerate.
- */
- usleep(1 * 1000 * 1000);
- retry_count--;
- }
- } while (1);
-
- /* compare usb vid/pid */
- if ((param->vid != h->vid) || (param->pid != h->pid))
- LOG_INFO("vid/pid are not identical: 0x%04X/0x%04X 0x%04X/0x%04X",
- param->vid, param->pid,
- h->vid, h->pid);
-
- /* check if mode is supported */
- err = ERROR_OK;
-
- switch (h->transport) {
- case HL_TRANSPORT_SWD:
- case HL_TRANSPORT_JTAG:
- if (h->version.jtag == 0)
- err = ERROR_FAIL;
- break;
- case HL_TRANSPORT_SWIM:
- if (h->version.swim == 0)
- err = ERROR_FAIL;
- break;
- default:
- err = ERROR_FAIL;
- break;
- }
-
- if (err != ERROR_OK) {
- LOG_ERROR("mode (transport) not supported by device");
- goto error_open;
- }
-
- api = h->version.jtag_api_max;
-
- LOG_INFO("using stlink api v%d", api);
-
- /* set the used jtag api, this will default to the newest supported version */
- h->jtag_api = api;
-
- /* initialize the debug hardware */
- err = stlink_usb_init_mode(h, param->connect_under_reset);
-
- if (err != ERROR_OK) {
- LOG_ERROR("init mode failed (unable to connect to the target)");
- goto error_open;
- }
-
- /* clock speed only supported by stlink/v2 and for firmware >= 22 */
- if (h->version.stlink >= 2 && h->version.jtag >= 22) {
- LOG_DEBUG("Supported clock speeds are:");
-
- for (unsigned i = 0; i < ARRAY_SIZE(stlink_khz_to_speed_map); i++)
- LOG_DEBUG("%d kHz", stlink_khz_to_speed_map[i].speed);
-
- stlink_speed(h, param->initial_interface_speed, false);
- }
-
- /* get cpuid, so we can determine the max page size
- * start with a safe default */
- h->max_mem_packet = (1 << 10);
-
- uint8_t buffer[4];
- err = stlink_usb_read_mem32(h, CPUID, 4, buffer);
- if (err == ERROR_OK) {
- uint32_t cpuid = le_to_h_u32(buffer);
- int i = (cpuid >> 4) & 0xf;
- if (i == 4 || i == 3) {
- /* Cortex-M3/M4 has 4096 bytes autoincrement range */
- h->max_mem_packet = (1 << 12);
- }
- }
-
- LOG_DEBUG("Using TAR autoincrement: %" PRIu32, h->max_mem_packet);
-
- *fd = h;
-
- return ERROR_OK;
-
-error_open:
- stlink_usb_close(h);
-
- return ERROR_FAIL;
-}
-
-int stlink_config_trace(void *handle, bool enabled, enum tpio_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
-{
- struct stlink_usb_handle_s *h = handle;
-
- if (enabled && (h->jtag_api < 2 || pin_protocol != ASYNC_UART)) {
- LOG_ERROR("The attached ST-LINK version doesn't support this trace mode");
- return ERROR_FAIL;
- }
-
- if (!enabled) {
- stlink_usb_trace_disable(h);
- return ERROR_OK;
- }
-
- if (*trace_freq > STLINK_TRACE_MAX_HZ) {
- LOG_ERROR("ST-LINK doesn't support SWO frequency higher than %u",
- STLINK_TRACE_MAX_HZ);
- return ERROR_FAIL;
- }
-
- stlink_usb_trace_disable(h);
-
- if (!*trace_freq)
- *trace_freq = STLINK_TRACE_MAX_HZ;
- h->trace.source_hz = *trace_freq;
-
- return stlink_usb_trace_enable(h);
-}
-
-/** */
-struct hl_layout_api_s stlink_usb_layout_api = {
- /** */
- .open = stlink_usb_open,
- /** */
- .close = stlink_usb_close,
- /** */
- .idcode = stlink_usb_idcode,
- /** */
- .state = stlink_usb_state,
- /** */
- .reset = stlink_usb_reset,
- /** */
- .assert_srst = stlink_usb_assert_srst,
- /** */
- .run = stlink_usb_run,
- /** */
- .halt = stlink_usb_halt,
- /** */
- .step = stlink_usb_step,
- /** */
- .read_regs = stlink_usb_read_regs,
- /** */
- .read_reg = stlink_usb_read_reg,
- /** */
- .write_reg = stlink_usb_write_reg,
- /** */
- .read_mem = stlink_usb_read_mem,
- /** */
- .write_mem = stlink_usb_write_mem,
- /** */
- .write_debug_reg = stlink_usb_write_debug_reg,
- /** */
- .override_target = stlink_usb_override_target,
- /** */
- .speed = stlink_speed,
- /** */
- .config_trace = stlink_config_trace,
- /** */
- .poll_trace = stlink_usb_trace_read,
-};
diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c
deleted file mode 100644
index 77b727c..0000000
--- a/src/jtag/drivers/sysfsgpio.c
+++ /dev/null
@@ -1,681 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* 2014-12: Addition of the SWD protocol support is based on the initial work
- * on bcm2835gpio.c by Paul Fertser and modifications by Jean-Christian de Rivaz. */
-
-/**
- * @file
- * This driver implements a bitbang jtag interface using gpio lines via
- * sysfs.
- * The aim of this driver implementation is use system GPIOs but avoid the
- * need for a additional kernel driver.
- * (Note memory mapped IO is another option, however it doesn't mix well with
- * the kernel gpiolib driver - which makes sense I guess.)
- *
- * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst
- * must be also be specified. The required jtag gpios are specified via the
- * sysfsgpio_jtag_nums command or the relevant sysfsgpio_XXX_num commang.
- * The srst and trst gpios are set via the sysfsgpio_srst_num and
- * sysfsgpio_trst_num respectively. GPIO numbering follows the kernel
- * convention of starting from 0.
- *
- * The gpios should not be in use by another entity, and must not be requested
- * by a kernel driver without also being exported by it (otherwise they can't
- * be exported by sysfs).
- *
- * The sysfs gpio interface can only manipulate one gpio at a time, so the
- * bitbang write handler remembers the last state for tck, tms, tdi to avoid
- * superfluous writes.
- * For speed the sysfs "value" entry is opened at init and held open.
- * This results in considerable gains over open-write-close (45s vs 900s)
- *
- * Further work could address:
- * -srst and trst open drain/ push pull
- * -configurable active high/low for srst & trst
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include "bitbang.h"
-
-/*
- * Helper func to determine if gpio number valid
- *
- * Assume here that there will be less than 1000 gpios on a system
- */
-static int is_gpio_valid(int gpio)
-{
- return gpio >= 0 && gpio < 1000;
-}
-
-/*
- * Helper func to open, write to and close a file
- * name and valstr must be null terminated.
- *
- * Returns negative on failure.
- */
-static int open_write_close(const char *name, const char *valstr)
-{
- int ret;
- int fd = open(name, O_WRONLY);
- if (fd < 0)
- return fd;
-
- ret = write(fd, valstr, strlen(valstr));
- close(fd);
-
- return ret;
-}
-
-/*
- * Helper func to unexport gpio from sysfs
- */
-static void unexport_sysfs_gpio(int gpio)
-{
- char gpiostr[4];
-
- if (!is_gpio_valid(gpio))
- return;
-
- snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
- if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0)
- LOG_ERROR("Couldn't unexport gpio %d", gpio);
-
- return;
-}
-
-/*
- * Exports and sets up direction for gpio.
- * If the gpio is an output, it is initialized according to init_high,
- * otherwise it is ignored.
- *
- * If the gpio is already exported we just show a warning and continue; if
- * openocd happened to crash (or was killed by user) then the gpios will not
- * have been cleaned up.
- */
-static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
-{
- char buf[40];
- char gpiostr[4];
- int ret;
-
- if (!is_gpio_valid(gpio))
- return ERROR_OK;
-
- snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
- ret = open_write_close("/sys/class/gpio/export", gpiostr);
- if (ret < 0) {
- if (errno == EBUSY) {
- LOG_WARNING("gpio %d is already exported", gpio);
- } else {
- LOG_ERROR("Couldn't export gpio %d", gpio);
- perror("sysfsgpio: ");
- return ERROR_FAIL;
- }
- }
-
- snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
- ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
- if (ret < 0) {
- LOG_ERROR("Couldn't set direction for gpio %d", gpio);
- perror("sysfsgpio: ");
- unexport_sysfs_gpio(gpio);
- return ERROR_FAIL;
- }
-
- snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
- ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
- if (ret < 0) {
- LOG_ERROR("Couldn't open value for gpio %d", gpio);
- perror("sysfsgpio: ");
- unexport_sysfs_gpio(gpio);
- }
-
- return ret;
-}
-
-/* gpio numbers for each gpio. Negative values are invalid */
-static int tck_gpio = -1;
-static int tms_gpio = -1;
-static int tdi_gpio = -1;
-static int tdo_gpio = -1;
-static int trst_gpio = -1;
-static int srst_gpio = -1;
-static int swclk_gpio = -1;
-static int swdio_gpio = -1;
-
-/*
- * file descriptors for /sys/class/gpio/gpioXX/value
- * Set up during init.
- */
-static int tck_fd = -1;
-static int tms_fd = -1;
-static int tdi_fd = -1;
-static int tdo_fd = -1;
-static int trst_fd = -1;
-static int srst_fd = -1;
-static int swclk_fd = -1;
-static int swdio_fd = -1;
-
-static int last_swclk;
-static int last_swdio;
-static bool last_stored;
-static bool swdio_input;
-
-static void sysfsgpio_swdio_drive(bool is_output)
-{
- char buf[40];
- int ret;
-
- snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", swdio_gpio);
- ret = open_write_close(buf, is_output ? "high" : "in");
- if (ret < 0) {
- LOG_ERROR("Couldn't set direction for gpio %d", swdio_gpio);
- perror("sysfsgpio: ");
- }
-
- last_stored = false;
- swdio_input = !is_output;
-}
-
-static int sysfsgpio_swdio_read(void)
-{
- char buf[1];
-
- /* important to seek to signal sysfs of new read */
- lseek(swdio_fd, 0, SEEK_SET);
- int ret = read(swdio_fd, &buf, sizeof(buf));
-
- if (ret < 0) {
- LOG_WARNING("reading swdio failed");
- return 0;
- }
-
- return buf[0] != '0';
-}
-
-static void sysfsgpio_swdio_write(int swclk, int swdio)
-{
- const char one[] = "1";
- const char zero[] = "0";
-
- size_t bytes_written;
-
- if (!swdio_input) {
- if (!last_stored || (swdio != last_swdio)) {
- bytes_written = write(swdio_fd, swdio ? &one : &zero, 1);
- if (bytes_written != 1)
- LOG_WARNING("writing swdio failed");
- }
- }
-
- /* write swclk last */
- if (!last_stored || (swclk != last_swclk)) {
- bytes_written = write(swclk_fd, swclk ? &one : &zero, 1);
- if (bytes_written != 1)
- LOG_WARNING("writing swclk failed");
- }
-
- last_swdio = swdio;
- last_swclk = swclk;
- last_stored = true;
-}
-
-/*
- * Bitbang interface read of TDO
- *
- * The sysfs value will read back either '0' or '1'. The trick here is to call
- * lseek to bypass buffering in the sysfs kernel driver.
- */
-static int sysfsgpio_read(void)
-{
- char buf[1];
-
- /* important to seek to signal sysfs of new read */
- lseek(tdo_fd, 0, SEEK_SET);
- int ret = read(tdo_fd, &buf, sizeof(buf));
-
- if (ret < 0) {
- LOG_WARNING("reading tdo failed");
- return 0;
- }
-
- return buf[0] != '0';
-}
-
-/*
- * Bitbang interface write of TCK, TMS, TDI
- *
- * Seeing as this is the only function where the outputs are changed,
- * we can cache the old value to avoid needlessly writing it.
- */
-static void sysfsgpio_write(int tck, int tms, int tdi)
-{
- if (swd_mode) {
- sysfsgpio_swdio_write(tck, tdi);
- return;
- }
-
- const char one[] = "1";
- const char zero[] = "0";
-
- static int last_tck;
- static int last_tms;
- static int last_tdi;
-
- static int first_time;
- size_t bytes_written;
-
- if (!first_time) {
- last_tck = !tck;
- last_tms = !tms;
- last_tdi = !tdi;
- first_time = 1;
- }
-
- if (tdi != last_tdi) {
- bytes_written = write(tdi_fd, tdi ? &one : &zero, 1);
- if (bytes_written != 1)
- LOG_WARNING("writing tdi failed");
- }
-
- if (tms != last_tms) {
- bytes_written = write(tms_fd, tms ? &one : &zero, 1);
- if (bytes_written != 1)
- LOG_WARNING("writing tms failed");
- }
-
- /* write clk last */
- if (tck != last_tck) {
- bytes_written = write(tck_fd, tck ? &one : &zero, 1);
- if (bytes_written != 1)
- LOG_WARNING("writing tck failed");
- }
-
- last_tdi = tdi;
- last_tms = tms;
- last_tck = tck;
-}
-
-/*
- * Bitbang interface to manipulate reset lines SRST and TRST
- *
- * (1) assert or (0) deassert reset lines
- */
-static void sysfsgpio_reset(int trst, int srst)
-{
- LOG_DEBUG("sysfsgpio_reset");
- const char one[] = "1";
- const char zero[] = "0";
- size_t bytes_written;
-
- /* assume active low */
- if (srst_fd >= 0) {
- bytes_written = write(srst_fd, srst ? &zero : &one, 1);
- if (bytes_written != 1)
- LOG_WARNING("writing srst failed");
- }
-
- /* assume active low */
- if (trst_fd >= 0) {
- bytes_written = write(trst_fd, trst ? &zero : &one, 1);
- if (bytes_written != 1)
- LOG_WARNING("writing trst failed");
- }
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums)
-{
- if (CMD_ARGC == 4) {
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
- } else if (CMD_ARGC != 0) {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- command_print(CMD_CTX,
- "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
- tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: tck = %d", tck_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: tms = %d", tms_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: tdo = %d", tdo_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: tdi = %d", tdi_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: srst = %d", srst_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: trst = %d", trst_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_swd_gpionums)
-{
- if (CMD_ARGC == 2) {
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
- } else if (CMD_ARGC != 0) {
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- command_print(CMD_CTX,
- "SysfsGPIO nums: swclk = %d, swdio = %d",
- swclk_gpio, swdio_gpio);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swclk)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: swclk = %d", swclk_gpio);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swdio)
-{
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
-
- command_print(CMD_CTX, "SysfsGPIO num: swdio = %d", swdio_gpio);
- return ERROR_OK;
-}
-
-static const struct command_registration sysfsgpio_command_handlers[] = {
- {
- .name = "sysfsgpio_jtag_nums",
- .handler = &sysfsgpio_handle_jtag_gpionums,
- .mode = COMMAND_CONFIG,
- .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
- .usage = "(tck tms tdi tdo)* ",
- },
- {
- .name = "sysfsgpio_tck_num",
- .handler = &sysfsgpio_handle_jtag_gpionum_tck,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tck.",
- },
- {
- .name = "sysfsgpio_tms_num",
- .handler = &sysfsgpio_handle_jtag_gpionum_tms,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tms.",
- },
- {
- .name = "sysfsgpio_tdo_num",
- .handler = &sysfsgpio_handle_jtag_gpionum_tdo,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tdo.",
- },
- {
- .name = "sysfsgpio_tdi_num",
- .handler = &sysfsgpio_handle_jtag_gpionum_tdi,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for tdi.",
- },
- {
- .name = "sysfsgpio_srst_num",
- .handler = &sysfsgpio_handle_jtag_gpionum_srst,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for srst.",
- },
- {
- .name = "sysfsgpio_trst_num",
- .handler = &sysfsgpio_handle_jtag_gpionum_trst,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for trst.",
- },
- {
- .name = "sysfsgpio_swd_nums",
- .handler = &sysfsgpio_handle_swd_gpionums,
- .mode = COMMAND_CONFIG,
- .help = "gpio numbers for swclk, swdio. (in that order)",
- .usage = "(swclk swdio)* ",
- },
- {
- .name = "sysfsgpio_swclk_num",
- .handler = &sysfsgpio_handle_swd_gpionum_swclk,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for swclk.",
- },
- {
- .name = "sysfsgpio_swdio_num",
- .handler = &sysfsgpio_handle_swd_gpionum_swdio,
- .mode = COMMAND_CONFIG,
- .help = "gpio number for swdio.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int sysfsgpio_init(void);
-static int sysfsgpio_quit(void);
-
-static const char * const sysfsgpio_transports[] = { "jtag", "swd", NULL };
-
-struct jtag_interface sysfsgpio_interface = {
- .name = "sysfsgpio",
- .supported = DEBUG_CAP_TMS_SEQ,
- .execute_queue = bitbang_execute_queue,
- .transports = sysfsgpio_transports,
- .swd = &bitbang_swd,
- .commands = sysfsgpio_command_handlers,
- .init = sysfsgpio_init,
- .quit = sysfsgpio_quit,
-};
-
-static struct bitbang_interface sysfsgpio_bitbang = {
- .read = sysfsgpio_read,
- .write = sysfsgpio_write,
- .reset = sysfsgpio_reset,
- .swdio_read = sysfsgpio_swdio_read,
- .swdio_drive = sysfsgpio_swdio_drive,
- .blink = 0
-};
-
-/* helper func to close and cleanup files only if they were valid/ used */
-static void cleanup_fd(int fd, int gpio)
-{
- if (gpio >= 0) {
- if (fd >= 0)
- close(fd);
-
- unexport_sysfs_gpio(gpio);
- }
-}
-
-static void cleanup_all_fds(void)
-{
- cleanup_fd(tck_fd, tck_gpio);
- cleanup_fd(tms_fd, tms_gpio);
- cleanup_fd(tdi_fd, tdi_gpio);
- cleanup_fd(tdo_fd, tdo_gpio);
- cleanup_fd(trst_fd, trst_gpio);
- cleanup_fd(srst_fd, srst_gpio);
-}
-
-static bool sysfsgpio_jtag_mode_possible(void)
-{
- if (!is_gpio_valid(tck_gpio))
- return 0;
- if (!is_gpio_valid(tms_gpio))
- return 0;
- if (!is_gpio_valid(tdi_gpio))
- return 0;
- if (!is_gpio_valid(tdo_gpio))
- return 0;
- return 1;
-}
-
-static bool sysfsgpio_swd_mode_possible(void)
-{
- if (!is_gpio_valid(swclk_gpio))
- return 0;
- if (!is_gpio_valid(swdio_gpio))
- return 0;
- return 1;
-}
-
-static int sysfsgpio_init(void)
-{
- bitbang_interface = &sysfsgpio_bitbang;
-
- LOG_INFO("SysfsGPIO JTAG/SWD bitbang driver");
-
- if (sysfsgpio_jtag_mode_possible()) {
- if (sysfsgpio_swd_mode_possible())
- LOG_INFO("JTAG and SWD modes enabled");
- else
- LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
- if (!is_gpio_valid(trst_gpio) && !is_gpio_valid(srst_gpio)) {
- LOG_ERROR("Require at least one of trst or srst gpios to be specified");
- return ERROR_JTAG_INIT_FAILED;
- }
- } else if (sysfsgpio_swd_mode_possible()) {
- LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
- } else {
- LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
- return ERROR_JTAG_INIT_FAILED;
- }
-
-
- /*
- * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
- * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
- * For SWD, SWCLK and SWDIO are configures as output high.
- */
- if (tck_gpio >= 0) {
- tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0);
- if (tck_fd < 0)
- goto out_error;
- }
-
- if (tms_gpio >= 0) {
- tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1);
- if (tms_fd < 0)
- goto out_error;
- }
-
- if (tdi_gpio >= 0) {
- tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0);
- if (tdi_fd < 0)
- goto out_error;
- }
-
- if (tdo_gpio >= 0) {
- tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0);
- if (tdo_fd < 0)
- goto out_error;
- }
-
- /* assume active low*/
- if (trst_gpio >= 0) {
- trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1);
- if (trst_fd < 0)
- goto out_error;
- }
-
- /* assume active low*/
- if (srst_gpio >= 0) {
- srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1);
- if (srst_fd < 0)
- goto out_error;
- }
-
- if (swclk_gpio >= 0) {
- swclk_fd = setup_sysfs_gpio(swclk_gpio, 1, 0);
- if (swclk_fd < 0)
- goto out_error;
- }
-
- if (swdio_gpio >= 0) {
- swdio_fd = setup_sysfs_gpio(swdio_gpio, 1, 0);
- if (swdio_fd < 0)
- goto out_error;
- }
-
- if (sysfsgpio_swd_mode_possible()) {
- if (swd_mode)
- bitbang_swd_switch_seq(JTAG_TO_SWD);
- else
- bitbang_swd_switch_seq(SWD_TO_JTAG);
- }
-
- return ERROR_OK;
-
-out_error:
- cleanup_all_fds();
- return ERROR_JTAG_INIT_FAILED;
-}
-
-static int sysfsgpio_quit(void)
-{
- cleanup_all_fds();
- return ERROR_OK;
-}
-
diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c
deleted file mode 100644
index 3db03b0..0000000
--- a/src/jtag/drivers/ti_icdi_usb.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/***************************************************************************
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <helper/binarybuffer.h>
-#include <jtag/interface.h>
-#include <jtag/hla/hla_layout.h>
-#include <jtag/hla/hla_transport.h>
-#include <jtag/hla/hla_interface.h>
-#include <target/target.h>
-
-#include <target/cortex_m.h>
-
-#include <libusb.h>
-
-#define ICDI_WRITE_ENDPOINT 0x02
-#define ICDI_READ_ENDPOINT 0x83
-
-#define ICDI_WRITE_TIMEOUT 1000
-#define ICDI_READ_TIMEOUT 1000
-#define ICDI_PACKET_SIZE 2048
-
-#define PACKET_START "$"
-#define PACKET_END "#"
-
-struct icdi_usb_handle_s {
- libusb_context *usb_ctx;
- libusb_device_handle *usb_dev;
-
- char *read_buffer;
- char *write_buffer;
- int max_packet;
- int read_count;
- uint32_t max_rw_packet; /* max X packet (read/write memory) transfers */
-};
-
-static int icdi_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
- uint32_t count, uint8_t *buffer);
-static int icdi_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
- uint32_t count, const uint8_t *buffer);
-
-static int remote_escape_output(const char *buffer, int len, char *out_buf, int *out_len, int out_maxlen)
-{
- int input_index, output_index;
-
- output_index = 0;
-
- for (input_index = 0; input_index < len; input_index++) {
-
- char b = buffer[input_index];
-
- if (b == '$' || b == '#' || b == '}' || b == '*') {
- /* These must be escaped. */
- if (output_index + 2 > out_maxlen)
- break;
- out_buf[output_index++] = '}';
- out_buf[output_index++] = b ^ 0x20;
- } else {
- if (output_index + 1 > out_maxlen)
- break;
- out_buf[output_index++] = b;
- }
- }
-
- *out_len = input_index;
- return output_index;
-}
-
-static int remote_unescape_input(const char *buffer, int len, char *out_buf, int out_maxlen)
-{
- int input_index, output_index;
- int escaped;
-
- output_index = 0;
- escaped = 0;
-
- for (input_index = 0; input_index < len; input_index++) {
-
- char b = buffer[input_index];
-
- if (output_index + 1 > out_maxlen)
- LOG_ERROR("Received too much data from the target.");
-
- if (escaped) {
- out_buf[output_index++] = b ^ 0x20;
- escaped = 0;
- } else if (b == '}')
- escaped = 1;
- else
- out_buf[output_index++] = b;
- }
-
- if (escaped)
- LOG_ERROR("Unmatched escape character in target response.");
-
- return output_index;
-}
-
-static int icdi_send_packet(void *handle, int len)
-{
- unsigned char cksum = 0;
- struct icdi_usb_handle_s *h = handle;
- int result, retry = 0;
- int transferred = 0;
-
- assert(handle != NULL);
-
- /* check we have a large enough buffer for checksum "#00" */
- if (len + 3 > h->max_packet) {
- LOG_ERROR("packet buffer too small");
- return ERROR_FAIL;
- }
-
- /* calculate checksum - offset start of packet */
- for (int i = 1; i < len; i++)
- cksum += h->write_buffer[i];
-
- len += sprintf(&h->write_buffer[len], PACKET_END "%02x", cksum);
-
-#ifdef _DEBUG_USB_COMMS_
- char buffer[50];
- char ch = h->write_buffer[1];
- if (ch == 'x' || ch == 'X')
- LOG_DEBUG("writing packet: <binary>");
- else {
- memcpy(buffer, h->write_buffer, len >= 50 ? 50-1 : len);
- buffer[len] = 0;
- LOG_DEBUG("writing packet: %s", buffer);
- }
-#endif
-
- while (1) {
-
- result = libusb_bulk_transfer(h->usb_dev, ICDI_WRITE_ENDPOINT, (unsigned char *)h->write_buffer, len,
- &transferred, ICDI_WRITE_TIMEOUT);
- if (result != 0 || transferred != len) {
- LOG_DEBUG("Error TX Data %d", result);
- return ERROR_FAIL;
- }
-
- /* check that the client got the message ok, or shall we resend */
- result = libusb_bulk_transfer(h->usb_dev, ICDI_READ_ENDPOINT, (unsigned char *)h->read_buffer, h->max_packet,
- &transferred, ICDI_READ_TIMEOUT);
- if (result != 0 || transferred < 1) {
- LOG_DEBUG("Error RX Data %d", result);
- return ERROR_FAIL;
- }
-
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("received reply: '%c' : count %d", h->read_buffer[0], transferred);
-#endif
-
- if (h->read_buffer[0] == '-') {
- LOG_DEBUG("Resending packet %d", ++retry);
- } else {
- if (h->read_buffer[0] != '+')
- LOG_DEBUG("Unexpected Reply from ICDI: %c", h->read_buffer[0]);
- break;
- }
-
- if (retry == 3) {
- LOG_DEBUG("maximum nack retries attempted");
- return ERROR_FAIL;
- }
- }
-
- retry = 0;
- h->read_count = transferred;
-
- while (1) {
-
- /* read reply from icdi */
- result = libusb_bulk_transfer(h->usb_dev, ICDI_READ_ENDPOINT, (unsigned char *)h->read_buffer + h->read_count,
- h->max_packet - h->read_count, &transferred, ICDI_READ_TIMEOUT);
-
-#ifdef _DEBUG_USB_COMMS_
- LOG_DEBUG("received data: count %d", transferred);
-#endif
-
- /* check for errors but retry for timeout */
- if (result != 0) {
-
- if (result == LIBUSB_ERROR_TIMEOUT) {
- LOG_DEBUG("Error RX timeout %d", result);
- } else {
- LOG_DEBUG("Error RX Data %d", result);
- return ERROR_FAIL;
- }
- }
-
- h->read_count += transferred;
-
- /* we need to make sure we have a full packet, including checksum */
- if (h->read_count > 5) {
-
- /* check that we have received an packet delimiter
- * we do not validate the checksum
- * reply should contain $...#AA - so we check for # */
- if (h->read_buffer[h->read_count - 3] == '#')
- return ERROR_OK;
- }
-
- if (retry++ == 3) {
- LOG_DEBUG("maximum data retries attempted");
- break;
- }
- }
-
- return ERROR_FAIL;
-}
-
-static int icdi_send_cmd(void *handle, const char *cmd)
-{
- struct icdi_usb_handle_s *h = handle;
-
- int cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "%s", cmd);
- return icdi_send_packet(handle, cmd_len);
-}
-
-static int icdi_send_remote_cmd(void *handle, const char *data)
-{
- struct icdi_usb_handle_s *h = handle;
-
- size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,");
- cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len);
-
- return icdi_send_packet(handle, cmd_len);
-}
-
-static int icdi_get_cmd_result(void *handle)
-{
- struct icdi_usb_handle_s *h = handle;
- int offset = 0;
- char ch;
-
- assert(handle != NULL);
-
- do {
- ch = h->read_buffer[offset++];
- if (offset > h->read_count)
- return ERROR_FAIL;
- } while (ch != '$');
-
- if (memcmp("OK", h->read_buffer + offset, 2) == 0)
- return ERROR_OK;
-
- if (h->read_buffer[offset] == 'E') {
- /* get error code */
- char result;
- if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1)
- return ERROR_FAIL;
- return result;
- }
-
- /* for now we assume everything else is ok */
- return ERROR_OK;
-}
-
-static int icdi_usb_idcode(void *handle, uint32_t *idcode)
-{
- *idcode = 0;
- return ERROR_OK;
-}
-
-static int icdi_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
-{
- uint8_t buf[4];
- /* REVISIT: There's no target pointer here so there's no way to use target_buffer_set_u32().
- * I guess all supported chips are little-endian anyway. */
- h_u32_to_le(buf, val);
- return icdi_usb_write_mem(handle, addr, 4, 1, buf);
-}
-
-static enum target_state icdi_usb_state(void *handle)
-{
- int result;
- struct icdi_usb_handle_s *h = handle;
- uint32_t dhcsr;
- uint8_t buf[4];
-
- result = icdi_usb_read_mem(h, DCB_DHCSR, 4, 1, buf);
- if (result != ERROR_OK)
- return TARGET_UNKNOWN;
-
- /* REVISIT: There's no target pointer here so there's no way to use target_buffer_get_u32().
- * I guess all supported chips are little-endian anyway. */
- dhcsr = le_to_h_u32(buf);
- if (dhcsr & S_HALT)
- return TARGET_HALTED;
-
- return TARGET_RUNNING;
-}
-
-static int icdi_usb_version(void *handle)
-{
- struct icdi_usb_handle_s *h = handle;
-
- char version[20];
-
- /* get info about icdi */
- int result = icdi_send_remote_cmd(handle, "version");
- if (result != ERROR_OK)
- return result;
-
- if (h->read_count < 8) {
- LOG_ERROR("Invalid Reply Received");
- return ERROR_FAIL;
- }
-
- /* convert reply */
- if (unhexify(version, h->read_buffer + 2, 4) != 4) {
- LOG_WARNING("unable to get ICDI version");
- return ERROR_OK;
- }
-
- /* null terminate and print info */
- version[4] = 0;
-
- LOG_INFO("ICDI Firmware version: %s", version);
-
- return ERROR_OK;
-}
-
-static int icdi_usb_query(void *handle)
-{
- int result;
-
- struct icdi_usb_handle_s *h = handle;
-
- result = icdi_send_cmd(handle, "qSupported");
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("query supported failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- /* from this we can get the max packet supported */
-
- /* query packet buffer size */
- char *offset = strstr(h->read_buffer, "PacketSize");
- if (offset) {
- char *separator;
- int max_packet;
-
- max_packet = strtol(offset + 11, &separator, 16);
- if (!max_packet)
- LOG_ERROR("invalid max packet, using defaults");
- else
- h->max_packet = max_packet;
- LOG_DEBUG("max packet supported : %i bytes", h->max_packet);
- }
-
-
- /* if required re allocate packet buffer */
- if (h->max_packet != ICDI_PACKET_SIZE) {
- h->read_buffer = realloc(h->read_buffer, h->max_packet);
- h->write_buffer = realloc(h->write_buffer, h->max_packet);
- if (h->read_buffer == 0 || h->write_buffer == 0) {
- LOG_ERROR("unable to reallocate memory");
- return ERROR_FAIL;
- }
- }
-
- /* set extended mode */
- result = icdi_send_cmd(handle, "!");
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("unable to enable extended mode: 0x%x", result);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int icdi_usb_reset(void *handle)
-{
- /* we do this in hla_target.c */
- return ERROR_OK;
-}
-
-static int icdi_usb_assert_srst(void *handle, int srst)
-{
- /* TODO not supported yet */
- return ERROR_COMMAND_NOTFOUND;
-}
-
-static int icdi_usb_run(void *handle)
-{
- int result;
-
- /* resume target at current address */
- result = icdi_send_cmd(handle, "c");
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("continue failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- return result;
-}
-
-static int icdi_usb_halt(void *handle)
-{
- int result;
-
- /* this query halts the target ?? */
- result = icdi_send_cmd(handle, "?");
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("halt failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- return result;
-}
-
-static int icdi_usb_step(void *handle)
-{
- int result;
-
- /* step target at current address */
- result = icdi_send_cmd(handle, "s");
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("step failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- return result;
-}
-
-static int icdi_usb_read_regs(void *handle)
-{
- /* currently unsupported */
- return ERROR_OK;
-}
-
-static int icdi_usb_read_reg(void *handle, int num, uint32_t *val)
-{
- int result;
- struct icdi_usb_handle_s *h = handle;
- char cmd[10];
-
- snprintf(cmd, sizeof(cmd), "p%x", num);
- result = icdi_send_cmd(handle, cmd);
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("register read failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- /* convert result */
- uint8_t buf[4];
- if (unhexify((char *)buf, h->read_buffer + 2, 4) != 4) {
- LOG_ERROR("failed to convert result");
- return ERROR_FAIL;
- }
- *val = le_to_h_u32(buf);
-
- return result;
-}
-
-static int icdi_usb_write_reg(void *handle, int num, uint32_t val)
-{
- int result;
- char cmd[20];
- uint8_t buf[4];
- h_u32_to_le(buf, val);
-
- int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num);
- hexify(cmd + cmd_len, (const char *)buf, 4, sizeof(cmd));
-
- result = icdi_send_cmd(handle, cmd);
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("register write failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- return result;
-}
-
-static int icdi_usb_read_mem_int(void *handle, uint32_t addr, uint32_t len, uint8_t *buffer)
-{
- int result;
- struct icdi_usb_handle_s *h = handle;
- char cmd[20];
-
- snprintf(cmd, sizeof(cmd), "x%" PRIx32 ",%" PRIx32, addr, len);
- result = icdi_send_cmd(handle, cmd);
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("memory read failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- /* unescape input */
- int read_len = remote_unescape_input(h->read_buffer + 5, h->read_count - 8, (char *)buffer, len);
- if (read_len != (int)len) {
- LOG_ERROR("read more bytes than expected: actual 0x%x expected 0x%" PRIx32, read_len, len);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int icdi_usb_write_mem_int(void *handle, uint32_t addr, uint32_t len, const uint8_t *buffer)
-{
- int result;
- struct icdi_usb_handle_s *h = handle;
-
- size_t cmd_len = snprintf(h->write_buffer, h->max_packet, PACKET_START "X%" PRIx32 ",%" PRIx32 ":", addr, len);
-
- int out_len;
- cmd_len += remote_escape_output((const char *)buffer, len, h->write_buffer + cmd_len,
- &out_len, h->max_packet - cmd_len);
-
- if (out_len < (int)len) {
- /* for now issue a error as we have no way of allocating a larger buffer */
- LOG_ERROR("memory buffer too small: requires 0x%x actual 0x%" PRIx32, out_len, len);
- return ERROR_FAIL;
- }
-
- result = icdi_send_packet(handle, cmd_len);
- if (result != ERROR_OK)
- return result;
-
- /* check result */
- result = icdi_get_cmd_result(handle);
- if (result != ERROR_OK) {
- LOG_ERROR("memory write failed: 0x%x", result);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int icdi_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- int retval = ERROR_OK;
- struct icdi_usb_handle_s *h = handle;
- uint32_t bytes_remaining;
-
- /* calculate byte count */
- count *= size;
-
- while (count) {
-
- bytes_remaining = h->max_rw_packet;
- if (count < bytes_remaining)
- bytes_remaining = count;
-
- retval = icdi_usb_read_mem_int(handle, addr, bytes_remaining, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- buffer += bytes_remaining;
- addr += bytes_remaining;
- count -= bytes_remaining;
- }
-
- return retval;
-}
-
-static int icdi_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- int retval = ERROR_OK;
- struct icdi_usb_handle_s *h = handle;
- uint32_t bytes_remaining;
-
- /* calculate byte count */
- count *= size;
-
- while (count) {
-
- bytes_remaining = h->max_rw_packet;
- if (count < bytes_remaining)
- bytes_remaining = count;
-
- retval = icdi_usb_write_mem_int(handle, addr, bytes_remaining, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- buffer += bytes_remaining;
- addr += bytes_remaining;
- count -= bytes_remaining;
- }
-
- return retval;
-}
-
-static int icdi_usb_override_target(const char *targetname)
-{
- return !strcmp(targetname, "cortex_m");
-}
-
-static int icdi_usb_close(void *handle)
-{
- struct icdi_usb_handle_s *h = handle;
-
- if (!h)
- return ERROR_OK;
-
- if (h->usb_dev)
- libusb_close(h->usb_dev);
-
- if (h->usb_ctx)
- libusb_exit(h->usb_ctx);
-
- if (h->read_buffer)
- free(h->read_buffer);
-
- if (h->write_buffer)
- free(h->write_buffer);
-
- free(handle);
-
- return ERROR_OK;
-}
-
-static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
-{
- int retval;
- struct icdi_usb_handle_s *h;
-
- LOG_DEBUG("icdi_usb_open");
-
- h = calloc(1, sizeof(struct icdi_usb_handle_s));
-
- if (h == 0) {
- LOG_ERROR("unable to allocate memory");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport,
- param->vid, param->pid);
-
- if (libusb_init(&h->usb_ctx) != 0) {
- LOG_ERROR("libusb init failed");
- goto error_open;
- }
-
- h->usb_dev = libusb_open_device_with_vid_pid(h->usb_ctx, param->vid, param->pid);
- if (!h->usb_dev) {
- LOG_ERROR("open failed");
- goto error_open;
- }
-
- if (libusb_claim_interface(h->usb_dev, 2)) {
- LOG_DEBUG("claim interface failed");
- goto error_open;
- }
-
- /* check if mode is supported */
- retval = ERROR_OK;
-
- switch (param->transport) {
-#if 0
- /* TODO place holder as swd is not currently supported */
- case HL_TRANSPORT_SWD:
-#endif
- case HL_TRANSPORT_JTAG:
- break;
- default:
- retval = ERROR_FAIL;
- break;
- }
-
- if (retval != ERROR_OK) {
- LOG_ERROR("mode (transport) not supported by device");
- goto error_open;
- }
-
- /* allocate buffer */
- h->read_buffer = malloc(ICDI_PACKET_SIZE);
- h->write_buffer = malloc(ICDI_PACKET_SIZE);
- h->max_packet = ICDI_PACKET_SIZE;
-
- if (h->read_buffer == 0 || h->write_buffer == 0) {
- LOG_DEBUG("malloc failed");
- goto error_open;
- }
-
- /* query icdi version etc */
- retval = icdi_usb_version(h);
- if (retval != ERROR_OK)
- goto error_open;
-
- /* query icdi support */
- retval = icdi_usb_query(h);
- if (retval != ERROR_OK)
- goto error_open;
-
- *fd = h;
-
- /* set the max target read/write buffer in bytes
- * as we are using gdb binary packets to transfer memory we have to
- * reserve half the buffer for any possible escape chars plus
- * at least 64 bytes for the gdb packet header */
- h->max_rw_packet = (((h->max_packet - 64) / 4) * 4) / 2;
-
- return ERROR_OK;
-
-error_open:
- icdi_usb_close(h);
-
- return ERROR_FAIL;
-}
-
-struct hl_layout_api_s icdi_usb_layout_api = {
- .open = icdi_usb_open,
- .close = icdi_usb_close,
- .idcode = icdi_usb_idcode,
- .state = icdi_usb_state,
- .reset = icdi_usb_reset,
- .assert_srst = icdi_usb_assert_srst,
- .run = icdi_usb_run,
- .halt = icdi_usb_halt,
- .step = icdi_usb_step,
- .read_regs = icdi_usb_read_regs,
- .read_reg = icdi_usb_read_reg,
- .write_reg = icdi_usb_write_reg,
- .read_mem = icdi_usb_read_mem,
- .write_mem = icdi_usb_write_mem,
- .write_debug_reg = icdi_usb_write_debug_reg,
- .override_target = icdi_usb_override_target,
- .custom_command = icdi_send_remote_cmd,
-};
diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c
deleted file mode 100644
index c319a11..0000000
--- a/src/jtag/drivers/ulink.c
+++ /dev/null
@@ -1,2316 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011-2013 by Martin Schmoelzer *
- * <martin.schmoelzer@student.tuwien.ac.at> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <math.h>
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <target/image.h>
-#include <libusb.h>
-#include "OpenULINK/include/msgtypes.h"
-
-/** USB Vendor ID of ULINK device in unconfigured state (no firmware loaded
- * yet) or with OpenULINK firmware. */
-#define ULINK_VID 0xC251
-
-/** USB Product ID of ULINK device in unconfigured state (no firmware loaded
- * yet) or with OpenULINK firmware. */
-#define ULINK_PID 0x2710
-
-/** Address of EZ-USB CPU Control & Status register. This register can be
- * written by issuing a Control EP0 vendor request. */
-#define CPUCS_REG 0x7F92
-
-/** USB Control EP0 bRequest: "Firmware Load". */
-#define REQUEST_FIRMWARE_LOAD 0xA0
-
-/** Value to write into CPUCS to put EZ-USB into reset. */
-#define CPU_RESET 0x01
-
-/** Value to write into CPUCS to put EZ-USB out of reset. */
-#define CPU_START 0x00
-
-/** Base address of firmware in EZ-USB code space. */
-#define FIRMWARE_ADDR 0x0000
-
-/** USB interface number */
-#define USB_INTERFACE 0
-
-/** libusb timeout in ms */
-#define USB_TIMEOUT 5000
-
-/** Delay (in microseconds) to wait while EZ-USB performs ReNumeration. */
-#define ULINK_RENUMERATION_DELAY 1500000
-
-/** Default location of OpenULINK firmware image. */
-#define ULINK_FIRMWARE_FILE PKGDATADIR "/OpenULINK/ulink_firmware.hex"
-
-/** Maximum size of a single firmware section. Entire EZ-USB code space = 8kB */
-#define SECTION_BUFFERSIZE 8192
-
-/** Tuning of OpenOCD SCAN commands split into multiple OpenULINK commands. */
-#define SPLIT_SCAN_THRESHOLD 10
-
-/** ULINK hardware type */
-enum ulink_type {
- /** Original ULINK adapter, based on Cypress EZ-USB (AN2131):
- * Full JTAG support, no SWD support. */
- ULINK_1,
-
- /** Newer ULINK adapter, based on NXP LPC2148. Currently unsupported. */
- ULINK_2,
-
- /** Newer ULINK adapter, based on EZ-USB FX2 + FPGA. Currently unsupported. */
- ULINK_PRO,
-
- /** Newer ULINK adapter, possibly based on ULINK 2. Currently unsupported. */
- ULINK_ME
-};
-
-enum ulink_payload_direction {
- PAYLOAD_DIRECTION_OUT,
- PAYLOAD_DIRECTION_IN
-};
-
-enum ulink_delay_type {
- DELAY_CLOCK_TCK,
- DELAY_CLOCK_TMS,
- DELAY_SCAN_IN,
- DELAY_SCAN_OUT,
- DELAY_SCAN_IO
-};
-
-/**
- * OpenULINK command (OpenULINK command queue element).
- *
- * For the OUT direction payload, things are quite easy: Payload is stored
- * in a rather small array (up to 63 bytes), the payload is always allocated
- * by the function generating the command and freed by ulink_clear_queue().
- *
- * For the IN direction payload, things get a little bit more complicated:
- * The maximum IN payload size for a single command is 64 bytes. Assume that
- * a single OpenOCD command needs to scan 256 bytes. This results in the
- * generation of four OpenULINK commands. The function generating these
- * commands shall allocate an uint8_t[256] array. Each command's #payload_in
- * pointer shall point to the corresponding offset where IN data shall be
- * placed, while #payload_in_start shall point to the first element of the 256
- * byte array.
- * - first command: #payload_in_start + 0
- * - second command: #payload_in_start + 64
- * - third command: #payload_in_start + 128
- * - fourth command: #payload_in_start + 192
- *
- * The last command sets #needs_postprocessing to true.
- */
-struct ulink_cmd {
- uint8_t id; /**< ULINK command ID */
-
- uint8_t *payload_out; /**< OUT direction payload data */
- uint8_t payload_out_size; /**< OUT direction payload size for this command */
-
- uint8_t *payload_in_start; /**< Pointer to first element of IN payload array */
- uint8_t *payload_in; /**< Pointer where IN payload shall be stored */
- uint8_t payload_in_size; /**< IN direction payload size for this command */
-
- /** Indicates if this command needs post-processing */
- bool needs_postprocessing;
-
- /** Indicates if ulink_clear_queue() should free payload_in_start */
- bool free_payload_in_start;
-
- /** Pointer to corresponding OpenOCD command for post-processing */
- struct jtag_command *cmd_origin;
-
- struct ulink_cmd *next; /**< Pointer to next command (linked list) */
-};
-
-/** Describes one driver instance */
-struct ulink {
- struct libusb_context *libusb_ctx;
- struct libusb_device_handle *usb_device_handle;
- enum ulink_type type;
-
- int delay_scan_in; /**< Delay value for SCAN_IN commands */
- int delay_scan_out; /**< Delay value for SCAN_OUT commands */
- int delay_scan_io; /**< Delay value for SCAN_IO commands */
- int delay_clock_tck; /**< Delay value for CLOCK_TMS commands */
- int delay_clock_tms; /**< Delay value for CLOCK_TCK commands */
-
- int commands_in_queue; /**< Number of commands in queue */
- struct ulink_cmd *queue_start; /**< Pointer to first command in queue */
- struct ulink_cmd *queue_end; /**< Pointer to last command in queue */
-};
-
-/**************************** Function Prototypes *****************************/
-
-/* USB helper functions */
-int ulink_usb_open(struct ulink **device);
-int ulink_usb_close(struct ulink **device);
-
-/* ULINK MCU (Cypress EZ-USB) specific functions */
-int ulink_cpu_reset(struct ulink *device, unsigned char reset_bit);
-int ulink_load_firmware_and_renumerate(struct ulink **device, const char *filename,
- uint32_t delay);
-int ulink_load_firmware(struct ulink *device, const char *filename);
-int ulink_write_firmware_section(struct ulink *device,
- struct image *firmware_image, int section_index);
-
-/* Generic helper functions */
-void ulink_print_signal_states(uint8_t input_signals, uint8_t output_signals);
-
-/* OpenULINK command generation helper functions */
-int ulink_allocate_payload(struct ulink_cmd *ulink_cmd, int size,
- enum ulink_payload_direction direction);
-
-/* OpenULINK command queue helper functions */
-int ulink_get_queue_size(struct ulink *device,
- enum ulink_payload_direction direction);
-void ulink_clear_queue(struct ulink *device);
-int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd);
-int ulink_execute_queued_commands(struct ulink *device, int timeout);
-
-#ifdef _DEBUG_JTAG_IO_
-const char *ulink_cmd_id_string(uint8_t id);
-void ulink_print_command(struct ulink_cmd *ulink_cmd);
-void ulink_print_queue(struct ulink *device);
-static int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f);
-#endif
-
-int ulink_append_scan_cmd(struct ulink *device,
- enum scan_type scan_type,
- int scan_size_bits,
- uint8_t *tdi,
- uint8_t *tdo_start,
- uint8_t *tdo,
- uint8_t tms_count_start,
- uint8_t tms_sequence_start,
- uint8_t tms_count_end,
- uint8_t tms_sequence_end,
- struct jtag_command *origin,
- bool postprocess);
-int ulink_append_clock_tms_cmd(struct ulink *device, uint8_t count,
- uint8_t sequence);
-int ulink_append_clock_tck_cmd(struct ulink *device, uint16_t count);
-int ulink_append_get_signals_cmd(struct ulink *device);
-int ulink_append_set_signals_cmd(struct ulink *device, uint8_t low,
- uint8_t high);
-int ulink_append_sleep_cmd(struct ulink *device, uint32_t us);
-int ulink_append_configure_tck_cmd(struct ulink *device,
- int delay_scan_in,
- int delay_scan_out,
- int delay_scan_io,
- int delay_tck,
- int delay_tms);
-int ulink_append_led_cmd(struct ulink *device, uint8_t led_state);
-int ulink_append_test_cmd(struct ulink *device);
-
-/* OpenULINK TCK frequency helper functions */
-int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay);
-
-/* Interface between OpenULINK and OpenOCD */
-static void ulink_set_end_state(tap_state_t endstate);
-int ulink_queue_statemove(struct ulink *device);
-
-int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd);
-int ulink_queue_tlr_reset(struct ulink *device, struct jtag_command *cmd);
-int ulink_queue_runtest(struct ulink *device, struct jtag_command *cmd);
-int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd);
-int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd);
-int ulink_queue_sleep(struct ulink *device, struct jtag_command *cmd);
-int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd);
-
-int ulink_post_process_scan(struct ulink_cmd *ulink_cmd);
-int ulink_post_process_queue(struct ulink *device);
-
-/* JTAG driver functions (registered in struct jtag_interface) */
-static int ulink_execute_queue(void);
-static int ulink_khz(int khz, int *jtag_speed);
-static int ulink_speed(int speed);
-static int ulink_speed_div(int speed, int *khz);
-static int ulink_init(void);
-static int ulink_quit(void);
-
-/****************************** Global Variables ******************************/
-
-struct ulink *ulink_handle;
-
-/**************************** USB helper functions ****************************/
-
-/**
- * Opens the ULINK device and claims its USB interface.
- *
- * Currently, only the original ULINK is supported
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_usb_open(struct ulink **device)
-{
- ssize_t num_devices, i;
- bool found;
- libusb_device **usb_devices;
- struct libusb_device_descriptor usb_desc;
- struct libusb_device_handle *usb_device_handle;
-
- num_devices = libusb_get_device_list((*device)->libusb_ctx, &usb_devices);
-
- if (num_devices <= 0)
- return ERROR_FAIL;
-
- found = false;
- for (i = 0; i < num_devices; i++) {
- if (libusb_get_device_descriptor(usb_devices[i], &usb_desc) != 0)
- continue;
- else if (usb_desc.idVendor == ULINK_VID && usb_desc.idProduct == ULINK_PID) {
- found = true;
- break;
- }
- }
-
- if (!found)
- return ERROR_FAIL;
-
- if (libusb_open(usb_devices[i], &usb_device_handle) != 0)
- return ERROR_FAIL;
- libusb_free_device_list(usb_devices, 1);
-
- if (libusb_claim_interface(usb_device_handle, 0) != 0)
- return ERROR_FAIL;
-
- (*device)->usb_device_handle = usb_device_handle;
- (*device)->type = ULINK_1;
-
- return ERROR_OK;
-}
-
-/**
- * Releases the ULINK interface and closes the USB device handle.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_usb_close(struct ulink **device)
-{
- if (libusb_release_interface((*device)->usb_device_handle, 0) != 0)
- return ERROR_FAIL;
-
- libusb_close((*device)->usb_device_handle);
-
- (*device)->usb_device_handle = NULL;
-
- return ERROR_OK;
-}
-
-/******************* ULINK CPU (EZ-USB) specific functions ********************/
-
-/**
- * Writes '0' or '1' to the CPUCS register, putting the EZ-USB CPU into reset
- * or out of reset.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param reset_bit 0 to put CPU into reset, 1 to put CPU out of reset.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_cpu_reset(struct ulink *device, unsigned char reset_bit)
-{
- int ret;
-
- ret = libusb_control_transfer(device->usb_device_handle,
- (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE),
- REQUEST_FIRMWARE_LOAD, CPUCS_REG, 0, &reset_bit, 1, USB_TIMEOUT);
-
- /* usb_control_msg() returns the number of bytes transferred during the
- * DATA stage of the control transfer - must be exactly 1 in this case! */
- if (ret != 1)
- return ERROR_FAIL;
- return ERROR_OK;
-}
-
-/**
- * Puts the ULINK's EZ-USB microcontroller into reset state, downloads
- * the firmware image, resumes the microcontroller and re-enumerates
- * USB devices.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * The usb_handle member will be modified during re-enumeration.
- * @param filename path to the Intel HEX file containing the firmware image.
- * @param delay the delay to wait for the device to re-enumerate.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_load_firmware_and_renumerate(struct ulink **device,
- const char *filename, uint32_t delay)
-{
- int ret;
-
- /* Basic process: After downloading the firmware, the ULINK will disconnect
- * itself and re-connect after a short amount of time so we have to close
- * the handle and re-enumerate USB devices */
-
- ret = ulink_load_firmware(*device, filename);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ulink_usb_close(device);
- if (ret != ERROR_OK)
- return ret;
-
- usleep(delay);
-
- ret = ulink_usb_open(device);
- if (ret != ERROR_OK)
- return ret;
-
- return ERROR_OK;
-}
-
-/**
- * Downloads a firmware image to the ULINK's EZ-USB microcontroller
- * over the USB bus.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param filename an absolute or relative path to the Intel HEX file
- * containing the firmware image.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_load_firmware(struct ulink *device, const char *filename)
-{
- struct image ulink_firmware_image;
- int ret, i;
-
- ret = ulink_cpu_reset(device, CPU_RESET);
- if (ret != ERROR_OK) {
- LOG_ERROR("Could not halt ULINK CPU");
- return ret;
- }
-
- ulink_firmware_image.base_address = 0;
- ulink_firmware_image.base_address_set = 0;
-
- ret = image_open(&ulink_firmware_image, filename, "ihex");
- if (ret != ERROR_OK) {
- LOG_ERROR("Could not load firmware image");
- return ret;
- }
-
- /* Download all sections in the image to ULINK */
- for (i = 0; i < ulink_firmware_image.num_sections; i++) {
- ret = ulink_write_firmware_section(device, &ulink_firmware_image, i);
- if (ret != ERROR_OK)
- return ret;
- }
-
- image_close(&ulink_firmware_image);
-
- ret = ulink_cpu_reset(device, CPU_START);
- if (ret != ERROR_OK) {
- LOG_ERROR("Could not restart ULINK CPU");
- return ret;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Send one contiguous firmware section to the ULINK's EZ-USB microcontroller
- * over the USB bus.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param firmware_image pointer to the firmware image that contains the section
- * which should be sent to the ULINK's EZ-USB microcontroller.
- * @param section_index index of the section within the firmware image.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_write_firmware_section(struct ulink *device,
- struct image *firmware_image, int section_index)
-{
- uint16_t addr, size, bytes_remaining, chunk_size;
- uint8_t data[SECTION_BUFFERSIZE];
- uint8_t *data_ptr = data;
- size_t size_read;
- int ret;
-
- size = (uint16_t)firmware_image->sections[section_index].size;
- addr = (uint16_t)firmware_image->sections[section_index].base_address;
-
- LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04x)", section_index, addr,
- size);
-
- /* Copy section contents to local buffer */
- ret = image_read_section(firmware_image, section_index, 0, size, data,
- &size_read);
-
- if ((ret != ERROR_OK) || (size_read != size)) {
- /* Propagating the return code would return '0' (misleadingly indicating
- * successful execution of the function) if only the size check fails. */
- return ERROR_FAIL;
- }
-
- bytes_remaining = size;
-
- /* Send section data in chunks of up to 64 bytes to ULINK */
- while (bytes_remaining > 0) {
- if (bytes_remaining > 64)
- chunk_size = 64;
- else
- chunk_size = bytes_remaining;
-
- ret = libusb_control_transfer(device->usb_device_handle,
- (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE),
- REQUEST_FIRMWARE_LOAD, addr, FIRMWARE_ADDR, (unsigned char *)data_ptr,
- chunk_size, USB_TIMEOUT);
-
- if (ret != (int)chunk_size) {
- /* Abort if libusb sent less data than requested */
- return ERROR_FAIL;
- }
-
- bytes_remaining -= chunk_size;
- addr += chunk_size;
- data_ptr += chunk_size;
- }
-
- return ERROR_OK;
-}
-
-/************************** Generic helper functions **************************/
-
-/**
- * Print state of interesting signals via LOG_INFO().
- *
- * @param input_signals input signal states as returned by CMD_GET_SIGNALS
- * @param output_signals output signal states as returned by CMD_GET_SIGNALS
- */
-void ulink_print_signal_states(uint8_t input_signals, uint8_t output_signals)
-{
- LOG_INFO("ULINK signal states: TDI: %i, TDO: %i, TMS: %i, TCK: %i, TRST: %i,"
- " SRST: %i",
- (output_signals & SIGNAL_TDI ? 1 : 0),
- (input_signals & SIGNAL_TDO ? 1 : 0),
- (output_signals & SIGNAL_TMS ? 1 : 0),
- (output_signals & SIGNAL_TCK ? 1 : 0),
- (output_signals & SIGNAL_TRST ? 0 : 1), /* Inverted by hardware */
- (output_signals & SIGNAL_RESET ? 0 : 1)); /* Inverted by hardware */
-}
-
-/**************** OpenULINK command generation helper functions ***************/
-
-/**
- * Allocate and initialize space in memory for OpenULINK command payload.
- *
- * @param ulink_cmd pointer to command whose payload should be allocated.
- * @param size the amount of memory to allocate (bytes).
- * @param direction which payload to allocate.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_allocate_payload(struct ulink_cmd *ulink_cmd, int size,
- enum ulink_payload_direction direction)
-{
- uint8_t *payload;
-
- payload = calloc(size, sizeof(uint8_t));
-
- if (payload == NULL) {
- LOG_ERROR("Could not allocate OpenULINK command payload: out of memory");
- return ERROR_FAIL;
- }
-
- switch (direction) {
- case PAYLOAD_DIRECTION_OUT:
- if (ulink_cmd->payload_out != NULL) {
- LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command");
- free(payload);
- return ERROR_FAIL;
- } else {
- ulink_cmd->payload_out = payload;
- ulink_cmd->payload_out_size = size;
- }
- break;
- case PAYLOAD_DIRECTION_IN:
- if (ulink_cmd->payload_in_start != NULL) {
- LOG_ERROR("BUG: Duplicate payload allocation for OpenULINK command");
- free(payload);
- return ERROR_FAIL;
- } else {
- ulink_cmd->payload_in_start = payload;
- ulink_cmd->payload_in = payload;
- ulink_cmd->payload_in_size = size;
-
- /* By default, free payload_in_start in ulink_clear_queue(). Commands
- * that do not want this behavior (e. g. split scans) must turn it off
- * separately! */
- ulink_cmd->free_payload_in_start = true;
- }
- break;
- }
-
- return ERROR_OK;
-}
-
-/****************** OpenULINK command queue helper functions ******************/
-
-/**
- * Get the current number of bytes in the queue, including command IDs.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param direction the transfer direction for which to get byte count.
- * @return the number of bytes currently stored in the queue for the specified
- * direction.
- */
-int ulink_get_queue_size(struct ulink *device,
- enum ulink_payload_direction direction)
-{
- struct ulink_cmd *current = device->queue_start;
- int sum = 0;
-
- while (current != NULL) {
- switch (direction) {
- case PAYLOAD_DIRECTION_OUT:
- sum += current->payload_out_size + 1; /* + 1 byte for Command ID */
- break;
- case PAYLOAD_DIRECTION_IN:
- sum += current->payload_in_size;
- break;
- }
-
- current = current->next;
- }
-
- return sum;
-}
-
-/**
- * Clear the OpenULINK command queue.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-void ulink_clear_queue(struct ulink *device)
-{
- struct ulink_cmd *current = device->queue_start;
- struct ulink_cmd *next = NULL;
-
- while (current != NULL) {
- /* Save pointer to next element */
- next = current->next;
-
- /* Free payloads: OUT payload can be freed immediately */
- free(current->payload_out);
- current->payload_out = NULL;
-
- /* IN payload MUST be freed ONLY if no other commands use the
- * payload_in_start buffer */
- if (current->free_payload_in_start == true) {
- free(current->payload_in_start);
- current->payload_in_start = NULL;
- current->payload_in = NULL;
- }
-
- /* Free queue element */
- free(current);
-
- /* Proceed with next element */
- current = next;
- }
-
- device->commands_in_queue = 0;
- device->queue_start = NULL;
- device->queue_end = NULL;
-}
-
-/**
- * Add a command to the OpenULINK command queue.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param ulink_cmd pointer to command that shall be appended to the OpenULINK
- * command queue.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd)
-{
- int newsize_out, newsize_in;
- int ret;
-
- newsize_out = ulink_get_queue_size(device, PAYLOAD_DIRECTION_OUT) + 1
- + ulink_cmd->payload_out_size;
-
- newsize_in = ulink_get_queue_size(device, PAYLOAD_DIRECTION_IN)
- + ulink_cmd->payload_in_size;
-
- /* Check if the current command can be appended to the queue */
- if ((newsize_out > 64) || (newsize_in > 64)) {
- /* New command does not fit. Execute all commands in queue before starting
- * new queue with the current command as first entry. */
- ret = ulink_execute_queued_commands(device, USB_TIMEOUT);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ulink_post_process_queue(device);
- if (ret != ERROR_OK)
- return ret;
-
- ulink_clear_queue(device);
- }
-
- if (device->queue_start == NULL) {
- /* Queue was empty */
- device->commands_in_queue = 1;
-
- device->queue_start = ulink_cmd;
- device->queue_end = ulink_cmd;
- } else {
- /* There are already commands in the queue */
- device->commands_in_queue++;
-
- device->queue_end->next = ulink_cmd;
- device->queue_end = ulink_cmd;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Sends all queued OpenULINK commands to the ULINK for execution.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_execute_queued_commands(struct ulink *device, int timeout)
-{
- struct ulink_cmd *current;
- int ret, i, index_out, index_in, count_out, count_in, transferred;
- uint8_t buffer[64];
-
-#ifdef _DEBUG_JTAG_IO_
- ulink_print_queue(device);
-#endif
-
- index_out = 0;
- count_out = 0;
- count_in = 0;
-
- for (current = device->queue_start; current; current = current->next) {
- /* Add command to packet */
- buffer[index_out] = current->id;
- index_out++;
- count_out++;
-
- for (i = 0; i < current->payload_out_size; i++)
- buffer[index_out + i] = current->payload_out[i];
- index_out += current->payload_out_size;
- count_in += current->payload_in_size;
- count_out += current->payload_out_size;
- }
-
- /* Send packet to ULINK */
- ret = libusb_bulk_transfer(device->usb_device_handle, (2 | LIBUSB_ENDPOINT_OUT),
- (unsigned char *)buffer, count_out, &transferred, timeout);
- if (ret != 0)
- return ERROR_FAIL;
- if (transferred != count_out)
- return ERROR_FAIL;
-
- /* Wait for response if commands contain IN payload data */
- if (count_in > 0) {
- ret = libusb_bulk_transfer(device->usb_device_handle, (2 | LIBUSB_ENDPOINT_IN),
- (unsigned char *)buffer, 64, &transferred, timeout);
- if (ret != 0)
- return ERROR_FAIL;
- if (transferred != count_in)
- return ERROR_FAIL;
-
- /* Write back IN payload data */
- index_in = 0;
- for (current = device->queue_start; current; current = current->next) {
- for (i = 0; i < current->payload_in_size; i++) {
- current->payload_in[i] = buffer[index_in];
- index_in++;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-#ifdef _DEBUG_JTAG_IO_
-
-/**
- * Convert an OpenULINK command ID (\a id) to a human-readable string.
- *
- * @param id the OpenULINK command ID.
- * @return the corresponding human-readable string.
- */
-const char *ulink_cmd_id_string(uint8_t id)
-{
- switch (id) {
- case CMD_SCAN_IN:
- return "CMD_SCAN_IN";
- break;
- case CMD_SLOW_SCAN_IN:
- return "CMD_SLOW_SCAN_IN";
- break;
- case CMD_SCAN_OUT:
- return "CMD_SCAN_OUT";
- break;
- case CMD_SLOW_SCAN_OUT:
- return "CMD_SLOW_SCAN_OUT";
- break;
- case CMD_SCAN_IO:
- return "CMD_SCAN_IO";
- break;
- case CMD_SLOW_SCAN_IO:
- return "CMD_SLOW_SCAN_IO";
- break;
- case CMD_CLOCK_TMS:
- return "CMD_CLOCK_TMS";
- break;
- case CMD_SLOW_CLOCK_TMS:
- return "CMD_SLOW_CLOCK_TMS";
- break;
- case CMD_CLOCK_TCK:
- return "CMD_CLOCK_TCK";
- break;
- case CMD_SLOW_CLOCK_TCK:
- return "CMD_SLOW_CLOCK_TCK";
- break;
- case CMD_SLEEP_US:
- return "CMD_SLEEP_US";
- break;
- case CMD_SLEEP_MS:
- return "CMD_SLEEP_MS";
- break;
- case CMD_GET_SIGNALS:
- return "CMD_GET_SIGNALS";
- break;
- case CMD_SET_SIGNALS:
- return "CMD_SET_SIGNALS";
- break;
- case CMD_CONFIGURE_TCK_FREQ:
- return "CMD_CONFIGURE_TCK_FREQ";
- break;
- case CMD_SET_LEDS:
- return "CMD_SET_LEDS";
- break;
- case CMD_TEST:
- return "CMD_TEST";
- break;
- default:
- return "CMD_UNKNOWN";
- break;
- }
-}
-
-/**
- * Print one OpenULINK command to stdout.
- *
- * @param ulink_cmd pointer to OpenULINK command.
- */
-void ulink_print_command(struct ulink_cmd *ulink_cmd)
-{
- int i;
-
- printf(" %-22s | OUT size = %i, bytes = 0x",
- ulink_cmd_id_string(ulink_cmd->id), ulink_cmd->payload_out_size);
-
- for (i = 0; i < ulink_cmd->payload_out_size; i++)
- printf("%02X ", ulink_cmd->payload_out[i]);
- printf("\n | IN size = %i\n",
- ulink_cmd->payload_in_size);
-}
-
-/**
- * Print the OpenULINK command queue to stdout.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- */
-void ulink_print_queue(struct ulink *device)
-{
- struct ulink_cmd *current;
-
- printf("OpenULINK command queue:\n");
-
- for (current = device->queue_start; current; current = current->next)
- ulink_print_command(current);
-}
-
-#endif /* _DEBUG_JTAG_IO_ */
-
-/**
- * Perform JTAG scan
- *
- * Creates and appends a JTAG scan command to the OpenULINK command queue.
- * A JTAG scan consists of three steps:
- * - Move to the desired SHIFT state, depending on scan type (IR/DR scan).
- * - Shift TDI data into the JTAG chain, optionally reading the TDO pin.
- * - Move to the desired end state.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param scan_type the type of the scan (IN, OUT, IO (bidirectional)).
- * @param scan_size_bits number of bits to shift into the JTAG chain.
- * @param tdi pointer to array containing TDI data.
- * @param tdo_start pointer to first element of array where TDO data shall be
- * stored. See #ulink_cmd for details.
- * @param tdo pointer to array where TDO data shall be stored
- * @param tms_count_start number of TMS state transitions to perform BEFORE
- * shifting data into the JTAG chain.
- * @param tms_sequence_start sequence of TMS state transitions that will be
- * performed BEFORE shifting data into the JTAG chain.
- * @param tms_count_end number of TMS state transitions to perform AFTER
- * shifting data into the JTAG chain.
- * @param tms_sequence_end sequence of TMS state transitions that will be
- * performed AFTER shifting data into the JTAG chain.
- * @param origin pointer to OpenOCD command that generated this scan command.
- * @param postprocess whether this command needs to be post-processed after
- * execution.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_scan_cmd(struct ulink *device, enum scan_type scan_type,
- int scan_size_bits, uint8_t *tdi, uint8_t *tdo_start, uint8_t *tdo,
- uint8_t tms_count_start, uint8_t tms_sequence_start, uint8_t tms_count_end,
- uint8_t tms_sequence_end, struct jtag_command *origin, bool postprocess)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret, i, scan_size_bytes;
- uint8_t bits_last_byte;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- /* Check size of command. USB buffer can hold 64 bytes, 1 byte is command ID,
- * 5 bytes are setup data -> 58 remaining payload bytes for TDI data */
- if (scan_size_bits > (58 * 8)) {
- LOG_ERROR("BUG: Tried to create CMD_SCAN_IO OpenULINK command with too"
- " large payload");
- free(cmd);
- return ERROR_FAIL;
- }
-
- scan_size_bytes = DIV_ROUND_UP(scan_size_bits, 8);
-
- bits_last_byte = scan_size_bits % 8;
- if (bits_last_byte == 0)
- bits_last_byte = 8;
-
- /* Allocate out_payload depending on scan type */
- switch (scan_type) {
- case SCAN_IN:
- if (device->delay_scan_in < 0)
- cmd->id = CMD_SCAN_IN;
- else
- cmd->id = CMD_SLOW_SCAN_IN;
- ret = ulink_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_OUT);
- break;
- case SCAN_OUT:
- if (device->delay_scan_out < 0)
- cmd->id = CMD_SCAN_OUT;
- else
- cmd->id = CMD_SLOW_SCAN_OUT;
- ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
- break;
- case SCAN_IO:
- if (device->delay_scan_io < 0)
- cmd->id = CMD_SCAN_IO;
- else
- cmd->id = CMD_SLOW_SCAN_IO;
- ret = ulink_allocate_payload(cmd, scan_size_bytes + 5, PAYLOAD_DIRECTION_OUT);
- break;
- default:
- LOG_ERROR("BUG: ulink_append_scan_cmd() encountered an unknown scan type");
- ret = ERROR_FAIL;
- break;
- }
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- /* Build payload_out that is common to all scan types */
- cmd->payload_out[0] = scan_size_bytes & 0xFF;
- cmd->payload_out[1] = bits_last_byte & 0xFF;
- cmd->payload_out[2] = ((tms_count_start & 0x0F) << 4) | (tms_count_end & 0x0F);
- cmd->payload_out[3] = tms_sequence_start;
- cmd->payload_out[4] = tms_sequence_end;
-
- /* Setup payload_out for types with OUT transfer */
- if ((scan_type == SCAN_OUT) || (scan_type == SCAN_IO)) {
- for (i = 0; i < scan_size_bytes; i++)
- cmd->payload_out[i + 5] = tdi[i];
- }
-
- /* Setup payload_in pointers for types with IN transfer */
- if ((scan_type == SCAN_IN) || (scan_type == SCAN_IO)) {
- cmd->payload_in_start = tdo_start;
- cmd->payload_in = tdo;
- cmd->payload_in_size = scan_size_bytes;
- }
-
- cmd->needs_postprocessing = postprocess;
- cmd->cmd_origin = origin;
-
- /* For scan commands, we free payload_in_start only when the command is
- * the last in a series of split commands or a stand-alone command */
- cmd->free_payload_in_start = postprocess;
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Perform TAP state transitions
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param count defines the number of TCK clock cycles generated (up to 8).
- * @param sequence defines the TMS pin levels for each state transition. The
- * Least-Significant Bit is read first.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_clock_tms_cmd(struct ulink *device, uint8_t count,
- uint8_t sequence)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- if (device->delay_clock_tms < 0)
- cmd->id = CMD_CLOCK_TMS;
- else
- cmd->id = CMD_SLOW_CLOCK_TMS;
-
- /* CMD_CLOCK_TMS has two OUT payload bytes and zero IN payload bytes */
- ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = count;
- cmd->payload_out[1] = sequence;
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Generate a defined amount of TCK clock cycles
- *
- * All other JTAG signals are left unchanged.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param count the number of TCK clock cycles to generate.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_clock_tck_cmd(struct ulink *device, uint16_t count)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- if (device->delay_clock_tck < 0)
- cmd->id = CMD_CLOCK_TCK;
- else
- cmd->id = CMD_SLOW_CLOCK_TCK;
-
- /* CMD_CLOCK_TCK has two OUT payload bytes and zero IN payload bytes */
- ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = count & 0xff;
- cmd->payload_out[1] = (count >> 8) & 0xff;
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Read JTAG signals.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_get_signals_cmd(struct ulink *device)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- cmd->id = CMD_GET_SIGNALS;
- cmd->needs_postprocessing = true;
-
- /* CMD_GET_SIGNALS has two IN payload bytes */
- ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_IN);
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Arbitrarily set JTAG output signals.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param low defines which signals will be de-asserted. Each bit corresponds
- * to a JTAG signal:
- * - SIGNAL_TDI
- * - SIGNAL_TMS
- * - SIGNAL_TCK
- * - SIGNAL_TRST
- * - SIGNAL_BRKIN
- * - SIGNAL_RESET
- * - SIGNAL_OCDSE
- * @param high defines which signals will be asserted.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_set_signals_cmd(struct ulink *device, uint8_t low,
- uint8_t high)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- cmd->id = CMD_SET_SIGNALS;
-
- /* CMD_SET_SIGNALS has two OUT payload bytes and zero IN payload bytes */
- ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = low;
- cmd->payload_out[1] = high;
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Sleep for a pre-defined number of microseconds
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param us the number microseconds to sleep.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_sleep_cmd(struct ulink *device, uint32_t us)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- cmd->id = CMD_SLEEP_US;
-
- /* CMD_SLEEP_US has two OUT payload bytes and zero IN payload bytes */
- ret = ulink_allocate_payload(cmd, 2, PAYLOAD_DIRECTION_OUT);
-
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = us & 0x00ff;
- cmd->payload_out[1] = (us >> 8) & 0x00ff;
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Set TCK delay counters
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param delay_scan_in delay count top value in jtag_slow_scan_in() function.
- * @param delay_scan_out delay count top value in jtag_slow_scan_out() function.
- * @param delay_scan_io delay count top value in jtag_slow_scan_io() function.
- * @param delay_tck delay count top value in jtag_clock_tck() function.
- * @param delay_tms delay count top value in jtag_slow_clock_tms() function.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_configure_tck_cmd(struct ulink *device, int delay_scan_in,
- int delay_scan_out, int delay_scan_io, int delay_tck, int delay_tms)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- cmd->id = CMD_CONFIGURE_TCK_FREQ;
-
- /* CMD_CONFIGURE_TCK_FREQ has five OUT payload bytes and zero
- * IN payload bytes */
- ret = ulink_allocate_payload(cmd, 5, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- if (delay_scan_in < 0)
- cmd->payload_out[0] = 0;
- else
- cmd->payload_out[0] = (uint8_t)delay_scan_in;
-
- if (delay_scan_out < 0)
- cmd->payload_out[1] = 0;
- else
- cmd->payload_out[1] = (uint8_t)delay_scan_out;
-
- if (delay_scan_io < 0)
- cmd->payload_out[2] = 0;
- else
- cmd->payload_out[2] = (uint8_t)delay_scan_io;
-
- if (delay_tck < 0)
- cmd->payload_out[3] = 0;
- else
- cmd->payload_out[3] = (uint8_t)delay_tck;
-
- if (delay_tms < 0)
- cmd->payload_out[4] = 0;
- else
- cmd->payload_out[4] = (uint8_t)delay_tms;
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Turn on/off ULINK LEDs.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param led_state which LED(s) to turn on or off. The following bits
- * influence the LEDS:
- * - Bit 0: Turn COM LED on
- * - Bit 1: Turn RUN LED on
- * - Bit 2: Turn COM LED off
- * - Bit 3: Turn RUN LED off
- * If both the on-bit and the off-bit for the same LED is set, the LED is
- * turned off.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_led_cmd(struct ulink *device, uint8_t led_state)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- cmd->id = CMD_SET_LEDS;
-
- /* CMD_SET_LEDS has one OUT payload byte and zero IN payload bytes */
- ret = ulink_allocate_payload(cmd, 1, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = led_state;
-
- return ulink_append_queue(device, cmd);
-}
-
-/**
- * Test command. Used to check if the ULINK device is ready to accept new
- * commands.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_append_test_cmd(struct ulink *device)
-{
- struct ulink_cmd *cmd = calloc(1, sizeof(struct ulink_cmd));
- int ret;
-
- if (cmd == NULL)
- return ERROR_FAIL;
-
- cmd->id = CMD_TEST;
-
- /* CMD_TEST has one OUT payload byte and zero IN payload bytes */
- ret = ulink_allocate_payload(cmd, 1, PAYLOAD_DIRECTION_OUT);
- if (ret != ERROR_OK) {
- free(cmd);
- return ret;
- }
-
- cmd->payload_out[0] = 0xAA;
-
- return ulink_append_queue(device, cmd);
-}
-
-/****************** OpenULINK TCK frequency helper functions ******************/
-
-/**
- * Calculate delay values for a given TCK frequency.
- *
- * The OpenULINK firmware uses five different speed values for different
- * commands. These speed values are calculated in these functions.
- *
- * The five different commands which support variable TCK frequency are
- * implemented twice in the firmware:
- * 1. Maximum possible frequency without any artificial delay
- * 2. Variable frequency with artificial linear delay loop
- *
- * To set the ULINK to maximum frequency, it is only neccessary to use the
- * corresponding command IDs. To set the ULINK to a lower frequency, the
- * delay loop top values have to be calculated first. Then, a
- * CMD_CONFIGURE_TCK_FREQ command needs to be sent to the ULINK device.
- *
- * The delay values are described by linear equations:
- * t = k * x + d
- * (t = period, k = constant, x = delay value, d = constant)
- *
- * Thus, the delay can be calculated as in the following equation:
- * x = (t - d) / k
- *
- * The constants in these equations have been determined and validated by
- * measuring the frequency resulting from different delay values.
- *
- * @param type for which command to calculate the delay value.
- * @param f TCK frequency for which to calculate the delay value in Hz.
- * @param delay where to store resulting delay value.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay)
-{
- float t, x, x_ceil;
-
- /* Calculate period of requested TCK frequency */
- t = 1.0 / (float)(f);
-
- switch (type) {
- case DELAY_CLOCK_TCK:
- x = (t - (float)(6E-6)) / (float)(4E-6);
- break;
- case DELAY_CLOCK_TMS:
- x = (t - (float)(8.5E-6)) / (float)(4E-6);
- break;
- case DELAY_SCAN_IN:
- x = (t - (float)(8.8308E-6)) / (float)(4E-6);
- break;
- case DELAY_SCAN_OUT:
- x = (t - (float)(1.0527E-5)) / (float)(4E-6);
- break;
- case DELAY_SCAN_IO:
- x = (t - (float)(1.3132E-5)) / (float)(4E-6);
- break;
- default:
- return ERROR_FAIL;
- break;
- }
-
- /* Check if the delay value is negative. This happens when a frequency is
- * requested that is too high for the delay loop implementation. In this
- * case, set delay value to zero. */
- if (x < 0)
- x = 0;
-
- /* We need to convert the exact delay value to an integer. Therefore, we
- * round the exact value UP to ensure that the resulting frequency is NOT
- * higher than the requested frequency. */
- x_ceil = ceilf(x);
-
- /* Check if the value is within limits */
- if (x_ceil > 255)
- return ERROR_FAIL;
-
- *delay = (int)x_ceil;
-
- return ERROR_OK;
-}
-
-#ifdef _DEBUG_JTAG_IO_
-/**
- * Calculate frequency for a given delay value.
- *
- * Similar to the #ulink_calculate_delay function, this function calculates the
- * TCK frequency for a given delay value by using linear equations of the form:
- * t = k * x + d
- * (t = period, k = constant, x = delay value, d = constant)
- *
- * @param type for which command to calculate the delay value.
- * @param delay delay value for which to calculate the resulting TCK frequency.
- * @param f where to store the resulting TCK frequency.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f)
-{
- float t, f_float, f_rounded;
-
- if (delay > 255)
- return ERROR_FAIL;
-
- switch (type) {
- case DELAY_CLOCK_TCK:
- if (delay < 0)
- t = (float)(2.666E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(6E-6);
- break;
- case DELAY_CLOCK_TMS:
- if (delay < 0)
- t = (float)(5.666E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(8.5E-6);
- break;
- case DELAY_SCAN_IN:
- if (delay < 0)
- t = (float)(5.5E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(8.8308E-6);
- break;
- case DELAY_SCAN_OUT:
- if (delay < 0)
- t = (float)(7.0E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(1.0527E-5);
- break;
- case DELAY_SCAN_IO:
- if (delay < 0)
- t = (float)(9.926E-6);
- else
- t = (float)(4E-6) * (float)(delay) + (float)(1.3132E-5);
- break;
- default:
- return ERROR_FAIL;
- break;
- }
-
- f_float = 1.0 / t;
- f_rounded = roundf(f_float);
- *f = (long)f_rounded;
-
- return ERROR_OK;
-}
-#endif
-
-/******************* Interface between OpenULINK and OpenOCD ******************/
-
-/**
- * Sets the end state follower (see interface.h) if \a endstate is a stable
- * state.
- *
- * @param endstate the state the end state follower should be set to.
- */
-static void ulink_set_end_state(tap_state_t endstate)
-{
- if (tap_is_state_stable(endstate))
- tap_set_end_state(endstate);
- else {
- LOG_ERROR("BUG: %s is not a valid end state", tap_state_name(endstate));
- exit(EXIT_FAILURE);
- }
-}
-
-/**
- * Move from the current TAP state to the current TAP end state.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_queue_statemove(struct ulink *device)
-{
- uint8_t tms_sequence, tms_count;
- int ret;
-
- if (tap_get_state() == tap_get_end_state()) {
- /* Do nothing if we are already there */
- return ERROR_OK;
- }
-
- tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
- tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
-
- ret = ulink_append_clock_tms_cmd(device, tms_count, tms_sequence);
-
- if (ret == ERROR_OK)
- tap_set_state(tap_get_end_state());
-
- return ret;
-}
-
-/**
- * Perform a scan operation on a JTAG register.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd)
-{
- uint32_t scan_size_bits, scan_size_bytes, bits_last_scan;
- uint32_t scans_max_payload, bytecount;
- uint8_t *tdi_buffer_start = NULL, *tdi_buffer = NULL;
- uint8_t *tdo_buffer_start = NULL, *tdo_buffer = NULL;
-
- uint8_t first_tms_count, first_tms_sequence;
- uint8_t last_tms_count, last_tms_sequence;
-
- uint8_t tms_count_pause, tms_sequence_pause;
- uint8_t tms_count_resume, tms_sequence_resume;
-
- uint8_t tms_count_start, tms_sequence_start;
- uint8_t tms_count_end, tms_sequence_end;
-
- enum scan_type type;
- int ret;
-
- /* Determine scan size */
- scan_size_bits = jtag_scan_size(cmd->cmd.scan);
- scan_size_bytes = DIV_ROUND_UP(scan_size_bits, 8);
-
- /* Determine scan type (IN/OUT/IO) */
- type = jtag_scan_type(cmd->cmd.scan);
-
- /* Determine number of scan commands with maximum payload */
- scans_max_payload = scan_size_bytes / 58;
-
- /* Determine size of last shift command */
- bits_last_scan = scan_size_bits - (scans_max_payload * 58 * 8);
-
- /* Allocate TDO buffer if required */
- if ((type == SCAN_IN) || (type == SCAN_IO)) {
- tdo_buffer_start = calloc(sizeof(uint8_t), scan_size_bytes);
-
- if (tdo_buffer_start == NULL)
- return ERROR_FAIL;
-
- tdo_buffer = tdo_buffer_start;
- }
-
- /* Fill TDI buffer if required */
- if ((type == SCAN_OUT) || (type == SCAN_IO)) {
- jtag_build_buffer(cmd->cmd.scan, &tdi_buffer_start);
- tdi_buffer = tdi_buffer_start;
- }
-
- /* Get TAP state transitions */
- if (cmd->cmd.scan->ir_scan) {
- ulink_set_end_state(TAP_IRSHIFT);
- first_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- first_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- tap_set_state(TAP_IRSHIFT);
- tap_set_end_state(cmd->cmd.scan->end_state);
- last_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- last_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- /* TAP state transitions for split scans */
- tms_count_pause = tap_get_tms_path_len(TAP_IRSHIFT, TAP_IRPAUSE);
- tms_sequence_pause = tap_get_tms_path(TAP_IRSHIFT, TAP_IRPAUSE);
- tms_count_resume = tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRSHIFT);
- tms_sequence_resume = tap_get_tms_path(TAP_IRPAUSE, TAP_IRSHIFT);
- } else {
- ulink_set_end_state(TAP_DRSHIFT);
- first_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- first_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- tap_set_state(TAP_DRSHIFT);
- tap_set_end_state(cmd->cmd.scan->end_state);
- last_tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
- last_tms_sequence = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- /* TAP state transitions for split scans */
- tms_count_pause = tap_get_tms_path_len(TAP_DRSHIFT, TAP_DRPAUSE);
- tms_sequence_pause = tap_get_tms_path(TAP_DRSHIFT, TAP_DRPAUSE);
- tms_count_resume = tap_get_tms_path_len(TAP_DRPAUSE, TAP_DRSHIFT);
- tms_sequence_resume = tap_get_tms_path(TAP_DRPAUSE, TAP_DRSHIFT);
- }
-
- /* Generate scan commands */
- bytecount = scan_size_bytes;
- while (bytecount > 0) {
- if (bytecount == scan_size_bytes) {
- /* This is the first scan */
- tms_count_start = first_tms_count;
- tms_sequence_start = first_tms_sequence;
- } else {
- /* Resume from previous scan */
- tms_count_start = tms_count_resume;
- tms_sequence_start = tms_sequence_resume;
- }
-
- if (bytecount > 58) { /* Full scan, at least one scan will follow */
- tms_count_end = tms_count_pause;
- tms_sequence_end = tms_sequence_pause;
-
- ret = ulink_append_scan_cmd(device,
- type,
- 58 * 8,
- tdi_buffer,
- tdo_buffer_start,
- tdo_buffer,
- tms_count_start,
- tms_sequence_start,
- tms_count_end,
- tms_sequence_end,
- cmd,
- false);
-
- bytecount -= 58;
-
- /* Update TDI and TDO buffer pointers */
- if (tdi_buffer_start != NULL)
- tdi_buffer += 58;
- if (tdo_buffer_start != NULL)
- tdo_buffer += 58;
- } else if (bytecount == 58) { /* Full scan, no further scans */
- tms_count_end = last_tms_count;
- tms_sequence_end = last_tms_sequence;
-
- ret = ulink_append_scan_cmd(device,
- type,
- 58 * 8,
- tdi_buffer,
- tdo_buffer_start,
- tdo_buffer,
- tms_count_start,
- tms_sequence_start,
- tms_count_end,
- tms_sequence_end,
- cmd,
- true);
-
- bytecount = 0;
- } else {/* Scan with less than maximum payload, no further scans */
- tms_count_end = last_tms_count;
- tms_sequence_end = last_tms_sequence;
-
- ret = ulink_append_scan_cmd(device,
- type,
- bits_last_scan,
- tdi_buffer,
- tdo_buffer_start,
- tdo_buffer,
- tms_count_start,
- tms_sequence_start,
- tms_count_end,
- tms_sequence_end,
- cmd,
- true);
-
- bytecount = 0;
- }
-
- if (ret != ERROR_OK) {
- free(tdi_buffer_start);
- return ret;
- }
- }
-
- free(tdi_buffer_start);
-
- /* Set current state to the end state requested by the command */
- tap_set_state(cmd->cmd.scan->end_state);
-
- return ERROR_OK;
-}
-
-/**
- * Move the TAP into the Test Logic Reset state.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_queue_tlr_reset(struct ulink *device, struct jtag_command *cmd)
-{
- int ret;
-
- ret = ulink_append_clock_tms_cmd(device, 5, 0xff);
-
- if (ret == ERROR_OK)
- tap_set_state(TAP_RESET);
-
- return ret;
-}
-
-/**
- * Run Test.
- *
- * Generate TCK clock cycles while remaining
- * in the Run-Test/Idle state.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_queue_runtest(struct ulink *device, struct jtag_command *cmd)
-{
- int ret;
-
- /* Only perform statemove if the TAP currently isn't in the TAP_IDLE state */
- if (tap_get_state() != TAP_IDLE) {
- ulink_set_end_state(TAP_IDLE);
- ulink_queue_statemove(device);
- }
-
- /* Generate the clock cycles */
- ret = ulink_append_clock_tck_cmd(device, cmd->cmd.runtest->num_cycles);
- if (ret != ERROR_OK)
- return ret;
-
- /* Move to end state specified in command */
- if (cmd->cmd.runtest->end_state != tap_get_state()) {
- tap_set_end_state(cmd->cmd.runtest->end_state);
- ulink_queue_statemove(device);
- }
-
- return ERROR_OK;
-}
-
-/**
- * Execute a JTAG_RESET command
- *
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_queue_reset(struct ulink *device, struct jtag_command *cmd)
-{
- uint8_t low = 0, high = 0;
-
- if (cmd->cmd.reset->trst) {
- tap_set_state(TAP_RESET);
- high |= SIGNAL_TRST;
- } else
- low |= SIGNAL_TRST;
-
- if (cmd->cmd.reset->srst)
- high |= SIGNAL_RESET;
- else
- low |= SIGNAL_RESET;
-
- return ulink_append_set_signals_cmd(device, low, high);
-}
-
-/**
- * Move to one TAP state or several states in succession.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_queue_pathmove(struct ulink *device, struct jtag_command *cmd)
-{
- int ret, i, num_states, batch_size, state_count;
- tap_state_t *path;
- uint8_t tms_sequence;
-
- num_states = cmd->cmd.pathmove->num_states;
- path = cmd->cmd.pathmove->path;
- state_count = 0;
-
- while (num_states > 0) {
- tms_sequence = 0;
-
- /* Determine batch size */
- if (num_states >= 8)
- batch_size = 8;
- else
- batch_size = num_states;
-
- for (i = 0; i < batch_size; i++) {
- if (tap_state_transition(tap_get_state(), false) == path[state_count]) {
- /* Append '0' transition: clear bit 'i' in tms_sequence */
- buf_set_u32(&tms_sequence, i, 1, 0x0);
- } else if (tap_state_transition(tap_get_state(), true)
- == path[state_count]) {
- /* Append '1' transition: set bit 'i' in tms_sequence */
- buf_set_u32(&tms_sequence, i, 1, 0x1);
- } else {
- /* Invalid state transition */
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
- tap_state_name(tap_get_state()),
- tap_state_name(path[state_count]));
- return ERROR_FAIL;
- }
-
- tap_set_state(path[state_count]);
- state_count++;
- num_states--;
- }
-
- /* Append CLOCK_TMS command to OpenULINK command queue */
- LOG_INFO(
- "pathmove batch: count = %i, sequence = 0x%x", batch_size, tms_sequence);
- ret = ulink_append_clock_tms_cmd(ulink_handle, batch_size, tms_sequence);
- if (ret != ERROR_OK)
- return ret;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Sleep for a specific amount of time.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param cmd pointer to the command that shall be executed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_queue_sleep(struct ulink *device, struct jtag_command *cmd)
-{
- /* IMPORTANT! Due to the time offset in command execution introduced by
- * command queueing, this needs to be implemented in the ULINK device */
- return ulink_append_sleep_cmd(device, cmd->cmd.sleep->us);
-}
-
-/**
- * Generate TCK cycles while remaining in a stable state.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @param cmd pointer to the command that shall be executed.
- */
-int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd)
-{
- int ret;
- unsigned num_cycles;
-
- if (!tap_is_state_stable(tap_get_state())) {
- LOG_ERROR("JTAG_STABLECLOCKS: state not stable");
- return ERROR_FAIL;
- }
-
- num_cycles = cmd->cmd.stableclocks->num_cycles;
-
- /* TMS stays either high (Test Logic Reset state) or low (all other states) */
- if (tap_get_state() == TAP_RESET)
- ret = ulink_append_set_signals_cmd(device, 0, SIGNAL_TMS);
- else
- ret = ulink_append_set_signals_cmd(device, SIGNAL_TMS, 0);
-
- if (ret != ERROR_OK)
- return ret;
-
- while (num_cycles > 0) {
- if (num_cycles > 0xFFFF) {
- /* OpenULINK CMD_CLOCK_TCK can generate up to 0xFFFF (uint16_t) cycles */
- ret = ulink_append_clock_tck_cmd(device, 0xFFFF);
- num_cycles -= 0xFFFF;
- } else {
- ret = ulink_append_clock_tck_cmd(device, num_cycles);
- num_cycles = 0;
- }
-
- if (ret != ERROR_OK)
- return ret;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Post-process JTAG_SCAN command
- *
- * @param ulink_cmd pointer to OpenULINK command that shall be processed.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_post_process_scan(struct ulink_cmd *ulink_cmd)
-{
- struct jtag_command *cmd = ulink_cmd->cmd_origin;
- int ret;
-
- switch (jtag_scan_type(cmd->cmd.scan)) {
- case SCAN_IN:
- case SCAN_IO:
- ret = jtag_read_buffer(ulink_cmd->payload_in_start, cmd->cmd.scan);
- break;
- case SCAN_OUT:
- /* Nothing to do for OUT scans */
- ret = ERROR_OK;
- break;
- default:
- LOG_ERROR("BUG: ulink_post_process_scan() encountered an unknown"
- " JTAG scan type");
- ret = ERROR_FAIL;
- break;
- }
-
- return ret;
-}
-
-/**
- * Perform post-processing of commands after OpenULINK queue has been executed.
- *
- * @param device pointer to struct ulink identifying ULINK driver instance.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-int ulink_post_process_queue(struct ulink *device)
-{
- struct ulink_cmd *current;
- struct jtag_command *openocd_cmd;
- int ret;
-
- current = device->queue_start;
-
- while (current != NULL) {
- openocd_cmd = current->cmd_origin;
-
- /* Check if a corresponding OpenOCD command is stored for this
- * OpenULINK command */
- if ((current->needs_postprocessing == true) && (openocd_cmd != NULL)) {
- switch (openocd_cmd->type) {
- case JTAG_SCAN:
- ret = ulink_post_process_scan(current);
- break;
- case JTAG_TLR_RESET:
- case JTAG_RUNTEST:
- case JTAG_RESET:
- case JTAG_PATHMOVE:
- case JTAG_SLEEP:
- case JTAG_STABLECLOCKS:
- /* Nothing to do for these commands */
- ret = ERROR_OK;
- break;
- default:
- ret = ERROR_FAIL;
- LOG_ERROR("BUG: ulink_post_process_queue() encountered unknown JTAG "
- "command type");
- break;
- }
-
- if (ret != ERROR_OK)
- return ret;
- }
-
- current = current->next;
- }
-
- return ERROR_OK;
-}
-
-/**************************** JTAG driver functions ***************************/
-
-/**
- * Executes the JTAG Command Queue.
- *
- * This is done in three stages: First, all OpenOCD commands are processed into
- * queued OpenULINK commands. Next, the OpenULINK command queue is sent to the
- * ULINK device and data received from the ULINK device is cached. Finally,
- * the post-processing function writes back data to the corresponding OpenOCD
- * commands.
- *
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int ulink_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue;
- int ret;
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_SCAN:
- ret = ulink_queue_scan(ulink_handle, cmd);
- break;
- case JTAG_TLR_RESET:
- ret = ulink_queue_tlr_reset(ulink_handle, cmd);
- break;
- case JTAG_RUNTEST:
- ret = ulink_queue_runtest(ulink_handle, cmd);
- break;
- case JTAG_RESET:
- ret = ulink_queue_reset(ulink_handle, cmd);
- break;
- case JTAG_PATHMOVE:
- ret = ulink_queue_pathmove(ulink_handle, cmd);
- break;
- case JTAG_SLEEP:
- ret = ulink_queue_sleep(ulink_handle, cmd);
- break;
- case JTAG_STABLECLOCKS:
- ret = ulink_queue_stableclocks(ulink_handle, cmd);
- break;
- default:
- ret = ERROR_FAIL;
- LOG_ERROR("BUG: encountered unknown JTAG command type");
- break;
- }
-
- if (ret != ERROR_OK)
- return ret;
-
- cmd = cmd->next;
- }
-
- if (ulink_handle->commands_in_queue > 0) {
- ret = ulink_execute_queued_commands(ulink_handle, USB_TIMEOUT);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ulink_post_process_queue(ulink_handle);
- if (ret != ERROR_OK)
- return ret;
-
- ulink_clear_queue(ulink_handle);
- }
-
- return ERROR_OK;
-}
-
-/**
- * Set the TCK frequency of the ULINK adapter.
- *
- * @param khz desired JTAG TCK frequency.
- * @param jtag_speed where to store corresponding adapter-specific speed value.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int ulink_khz(int khz, int *jtag_speed)
-{
- int ret;
-
- if (khz == 0) {
- LOG_ERROR("RCLK not supported");
- return ERROR_FAIL;
- }
-
- /* CLOCK_TCK commands are decoupled from others. Therefore, the frequency
- * setting can be done independently from all other commands. */
- if (khz >= 375)
- ulink_handle->delay_clock_tck = -1;
- else {
- ret = ulink_calculate_delay(DELAY_CLOCK_TCK, khz * 1000,
- &ulink_handle->delay_clock_tck);
- if (ret != ERROR_OK)
- return ret;
- }
-
- /* SCAN_{IN,OUT,IO} commands invoke CLOCK_TMS commands. Therefore, if the
- * requested frequency goes below the maximum frequency for SLOW_CLOCK_TMS
- * commands, all SCAN commands MUST also use the variable frequency
- * implementation! */
- if (khz >= 176) {
- ulink_handle->delay_clock_tms = -1;
- ulink_handle->delay_scan_in = -1;
- ulink_handle->delay_scan_out = -1;
- ulink_handle->delay_scan_io = -1;
- } else {
- ret = ulink_calculate_delay(DELAY_CLOCK_TMS, khz * 1000,
- &ulink_handle->delay_clock_tms);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ulink_calculate_delay(DELAY_SCAN_IN, khz * 1000,
- &ulink_handle->delay_scan_in);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ulink_calculate_delay(DELAY_SCAN_OUT, khz * 1000,
- &ulink_handle->delay_scan_out);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ulink_calculate_delay(DELAY_SCAN_IO, khz * 1000,
- &ulink_handle->delay_scan_io);
- if (ret != ERROR_OK)
- return ret;
- }
-
-#ifdef _DEBUG_JTAG_IO_
- long f_tck, f_tms, f_scan_in, f_scan_out, f_scan_io;
-
- ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck,
- &f_tck);
- ulink_calculate_frequency(DELAY_CLOCK_TMS, ulink_handle->delay_clock_tms,
- &f_tms);
- ulink_calculate_frequency(DELAY_SCAN_IN, ulink_handle->delay_scan_in,
- &f_scan_in);
- ulink_calculate_frequency(DELAY_SCAN_OUT, ulink_handle->delay_scan_out,
- &f_scan_out);
- ulink_calculate_frequency(DELAY_SCAN_IO, ulink_handle->delay_scan_io,
- &f_scan_io);
-
- DEBUG_JTAG_IO("ULINK TCK setup: delay_tck = %i (%li Hz),",
- ulink_handle->delay_clock_tck, f_tck);
- DEBUG_JTAG_IO(" delay_tms = %i (%li Hz),",
- ulink_handle->delay_clock_tms, f_tms);
- DEBUG_JTAG_IO(" delay_scan_in = %i (%li Hz),",
- ulink_handle->delay_scan_in, f_scan_in);
- DEBUG_JTAG_IO(" delay_scan_out = %i (%li Hz),",
- ulink_handle->delay_scan_out, f_scan_out);
- DEBUG_JTAG_IO(" delay_scan_io = %i (%li Hz),",
- ulink_handle->delay_scan_io, f_scan_io);
-#endif
-
- /* Configure the ULINK device with the new delay values */
- ret = ulink_append_configure_tck_cmd(ulink_handle,
- ulink_handle->delay_scan_in,
- ulink_handle->delay_scan_out,
- ulink_handle->delay_scan_io,
- ulink_handle->delay_clock_tck,
- ulink_handle->delay_clock_tms);
-
- if (ret != ERROR_OK)
- return ret;
-
- *jtag_speed = khz;
-
- return ERROR_OK;
-}
-
-/**
- * Set the TCK frequency of the ULINK adapter.
- *
- * Because of the way the TCK frequency is set up in the OpenULINK firmware,
- * there are five different speed settings. To simplify things, the
- * adapter-specific speed setting value is identical to the TCK frequency in
- * khz.
- *
- * @param speed desired adapter-specific speed value.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int ulink_speed(int speed)
-{
- int dummy;
-
- return ulink_khz(speed, &dummy);
-}
-
-/**
- * Convert adapter-specific speed value to corresponding TCK frequency in kHz.
- *
- * Because of the way the TCK frequency is set up in the OpenULINK firmware,
- * there are five different speed settings. To simplify things, the
- * adapter-specific speed setting value is identical to the TCK frequency in
- * khz.
- *
- * @param speed adapter-specific speed value.
- * @param khz where to store corresponding TCK frequency in kHz.
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int ulink_speed_div(int speed, int *khz)
-{
- *khz = speed;
-
- return ERROR_OK;
-}
-
-/**
- * Initiates the firmware download to the ULINK adapter and prepares
- * the USB handle.
- *
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int ulink_init(void)
-{
- int ret, transferred;
- char str_manufacturer[20];
- bool download_firmware = false;
- unsigned char *dummy;
- uint8_t input_signals, output_signals;
-
- ulink_handle = calloc(1, sizeof(struct ulink));
- if (ulink_handle == NULL)
- return ERROR_FAIL;
-
- libusb_init(&ulink_handle->libusb_ctx);
-
- ret = ulink_usb_open(&ulink_handle);
- if (ret != ERROR_OK) {
- LOG_ERROR("Could not open ULINK device");
- free(ulink_handle);
- ulink_handle = NULL;
- return ret;
- }
-
- /* Get String Descriptor to determine if firmware needs to be loaded */
- ret = libusb_get_string_descriptor_ascii(ulink_handle->usb_device_handle, 1, (unsigned char *)str_manufacturer, 20);
- if (ret < 0) {
- /* Could not get descriptor -> Unconfigured or original Keil firmware */
- download_firmware = true;
- } else {
- /* We got a String Descriptor, check if it is the correct one */
- if (strncmp(str_manufacturer, "OpenULINK", 9) != 0)
- download_firmware = true;
- }
-
- if (download_firmware == true) {
- LOG_INFO("Loading OpenULINK firmware. This is reversible by power-cycling"
- " ULINK device.");
- ret = ulink_load_firmware_and_renumerate(&ulink_handle,
- ULINK_FIRMWARE_FILE, ULINK_RENUMERATION_DELAY);
- if (ret != ERROR_OK) {
- LOG_ERROR("Could not download firmware and re-numerate ULINK");
- free(ulink_handle);
- ulink_handle = NULL;
- return ret;
- }
- } else
- LOG_INFO("ULINK device is already running OpenULINK firmware");
-
- /* Initialize OpenULINK command queue */
- ulink_clear_queue(ulink_handle);
-
- /* Issue one test command with short timeout */
- ret = ulink_append_test_cmd(ulink_handle);
- if (ret != ERROR_OK)
- return ret;
-
- ret = ulink_execute_queued_commands(ulink_handle, 200);
- if (ret != ERROR_OK) {
- /* Sending test command failed. The ULINK device may be forever waiting for
- * the host to fetch an USB Bulk IN packet (e. g. OpenOCD crashed or was
- * shut down by the user via Ctrl-C. Try to retrieve this Bulk IN packet. */
- dummy = calloc(64, sizeof(uint8_t));
-
- ret = libusb_bulk_transfer(ulink_handle->usb_device_handle, (2 | LIBUSB_ENDPOINT_IN),
- dummy, 64, &transferred, 200);
-
- free(dummy);
-
- if (ret != 0 || transferred == 0) {
- /* Bulk IN transfer failed -> unrecoverable error condition */
- LOG_ERROR("Cannot communicate with ULINK device. Disconnect ULINK from "
- "the USB port and re-connect, then re-run OpenOCD");
- free(ulink_handle);
- ulink_handle = NULL;
- return ERROR_FAIL;
- }
-#ifdef _DEBUG_USB_COMMS_
- else {
- /* Successfully received Bulk IN packet -> continue */
- LOG_INFO("Recovered from lost Bulk IN packet");
- }
-#endif
- }
- ulink_clear_queue(ulink_handle);
-
- ulink_append_get_signals_cmd(ulink_handle);
- ulink_execute_queued_commands(ulink_handle, 200);
-
- /* Post-process the single CMD_GET_SIGNALS command */
- input_signals = ulink_handle->queue_start->payload_in[0];
- output_signals = ulink_handle->queue_start->payload_in[1];
-
- ulink_print_signal_states(input_signals, output_signals);
-
- ulink_clear_queue(ulink_handle);
-
- return ERROR_OK;
-}
-
-/**
- * Closes the USB handle for the ULINK device.
- *
- * @return on success: ERROR_OK
- * @return on failure: ERROR_FAIL
- */
-static int ulink_quit(void)
-{
- int ret;
-
- ret = ulink_usb_close(&ulink_handle);
- free(ulink_handle);
-
- return ret;
-}
-
-/**
- * Set a custom path to ULINK firmware image and force downloading to ULINK.
- */
-COMMAND_HANDLER(ulink_download_firmware_handler)
-{
- int ret;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
-
- LOG_INFO("Downloading ULINK firmware image %s", CMD_ARGV[0]);
-
- /* Download firmware image in CMD_ARGV[0] */
- ret = ulink_load_firmware_and_renumerate(&ulink_handle, CMD_ARGV[0],
- ULINK_RENUMERATION_DELAY);
-
- return ret;
-}
-
-/*************************** Command Registration **************************/
-
-static const struct command_registration ulink_command_handlers[] = {
- {
- .name = "ulink_download_firmware",
- .handler = &ulink_download_firmware_handler,
- .mode = COMMAND_EXEC,
- .help = "download firmware image to ULINK device",
- .usage = "path/to/ulink_firmware.hex",
- },
- COMMAND_REGISTRATION_DONE,
-};
-
-struct jtag_interface ulink_interface = {
- .name = "ulink",
-
- .commands = ulink_command_handlers,
- .transports = jtag_only,
-
- .execute_queue = ulink_execute_queue,
- .khz = ulink_khz,
- .speed = ulink_speed,
- .speed_div = ulink_speed_div,
-
- .init = ulink_init,
- .quit = ulink_quit
-};
diff --git a/src/jtag/drivers/usb_blaster/Makefile.am b/src/jtag/drivers/usb_blaster/Makefile.am
deleted file mode 100644
index 0fb4700..0000000
--- a/src/jtag/drivers/usb_blaster/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-include $(top_srcdir)/common.mk
-
-AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS)
-
-noinst_LTLIBRARIES = libocdusbblaster.la
-libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC)
-
-USB_BLASTER_SRC = usb_blaster.c
-
-if USB_BLASTER_LIBFTDI
-USB_BLASTER_SRC += ublast_access_ftdi.c
-endif
-
-if USB_BLASTER_FTD2XX
-USB_BLASTER_SRC += ublast_access_ftd2xx.c
-endif
-
-if USB_BLASTER_2
-USB_BLASTER_SRC += ublast2_access_libusb.c
-endif
-
-noinst_HEADERS = ublast_access.h
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/jtag/drivers/usb_blaster/README.CheapClone b/src/jtag/drivers/usb_blaster/README.CheapClone
deleted file mode 100644
index 983a441..0000000
--- a/src/jtag/drivers/usb_blaster/README.CheapClone
+++ /dev/null
@@ -1,71 +0,0 @@
-USB Blaster Cheap Clone
-=======================
-
-The Altera USB Blaster has a cheap clone, based on :
- - a Cypress CY7C68013A-56PVXC as the main chip
- - a 74HC244D as the output latch
- - a 24 MHz quartz
- - a EEPROM 24C64BN
-
-The schematics (cut down to essential) is :
-
- /-----------------+----------------------\
- +--------------+ | | |
-USB--| CY7C68013A | | +----------+ | |
- | | | | 74HC244D | | |
- . . | | | | |
- . . \--o 1 20 o | 10 pins header |
- | 47 o-- TCK --o 2 19 o---/ +-------+ |
- | 46 o-- TDO --o 3 18 o-- TCK -----o 1 2 o |
- | 45 o-- TMS --o 4 17 o-- TDO -----o 3 4 o |
- | 44 o o 5 16 o-- TMS -----o 5 6 o |
- | 43 o-- o 6 15 o o 7 8 o |
- | 42 o-- o 7 14 o +--o 9 10 o |
- | 41 o-- TDI --o 8 13 o-- ? | +-------+ |
- . 40 o-- nOE \ o 9 12 o-- TDI --+ |
- . . | o 10 11 o |
- o 28 29 o | | | |
- | | | +----------+ |
- +--------------+ \ |
- ---------------------------------------/
-
-From this one can deduce that :
- - the cypress emulates the Altera chip
- - as the cypress pins used are 41-47, all output/input are controlled by 8051
- PortA.
- - as the 8051 is clocked at 24Mhz, and because each USB byte is handled by the
- 8051, assuming a 40 instruction cycles per USB packet, the maximum throughput
- would be around 500 kHz.
-
-Pinout
-======
- Port A.0: nOE (output enable of 74HC244D)
- Port A.1: TDI
- Port A.5: TMS
- Port A.6: TDO
- Port A.7: TCK
-
-Throughput considerations
-=========================
-Mesurements on a scope reveal that :
- - for bitbang mode, the throughtput is 56.5 kbits/s
- (as each clock transition is mesured at 17.7us)
- - for byteshift mode, the throughput is 107.7 kbits/s
- (as 63 bits TDI transmission is mesured in 585 us)
-
-Let's suppose that to upload a 32 bits value, it is necessary to :
- - move from IDLE to DR-SHIFT : 3 bitbang (3 TMS transitions)
- - input the 32 bits of data : 1 byteshift (24 bits) + 8 bitbang (8 bits)
- - move from DR-SHIFT to IDLE : 5 bitbang (5 TMS transitions)
-So for this 32 bits of data, the time would be :
- 3 * 17.7us + 1 * 585us/63*24 + 5 * 17.7us
- = 53.1us + 222us + 88.5us
- = 363us
-
-Throughtput in bit/s: 32 * (1 / 363E-6) = 88000 bits/s
-Throughtput in bytes/s: 11kBytes/s
-
-Conclusion
-==========
-Contrary to the original USB Blaster, the cheap clone will never reach high
-transfer speeds over JTAG.
diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c
deleted file mode 100644
index d991733..0000000
--- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Driver for USB-JTAG, Altera USB-Blaster II and compatibles
- *
- * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <libusb_common.h>
-#include <target/image.h>
-
-#include "ublast_access.h"
-
-#define USBBLASTER_CTRL_READ_REV 0x94
-#define USBBLASTER_CTRL_LOAD_FIRM 0xA0
-#define USBBLASTER_EPOUT 4
-#define USBBLASTER_EPIN 8
-
-#define EZUSB_CPUCS 0xe600
-#define CPU_RESET 1
-
-/** Maximum size of a single firmware section. Entire EZ-USB code space = 16kB */
-#define SECTION_BUFFERSIZE 16384
-
-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,
- USBBLASTER_EPIN | \
- LIBUSB_ENDPOINT_IN,
- (char *)buf,
- size,
- 100);
- return ERROR_OK;
-}
-
-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,
- USBBLASTER_EPOUT | \
- LIBUSB_ENDPOINT_OUT,
- (char *)buf,
- size,
- 100);
- return ERROR_OK;
-}
-
-static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libusb_dev,
- struct image *firmware_image, int section_index)
-{
- uint16_t chunk_size;
- uint8_t data[SECTION_BUFFERSIZE];
- uint8_t *data_ptr = data;
- size_t size_read;
-
- uint16_t size = (uint16_t)firmware_image->sections[section_index].size;
- uint16_t addr = (uint16_t)firmware_image->sections[section_index].base_address;
-
- LOG_DEBUG("section %02i at addr 0x%04x (size 0x%04x)", section_index, addr,
- size);
-
- /* Copy section contents to local buffer */
- int ret = image_read_section(firmware_image, section_index, 0, size, data,
- &size_read);
-
- if ((ret != ERROR_OK) || (size_read != size)) {
- /* Propagating the return code would return '0' (misleadingly indicating
- * successful execution of the function) if only the size check fails. */
- return ERROR_FAIL;
- }
-
- uint16_t bytes_remaining = size;
-
- /* Send section data in chunks of up to 64 bytes to ULINK */
- while (bytes_remaining > 0) {
- if (bytes_remaining > 64)
- chunk_size = 64;
- else
- chunk_size = bytes_remaining;
-
- jtag_libusb_control_transfer(libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
- LIBUSB_ENDPOINT_OUT,
- USBBLASTER_CTRL_LOAD_FIRM,
- addr,
- 0,
- (char *)data_ptr,
- chunk_size,
- 100);
-
- bytes_remaining -= chunk_size;
- addr += chunk_size;
- data_ptr += chunk_size;
- }
-
- return ERROR_OK;
-}
-
-static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_dev,
- struct ublast_lowlevel *low)
-{
- struct image ublast2_firmware_image;
-
- if (!low->firmware_path) {
- LOG_ERROR("No firmware path specified");
- return ERROR_FAIL;
- }
-
- ublast2_firmware_image.base_address = 0;
- ublast2_firmware_image.base_address_set = 0;
-
- int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex");
- if (ret != ERROR_OK) {
- LOG_ERROR("Could not load firmware image");
- return ret;
- }
-
- /** A host loader program must write 0x01 to the CPUCS register
- * to put the CPU into RESET, load all or part of the EZUSB
- * RAM with firmware, then reload the CPUCS register
- * with ‘0’ to take the CPU out of RESET. The CPUCS register
- * (at 0xE600) is the only EZ-USB register that can be written
- * using the Firmware Download command.
- */
-
- char value = CPU_RESET;
- jtag_libusb_control_transfer(libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
- LIBUSB_ENDPOINT_OUT,
- USBBLASTER_CTRL_LOAD_FIRM,
- EZUSB_CPUCS,
- 0,
- &value,
- 1,
- 100);
-
- /* Download all sections in the image to ULINK */
- for (int i = 0; i < ublast2_firmware_image.num_sections; i++) {
- ret = ublast2_write_firmware_section(libusb_dev,
- &ublast2_firmware_image, i);
- if (ret != ERROR_OK) {
- LOG_ERROR("Error while downloading the firmware");
- return ret;
- }
- }
-
- value = !CPU_RESET;
- jtag_libusb_control_transfer(libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
- LIBUSB_ENDPOINT_OUT,
- USBBLASTER_CTRL_LOAD_FIRM,
- EZUSB_CPUCS,
- 0,
- &value,
- 1,
- 100);
-
- image_close(&ublast2_firmware_image);
-
- return ERROR_OK;
-}
-
-static int ublast2_libusb_init(struct ublast_lowlevel *low)
-{
- const uint16_t vids[] = { low->ublast_vid_uninit, 0 };
- const uint16_t pids[] = { low->ublast_pid_uninit, 0 };
- struct jtag_libusb_device_handle *temp;
- bool renumeration = false;
- int ret;
-
- if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) {
- LOG_INFO("Altera USB-Blaster II (uninitialized) found");
- LOG_INFO("Loading firmware...");
- ret = load_usb_blaster_firmware(temp, low);
- jtag_libusb_close(temp);
- if (ret != ERROR_OK)
- return ret;
- renumeration = true;
- }
-
- const uint16_t vids_renum[] = { low->ublast_vid, 0 };
- const uint16_t pids_renum[] = { low->ublast_pid, 0 };
-
- if (renumeration == false) {
- if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) {
- LOG_ERROR("Altera USB-Blaster II not found");
- return ERROR_FAIL;
- }
- } else {
- int retry = 10;
- while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) {
- usleep(1000000);
- LOG_INFO("Waiting for renumerate...");
- }
-
- if (!retry) {
- LOG_ERROR("Altera USB-Blaster II not found");
- return ERROR_FAIL;
- }
- }
-
- char buffer[5];
- jtag_libusb_control_transfer(low->libusb_dev,
- LIBUSB_REQUEST_TYPE_VENDOR | \
- LIBUSB_ENDPOINT_IN,
- USBBLASTER_CTRL_READ_REV,
- 0,
- 0,
- buffer,
- 5,
- 100);
-
- LOG_INFO("Altera USB-Blaster II found (Firm. rev. = %s)", buffer);
-
- return ERROR_OK;
-}
-
-static int ublast2_libusb_quit(struct ublast_lowlevel *low)
-{
- jtag_libusb_close(low->libusb_dev);
- return ERROR_OK;
-};
-
-static struct ublast_lowlevel low = {
- .open = ublast2_libusb_init,
- .close = ublast2_libusb_quit,
- .read = ublast2_libusb_read,
- .write = ublast2_libusb_write,
- .flags = COPY_TDO_BUFFER,
-};
-
-struct ublast_lowlevel *ublast2_register_libusb(void)
-{
- return &low;
-}
diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h
deleted file mode 100644
index 00349d2..0000000
--- a/src/jtag/drivers/usb_blaster/ublast_access.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Driver for USB-JTAG, Altera USB-Blaster and compatibles
- *
- * Inspired from original code from Kolja Waschk's USB-JTAG project
- * (http://www.ixo.de/info/usb_jtag/), and from openocd project.
- *
- * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com
- * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
- * Copyright (C) 2011 Ali Lown ali@lown.me.uk
- * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
- * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H
-#define OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H
-
-#include <libusb_common.h>
-
-/* Low level flags */
-#define COPY_TDO_BUFFER (1 << 0)
-
-struct ublast_lowlevel {
- uint16_t ublast_vid;
- uint16_t ublast_pid;
- uint16_t ublast_vid_uninit;
- uint16_t ublast_pid_uninit;
- char *ublast_device_desc;
- struct jtag_libusb_device_handle *libusb_dev;
- char *firmware_path;
-
- int (*write)(struct ublast_lowlevel *low, uint8_t *buf, int size,
- uint32_t *bytes_written);
- int (*read)(struct ublast_lowlevel *low, uint8_t *buf, unsigned size,
- uint32_t *bytes_read);
- int (*open)(struct ublast_lowlevel *low);
- int (*close)(struct ublast_lowlevel *low);
- int (*speed)(struct ublast_lowlevel *low, int speed);
-
- void *priv;
- int flags;
-};
-
-/**
- * ublast_register_ftdi - get a lowlevel USB Blaster driver
- * ublast_register_ftd2xx - get a lowlevel USB Blaster driver
- * ublast2_register_libusb - get a lowlevel USB Blaster II driver
- *
- * Get a lowlevel USB-Blaster driver. In the current implementation, there are 3
- * possible lowlevel drivers :
- * - one based on libftdi from ftdichip.com
- * - one based on libftdxx, the free alternative
- * - one based on libusb, specific to the USB-Blaster II
- *
- * Returns the lowlevel driver structure.
- */
-extern struct ublast_lowlevel *ublast_register_ftdi(void);
-extern struct ublast_lowlevel *ublast_register_ftd2xx(void);
-extern struct ublast_lowlevel *ublast2_register_libusb(void);
-
-#endif /* OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H */
diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c b/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c
deleted file mode 100644
index ffcf312..0000000
--- a/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Driver for USB-JTAG, Altera USB-Blaster and compatibles
- *
- * Inspired from original code from Kolja Waschk's USB-JTAG project
- * (http://www.ixo.de/info/usb_jtag/), and from openocd project.
- *
- * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
- * Copyright (C) 2011 Ali Lown ali@lown.me.uk
- * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
- * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-
-#include "ublast_access.h"
-
-#include <ftd2xx.h>
-#include "jtag/drivers/ftd2xx_common.h"
-
-static FT_HANDLE *ublast_getftdih(struct ublast_lowlevel *low)
-{
- return low->priv;
-}
-
-static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
- uint32_t *bytes_written)
-{
- FT_STATUS status;
- DWORD dw_bytes_written;
- FT_HANDLE *ftdih = ublast_getftdih(low);
-
- status = FT_Write(*ftdih, buf, size, &dw_bytes_written);
- if (status != FT_OK) {
- *bytes_written = dw_bytes_written;
- LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_written = dw_bytes_written;
- return ERROR_OK;
-}
-
-static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf,
- unsigned size, uint32_t *bytes_read)
-{
- DWORD dw_bytes_read;
- FT_STATUS status;
- FT_HANDLE *ftdih = ublast_getftdih(low);
-
- status = FT_Read(*ftdih, buf, size, &dw_bytes_read);
- if (status != FT_OK) {
- *bytes_read = dw_bytes_read;
- LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_read = dw_bytes_read;
- return ERROR_OK;
-}
-
-static int ublast_ftd2xx_init(struct ublast_lowlevel *low)
-{
- FT_STATUS status;
- FT_HANDLE *ftdih = ublast_getftdih(low);
- uint8_t latency_timer;
-
- LOG_INFO("usb blaster interface using FTD2XX");
- /* Open by device description */
- if (low->ublast_device_desc == NULL) {
- LOG_WARNING("no usb blaster device description specified, "
- "using default 'USB-Blaster'");
- low->ublast_device_desc = "USB-Blaster";
- }
-
-#if IS_WIN32 == 0
- /* Add non-standard Vid/Pid to the linux driver */
- status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid);
- if (status != FT_OK) {
- LOG_WARNING("couldn't add %4.4x:%4.4x",
- low->ublast_vid, low->ublast_pid);
- }
-#endif
- status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION,
- ftdih);
- if (status != FT_OK) {
- DWORD num_devices;
-
- LOG_ERROR("unable to open ftdi device: %s",
- ftd2xx_status_string(status));
- status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
- if (status == FT_OK) {
- char **desc_array =
- malloc(sizeof(char *) * (num_devices + 1));
- unsigned int i;
-
- for (i = 0; i < num_devices; i++)
- desc_array[i] = malloc(64);
- desc_array[num_devices] = NULL;
-
- status = FT_ListDevices(desc_array, &num_devices,
- FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
-
- if (status == FT_OK) {
- LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices);
- for (i = 0; i < num_devices; i++)
- LOG_ERROR("%i: %s", i, desc_array[i]);
- }
-
- for (i = 0; i < num_devices; i++)
- free(desc_array[i]);
- free(desc_array);
- } else {
- printf("ListDevices: NONE\n");
- }
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_SetLatencyTimer(*ftdih, 2);
- if (status != FT_OK) {
- LOG_ERROR("unable to set latency timer: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_INIT_FAILED;
- }
-
- status = FT_GetLatencyTimer(*ftdih, &latency_timer);
- if (status != FT_OK)
- LOG_ERROR("unable to get latency timer: %s",
- ftd2xx_status_string(status));
- else
- LOG_DEBUG("current latency timer: %i", latency_timer);
-
- status = FT_SetBitMode(*ftdih, 0x00, 0);
- if (status != FT_OK) {
- LOG_ERROR("unable to disable bit i/o mode: %s",
- ftd2xx_status_string(status));
- return ERROR_JTAG_INIT_FAILED;
- }
- return ERROR_OK;
-}
-
-static int ublast_ftd2xx_quit(struct ublast_lowlevel *low)
-{
- FT_HANDLE *ftdih = ublast_getftdih(low);
-
- FT_Close(*ftdih);
- return ERROR_OK;
-}
-
-static struct ublast_lowlevel_priv {
- FT_HANDLE ftdih;
-} info;
-
-static struct ublast_lowlevel low = {
- .open = ublast_ftd2xx_init,
- .close = ublast_ftd2xx_quit,
- .read = ublast_ftd2xx_read,
- .write = ublast_ftd2xx_write,
- .priv = &info,
-};
-
-struct ublast_lowlevel *ublast_register_ftd2xx(void)
-{
- return &low;
-}
diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c
deleted file mode 100644
index cb442f2..0000000
--- a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Driver for USB-JTAG, Altera USB-Blaster and compatibles
- *
- * Inspired from original code from Kolja Waschk's USB-JTAG project
- * (http://www.ixo.de/info/usb_jtag/), and from openocd project.
- *
- * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
- * Copyright (C) 2011 Ali Lown ali@lown.me.uk
- * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
- * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-
-#include "ublast_access.h"
-#include <ftdi.h>
-
-static struct ftdi_context *ublast_getftdic(struct ublast_lowlevel *low)
-{
- return low->priv;
-}
-
-static int ublast_ftdi_read(struct ublast_lowlevel *low, uint8_t *buf,
- unsigned size, uint32_t *bytes_read)
-{
- int retval;
- int timeout = 100;
- struct ftdi_context *ftdic = ublast_getftdic(low);
-
- *bytes_read = 0;
- while ((*bytes_read < size) && timeout--) {
- retval = ftdi_read_data(ftdic, buf + *bytes_read,
- size - *bytes_read);
- if (retval < 0) {
- *bytes_read = 0;
- LOG_ERROR("ftdi_read_data: %s",
- ftdi_get_error_string(ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_read += retval;
- }
- return ERROR_OK;
-}
-
-static int ublast_ftdi_write(struct ublast_lowlevel *low, uint8_t *buf, int size,
- uint32_t *bytes_written)
-{
- int retval;
- struct ftdi_context *ftdic = ublast_getftdic(low);
-
- retval = ftdi_write_data(ftdic, buf, size);
- if (retval < 0) {
- *bytes_written = 0;
- LOG_ERROR("ftdi_write_data: %s",
- ftdi_get_error_string(ftdic));
- return ERROR_JTAG_DEVICE_ERROR;
- }
- *bytes_written = retval;
- return ERROR_OK;
-}
-
-static int ublast_ftdi_init(struct ublast_lowlevel *low)
-{
- uint8_t latency_timer;
- struct ftdi_context *ftdic = ublast_getftdic(low);
-
- LOG_INFO("usb blaster interface using libftdi");
- if (ftdi_init(ftdic) < 0)
- return ERROR_JTAG_INIT_FAILED;
-
- /* context, vendor id, product id */
- if (ftdi_usb_open(ftdic, low->ublast_vid, low->ublast_pid) < 0) {
- LOG_ERROR("unable to open ftdi device: %s", ftdic->error_str);
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_usb_reset(ftdic) < 0) {
- LOG_ERROR("unable to reset ftdi device");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_set_latency_timer(ftdic, 2) < 0) {
- LOG_ERROR("unable to set latency timer");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- if (ftdi_get_latency_timer(ftdic, &latency_timer) < 0)
- LOG_ERROR("unable to get latency timer");
- else
- LOG_DEBUG("current latency timer: %u", latency_timer);
-
- ftdi_disable_bitbang(ftdic);
- return ERROR_OK;
-}
-
-static int ublast_ftdi_quit(struct ublast_lowlevel *low)
-{
- struct ftdi_context *ftdic = ublast_getftdic(low);
-
- ftdi_usb_close(ftdic);
- ftdi_deinit(ftdic);
- return ERROR_OK;
-};
-
-static struct ublast_lowlevel_priv {
- struct ftdi_context ftdic;
-} info;
-
-static struct ublast_lowlevel low = {
- .open = ublast_ftdi_init,
- .close = ublast_ftdi_quit,
- .read = ublast_ftdi_read,
- .write = ublast_ftdi_write,
- .priv = &info,
-};
-
-struct ublast_lowlevel *ublast_register_ftdi(void)
-{
- return &low;
-}
diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c
deleted file mode 100644
index 8f3f327..0000000
--- a/src/jtag/drivers/usb_blaster/usb_blaster.c
+++ /dev/null
@@ -1,1079 +0,0 @@
-/*
- * Driver for USB-JTAG, Altera USB-Blaster and compatibles
- *
- * Inspired from original code from Kolja Waschk's USB-JTAG project
- * (http://www.ixo.de/info/usb_jtag/), and from openocd project.
- *
- * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com
- * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr
- * Copyright (C) 2011 Ali Lown ali@lown.me.uk
- * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca
- * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.de
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/*
- * The following information is originally from Kolja Waschk's USB-JTAG,
- * where it was obtained by reverse engineering an Altera USB-Blaster.
- * See http://www.ixo.de/info/usb_jtag/ for USB-Blaster block diagram and
- * usb_jtag-20080705-1200.zip#usb_jtag/host/openocd for protocol.
- *
- * The same information is also on the UrJTAG mediawiki, with some additional
- * notes on bits marked as "unknown" by usb_jtag.
- * (http://sourceforge.net/apps/mediawiki/urjtag/index.php?
- * title=Cable_Altera_USB-Blaster)
- *
- * USB-JTAG, Altera USB-Blaster and compatibles are typically implemented as
- * an FTDIChip FT245 followed by a CPLD which handles a two-mode protocol:
- *
- * _________
- * | |
- * | AT93C46 |
- * |_________|
- * __|__________ _________
- * | | | |
- * USB__| FTDI 245BM |__| EPM7064 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK)
- * |_____________| |_________|
- * __|__________ _|___________
- * | | | |
- * | 6 MHz XTAL | | 24 MHz Osc. |
- * |_____________| |_____________|
- *
- * USB-JTAG, Altera USB-Blaster II are typically implemented as a Cypress
- * EZ-USB FX2LP followed by a CPLD.
- * _____________ _________
- * | | | |
- * USB__| EZ-USB FX2 |__| EPM570 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK)
- * |_____________| |_________|
- * __|__________
- * | |
- * | 24 MHz XTAL |
- * |_____________|
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if IS_CYGWIN == 1
-#include "windows.h"
-#undef LOG_ERROR
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <helper/time_support.h>
-#include "ublast_access.h"
-
-/* system includes */
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <time.h>
-
-/* Size of USB endpoint max packet size, ie. 64 bytes */
-#define MAX_PACKET_SIZE 64
-/*
- * Size of data buffer that holds bytes in byte-shift mode.
- * This buffer can hold multiple USB packets aligned to
- * MAX_PACKET_SIZE bytes boundaries.
- * BUF_LEN must be grater than or equal MAX_PACKET_SIZE.
- */
-#define BUF_LEN 4096
-
-/* USB-Blaster II specific command */
-#define CMD_COPY_TDO_BUFFER 0x5F
-
-enum gpio_steer {
- FIXED_0 = 0,
- FIXED_1,
- SRST,
- TRST,
-};
-
-struct ublast_info {
- enum gpio_steer pin6;
- enum gpio_steer pin8;
- int tms;
- int tdi;
- bool trst_asserted;
- bool srst_asserted;
- uint8_t buf[BUF_LEN];
- int bufidx;
-
- char *lowlevel_name;
- struct ublast_lowlevel *drv;
- char *ublast_device_desc;
- uint16_t ublast_vid, ublast_pid;
- uint16_t ublast_vid_uninit, ublast_pid_uninit;
- int flags;
- char *firmware_path;
-};
-
-/*
- * Global device control
- */
-static struct ublast_info info = {
- .ublast_vid = 0x09fb, /* Altera */
- .ublast_pid = 0x6001, /* USB-Blaster */
- .lowlevel_name = NULL,
- .srst_asserted = false,
- .trst_asserted = false,
- .pin6 = FIXED_1,
- .pin8 = FIXED_1,
-};
-
-/*
- * Available lowlevel drivers (FTDI, FTD2xx, ...)
- */
-struct drvs_map {
- char *name;
- struct ublast_lowlevel *(*drv_register)(void);
-};
-
-static struct drvs_map lowlevel_drivers_map[] = {
-#if BUILD_USB_BLASTER_LIBFTDI
- { .name = "ftdi", .drv_register = ublast_register_ftdi },
-#endif
-#if BUILD_USB_BLASTER_FTD2XX
- { .name = "ftd2xx", .drv_register = ublast_register_ftd2xx },
-#endif
-#if BUILD_USB_BLASTER_2
- { .name = "ublast2", .drv_register = ublast2_register_libusb },
-#endif
- { NULL, NULL },
-};
-
-/*
- * Access functions to lowlevel driver, agnostic of libftdi/libftdxx
- */
-static char *hexdump(uint8_t *buf, unsigned int size)
-{
- unsigned int i;
- char *str = calloc(size * 2 + 1, 1);
-
- for (i = 0; i < size; i++)
- sprintf(str + 2*i, "%02x", buf[i]);
- return str;
-}
-
-static int ublast_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read)
-{
- int ret = info.drv->read(info.drv, buf, size, bytes_read);
- char *str = hexdump(buf, *bytes_read);
-
- DEBUG_JTAG_IO("(size=%d, buf=[%s]) -> %u", size, str,
- *bytes_read);
- free(str);
- return ret;
-}
-
-static int ublast_buf_write(uint8_t *buf, int size, uint32_t *bytes_written)
-{
- int ret = info.drv->write(info.drv, buf, size, bytes_written);
- char *str = hexdump(buf, *bytes_written);
-
- DEBUG_JTAG_IO("(size=%d, buf=[%s]) -> %u", size, str,
- *bytes_written);
- free(str);
- return ret;
-}
-
-static int nb_buf_remaining(void)
-{
- return BUF_LEN - info.bufidx;
-}
-
-static void ublast_flush_buffer(void)
-{
- unsigned int retlen;
- int nb = info.bufidx, ret = ERROR_OK;
-
- while (ret == ERROR_OK && nb > 0) {
- ret = ublast_buf_write(info.buf, nb, &retlen);
- nb -= retlen;
- }
- info.bufidx = 0;
-}
-
-/*
- * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data
- * bits (bidirectional) in a single USB packet. A header byte has to be sent as
- * the first byte in a packet with the following meaning:
- *
- * Bit 7 (0x80): Must be set to indicate byte-shift mode.
- * Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
- * Bit 5..0: Define the number N of following bytes
- *
- * All N following bytes will then be clocked out serially on TDI. If Bit 6 was
- * set, it will afterwards return N bytes with TDO data read while clocking out
- * the TDI data. LSB of the first byte after the header byte will appear first
- * on TDI.
- */
-
-/* Simple bit banging mode:
- *
- * Bit 7 (0x80): Must be zero (see byte-shift mode above)
- * Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
- * in return.
- * Bit 5 (0x20): Output Enable/LED.
- * Bit 4 (0x10): TDI Output.
- * Bit 3 (0x08): nCS Output (not used in JTAG mode).
- * Bit 2 (0x04): nCE Output (not used in JTAG mode).
- * Bit 1 (0x02): TMS Output.
- * Bit 0 (0x01): TCK Output.
- *
- * For transmitting a single data bit, you need to write two bytes (one for
- * setting up TDI/TMS/TCK=0, and one to trigger TCK high with same TDI/TMS
- * held). Up to 64 bytes can be combined in a single USB packet.
- * It isn't possible to read a data without transmitting data.
- */
-
-#define TCK (1 << 0)
-#define TMS (1 << 1)
-#define NCE (1 << 2)
-#define NCS (1 << 3)
-#define TDI (1 << 4)
-#define LED (1 << 5)
-#define READ (1 << 6)
-#define SHMODE (1 << 7)
-#define READ_TDO (1 << 0)
-
-/**
- * ublast_queue_byte - queue one 'bitbang mode' byte for USB Blaster
- * @abyte: the byte to queue
- *
- * Queues one byte in 'bitbang mode' to the USB Blaster. The byte is not
- * actually sent, but stored in a buffer. The write is performed once
- * the buffer is filled, or if an explicit ublast_flush_buffer() is called.
- */
-static void ublast_queue_byte(uint8_t abyte)
-{
- if (nb_buf_remaining() < 1)
- ublast_flush_buffer();
- info.buf[info.bufidx++] = abyte;
- if (nb_buf_remaining() == 0)
- ublast_flush_buffer();
- DEBUG_JTAG_IO("(byte=0x%02x)", abyte);
-}
-
-/**
- * ublast_compute_pin - compute if gpio should be asserted
- * @steer: control (ie. TRST driven, SRST driven, of fixed)
- *
- * Returns pin value (1 means driven high, 0 mean driven low)
- */
-bool ublast_compute_pin(enum gpio_steer steer)
-{
- switch (steer) {
- case FIXED_0:
- return 0;
- case FIXED_1:
- return 1;
- case SRST:
- return !info.srst_asserted;
- case TRST:
- return !info.trst_asserted;
- default:
- return 1;
- }
-}
-
-/**
- * ublast_build_out - build bitbang mode output byte
- * @type: says if reading back TDO is required
- *
- * Returns the compute bitbang mode byte
- */
-static uint8_t ublast_build_out(enum scan_type type)
-{
- uint8_t abyte = 0;
-
- abyte |= info.tms ? TMS : 0;
- abyte |= ublast_compute_pin(info.pin6) ? NCE : 0;
- abyte |= ublast_compute_pin(info.pin8) ? NCS : 0;
- abyte |= info.tdi ? TDI : 0;
- abyte |= LED;
- if (type == SCAN_IN || type == SCAN_IO)
- abyte |= READ;
- return abyte;
-}
-
-/**
- * ublast_reset - reset the JTAG device is possible
- * @trst: 1 if TRST is to be asserted
- * @srst: 1 if SRST is to be asserted
- */
-static void ublast_reset(int trst, int srst)
-{
- uint8_t out_value;
-
- info.trst_asserted = trst;
- info.srst_asserted = srst;
- out_value = ublast_build_out(SCAN_OUT);
- ublast_queue_byte(out_value);
- ublast_flush_buffer();
-}
-
-/**
- * ublast_clock_tms - clock a TMS transition
- * @tms: the TMS to be sent
- *
- * Triggers a TMS transition (ie. one JTAG TAP state move).
- */
-static void ublast_clock_tms(int tms)
-{
- uint8_t out;
-
- DEBUG_JTAG_IO("(tms=%d)", !!tms);
- info.tms = !!tms;
- info.tdi = 0;
- out = ublast_build_out(SCAN_OUT);
- ublast_queue_byte(out);
- ublast_queue_byte(out | TCK);
-}
-
-/**
- * ublast_idle_clock - put back TCK to low level
- *
- * See ublast_queue_tdi() comment for the usage of this function.
- */
-static void ublast_idle_clock(void)
-{
- uint8_t out = ublast_build_out(SCAN_OUT);
-
- DEBUG_JTAG_IO(".");
- ublast_queue_byte(out);
-}
-
-/**
- * ublast_clock_tdi - Output a TDI with bitbang mode
- * @tdi: the TDI bit to be shifted out
- * @type: scan type (ie. does a readback of TDO is required)
- *
- * Output a TDI bit and assert clock to push it into the JTAG device :
- * - writing out TCK=0, TMS=<old_state>=0, TDI=<tdi>
- * - writing out TCK=1, TMS=<new_state>, TDI=<tdi> which triggers the JTAG
- * device aquiring the data.
- *
- * If a TDO is to be read back, the required read is requested (bitbang mode),
- * and the USB Blaster will send back a byte with bit0 reprensenting the TDO.
- */
-static void ublast_clock_tdi(int tdi, enum scan_type type)
-{
- uint8_t out;
-
- DEBUG_JTAG_IO("(tdi=%d)", !!tdi);
- info.tdi = !!tdi;
-
- out = ublast_build_out(SCAN_OUT);
- ublast_queue_byte(out);
-
- out = ublast_build_out(type);
- ublast_queue_byte(out | TCK);
-}
-
-/**
- * ublast_clock_tdi_flip_tms - Output a TDI with bitbang mode, change JTAG state
- * @tdi: the TDI bit to be shifted out
- * @type: scan type (ie. does a readback of TDO is required)
- *
- * This function is the same as ublast_clock_tdi(), but it changes also the TMS
- * while outputing the TDI. This should be the last TDI output of a TDI
- * sequence, which will change state from :
- * - IRSHIFT -> IREXIT1
- * - or DRSHIFT -> DREXIT1
- */
-static void ublast_clock_tdi_flip_tms(int tdi, enum scan_type type)
-{
- uint8_t out;
-
- DEBUG_JTAG_IO("(tdi=%d)", !!tdi);
- info.tdi = !!tdi;
- info.tms = !info.tms;
-
- out = ublast_build_out(SCAN_OUT);
- ublast_queue_byte(out);
-
- out = ublast_build_out(type);
- ublast_queue_byte(out | TCK);
-
- out = ublast_build_out(SCAN_OUT);
- ublast_queue_byte(out);
-}
-
-/**
- * ublast_queue_bytes - queue bytes for the USB Blaster
- * @bytes: byte array
- * @nb_bytes: number of bytes
- *
- * Queues bytes to be sent to the USB Blaster. The bytes are not
- * actually sent, but stored in a buffer. The write is performed once
- * the buffer is filled, or if an explicit ublast_flush_buffer() is called.
- */
-static void ublast_queue_bytes(uint8_t *bytes, int nb_bytes)
-{
- if (info.bufidx + nb_bytes > BUF_LEN) {
- LOG_ERROR("buggy code, should never queue more that %d bytes",
- info.bufidx + nb_bytes);
- exit(-1);
- }
- DEBUG_JTAG_IO("(nb_bytes=%d, bytes=[0x%02x, ...])", nb_bytes,
- bytes ? bytes[0] : 0);
- if (bytes)
- memcpy(&info.buf[info.bufidx], bytes, nb_bytes);
- else
- memset(&info.buf[info.bufidx], 0, nb_bytes);
- info.bufidx += nb_bytes;
- if (nb_buf_remaining() == 0)
- ublast_flush_buffer();
-}
-
-/**
- * ublast_tms_seq - write a TMS sequence transition to JTAG
- * @bits: TMS bits to be written (bit0, bit1 .. bitN)
- * @nb_bits: number of TMS bits (between 1 and 8)
- *
- * Write a serie of TMS transitions, where each transition consists in :
- * - writing out TCK=0, TMS=<new_state>, TDI=<???>
- * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
- * The function ensures that at the end of the sequence, the clock (TCK) is put
- * low.
- */
-static void ublast_tms_seq(const uint8_t *bits, int nb_bits)
-{
- int i;
-
- DEBUG_JTAG_IO("(bits=%02x..., nb_bits=%d)", bits[0], nb_bits);
- for (i = 0; i < nb_bits; i++)
- ublast_clock_tms((bits[i / 8] >> (i % 8)) & 0x01);
- ublast_idle_clock();
-}
-
-/**
- * ublast_tms - write a tms command
- * @cmd: tms command
- */
-static void ublast_tms(struct tms_command *cmd)
-{
- DEBUG_JTAG_IO("(num_bits=%d)", cmd->num_bits);
- ublast_tms_seq(cmd->bits, cmd->num_bits);
-}
-
-/**
- * ublast_path_move - write a TMS sequence transition to JTAG
- * @cmd: path transition
- *
- * Write a serie of TMS transitions, where each transition consists in :
- * - writing out TCK=0, TMS=<new_state>, TDI=<???>
- * - writing out TCK=1, TMS=<new_state>, TDI=<???> which triggers the transition
- * The function ensures that at the end of the sequence, the clock (TCK) is put
- * low.
- */
-static void ublast_path_move(struct pathmove_command *cmd)
-{
- int i;
-
- DEBUG_JTAG_IO("(num_states=%d, last_state=%d)",
- cmd->num_states, cmd->path[cmd->num_states - 1]);
- for (i = 0; i < cmd->num_states; i++) {
- if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
- ublast_clock_tms(0);
- if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
- ublast_clock_tms(1);
- tap_set_state(cmd->path[i]);
- }
- ublast_idle_clock();
-}
-
-/**
- * ublast_state_move - move JTAG state to the target state
- * @state: the target state
- *
- * Input the correct TMS sequence to the JTAG TAP so that we end up in the
- * target state. This assumes the current state (tap_get_state()) is correct.
- */
-static void ublast_state_move(tap_state_t state)
-{
- uint8_t tms_scan;
- int tms_len;
-
- DEBUG_JTAG_IO("(from %s to %s)", tap_state_name(tap_get_state()),
- tap_state_name(state));
- if (tap_get_state() == state)
- return;
- tms_scan = tap_get_tms_path(tap_get_state(), state);
- tms_len = tap_get_tms_path_len(tap_get_state(), state);
- ublast_tms_seq(&tms_scan, tms_len);
- tap_set_state(state);
-}
-
-/**
- * ublast_read_byteshifted_tdos - read TDO of byteshift writes
- * @buf: the buffer to store the bits
- * @nb_bits: the number of bits
- *
- * Reads back from USB Blaster TDO bits, triggered by a 'byteshift write', ie. eight
- * bits per received byte from USB interface, and store them in buffer.
- *
- * As the USB blaster stores the TDO bits in LSB (ie. first bit in (byte0,
- * bit0), second bit in (byte0, bit1), ...), which is what we want to return,
- * simply read bytes from USB interface and store them.
- *
- * Returns ERROR_OK if OK, ERROR_xxx if a read error occured
- */
-static int ublast_read_byteshifted_tdos(uint8_t *buf, int nb_bytes)
-{
- unsigned int retlen;
- int ret = ERROR_OK;
-
- DEBUG_JTAG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bytes * 8);
- ublast_flush_buffer();
- while (ret == ERROR_OK && nb_bytes > 0) {
- ret = ublast_buf_read(buf, nb_bytes, &retlen);
- nb_bytes -= retlen;
- }
- return ret;
-}
-
-/**
- * ublast_read_bitbang_tdos - read TDO of bitbang writes
- * @buf: the buffer to store the bits
- * @nb_bits: the number of bits
- *
- * Reads back from USB Blaster TDO bits, triggered by a 'bitbang write', ie. one
- * bit per received byte from USB interface, and store them in buffer, where :
- * - first bit is stored in byte0, bit0 (LSB)
- * - second bit is stored in byte0, bit 1
- * ...
- * - eight bit is sotred in byte0, bit 7
- * - ninth bit is sotred in byte1, bit 0
- * - etc ...
- *
- * Returns ERROR_OK if OK, ERROR_xxx if a read error occured
- */
-static int ublast_read_bitbang_tdos(uint8_t *buf, int nb_bits)
-{
- int nb1 = nb_bits;
- int i, ret = ERROR_OK;
- unsigned int retlen;
- uint8_t tmp[8];
-
- DEBUG_JTAG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bits);
-
- /*
- * Ensure all previous bitbang writes were issued to the dongle, so that
- * it returns back the read values.
- */
- ublast_flush_buffer();
-
- ret = ublast_buf_read(tmp, nb1, &retlen);
- for (i = 0; ret == ERROR_OK && i < nb1; i++)
- if (tmp[i] & READ_TDO)
- *buf |= (1 << i);
- else
- *buf &= ~(1 << i);
- return ret;
-}
-
-/**
- * ublast_queue_tdi - short description
- * @bits: bits to be queued on TDI (or NULL if 0 are to be queued)
- * @nb_bits: number of bits
- * @scan: scan type (ie. if TDO read back is required or not)
- *
- * Outputs a serie of TDI bits on TDI.
- * As a side effect, the last TDI bit is sent along a TMS=1, and triggers a JTAG
- * TAP state shift if input bits were non NULL.
- *
- * In order to not saturate the USB Blaster queues, this method reads back TDO
- * if the scan type requests it, and stores them back in bits.
- *
- * As a side note, the state of TCK when entering this function *must* be
- * low. This is because byteshift mode outputs TDI on rising TCK and reads TDO
- * on falling TCK if and only if TCK is low before queuing byteshift mode bytes.
- * If TCK was high, the USB blaster will queue TDI on falling edge, and read TDO
- * on rising edge !!!
- */
-static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan)
-{
- int nb8 = nb_bits / 8;
- int nb1 = nb_bits % 8;
- int nbfree_in_packet, i, trans = 0, read_tdos;
- uint8_t *tdos = calloc(1, nb_bits / 8 + 1);
- static uint8_t byte0[BUF_LEN];
-
- /*
- * As the last TDI bit should always be output in bitbang mode in order
- * to activate the TMS=1 transition to EXIT_?R state. Therefore a
- * situation where nb_bits is a multiple of 8 is handled as follows:
- * - the number of TDI shifted out in "byteshift mode" is 8 less than
- * nb_bits
- * - nb1 = 8
- * This ensures that nb1 is never 0, and allows the TMS transition.
- */
- if (nb8 > 0 && nb1 == 0) {
- nb8--;
- nb1 = 8;
- }
-
- read_tdos = (scan == SCAN_IN || scan == SCAN_IO);
- for (i = 0; i < nb8; i += trans) {
- /*
- * Calculate number of bytes to fill USB packet of size MAX_PACKET_SIZE
- */
- nbfree_in_packet = (MAX_PACKET_SIZE - (info.bufidx%MAX_PACKET_SIZE));
- trans = MIN(nbfree_in_packet - 1, nb8 - i);
-
- /*
- * Queue a byte-shift mode transmission, with as many bytes as
- * is possible with regard to :
- * - current filling level of write buffer
- * - remaining bytes to write in byte-shift mode
- */
- if (read_tdos)
- ublast_queue_byte(SHMODE | READ | trans);
- else
- ublast_queue_byte(SHMODE | trans);
- if (bits)
- ublast_queue_bytes(&bits[i], trans);
- else
- ublast_queue_bytes(byte0, trans);
- if (read_tdos) {
- if (info.flags & COPY_TDO_BUFFER)
- ublast_queue_byte(CMD_COPY_TDO_BUFFER);
- ublast_read_byteshifted_tdos(&tdos[i], trans);
- }
- }
-
- /*
- * Queue the remaining TDI bits in bitbang mode.
- */
- for (i = 0; i < nb1; i++) {
- int tdi = bits ? bits[nb8 + i / 8] & (1 << i) : 0;
- if (bits && i == nb1 - 1)
- ublast_clock_tdi_flip_tms(tdi, scan);
- else
- ublast_clock_tdi(tdi, scan);
- }
- if (nb1 && read_tdos) {
- if (info.flags & COPY_TDO_BUFFER)
- ublast_queue_byte(CMD_COPY_TDO_BUFFER);
- ublast_read_bitbang_tdos(&tdos[nb8], nb1);
- }
-
- if (bits)
- memcpy(bits, tdos, DIV_ROUND_UP(nb_bits, 8));
- free(tdos);
-
- /*
- * Ensure clock is in lower state
- */
- ublast_idle_clock();
-}
-
-static void ublast_runtest(int cycles, tap_state_t state)
-{
- DEBUG_JTAG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state);
-
- ublast_state_move(TAP_IDLE);
- ublast_queue_tdi(NULL, cycles, SCAN_OUT);
- ublast_state_move(state);
-}
-
-static void ublast_stableclocks(int cycles)
-{
- DEBUG_JTAG_IO("%s(cycles=%i)", __func__, cycles);
- ublast_queue_tdi(NULL, cycles, SCAN_OUT);
-}
-
-/**
- * ublast_scan - launches a DR-scan or IR-scan
- * @cmd: the command to launch
- *
- * Launch a JTAG IR-scan or DR-scan
- *
- * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
- */
-static int ublast_scan(struct scan_command *cmd)
-{
- int scan_bits;
- uint8_t *buf = NULL;
- enum scan_type type;
- int ret = ERROR_OK;
- static const char * const type2str[] = { "", "SCAN_IN", "SCAN_OUT", "SCAN_IO" };
- char *log_buf = NULL;
-
- type = jtag_scan_type(cmd);
- scan_bits = jtag_build_buffer(cmd, &buf);
-
- if (cmd->ir_scan)
- ublast_state_move(TAP_IRSHIFT);
- else
- ublast_state_move(TAP_DRSHIFT);
-
- log_buf = hexdump(buf, DIV_ROUND_UP(scan_bits, 8));
- DEBUG_JTAG_IO("%s(scan=%s, type=%s, bits=%d, buf=[%s], end_state=%d)", __func__,
- cmd->ir_scan ? "IRSCAN" : "DRSCAN",
- type2str[type],
- scan_bits, log_buf, cmd->end_state);
- free(log_buf);
-
- ublast_queue_tdi(buf, scan_bits, type);
-
- /*
- * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
- * forward to a stable IRPAUSE or DRPAUSE.
- */
- ublast_clock_tms(0);
- if (cmd->ir_scan)
- tap_set_state(TAP_IRPAUSE);
- else
- tap_set_state(TAP_DRPAUSE);
-
- ret = jtag_read_buffer(buf, cmd);
- if (buf)
- free(buf);
- ublast_state_move(cmd->end_state);
- return ret;
-}
-
-static void ublast_usleep(int us)
-{
- DEBUG_JTAG_IO("%s(us=%d)", __func__, us);
- jtag_sleep(us);
-}
-
-static void ublast_initial_wipeout(void)
-{
- static uint8_t tms_reset = 0xff;
- uint8_t out_value;
- uint32_t retlen;
- int i;
-
- out_value = ublast_build_out(SCAN_OUT);
- for (i = 0; i < BUF_LEN; i++)
- info.buf[i] = out_value | ((i % 2) ? TCK : 0);
-
- /*
- * Flush USB-Blaster queue fifos
- * - empty the write FIFO (128 bytes)
- * - empty the read FIFO (384 bytes)
- */
- ublast_buf_write(info.buf, BUF_LEN, &retlen);
- /*
- * Put JTAG in RESET state (five 1 on TMS)
- */
- ublast_tms_seq(&tms_reset, 5);
- tap_set_state(TAP_RESET);
-}
-
-static int ublast_execute_queue(void)
-{
- struct jtag_command *cmd;
- static int first_call = 1;
- int ret = ERROR_OK;
-
- if (first_call) {
- first_call--;
- ublast_initial_wipeout();
- }
-
- for (cmd = jtag_command_queue; ret == ERROR_OK && cmd != NULL;
- cmd = cmd->next) {
- switch (cmd->type) {
- case JTAG_RESET:
- ublast_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
- ublast_runtest(cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
- break;
- case JTAG_STABLECLOCKS:
- ublast_stableclocks(cmd->cmd.stableclocks->num_cycles);
- break;
- case JTAG_TLR_RESET:
- ublast_state_move(cmd->cmd.statemove->end_state);
- break;
- case JTAG_PATHMOVE:
- ublast_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_TMS:
- ublast_tms(cmd->cmd.tms);
- break;
- case JTAG_SLEEP:
- ublast_usleep(cmd->cmd.sleep->us);
- break;
- case JTAG_SCAN:
- ret = ublast_scan(cmd->cmd.scan);
- break;
- }
- }
-
- ublast_flush_buffer();
- return ret;
-}
-
-/**
- * ublast_init - Initialize the Altera device
- *
- * Initialize the device :
- * - open the USB device
- * - pretend it's initialized while actual init is delayed until first jtag command
- *
- * Returns ERROR_OK if USB device found, error if not.
- */
-static int ublast_init(void)
-{
- int ret, i;
-
- if (info.lowlevel_name) {
- for (i = 0; lowlevel_drivers_map[i].name; i++)
- if (!strcmp(lowlevel_drivers_map[i].name, info.lowlevel_name))
- break;
- if (lowlevel_drivers_map[i].name)
- info.drv = lowlevel_drivers_map[i].drv_register();
- if (!info.drv) {
- LOG_ERROR("no lowlevel driver found for %s or lowlevel driver opening error",
- info.lowlevel_name);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- } else {
- LOG_INFO("No lowlevel driver configured, will try them all");
- for (i = 0; !info.drv && lowlevel_drivers_map[i].name; i++)
- info.drv = lowlevel_drivers_map[i].drv_register();
- if (!info.drv) {
- LOG_ERROR("no lowlevel driver found");
- return ERROR_JTAG_DEVICE_ERROR;
- }
- info.lowlevel_name = strdup(lowlevel_drivers_map[i-1].name);
- }
-
- /*
- * Register the lowlevel driver
- */
- info.drv->ublast_vid = info.ublast_vid;
- info.drv->ublast_pid = info.ublast_pid;
- info.drv->ublast_vid_uninit = info.ublast_vid_uninit;
- info.drv->ublast_pid_uninit = info.ublast_pid_uninit;
- info.drv->ublast_device_desc = info.ublast_device_desc;
- info.drv->firmware_path = info.firmware_path;
-
- info.flags |= info.drv->flags;
-
- ret = info.drv->open(info.drv);
-
- /*
- * Let lie here : the TAP is in an unknown state, but the first
- * execute_queue() will trigger a ublast_initial_wipeout(), which will
- * put the TAP in RESET.
- */
- tap_set_state(TAP_RESET);
- return ret;
-}
-
-/**
- * ublast_quit - Release the Altera device
- *
- * Releases the device :
- * - put the device pins in 'high impedance' mode
- * - close the USB device
- *
- * Returns always ERROR_OK
- */
-static int ublast_quit(void)
-{
- uint8_t byte0 = 0;
- unsigned int retlen;
-
- ublast_buf_write(&byte0, 1, &retlen);
- return info.drv->close(info.drv);
-}
-
-COMMAND_HANDLER(ublast_handle_device_desc_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- info.ublast_device_desc = strdup(CMD_ARGV[0]);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ublast_handle_vid_pid_command)
-{
- if (CMD_ARGC > 4) {
- LOG_WARNING("ignoring extra IDs in ublast_vid_pid "
- "(maximum is 2 pairs)");
- CMD_ARGC = 4;
- }
-
- if (CMD_ARGC >= 2) {
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], info.ublast_vid);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], info.ublast_pid);
- } else {
- LOG_WARNING("incomplete ublast_vid_pid configuration");
- }
-
- if (CMD_ARGC == 4) {
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], info.ublast_vid_uninit);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], info.ublast_pid_uninit);
- } else {
- LOG_WARNING("incomplete ublast_vid_pid configuration");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ublast_handle_pin_command)
-{
- uint8_t out_value;
- const char * const pin_name = CMD_ARGV[0];
- enum gpio_steer *steer = NULL;
- static const char * const pin_val_str[] = {
- [FIXED_0] = "0",
- [FIXED_1] = "1",
- [SRST] = "SRST driven",
- [TRST] = "TRST driven",
- };
-
- if (CMD_ARGC > 2) {
- LOG_ERROR("%s takes exactly one or two arguments", CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (!strcmp(pin_name, "pin6"))
- steer = &info.pin6;
- if (!strcmp(pin_name, "pin8"))
- steer = &info.pin8;
- if (!steer) {
- LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"",
- CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (CMD_ARGC == 1) {
- LOG_INFO("%s: %s is set as %s\n", CMD_NAME, pin_name,
- pin_val_str[*steer]);
- }
-
- if (CMD_ARGC == 2) {
- const char * const pin_value = CMD_ARGV[1];
- char val = pin_value[0];
-
- if (strlen(pin_value) > 1)
- val = '?';
- switch (tolower((unsigned char)val)) {
- case '0':
- *steer = FIXED_0;
- break;
- case '1':
- *steer = FIXED_1;
- break;
- case 't':
- *steer = TRST;
- break;
- case 's':
- *steer = SRST;
- break;
- default:
- LOG_ERROR("%s: pin value must be 0, 1, s (SRST) or t (TRST)",
- pin_value);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (info.drv) {
- out_value = ublast_build_out(SCAN_OUT);
- ublast_queue_byte(out_value);
- ublast_flush_buffer();
- }
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ublast_handle_lowlevel_drv_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- info.lowlevel_name = strdup(CMD_ARGV[0]);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(ublast_firmware_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- info.firmware_path = strdup(CMD_ARGV[0]);
-
- return ERROR_OK;
-}
-
-
-static const struct command_registration ublast_command_handlers[] = {
- {
- .name = "usb_blaster_device_desc",
- .handler = ublast_handle_device_desc_command,
- .mode = COMMAND_CONFIG,
- .help = "set the USB device description of the USB-Blaster",
- .usage = "description-string",
- },
- {
- .name = "usb_blaster_vid_pid",
- .handler = ublast_handle_vid_pid_command,
- .mode = COMMAND_CONFIG,
- .help = "the vendor ID and product ID of the USB-Blaster and " \
- "vendor ID and product ID of the uninitialized device " \
- "for USB-Blaster II",
- .usage = "vid pid vid_uninit pid_uninit",
- },
- {
- .name = "usb_blaster_lowlevel_driver",
- .handler = ublast_handle_lowlevel_drv_command,
- .mode = COMMAND_CONFIG,
- .help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx, ublast2)",
- .usage = "(ftdi|ftd2xx|ublast2)",
- },
- {
- .name = "usb_blaster_pin",
- .handler = ublast_handle_pin_command,
- .mode = COMMAND_ANY,
- .help = "show or set pin state for the unused GPIO pins",
- .usage = "(pin6|pin8) (0|1|s|t)",
- },
- {
- .name = "usb_blaster_firmware",
- .handler = &ublast_firmware_command,
- .mode = COMMAND_CONFIG,
- .help = "configure the USB-Blaster II firmware location",
- .usage = "path/to/blaster_xxxx.hex",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface usb_blaster_interface = {
- .name = "usb_blaster",
- .commands = ublast_command_handlers,
- .supported = DEBUG_CAP_TMS_SEQ,
-
- .execute_queue = ublast_execute_queue,
- .init = ublast_init,
- .quit = ublast_quit,
-};
diff --git a/src/jtag/drivers/usb_common.c b/src/jtag/drivers/usb_common.c
deleted file mode 100644
index 54be6a6..0000000
--- a/src/jtag/drivers/usb_common.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "usb_common.h"
-
-
-static bool jtag_usb_match(struct usb_device *dev,
- const uint16_t vids[], const uint16_t pids[])
-{
- for (unsigned i = 0; vids[i] && pids[i]; i++) {
- if (dev->descriptor.idVendor == vids[i] &&
- dev->descriptor.idProduct == pids[i])
- return true;
- }
- return false;
-}
-
-int jtag_usb_open(const uint16_t vids[], const uint16_t pids[],
- struct usb_dev_handle **out)
-{
- usb_find_busses();
- usb_find_devices();
-
- struct usb_bus *busses = usb_get_busses();
- for (struct usb_bus *bus = busses; bus; bus = bus->next) {
- for (struct usb_device *dev = bus->devices; dev; dev = dev->next) {
- if (!jtag_usb_match(dev, vids, pids))
- continue;
-
- *out = usb_open(dev);
- if (NULL == *out)
- return -errno;
- return 0;
- }
- }
- return -ENODEV;
-}
diff --git a/src/jtag/drivers/usb_common.h b/src/jtag/drivers/usb_common.h
deleted file mode 100644
index 4d2bd26..0000000
--- a/src/jtag/drivers/usb_common.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_USB_COMMON_H
-#define OPENOCD_JTAG_DRIVERS_USB_COMMON_H
-
-#include <usb.h>
-
-int jtag_usb_open(const uint16_t vids[], const uint16_t pids[],
- struct usb_dev_handle **out);
-
-#endif /* OPENOCD_JTAG_DRIVERS_USB_COMMON_H */
diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c
deleted file mode 100644
index d81c329..0000000
--- a/src/jtag/drivers/usbprog.c
+++ /dev/null
@@ -1,619 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Benedikt Sauter *
- * sauter@ixbat.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * This file is based on Dominic Rath's amt_jtagaccel.c.
- *
- * usbprog is a free programming adapter. You can easily install
- * different firmware versions from an "online pool" over USB.
- * The adapter can be used for programming and debugging AVR and ARM
- * processors, as USB to RS232 converter, as JTAG interface or as
- * simple I/O interface (5 lines).
- *
- * http://www.embedded-projects.net/usbprog
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include "usb_common.h"
-
-#define VID 0x1781
-#define PID 0x0c63
-
-/* Pins at usbprog */
-#define TDO_BIT 0
-#define TDI_BIT 3
-#define TCK_BIT 2
-#define TMS_BIT 1
-
-static void usbprog_end_state(tap_state_t state);
-static void usbprog_state_move(void);
-static void usbprog_path_move(struct pathmove_command *cmd);
-static void usbprog_runtest(int num_cycles);
-static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size);
-
-#define UNKNOWN_COMMAND 0x00
-#define PORT_DIRECTION 0x01
-#define PORT_SET 0x02
-#define PORT_GET 0x03
-#define PORT_SETBIT 0x04
-#define PORT_GETBIT 0x05
-#define WRITE_TDI 0x06
-#define READ_TDO 0x07
-#define WRITE_AND_READ 0x08
-#define WRITE_TMS 0x09
-#define WRITE_TMS_CHAIN 0x0A
-
-struct usbprog_jtag {
- struct usb_dev_handle *usb_handle;
-};
-
-static struct usbprog_jtag *usbprog_jtag_handle;
-
-static struct usbprog_jtag *usbprog_jtag_open(void);
-/* static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag); */
-static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);
-static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);
-
-static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char *buffer, int size);
-static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char *buffer, int size);
-static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char *buffer, int size);
-static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan);
-
-static char tms_chain[64];
-static int tms_chain_index;
-
-static void usbprog_jtag_tms_collect(char tms_scan);
-static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag);
-
-static void usbprog_write(int tck, int tms, int tdi);
-static void usbprog_reset(int trst, int srst);
-
-static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction);
-static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag, unsigned char value);
-/* static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag); */
-static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag, int bit, int value);
-/* static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit); */
-
-static int usbprog_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
-
- while (cmd) {
- switch (cmd->type) {
- case JTAG_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-#endif
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
- usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- break;
- case JTAG_RUNTEST:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("runtest %i cycles, end in %i",
- cmd->cmd.runtest->num_cycles,
- cmd->cmd.runtest->end_state);
-#endif
- usbprog_end_state(cmd->cmd.runtest->end_state);
- usbprog_runtest(cmd->cmd.runtest->num_cycles);
- break;
- case JTAG_TLR_RESET:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
-#endif
- usbprog_end_state(cmd->cmd.statemove->end_state);
- usbprog_state_move();
- break;
- case JTAG_PATHMOVE:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("pathmove: %i states, end in %i",
- cmd->cmd.pathmove->num_states,
- cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-#endif
- usbprog_path_move(cmd->cmd.pathmove);
- break;
- case JTAG_SCAN:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
-#endif
- usbprog_end_state(cmd->cmd.scan->end_state);
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
- if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
- return ERROR_JTAG_QUEUE_FAILED;
- if (buffer)
- free(buffer);
- break;
- case JTAG_SLEEP:
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
-#endif
- jtag_sleep(cmd->cmd.sleep->us);
- break;
- default:
- LOG_ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
-
- cmd = cmd->next;
- }
-
- return ERROR_OK;
-}
-
-static int usbprog_init(void)
-{
- usbprog_jtag_handle = usbprog_jtag_open();
-
- tms_chain_index = 0;
- if (usbprog_jtag_handle == 0) {
- LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
- return ERROR_JTAG_INIT_FAILED;
- }
-
- LOG_INFO("USB JTAG Interface ready!");
-
- usbprog_jtag_init(usbprog_jtag_handle);
- usbprog_reset(0, 0);
- usbprog_write(0, 0, 0);
-
- return ERROR_OK;
-}
-
-static int usbprog_quit(void)
-{
- return ERROR_OK;
-}
-
-/*************** jtag execute commands **********************/
-static void usbprog_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-static void usbprog_state_move(void)
-{
- uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
-
- usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);
-
- tap_set_state(tap_get_end_state());
-}
-
-static void usbprog_path_move(struct pathmove_command *cmd)
-{
- int num_states = cmd->num_states;
- int state_count;
-
- /* There may be queued transitions, and before following a specified
- path, we must flush those queued transitions */
- usbprog_jtag_tms_send(usbprog_jtag_handle);
-
- state_count = 0;
- while (num_states) {
- if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) {
- /* LOG_INFO("1"); */
- usbprog_write(0, 0, 0);
- usbprog_write(1, 0, 0);
- } else if (tap_state_transition(tap_get_state(),
- true) == cmd->path[state_count]) {
- /* LOG_INFO("2"); */
- usbprog_write(0, 1, 0);
- usbprog_write(1, 1, 0);
- } else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(tap_get_state()),
- tap_state_name(cmd->path[state_count]));
- exit(-1);
- }
-
- tap_set_state(cmd->path[state_count]);
- state_count++;
- num_states--;
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void usbprog_runtest(int num_cycles)
-{
- int i;
-
- /* only do a state_move when we're not already in IDLE */
- if (tap_get_state() != TAP_IDLE) {
- usbprog_end_state(TAP_IDLE);
- usbprog_state_move();
- }
-
- /* execute num_cycles */
- if (num_cycles > 0) {
- usbprog_jtag_tms_send(usbprog_jtag_handle);
- usbprog_write(0, 0, 0);
- } else {
- usbprog_jtag_tms_send(usbprog_jtag_handle);
- /* LOG_INFO("NUM CYCLES %i",num_cycles); */
- }
-
- for (i = 0; i < num_cycles; i++) {
- usbprog_write(1, 0, 0);
- usbprog_write(0, 0, 0);
- }
-
-#ifdef _DEBUG_JTAG_IO_
- LOG_DEBUG("runtest: cur_state %s end_state %s", tap_state_name(
- tap_get_state()), tap_state_name(tap_get_end_state()));
-#endif
-
- /* finish in end_state */
- /*
- usbprog_end_state(saved_end_state);
- if (tap_get_state() != tap_get_end_state())
- usbprog_state_move();
- */
-}
-
-static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
-{
- tap_state_t saved_end_state = tap_get_end_state();
-
- if (ir_scan)
- usbprog_end_state(TAP_IRSHIFT);
- else
- usbprog_end_state(TAP_DRSHIFT);
-
- /* Only move if we're not already there */
- if (tap_get_state() != tap_get_end_state())
- usbprog_state_move();
-
- usbprog_end_state(saved_end_state);
-
- usbprog_jtag_tms_send(usbprog_jtag_handle);
-
- void (*f)(struct usbprog_jtag *usbprog_jtag, char *buffer_local, int size);
- switch (type) {
- case SCAN_OUT:
- f = &usbprog_jtag_write_tdi;
- break;
- case SCAN_IN:
- f = &usbprog_jtag_read_tdo;
- break;
- case SCAN_IO:
- f = &usbprog_jtag_write_and_read;
- break;
- default:
- LOG_ERROR("unknown scan type: %i", type);
- exit(-1);
- }
- f(usbprog_jtag_handle, (char *)buffer, scan_size);
-
- /* The adapter does the transition to PAUSE internally */
- if (ir_scan)
- tap_set_state(TAP_IRPAUSE);
- else
- tap_set_state(TAP_DRPAUSE);
-
- if (tap_get_state() != tap_get_end_state())
- usbprog_state_move();
-}
-
-/*************** jtag wrapper functions *********************/
-
-static void usbprog_write(int tck, int tms, int tdi)
-{
- unsigned char output_value = 0x00;
-
- if (tms)
- output_value |= (1 << TMS_BIT);
- if (tdi)
- output_value |= (1 << TDI_BIT);
- if (tck)
- output_value |= (1 << TCK_BIT);
-
- usbprog_jtag_write_slice(usbprog_jtag_handle, output_value);
-}
-
-/* (1) assert or (0) deassert reset lines */
-static void usbprog_reset(int trst, int srst)
-{
- LOG_DEBUG("trst: %i, srst: %i", trst, srst);
-
- if (trst)
- usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);
- else
- usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);
-
- if (srst)
- usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);
- else
- usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);
-}
-
-/*************** jtag lowlevel functions ********************/
-
-struct usb_bus *busses;
-
-struct usbprog_jtag *usbprog_jtag_open(void)
-{
- usb_set_debug(10);
- usb_init();
-
- const uint16_t vids[] = { VID, 0 };
- const uint16_t pids[] = { PID, 0 };
- struct usb_dev_handle *dev;
- if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
- return NULL;
-
- struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));
- tmp->usb_handle = dev;
-
- usb_set_configuration(dev, 1);
- usb_claim_interface(dev, 0);
- usb_set_altinterface(dev, 0);
-
- return tmp;
-}
-
-#if 0
-static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
-{
- usb_close(usbprog_jtag->usb_handle);
- free(usbprog_jtag);
-}
-#endif
-
-static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
-{
- int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg, msglen, 100);
- if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \
- (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
- return 1;
- if (res == msglen) {
- /* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */
- res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);
- if (res > 0)
- return (unsigned char)msg[1];
- else
- return -1;
- } else
- return -1;
- return 0;
-}
-
-static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)
-{
- usbprog_jtag_set_direction(usbprog_jtag, 0xFE);
-}
-
-static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char *buffer, int size)
-{
- char tmp[64]; /* fastes packet size for usb controller */
- int send_bits, bufindex = 0, fillindex = 0, i, loops;
-
- char swap;
- /* 61 byte can be transfered (488 bit) */
-
- while (size > 0) {
- if (size > 488) {
- send_bits = 488;
- size = size - 488;
- loops = 61;
- } else {
- send_bits = size;
- loops = size / 8;
- loops++;
- size = 0;
- }
- tmp[0] = WRITE_AND_READ;
- tmp[1] = (char)(send_bits >> 8); /* high */
- tmp[2] = (char)(send_bits); /* low */
-
- for (i = 0; i < loops; i++) {
- tmp[3 + i] = buffer[bufindex];
- bufindex++;
- }
-
- if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64) {
- /* LOG_INFO("HALLLLOOO2 %i",(int)tmp[0]); */
- usleep(1);
- int timeout = 0;
- while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1) {
- timeout++;
- if (timeout > 10)
- break;
- }
-
- for (i = 0; i < loops; i++) {
- swap = tmp[3 + i];
- buffer[fillindex++] = swap;
- }
- }
- }
-}
-
-static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char *buffer, int size)
-{
- char tmp[64]; /* fastes packet size for usb controller */
- int send_bits, fillindex = 0, i, loops;
-
- char swap;
- /* 61 byte can be transfered (488 bit) */
-
- while (size > 0) {
- if (size > 488) {
- send_bits = 488;
- size = size - 488;
- loops = 61;
- } else {
- send_bits = size;
- loops = size / 8;
- loops++;
- size = 0;
- }
- tmp[0] = WRITE_AND_READ;
- tmp[1] = (char)(send_bits >> 8); /* high */
- tmp[2] = (char)(send_bits); /* low */
-
- usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);
-
- /* LOG_INFO("HALLLLOOO3 %i",(int)tmp[0]); */
- int timeout = 0;
- usleep(1);
- while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1) {
- timeout++;
- if (timeout > 10)
- break;
- }
-
- for (i = 0; i < loops; i++) {
- swap = tmp[3 + i];
- buffer[fillindex++] = swap;
- }
- }
-}
-
-static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char *buffer, int size)
-{
- char tmp[64]; /* fastes packet size for usb controller */
- int send_bits, bufindex = 0, i, loops;
-
- /* 61 byte can be transfered (488 bit) */
- while (size > 0) {
- if (size > 488) {
- send_bits = 488;
- size = size - 488;
- loops = 61;
- } else {
- send_bits = size;
- loops = size/8;
- /* if (loops == 0) */
- loops++;
- size = 0;
- }
- tmp[0] = WRITE_TDI;
- tmp[1] = (char)(send_bits >> 8); /* high */
- tmp[2] = (char)(send_bits); /* low */
-
- for (i = 0; i < loops; i++) {
- tmp[3 + i] = buffer[bufindex];
- bufindex++;
- }
- usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);
- }
-}
-
-static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)
-{
- usbprog_jtag_tms_collect(tms_scan);
-}
-
-static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)
-{
- char tmp[2];
- tmp[0] = PORT_DIRECTION;
- tmp[1] = (char)direction;
- usbprog_jtag_message(usbprog_jtag, tmp, 2);
-}
-
-static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag, unsigned char value)
-{
- char tmp[2];
- tmp[0] = PORT_SET;
- tmp[1] = (char)value;
- usbprog_jtag_message(usbprog_jtag, tmp, 2);
-}
-
-#if 0
-static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)
-{
- char tmp[2];
- tmp[0] = PORT_GET;
- tmp[1] = 0x00;
- return usbprog_jtag_message(usbprog_jtag, tmp, 2);
-}
-#endif
-
-static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag, int bit, int value)
-{
- char tmp[3];
- tmp[0] = PORT_SETBIT;
- tmp[1] = (char)bit;
- if (value == 1)
- tmp[2] = 0x01;
- else
- tmp[2] = 0x00;
- usbprog_jtag_message(usbprog_jtag, tmp, 3);
-}
-
-#if 0
-static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)
-{
- char tmp[2];
- tmp[0] = PORT_GETBIT;
- tmp[1] = (char)bit;
-
- if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)
- return 1;
- else
- return 0;
-}
-#endif
-
-static void usbprog_jtag_tms_collect(char tms_scan)
-{
- tms_chain[tms_chain_index] = tms_scan;
- tms_chain_index++;
-}
-
-static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
-{
- int i;
- /* LOG_INFO("TMS SEND"); */
- if (tms_chain_index > 0) {
- char tmp[tms_chain_index + 2];
- tmp[0] = WRITE_TMS_CHAIN;
- tmp[1] = (char)(tms_chain_index);
- for (i = 0; i < tms_chain_index + 1; i++)
- tmp[2 + i] = tms_chain[i];
- usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);
- tms_chain_index = 0;
- }
-}
-
-struct jtag_interface usbprog_interface = {
- .name = "usbprog",
-
- .execute_queue = usbprog_execute_queue,
- .init = usbprog_init,
- .quit = usbprog_quit
-};
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c
deleted file mode 100644
index 0d60725..0000000
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "../versaloon_include.h"
-#include "../versaloon.h"
-#include "../versaloon_internal.h"
-#include "usbtoxxx.h"
-#include "usbtoxxx_internal.h"
-
-RESULT usbtogpio_init(uint8_t interface_index)
-{
- return usbtoxxx_init_command(USB_TO_GPIO, interface_index);
-}
-
-RESULT usbtogpio_fini(uint8_t interface_index)
-{
- return usbtoxxx_fini_command(USB_TO_GPIO, interface_index);
-}
-
-RESULT usbtogpio_config(uint8_t interface_index, uint32_t mask,
- uint32_t dir_mask, uint32_t pull_en_mask,
- uint32_t input_pull_mask)
-{
- uint8_t conf[8];
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- dir_mask &= mask;
- SET_LE_U16(&conf[0], mask);
- SET_LE_U16(&conf[2], dir_mask);
- SET_LE_U16(&conf[4], pull_en_mask);
- SET_LE_U16(&conf[6], input_pull_mask);
-
- return usbtoxxx_conf_command(USB_TO_GPIO, interface_index, conf,
- sizeof(conf));
-}
-
-RESULT usbtogpio_in(uint8_t interface_index, uint32_t mask, uint32_t *value)
-{
- uint8_t buf[2];
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- SET_LE_U16(&buf[0], mask);
-
- return usbtoxxx_in_command(USB_TO_GPIO, interface_index, buf, 2, 2,
- (uint8_t *)value, 0, 2, 0);
-}
-
-RESULT usbtogpio_out(uint8_t interface_index, uint32_t mask, uint32_t value)
-{
- uint8_t buf[4];
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- SET_LE_U16(&buf[0], mask);
- SET_LE_U16(&buf[2], value);
-
- return usbtoxxx_out_command(USB_TO_GPIO, interface_index, buf, 4, 0);
-}
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c
deleted file mode 100644
index f2ea175..0000000
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "../versaloon_include.h"
-#include "../versaloon.h"
-#include "../versaloon_internal.h"
-#include "usbtoxxx.h"
-#include "usbtoxxx_internal.h"
-
-RESULT usbtojtagraw_init(uint8_t interface_index)
-{
- return usbtoxxx_init_command(USB_TO_JTAG_RAW, interface_index);
-}
-
-RESULT usbtojtagraw_fini(uint8_t interface_index)
-{
- return usbtoxxx_fini_command(USB_TO_JTAG_RAW, interface_index);
-}
-
-RESULT usbtojtagraw_config(uint8_t interface_index, uint32_t kHz)
-{
- uint8_t cfg_buf[4];
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- SET_LE_U32(&cfg_buf[0], kHz);
-
- return usbtoxxx_conf_command(USB_TO_JTAG_RAW, interface_index, cfg_buf, 4);
-}
-
-RESULT usbtojtagraw_execute(uint8_t interface_index, uint8_t *tdi,
- uint8_t *tms, uint8_t *tdo, uint32_t bitlen)
-{
- uint16_t bytelen;
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- if (bitlen > 8 * 0xFFFF)
- return ERROR_FAIL;
- bytelen = (uint16_t)((bitlen + 7) >> 3);
-
- SET_LE_U32(&versaloon_cmd_buf[0], bitlen);
- memcpy(versaloon_cmd_buf + 4, tdi, bytelen);
- memcpy(versaloon_cmd_buf + 4 + bytelen, tms, bytelen);
-
- return usbtoxxx_inout_command(USB_TO_JTAG_RAW, interface_index,
- versaloon_cmd_buf, 4 + bytelen * 2, bytelen, tdo, 0, bytelen, 0);
-}
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c
deleted file mode 100644
index 16433af..0000000
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "../versaloon_include.h"
-#include "../versaloon.h"
-#include "../versaloon_internal.h"
-#include "usbtoxxx.h"
-#include "usbtoxxx_internal.h"
-
-RESULT usbtopwr_init(uint8_t interface_index)
-{
- return usbtoxxx_init_command(USB_TO_POWER, interface_index);
-}
-
-RESULT usbtopwr_fini(uint8_t interface_index)
-{
- return usbtoxxx_fini_command(USB_TO_POWER, interface_index);
-}
-
-RESULT usbtopwr_config(uint8_t interface_index)
-{
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- return usbtoxxx_conf_command(USB_TO_POWER, interface_index, NULL, 0);
-}
-
-RESULT usbtopwr_output(uint8_t interface_index, uint16_t mV)
-{
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- return usbtoxxx_out_command(USB_TO_POWER, interface_index, (uint8_t *)&mV,
- 2, 0);
-}
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c
deleted file mode 100644
index ef1b675..0000000
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "../versaloon_include.h"
-#include "../versaloon.h"
-#include "../versaloon_internal.h"
-#include "usbtoxxx.h"
-#include "usbtoxxx_internal.h"
-
-RESULT usbtoswd_read_callback(void *p, uint8_t *src, uint8_t *processed)
-{
- struct versaloon_pending_t *pending = (struct versaloon_pending_t *)p;
-
- if (pending->extra_data != NULL)
- *((uint8_t *)pending->extra_data) = src[0];
-
- return ERROR_OK;
-}
-
-RESULT usbtoswd_write_callback(void *p, uint8_t *src, uint8_t *processed)
-{
- struct versaloon_pending_t *pending = (struct versaloon_pending_t *)p;
-
- if (pending->extra_data != NULL)
- *((uint8_t *)pending->extra_data) = src[0];
-
- /* mark it processed to ignore other input data */
- *processed = 1;
- return ERROR_OK;
-}
-
-RESULT usbtoswd_init(uint8_t interface_index)
-{
- return usbtoxxx_init_command(USB_TO_SWD, interface_index);
-}
-
-RESULT usbtoswd_fini(uint8_t interface_index)
-{
- return usbtoxxx_fini_command(USB_TO_SWD, interface_index);
-}
-
-RESULT usbtoswd_config(uint8_t interface_index, uint8_t trn, uint16_t retry,
- uint16_t dly)
-{
- uint8_t cfg_buf[5];
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- cfg_buf[0] = trn;
- SET_LE_U16(&cfg_buf[1], retry);
- SET_LE_U16(&cfg_buf[3], dly);
-
- return usbtoxxx_conf_command(USB_TO_SWD, interface_index, cfg_buf, 5);
-}
-
-RESULT usbtoswd_seqout(uint8_t interface_index, const uint8_t *data,
- uint16_t bitlen)
-{
- uint16_t bytelen = (bitlen + 7) >> 3;
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- SET_LE_U16(&versaloon_cmd_buf[0], bitlen);
- memcpy(versaloon_cmd_buf + 2, data, bytelen);
-
- return usbtoxxx_out_command(USB_TO_SWD, interface_index,
- versaloon_cmd_buf, bytelen + 2, 0);
-}
-
-RESULT usbtoswd_seqin(uint8_t interface_index, uint8_t *data, uint16_t bitlen)
-{
- uint16_t bytelen = (bitlen + 7) >> 3;
- uint8_t buff[2];
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- SET_LE_U16(&buff[0], bitlen);
-
- return usbtoxxx_in_command(USB_TO_SWD, interface_index, buff, 2, bytelen,
- data, 0, bytelen, 0);
-}
-
-RESULT usbtoswd_transact(uint8_t interface_index, uint8_t request,
- uint32_t *data, uint8_t *ack)
-{
- uint8_t parity;
- uint8_t buff[5];
-
-#if PARAM_CHECK
- if (interface_index > 7) {
- LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index);
- return ERROR_FAIL;
- }
-#endif
-
- parity = (request >> 1) & 1;
- parity += (request >> 2) & 1;
- parity += (request >> 3) & 1;
- parity += (request >> 4) & 1;
- parity &= 1;
- buff[0] = (request | 0x81 | (parity << 5)) & ~0x40;
- if (data != NULL)
- SET_LE_U32(&buff[1], *data);
- else
- memset(buff + 1, 0, 4);
-
- versaloon_set_extra_data(ack);
- if (request & 0x04) {
- /* read */
- versaloon_set_callback(usbtoswd_read_callback);
- } else {
- /* write */
- versaloon_set_callback(usbtoswd_write_callback);
- }
-
- /* Input buffer must be passed even for write operations. Otherwise
- * the callback function is not called and ack value is not set. */
- return usbtoxxx_inout_command(USB_TO_SWD, interface_index, buff, 5, 5,
- (uint8_t *)data, 1, 4, 0);
-}
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c
deleted file mode 100644
index 53a7e98..0000000
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "../versaloon_include.h"
-#include "../versaloon.h"
-#include "../versaloon_internal.h"
-#include "usbtoxxx.h"
-#include "usbtoxxx_internal.h"
-
-#define N_A "n/a"
-
-const char *types_name[96] = {
- "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm",
- "usbtoadc", "usbtodac",
- "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay",
- N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
- N_A, N_A, N_A, N_A, N_A, N_A, N_A,
- "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw",
- "usbtolpcicp", "usbtoswd", "usbtojtagraw",
- "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
- N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
- "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
- "usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A,
- N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall"
-};
-
-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]))]
-
-static uint8_t type_pre;
-static uint16_t usbtoxxx_buffer_index;
-static uint16_t usbtoxxx_current_cmd_index;
-static uint8_t *usbtoxxx_buffer;
-
-uint16_t collect_index;
-uint8_t collect_cmd;
-static uint8_t poll_nesting;
-
-struct usbtoxxx_context_t {
- uint8_t type_pre;
- uint8_t *usbtoxxx_buffer;
- uint16_t usbtoxxx_current_cmd_index;
- uint16_t usbtoxxx_buffer_index;
- uint16_t versaloon_pending_idx;
-};
-static struct usbtoxxx_context_t poll_context;
-
-static void usbtoxxx_save_context(struct usbtoxxx_context_t *c)
-{
- c->type_pre = type_pre;
- c->usbtoxxx_buffer = usbtoxxx_buffer;
- c->usbtoxxx_buffer_index = usbtoxxx_buffer_index;
- c->usbtoxxx_current_cmd_index = usbtoxxx_current_cmd_index;
- c->versaloon_pending_idx = versaloon_pending_idx;
-}
-
-static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c)
-{
- type_pre = c->type_pre;
- usbtoxxx_buffer = c->usbtoxxx_buffer;
- usbtoxxx_buffer_index = c->usbtoxxx_buffer_index;
- usbtoxxx_current_cmd_index = c->usbtoxxx_current_cmd_index;
- versaloon_pending_idx = c->versaloon_pending_idx;
-}
-
-RESULT usbtoxxx_validate_current_command_type(void)
-{
- if (type_pre > 0) {
- /* not the first command */
- if (NULL == usbtoxxx_buffer) {
- LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
- return ERRCODE_INVALID_BUFFER;
- }
-
- usbtoxxx_buffer[0] = type_pre;
- SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
-
- usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
- } else {
- /* first command */
- usbtoxxx_buffer_index = 3;
- }
-
- /* prepare for next command */
- usbtoxxx_current_cmd_index = 3;
- usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
-
- collect_index = 0;
- collect_cmd = 0;
-
- return ERROR_OK;
-}
-
-RESULT usbtoxxx_execute_command(void)
-{
- uint16_t i;
- uint16_t inlen;
- RESULT result = ERROR_OK;
-
- if (poll_nesting) {
- LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
- versaloon_free_want_pos();
- return ERROR_FAIL;
- }
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- versaloon_free_want_pos();
- return ERRCODE_FAILURE_OPERATION;
- }
- if (3 == usbtoxxx_buffer_index) {
- versaloon_free_want_pos();
- return ERROR_OK;
- }
-
- versaloon_buf[0] = USB_TO_ALL;
- SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
-
- if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen)) {
- versaloon_free_want_pos();
- return ERROR_FAIL;
- }
-
- /* process return data */
- usbtoxxx_buffer_index = 0;
- for (i = 0; i < versaloon_pending_idx; i++) {
- /* check result */
- if ((0 == i) || !((versaloon_pending[i].collect)
- && (versaloon_pending[i - 1].collect)
- && (versaloon_pending[i].cmd
- == versaloon_pending[i - 1].cmd))) {
- if (USB_TO_XXX_CMD_NOT_SUPPORT
- == versaloon_buf[usbtoxxx_buffer_index]) {
- LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
- usbtoxxx_get_type_name(versaloon_pending[i].type),
- "current dongle");
- result = ERROR_FAIL;
- break;
- } else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index]) {
- LOG_ERROR("%s command 0x%02x failed with 0x%02x",
- usbtoxxx_get_type_name(versaloon_pending[i].type),
- versaloon_pending[i].cmd,
- versaloon_buf[usbtoxxx_buffer_index]);
- result = ERROR_FAIL;
- break;
- }
- usbtoxxx_buffer_index++;
- }
-
- /* get result data */
- if (versaloon_pending[i].pos != NULL) {
- uint8_t processed = 0;
-
- if (versaloon_pending[i].callback != NULL) {
- versaloon_pending[i].callback(&versaloon_pending[i],
- versaloon_buf + usbtoxxx_buffer_index, &processed);
- }
- if (!processed) {
- struct versaloon_want_pos_t *tmp;
-
- tmp = versaloon_pending[i].pos;
- while (tmp != NULL) {
- if ((tmp->buff != NULL) && (tmp->size > 0)) {
- memcpy(tmp->buff,
- versaloon_buf + usbtoxxx_buffer_index
- + tmp->offset,
- tmp->size);
- }
- struct versaloon_want_pos_t *free_tmp;
- free_tmp = tmp;
- tmp = tmp->next;
- free(free_tmp);
- }
- versaloon_pending[i].pos = NULL;
- }
- } else if ((versaloon_pending[i].want_data_size > 0)
- && (versaloon_pending[i].data_buffer != NULL)) {
- uint8_t processed = 0;
-
- if (versaloon_pending[i].callback != NULL) {
- versaloon_pending[i].callback(&versaloon_pending[i],
- versaloon_buf + usbtoxxx_buffer_index, &processed);
- }
- if (!processed) {
- memcpy(versaloon_pending[i].data_buffer,
- versaloon_buf + usbtoxxx_buffer_index
- + versaloon_pending[i].want_data_pos,
- versaloon_pending[i].want_data_size);
- }
- }
- usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
- if (usbtoxxx_buffer_index > inlen) {
- LOG_BUG("%s command 0x%02x process error",
- usbtoxxx_get_type_name(versaloon_pending[i].type),
- versaloon_pending[i].cmd);
- result = ERROR_FAIL;
- break;
- }
- }
-
- /* data is not the right size */
- if (inlen != usbtoxxx_buffer_index) {
- LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
- result = ERROR_FAIL;
- }
-
- if (versaloon_pending_idx > 0)
- versaloon_pending_idx = 0;
- else {
- /* no receive data, avoid collision */
- sleep_ms(10);
- }
-
- type_pre = 0;
- collect_cmd = 0;
- collect_index = 0;
- versaloon_free_want_pos();
- return result;
-}
-
-RESULT usbtoxxx_init(void)
-{
- versaloon_pending_idx = 0;
-
- if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
- (ERROR_OK != usbtoxxx_execute_command()))
- return ERROR_FAIL;
- LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
- GET_LE_U32(&usbtoxxx_abilities[0]),
- GET_LE_U32(&usbtoxxx_abilities[4]),
- GET_LE_U32(&usbtoxxx_abilities[8]));
- return ERROR_OK;
-}
-
-RESULT usbtoxxx_fini(void)
-{
- usbtoxxx_buffer = NULL;
- type_pre = 0;
- return ERROR_OK;
-}
-
-bool usbtoxxx_interface_supported(uint8_t cmd)
-{
- if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
- (cmd > VERSALOON_USB_TO_XXX_CMD_END))
- return false;
-
- cmd -= VERSALOON_USB_TO_XXX_CMD_START;
- return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
-}
-
-RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
-{
- /* check free space, commit if not enough */
- if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
- >= versaloon_buf_size)
- || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) {
- struct usbtoxxx_context_t context_tmp;
- uint8_t poll_nesting_tmp = 0;
-
- memset(&context_tmp, 0, sizeof(context_tmp));
- if (poll_nesting) {
- if (0 == poll_context.type_pre) {
- LOG_BUG("USB_TO_POLL toooooo long");
- return ERROR_OK;
- }
-
- usbtoxxx_save_context(&context_tmp);
- usbtoxxx_pop_context(&poll_context);
- poll_nesting_tmp = poll_nesting;
- poll_nesting = 0;
- }
-
- if (usbtoxxx_execute_command() != ERROR_OK)
- return ERROR_FAIL;
-
- if (poll_nesting_tmp) {
- uint16_t newlen, oldlen;
-
- newlen = context_tmp.versaloon_pending_idx
- - poll_context.versaloon_pending_idx;
- memcpy(&versaloon_pending[0],
- &versaloon_pending[poll_context.versaloon_pending_idx],
- sizeof(versaloon_pending[0]) * newlen);
- context_tmp.versaloon_pending_idx = newlen;
- oldlen = poll_context.usbtoxxx_buffer_index
- + poll_context.usbtoxxx_current_cmd_index;
- newlen = context_tmp.usbtoxxx_buffer_index
- + context_tmp.usbtoxxx_current_cmd_index;
- memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
- oldlen -= 3;
- context_tmp.usbtoxxx_buffer -= oldlen;
- context_tmp.usbtoxxx_buffer_index -= oldlen;
- usbtoxxx_pop_context(&context_tmp);
- poll_nesting = poll_nesting_tmp;
- }
- }
- return ERROR_OK;
-}
-
-RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
- uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
- uint16_t wantpos, uint16_t wantlen, uint8_t collect)
-{
- uint16_t len_tmp;
-
- /* 3 more bytes by usbtoxxx_validate_current_command_type */
- /* 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) */
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6))
- return ERROR_FAIL;
-
- if ((type_pre != type) || (NULL == usbtoxxx_buffer)) {
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
- type_pre = type;
- }
-
- if ((0 == collect_index) || (collect_cmd != cmd)) {
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
-
- if (collect) {
- collect_index = usbtoxxx_current_cmd_index;
- collect_cmd = cmd;
- } else {
- collect_index = 0;
- collect_cmd = 0;
- }
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
- usbtoxxx_current_cmd_index += 2;
- } else {
- len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
- SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
- }
-
- if (cmdbuf != NULL) {
- memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
- usbtoxxx_current_cmd_index += cmdlen;
- }
-
- return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
- wantbuf, collect);
-}
-
-RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
-{
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
- return ERROR_FAIL;
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
- type_pre = USB_TO_INFO;
-
- return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
- USB_TO_XXX_ABILITIES_LEN, abilities, 0);
-}
-
-RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
-{
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
- return ERROR_FAIL;
- if (!poll_nesting)
- usbtoxxx_save_context(&poll_context);
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
- poll_nesting++;
- type_pre = USB_TO_POLL;
-
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
- usbtoxxx_current_cmd_index += 2;
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
- usbtoxxx_current_cmd_index += 2;
-
- return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
-}
-
-RESULT usbtopoll_end(void)
-{
- if (!poll_nesting) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
- return ERRCODE_FAILURE_OPERATION;
- }
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
- return ERROR_FAIL;
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
-
- poll_nesting--;
- type_pre = USB_TO_POLL;
-
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
-
- return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
-}
-
-RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
- uint32_t mask, uint32_t value)
-{
- uint8_t i;
-
- if (size > 4) {
- LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
- return ERRCODE_INVALID_PARAMETER;
- }
- if (!poll_nesting) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
- return ERRCODE_FAILURE_OPERATION;
- }
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
- return ERROR_FAIL;
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
-
- type_pre = USB_TO_POLL;
-
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
- usbtoxxx_current_cmd_index += 2;
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
- for (i = 0; i < size; i++)
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
- for (i = 0; i < size; i++)
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
-
- return ERROR_OK;
-}
-
-RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
- uint32_t mask, uint32_t value)
-{
- uint8_t i;
-
- if (size > 4) {
- LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
- return ERRCODE_INVALID_PARAMETER;
- }
- if (!poll_nesting) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
- return ERRCODE_FAILURE_OPERATION;
- }
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
- return ERROR_FAIL;
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
-
- type_pre = USB_TO_POLL;
-
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
- usbtoxxx_current_cmd_index += 2;
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
- for (i = 0; i < size; i++)
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
- for (i = 0; i < size; i++)
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
-
- return ERROR_OK;
-}
-
-RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
-{
- if (!poll_nesting) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
- return ERRCODE_FAILURE_OPERATION;
- }
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
- return ERROR_FAIL;
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
-
- type_pre = USB_TO_POLL;
-
- usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
- usbtoxxx_current_cmd_index += 2;
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
- usbtoxxx_current_cmd_index += 2;
- memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
- usbtoxxx_current_cmd_index += size;
-
- return ERROR_OK;
-}
-
-RESULT usbtodelay_delay(uint16_t dly)
-{
- if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
- return ERROR_FAIL;
-
- if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
- LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
- return ERRCODE_FAILURE_OPERATION;
- }
- type_pre = USB_TO_DELAY;
-
- SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
- usbtoxxx_current_cmd_index += 2;
-
- return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
-}
-
-RESULT usbtodelay_delayms(uint16_t ms)
-{
- return usbtodelay_delay(ms | 0x8000);
-}
-
-RESULT usbtodelay_delayus(uint16_t us)
-{
- return usbtodelay_delay(us & 0x7FFF);
-}
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h
deleted file mode 100644
index 98a056a..0000000
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_H
-#define OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_H
-
-RESULT usbtoxxx_init(void);
-RESULT usbtoxxx_fini(void);
-RESULT usbtoxxx_execute_command(void);
-
-#define USB_TO_XXX_ABILITIES_LEN 12
-extern uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
-bool usbtoxxx_interface_supported(uint8_t cmd);
-
-/* USB_TO_INFO */
-RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN]);
-
-/* USB_TO_DELAY */
-RESULT usbtodelay_delay(uint16_t dly);
-RESULT usbtodelay_delayms(uint16_t ms);
-RESULT usbtodelay_delayus(uint16_t us);
-
-/* USB_TO_USART */
-RESULT usbtousart_init(uint8_t interface_index);
-RESULT usbtousart_fini(uint8_t interface_index);
-RESULT usbtousart_config(uint8_t interface_index, uint32_t baudrate,
- uint8_t datalength, uint8_t mode);
-RESULT usbtousart_send(uint8_t interface_index, uint8_t *buf, uint16_t len);
-RESULT usbtousart_receive(uint8_t interface_index, uint8_t *buf, uint16_t len);
-RESULT usbtousart_status(uint8_t interface_index,
- struct usart_status_t *status);
-
-/* USB_TO_SPI */
-RESULT usbtospi_init(uint8_t interface_index);
-RESULT usbtospi_fini(uint8_t interface_index);
-RESULT usbtospi_config(uint8_t interface_index, uint32_t kHz, uint8_t mode);
-RESULT usbtospi_io(uint8_t interface_index, uint8_t *out, uint8_t *in,
- uint16_t bytelen);
-
-/* USB_TO_GPIO */
-RESULT usbtogpio_init(uint8_t interface_index);
-RESULT usbtogpio_fini(uint8_t interface_index);
-RESULT usbtogpio_config(uint8_t interface_index, uint32_t mask,
- uint32_t dir_mask, uint32_t pull_en_mask,
- uint32_t input_pull_mask);
-RESULT usbtogpio_in(uint8_t interface_index, uint32_t mask, uint32_t *value);
-RESULT usbtogpio_out(uint8_t interface_index, uint32_t mask, uint32_t value);
-
-/* USB_TO_ISSP */
-RESULT usbtoissp_init(uint8_t interface_index);
-RESULT usbtoissp_fini(uint8_t interface_index);
-RESULT usbtoissp_enter_program_mode(uint8_t interface_index, uint8_t mode);
-RESULT usbtoissp_leave_program_mode(uint8_t interface_index, uint8_t mode);
-RESULT usbtoissp_wait_and_poll(uint8_t interface_index);
-RESULT usbtoissp_vector(uint8_t interface_index, uint8_t operate, uint8_t addr,
- uint8_t data, uint8_t *buf);
-
-/* USB_TO_LPCICP */
-RESULT usbtolpcicp_init(uint8_t interface_index);
-RESULT usbtolpcicp_fini(uint8_t interface_index);
-RESULT usbtolpcicp_config(uint8_t interface_index);
-RESULT usbtolpcicp_enter_program_mode(uint8_t interface_index);
-RESULT usbtolpcicp_in(uint8_t interface_index, uint8_t *buff, uint16_t len);
-RESULT usbtolpcicp_out(uint8_t interface_index, uint8_t *buff, uint16_t len);
-RESULT usbtolpcicp_poll_ready(uint8_t interface_index, uint8_t data,
- uint8_t *ret, uint8_t setmask, uint8_t clearmask, uint16_t pollcnt);
-
-/* USB_TO_JTAG_LL */
-RESULT usbtojtagll_init(uint8_t interface_index);
-RESULT usbtojtagll_fini(uint8_t interface_index);
-RESULT usbtojtagll_config(uint8_t interface_index, uint32_t kHz);
-RESULT usbtojtagll_tms(uint8_t interface_index, uint8_t *tms, uint8_t bytelen);
-RESULT usbtojtagll_tms_clocks(uint8_t interface_index, uint32_t bytelen,
- uint8_t tms);
-RESULT usbtojtagll_scan(uint8_t interface_index, uint8_t *data,
- uint16_t bitlen, uint8_t tms_before_valid,
- uint8_t tms_before, uint8_t tms_after0,
- uint8_t tms_after1);
-
-/* USB_TO_JTAG_HL */
-RESULT usbtojtaghl_init(uint8_t interface_index);
-RESULT usbtojtaghl_fini(uint8_t interface_index);
-RESULT usbtojtaghl_config(uint8_t interface_index, uint32_t kHz, uint8_t ub,
- uint8_t ua, uint16_t bb, uint16_t ba);
-RESULT usbtojtaghl_ir(uint8_t interface_index, uint8_t *ir, uint16_t bitlen,
- uint8_t idle, uint8_t want_ret);
-RESULT usbtojtaghl_dr(uint8_t interface_index, uint8_t *dr, uint16_t bitlen,
- uint8_t idle, uint8_t want_ret);
-RESULT usbtojtaghl_tms(uint8_t interface_index, uint8_t *tms, uint16_t bitlen);
-RESULT usbtojtaghl_runtest(uint8_t interface_index, uint32_t cycles);
-RESULT usbtojtaghl_register_callback(uint8_t index, jtag_callback_t send_callback,
- jtag_callback_t receive_callback);
-
-/* USB_TO_JTAG_RAW */
-RESULT usbtojtagraw_init(uint8_t interface_index);
-RESULT usbtojtagraw_fini(uint8_t interface_index);
-RESULT usbtojtagraw_config(uint8_t interface_index, uint32_t kHz);
-RESULT usbtojtagraw_execute(uint8_t interface_index, uint8_t *tdi,
- uint8_t *tms, uint8_t *tdo, uint32_t bitlen);
-
-/* USB_TO_C2 */
-RESULT usbtoc2_init(uint8_t interface_index);
-RESULT usbtoc2_fini(uint8_t interface_index);
-RESULT usbtoc2_writeaddr(uint8_t interface_index, uint8_t addr);
-RESULT usbtoc2_readaddr(uint8_t interface_index, uint8_t *data);
-RESULT usbtoc2_writedata(uint8_t interface_index, uint8_t *buf, uint8_t len);
-RESULT usbtoc2_readdata(uint8_t interface_index, uint8_t *buf, uint8_t len);
-
-/* USB_TO_I2C */
-RESULT usbtoi2c_init(uint8_t interface_index);
-RESULT usbtoi2c_fini(uint8_t interface_index);
-RESULT usbtoi2c_config(uint8_t interface_index, uint16_t kHz,
- uint16_t byte_interval, uint16_t max_dly);
-RESULT usbtoi2c_read(uint8_t interface_index, uint16_t chip_addr,
- uint8_t *data, uint16_t data_len, uint8_t stop,
- bool nacklast);
-RESULT usbtoi2c_write(uint8_t interface_index, uint16_t chip_addr,
- uint8_t *data, uint16_t data_len, uint8_t stop);
-
-/* USB_TO_MSP430_JTAG */
-RESULT usbtomsp430jtag_init(uint8_t interface_index);
-RESULT usbtomsp430jtag_fini(uint8_t interface_index);
-RESULT usbtomsp430jtag_config(uint8_t interface_index, uint8_t has_test);
-RESULT usbtomsp430jtag_ir(uint8_t interface_index, uint8_t *ir,
- uint8_t want_ret);
-RESULT usbtomsp430jtag_dr(uint8_t interface_index, uint32_t *dr,
- uint8_t bitlen, uint8_t want_ret);
-RESULT usbtomsp430jtag_tclk(uint8_t interface_index, uint8_t value);
-RESULT usbtomsp430jtag_tclk_strobe(uint8_t interface_index, uint16_t cnt);
-RESULT usbtomsp430jtag_reset(uint8_t interface_index);
-RESULT usbtomsp430jtag_poll(uint8_t interface_index, uint32_t dr,
- uint32_t mask, uint32_t value, uint8_t len,
- uint16_t poll_cnt, uint8_t toggle_tclk);
-
-/* USB_TO_MSP430_SBW */
-RESULT usbtomsp430sbw_init(uint8_t interface_index);
-RESULT usbtomsp430sbw_fini(uint8_t interface_index);
-RESULT usbtomsp430sbw_config(uint8_t interface_index, uint8_t has_test);
-RESULT usbtomsp430sbw_ir(uint8_t interface_index, uint8_t *ir,
- uint8_t want_ret);
-RESULT usbtomsp430sbw_dr(uint8_t interface_index, uint32_t *dr,
- uint8_t bitlen, uint8_t want_ret);
-RESULT usbtomsp430sbw_tclk(uint8_t interface_index, uint8_t value);
-RESULT usbtomsp430sbw_tclk_strobe(uint8_t interface_index, uint16_t cnt);
-RESULT usbtomsp430sbw_reset(uint8_t interface_index);
-RESULT usbtomsp430sbw_poll(uint8_t interface_index, uint32_t dr, uint32_t mask,
- uint32_t value, uint8_t len, uint16_t poll_cnt,
- uint8_t toggle_tclk);
-
-/* USB_TO_POWER */
-RESULT usbtopwr_init(uint8_t interface_index);
-RESULT usbtopwr_fini(uint8_t interface_index);
-RESULT usbtopwr_config(uint8_t interface_index);
-RESULT usbtopwr_output(uint8_t interface_index, uint16_t mV);
-
-/* USB_TO_POLL */
-RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us);
-RESULT usbtopoll_end(void);
-RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
- uint32_t mask, uint32_t value);
-RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
- uint32_t mask, uint32_t value);
-RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff);
-
-/* USB_TO_SWD */
-RESULT usbtoswd_init(uint8_t interface_index);
-RESULT usbtoswd_fini(uint8_t interface_index);
-RESULT usbtoswd_config(uint8_t interface_index, uint8_t trn, uint16_t retry,
- uint16_t dly);
-RESULT usbtoswd_seqout(uint8_t interface_index, const uint8_t *data,
- uint16_t bitlen);
-RESULT usbtoswd_seqin(uint8_t interface_index, uint8_t *data, uint16_t bitlen);
-RESULT usbtoswd_transact(uint8_t interface_index, uint8_t request,
- uint32_t *data, uint8_t *ack);
-
-/* USB_TO_SWIM */
-RESULT usbtoswim_init(uint8_t interface_index);
-RESULT usbtoswim_fini(uint8_t interface_index);
-RESULT usbtoswim_config(uint8_t interface_index, uint8_t mHz, uint8_t cnt0,
- uint8_t cnt1);
-RESULT usbtoswim_srst(uint8_t interface_index);
-RESULT usbtoswim_wotf(uint8_t interface_index, uint8_t *data,
- uint16_t bytelen, uint32_t addr);
-RESULT usbtoswim_rotf(uint8_t interface_index, uint8_t *data,
- uint16_t bytelen, uint32_t addr);
-RESULT usbtoswim_sync(uint8_t interface_index, uint8_t mHz);
-RESULT usbtoswim_enable(uint8_t interface_index);
-
-/* USB_TO_BDM */
-RESULT usbtobdm_init(uint8_t interface_index);
-RESULT usbtobdm_fini(uint8_t interface_index);
-RESULT usbtobdm_sync(uint8_t interface_index, uint16_t *khz);
-RESULT usbtobdm_transact(uint8_t interface_index, uint8_t *out,
- uint8_t outlen, uint8_t *in, uint8_t inlen, uint8_t delay, uint8_t ack);
-
-/* USB_TO_DUSI */
-RESULT usbtodusi_init(uint8_t interface_index);
-RESULT usbtodusi_fini(uint8_t interface_index);
-RESULT usbtodusi_config(uint8_t interface_index, uint32_t kHz, uint8_t mode);
-RESULT usbtodusi_io(uint8_t interface_index, uint8_t *mo, uint8_t *mi,
- uint8_t *so, uint8_t *si, uint32_t bitlen);
-
-/* USB_TO_MICROWIRE */
-RESULT usbtomicrowire_init(uint8_t interface_index);
-RESULT usbtomicrowire_fini(uint8_t interface_index);
-RESULT usbtomicrowire_config(uint8_t interface_index, uint16_t kHz,
- uint8_t sel_polarity);
-RESULT usbtomicrowire_transport(uint8_t interface_index,
- uint32_t opcode, uint8_t opcode_bitlen,
- uint32_t addr, uint8_t addr_bitlen,
- uint32_t data, uint8_t data_bitlen,
- uint8_t *reply, uint8_t reply_bitlen);
-RESULT usbtomicrowire_poll(uint8_t interface_index, uint16_t interval_us,
- uint16_t retry_cnt);
-
-/* USB_TO_PWM */
-RESULT usbtopwm_init(uint8_t interface_index);
-RESULT usbtopwm_fini(uint8_t interface_index);
-RESULT usbtopwm_config(uint8_t interface_index, uint16_t kHz, uint8_t mode);
-RESULT usbtopwm_out(uint8_t interface_index, uint16_t count, uint16_t *rate);
-RESULT usbtopwm_in(uint8_t interface_index, uint16_t count, uint16_t *rate);
-
-#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_H */
diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h
deleted file mode 100644
index e40667e..0000000
--- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_INTERNAL_H
-#define OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_INTERNAL_H
-
-/* USB_TO_XXX USB Commands */
-/* Page0 */
-#define USB_TO_USART (VERSALOON_USB_TO_XXX_CMD_START + 0x00)
-#define USB_TO_SPI (VERSALOON_USB_TO_XXX_CMD_START + 0x01)
-#define USB_TO_I2C (VERSALOON_USB_TO_XXX_CMD_START + 0x02)
-#define USB_TO_GPIO (VERSALOON_USB_TO_XXX_CMD_START + 0x03)
-#define USB_TO_CAN (VERSALOON_USB_TO_XXX_CMD_START + 0x04)
-#define USB_TO_PWM (VERSALOON_USB_TO_XXX_CMD_START + 0x05)
-#define USB_TO_ADC (VERSALOON_USB_TO_XXX_CMD_START + 0x06)
-#define USB_TO_DAC (VERSALOON_USB_TO_XXX_CMD_START + 0x07)
-#define USB_TO_MICROWIRE (VERSALOON_USB_TO_XXX_CMD_START + 0x08)
-#define USB_TO_SWIM (VERSALOON_USB_TO_XXX_CMD_START + 0x09)
-#define USB_TO_DUSI (VERSALOON_USB_TO_XXX_CMD_START + 0x0A)
-/* Page1 */
-#define USB_TO_JTAG_LL (VERSALOON_USB_TO_XXX_CMD_START + 0x20)
-#define USB_TO_JTAG_HL (VERSALOON_USB_TO_XXX_CMD_START + 0x21)
-#define USB_TO_ISSP (VERSALOON_USB_TO_XXX_CMD_START + 0x22)
-#define USB_TO_C2 (VERSALOON_USB_TO_XXX_CMD_START + 0x23)
-#define USB_TO_SBW (VERSALOON_USB_TO_XXX_CMD_START + 0x24)
-#define USB_TO_LPCICP (VERSALOON_USB_TO_XXX_CMD_START + 0x25)
-#define USB_TO_SWD (VERSALOON_USB_TO_XXX_CMD_START + 0x26)
-#define USB_TO_JTAG_RAW (VERSALOON_USB_TO_XXX_CMD_START + 0x27)
-#define USB_TO_BDM (VERSALOON_USB_TO_XXX_CMD_START + 0x28)
-#define USB_TO_MSP430_JTAG (VERSALOON_USB_TO_XXX_CMD_START + 0x38)
-/* Page2 */
-#define USB_TO_POWER (VERSALOON_USB_TO_XXX_CMD_START + 0x40)
-#define USB_TO_DELAY (VERSALOON_USB_TO_XXX_CMD_START + 0x41)
-#define USB_TO_POLL (VERSALOON_USB_TO_XXX_CMD_START + 0x42)
-#define USB_TO_INFO (VERSALOON_USB_TO_XXX_CMD_START + 0x5E)
-#define USB_TO_ALL (VERSALOON_USB_TO_XXX_CMD_START + 0x5F)
-
-/* USB_TO_XXX Masks */
-#define USB_TO_XXX_CMDMASK 0xF8
-#define USB_TO_XXX_CMDSHIFT 3
-#define USB_TO_XXX_IDXMASK 0x07
-/* USB_TO_XXX Sub Commands */
-/* Common Sub Commands */
-#define USB_TO_XXX_INIT (0x00 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_FINI (0x01 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_CONFIG (0x02 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_GETHWINFO (0x03 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_STATUS (0X04 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_IN_OUT (0x05 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_IN (0x06 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_OUT (0x07 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_POLL (0x08 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_SPECIAL (0x09 << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_RESET (0x0A << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_SYNC (0x0B << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_ENABLE (0x0C << USB_TO_XXX_CMDSHIFT)
-#define USB_TO_XXX_DISABLE (0x0D << USB_TO_XXX_CMDSHIFT)
-/* USB_TO_POLL */
-#define USB_TO_POLL_START 0x00
-#define USB_TO_POLL_END 0x01
-#define USB_TO_POLL_CHECKOK 0x02
-#define USB_TO_POLL_CHECKFAIL 0x03
-#define USB_TO_POLL_VERIFYBUFF 0x04
-
-/* USB_TO_XXX Replys */
-#define USB_TO_XXX_OK 0x00
-#define USB_TO_XXX_FAILED 0x01
-#define USB_TO_XXX_TIME_OUT 0x02
-#define USB_TO_XXX_INVALID_INDEX 0x03
-#define USB_TO_XXX_INVALID_PARA 0x04
-#define USB_TO_XXX_INVALID_CMD 0x05
-#define USB_TO_XXX_CMD_NOT_SUPPORT 0x06
-
-/* USB_TO_XXX */
-RESULT usbtoxxx_add_pending(uint8_t type, uint8_t cmd, uint16_t
- actual_szie, uint16_t want_pos,
- uint16_t want_size, uint8_t *buffer);
-
-RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
- uint16_t cmdlen, uint16_t retlen,
- uint8_t *wantbuf, uint16_t wantpos,
- uint16_t wantlen, uint8_t collect);
-
-#define usbtoxxx_init_command(type, port) \
- usbtoxxx_add_command((type), (USB_TO_XXX_INIT | (port)), \
- NULL, 0, 0, NULL, 0, 0, 0)
-#define usbtoxxx_fini_command(type, port) \
- usbtoxxx_add_command((type), (USB_TO_XXX_FINI | (port)), \
- NULL, 0, 0, NULL, 0, 0, 0)
-#define usbtoxxx_conf_command(type, port, cmdbuf, cmdlen) \
- usbtoxxx_add_command((type), (USB_TO_XXX_CONFIG | (port)), \
- (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0)
-#define usbtoxxx_inout_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \
- wantpos, wantlen, c) \
- usbtoxxx_add_command((type), (USB_TO_XXX_IN_OUT | (port)), \
- (cmdbuf), (cmdlen), (retlen), (wantbuf), \
- (wantpos), (wantlen), (c))
-#define usbtoxxx_in_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \
- wantpos, wantlen, c) \
- usbtoxxx_add_command((type), (USB_TO_XXX_IN | (port)), (cmdbuf), \
- (cmdlen), (retlen), (wantbuf), (wantpos), \
- (wantlen), (c))
-#define usbtoxxx_out_command(type, port, cmdbuf, cmdlen, c) \
- usbtoxxx_add_command((type), (USB_TO_XXX_OUT | (port)), (cmdbuf), \
- (cmdlen), 0, NULL, 0, 0, (c))
-#define usbtoxxx_poll_command(type, port, cmdbuf, cmdlen, retbuf, retlen) \
- usbtoxxx_add_command((type), (USB_TO_XXX_POLL | (port)), (cmdbuf), \
- (cmdlen), (retlen), (retbuf), 0, (retlen), 0)
-#define usbtoxxx_status_command(type, port, retlen, wantbuf, wantpos, wantlen, c) \
- usbtoxxx_add_command((type), (USB_TO_XXX_STATUS | (port)), \
- NULL, 0, (retlen), (wantbuf), (wantpos), \
- (wantlen), (c))
-#define usbtoxxx_special_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \
- wantpos, wantlen, c) \
- usbtoxxx_add_command((type), (USB_TO_XXX_SPECIAL | (port)), \
- (cmdbuf), (cmdlen), retlen, wantbuf, \
- wantpos, wantlen, (c))
-#define usbtoxxx_reset_command(type, port, cmdbuf, cmdlen) \
- usbtoxxx_add_command((type), (USB_TO_XXX_RESET | (port)), \
- (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0)
-#define usbtoxxx_sync_command(type, port, cmdbuf, cmdlen, retlen, wantbuf) \
- usbtoxxx_add_command((type), (USB_TO_XXX_SYNC | (port)), \
- (cmdbuf), (cmdlen), (retlen), (wantbuf), 0, \
- (retlen), 0)
-#define usbtoxxx_enable_command(type, port, cmdbuf, cmdlen) \
- usbtoxxx_add_command((type), (USB_TO_XXX_ENABLE | (port)), \
- (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0)
-#define usbtoxxx_disable_command(type, port, cmdbuf, cmdlen) \
- usbtoxxx_add_command((type), (USB_TO_XXX_DISABLE | (port)), \
- (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0)
-
-/* USB_TO_SPI */
-#define USB_TO_SPI_BAUDRATE_MSK 0x1F
-#define USB_TO_SPI_CPOL_MSK 0x20
-#define USB_TO_SPI_CPHA_MSK 0x40
-#define USB_TO_SPI_MSB_FIRST 0x80
-
-/* USB_TO_DUSI */
-#define USB_TO_DUSI_BAUDRATE_MSK 0x1F
-#define USB_TO_DUSI_CPOL_MSK 0x20
-#define USB_TO_DUSI_CPHA_MSK 0x40
-#define USB_TO_DUSI_MSB_FIRST 0x80
-
-/* USB_TO_GPIO */
-#define USB_TO_GPIO_DIR_MSK 0x01
-
-#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_INTERNAL_H */
diff --git a/src/jtag/drivers/versaloon/versaloon.c b/src/jtag/drivers/versaloon/versaloon.c
deleted file mode 100644
index 1463839..0000000
--- a/src/jtag/drivers/versaloon/versaloon.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <libusb.h>
-
-#include "versaloon_include.h"
-#include "versaloon.h"
-#include "versaloon_internal.h"
-#include "usbtoxxx/usbtoxxx.h"
-
-uint8_t *versaloon_buf;
-uint8_t *versaloon_cmd_buf;
-uint16_t versaloon_buf_size;
-
-struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
-uint16_t versaloon_pending_idx;
-
-libusb_device_handle *versaloon_usb_device_handle;
-static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT;
-
-RESULT versaloon_init(void);
-RESULT versaloon_fini(void);
-RESULT versaloon_get_target_voltage(uint16_t *voltage);
-RESULT versaloon_set_target_voltage(uint16_t voltage);
-RESULT versaloon_delay_ms(uint16_t ms);
-RESULT versaloon_delay_us(uint16_t us);
-
-struct versaloon_interface_t versaloon_interface = {
- .init = versaloon_init,
- .fini = versaloon_fini,
- { /* adaptors */
- { /* target_voltage */
- .get = versaloon_get_target_voltage,
- .set = versaloon_set_target_voltage,
- },
- { /* gpio */
- .init = usbtogpio_init,
- .fini = usbtogpio_fini,
- .config = usbtogpio_config,
- .out = usbtogpio_out,
- .in = usbtogpio_in,
- },
- { /* delay */
- .delayms = versaloon_delay_ms,
- .delayus = versaloon_delay_us,
- },
- { /* swd */
- .init = usbtoswd_init,
- .fini = usbtoswd_fini,
- .config = usbtoswd_config,
- .seqout = usbtoswd_seqout,
- .seqin = usbtoswd_seqin,
- .transact = usbtoswd_transact,
- },
- { /* jtag_raw */
- .init = usbtojtagraw_init,
- .fini = usbtojtagraw_fini,
- .config = usbtojtagraw_config,
- .execute = usbtojtagraw_execute,
- },
- .peripheral_commit = usbtoxxx_execute_command,
- },
- { /* usb_setting */
- .vid = VERSALOON_VID,
- .pid = VERSALOON_PID,
- .ep_out = VERSALOON_OUTP,
- .ep_in = VERSALOON_INP,
- .interface = VERSALOON_IFACE,
- .serialstring = NULL,
- .buf_size = 256,
- }
-};
-
-/* programmer_cmd */
-static uint32_t versaloon_pending_id;
-static versaloon_callback_t versaloon_callback;
-static void *versaloon_extra_data;
-static struct versaloon_want_pos_t *versaloon_want_pos;
-
-void versaloon_set_pending_id(uint32_t id)
-{
- versaloon_pending_id = id;
-}
-void versaloon_set_callback(versaloon_callback_t callback)
-{
- versaloon_callback = callback;
-}
-void versaloon_set_extra_data(void *p)
-{
- versaloon_extra_data = p;
-}
-
-void versaloon_free_want_pos(void)
-{
- uint16_t i;
- struct versaloon_want_pos_t *tmp, *free_tmp;
-
- tmp = versaloon_want_pos;
- while (tmp != NULL) {
- free_tmp = tmp;
- tmp = tmp->next;
- free(free_tmp);
- }
- versaloon_want_pos = NULL;
-
- for (i = 0; i < dimof(versaloon_pending); i++) {
- tmp = versaloon_pending[i].pos;
- while (tmp != NULL) {
- free_tmp = tmp;
- tmp = tmp->next;
- free(free_tmp);
- }
- versaloon_pending[i].pos = NULL;
- }
-}
-
-RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff)
-{
- struct versaloon_want_pos_t *new_pos = NULL;
-
- new_pos = malloc(sizeof(*new_pos));
- if (NULL == new_pos) {
- LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
- return ERRCODE_NOT_ENOUGH_MEMORY;
- }
- new_pos->offset = offset;
- new_pos->size = size;
- new_pos->buff = buff;
- new_pos->next = NULL;
-
- if (NULL == versaloon_want_pos)
- versaloon_want_pos = new_pos;
- else {
- struct versaloon_want_pos_t *tmp = versaloon_want_pos;
-
- while (tmp->next != NULL)
- tmp = tmp->next;
- tmp->next = new_pos;
- }
-
- return ERROR_OK;
-}
-
-RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie,
- uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect)
-{
-#if PARAM_CHECK
- if (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER) {
- LOG_BUG(ERRMSG_INVALID_INDEX, versaloon_pending_idx,
- "versaloon pending data");
- return ERROR_FAIL;
- }
-#endif
-
- versaloon_pending[versaloon_pending_idx].type = type;
- versaloon_pending[versaloon_pending_idx].cmd = cmd;
- versaloon_pending[versaloon_pending_idx].actual_data_size = actual_szie;
- versaloon_pending[versaloon_pending_idx].want_data_pos = want_pos;
- versaloon_pending[versaloon_pending_idx].want_data_size = want_size;
- versaloon_pending[versaloon_pending_idx].data_buffer = buffer;
- versaloon_pending[versaloon_pending_idx].collect = collect;
- versaloon_pending[versaloon_pending_idx].id = versaloon_pending_id;
- versaloon_pending_id = 0;
- versaloon_pending[versaloon_pending_idx].extra_data = versaloon_extra_data;
- versaloon_extra_data = NULL;
- versaloon_pending[versaloon_pending_idx].callback = versaloon_callback;
- versaloon_callback = NULL;
- versaloon_pending[versaloon_pending_idx].pos = versaloon_want_pos;
- versaloon_want_pos = NULL;
- versaloon_pending_idx++;
-
- return ERROR_OK;
-}
-
-RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen)
-{
- int ret;
- int transferred;
-
-#if PARAM_CHECK
- if (NULL == versaloon_buf) {
- LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
- return ERRCODE_INVALID_BUFFER;
- }
- if ((0 == out_len) || (out_len > versaloon_interface.usb_setting.buf_size)) {
- LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
- return ERRCODE_INVALID_PARAMETER;
- }
-#endif
-
- ret = libusb_bulk_transfer(versaloon_usb_device_handle,
- versaloon_interface.usb_setting.ep_out,
- versaloon_buf, out_len, &transferred, versaloon_usb_to);
- if (0 != ret || transferred != out_len) {
- LOG_ERROR(ERRMSG_FAILURE_OPERATION, "send usb data");
- return ERRCODE_FAILURE_OPERATION;
- }
-
- if (inlen != NULL) {
- ret = libusb_bulk_transfer(versaloon_usb_device_handle,
- versaloon_interface.usb_setting.ep_in,
- versaloon_buf, versaloon_interface.usb_setting.buf_size,
- &transferred, versaloon_usb_to);
- if (0 == ret) {
- *inlen = (uint16_t)transferred;
- return ERROR_OK;
- } else {
- LOG_ERROR(ERRMSG_FAILURE_OPERATION, "receive usb data");
- return ERROR_FAIL;
- }
- } else
- return ERROR_OK;
-}
-
-#define VERSALOON_RETRY_CNT 10
-RESULT versaloon_init(void)
-{
- uint16_t ret = 0;
- uint8_t retry;
- uint32_t timeout_tmp;
-
- /* malloc temporary buffer */
- versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size);
- if (NULL == versaloon_buf) {
- LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
- return ERRCODE_NOT_ENOUGH_MEMORY;
- }
-
- /* connect to versaloon */
- timeout_tmp = versaloon_usb_to;
- /* not output error message when connectting */
- /* 100ms delay when connect */
- versaloon_usb_to = 100;
- for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++) {
- versaloon_buf[0] = VERSALOON_GET_INFO;
- if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3))
- break;
- }
- versaloon_usb_to = timeout_tmp;
- if (VERSALOON_RETRY_CNT == retry) {
- versaloon_fini();
- LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
- return ERRCODE_FAILURE_OPERATION;
- }
-
- versaloon_buf[ret] = 0;
- versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8);
- versaloon_interface.usb_setting.buf_size = versaloon_buf_size;
- LOG_INFO("%s", versaloon_buf + 2);
-
- /* free temporary buffer */
- free(versaloon_buf);
- versaloon_buf = NULL;
-
- versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size);
- if (NULL == versaloon_buf) {
- versaloon_fini();
- LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
- return ERRCODE_NOT_ENOUGH_MEMORY;
- }
- versaloon_cmd_buf = malloc(versaloon_interface.usb_setting.buf_size - 3);
- if (NULL == versaloon_cmd_buf) {
- versaloon_fini();
- LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
- return ERRCODE_NOT_ENOUGH_MEMORY;
- }
- if (ERROR_OK != usbtoxxx_init()) {
- LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx");
- return ERROR_FAIL;
- }
- return versaloon_get_target_voltage(&ret);
-}
-
-RESULT versaloon_fini(void)
-{
- if (versaloon_usb_device_handle != NULL) {
- usbtoxxx_fini();
- versaloon_free_want_pos();
-
- versaloon_usb_device_handle = NULL;
-
- if (versaloon_buf != NULL) {
- free(versaloon_buf);
- versaloon_buf = NULL;
- }
- if (versaloon_cmd_buf != NULL) {
- free(versaloon_cmd_buf);
- versaloon_cmd_buf = NULL;
- }
- }
-
- return ERROR_OK;
-}
-
-RESULT versaloon_set_target_voltage(uint16_t voltage)
-{
- usbtopwr_init(0);
- usbtopwr_config(0);
- usbtopwr_output(0, voltage);
- usbtopwr_fini(0);
-
- return usbtoxxx_execute_command();
-}
-
-RESULT versaloon_get_target_voltage(uint16_t *voltage)
-{
- uint16_t inlen;
-
-#if PARAM_CHECK
- if (NULL == versaloon_buf) {
- LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
- return ERRCODE_INVALID_BUFFER;
- }
- if (NULL == voltage) {
- LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
- return ERRCODE_INVALID_PARAMETER;
- }
-#endif
-
- versaloon_buf[0] = VERSALOON_GET_TVCC;
-
- if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2)) {
- LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
- return ERRCODE_FAILURE_OPERATION;
- } else {
- *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8);
- return ERROR_OK;
- }
-}
-
-RESULT versaloon_delay_ms(uint16_t ms)
-{
- return usbtodelay_delay(ms | 0x8000);
-}
-
-RESULT versaloon_delay_us(uint16_t us)
-{
- return usbtodelay_delay(us & 0x7FFF);
-}
diff --git a/src/jtag/drivers/versaloon/versaloon.h b/src/jtag/drivers/versaloon/versaloon.h
deleted file mode 100644
index 9d92bca..0000000
--- a/src/jtag/drivers/versaloon/versaloon.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H
-#define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H
-
-#include <libusb.h>
-
-struct usart_status_t {
- uint32_t tx_buff_avail;
- uint32_t tx_buff_size;
- uint32_t rx_buff_avail;
- uint32_t rx_buff_size;
-};
-
-#include "usbtoxxx/usbtoxxx.h"
-
-/* GPIO pins */
-#define GPIO_SRST (1 << 0)
-#define GPIO_TRST (1 << 1)
-#define GPIO_USR1 (1 << 2)
-#define GPIO_USR2 (1 << 3)
-#define GPIO_TCK (1 << 4)
-#define GPIO_TDO (1 << 5)
-#define GPIO_TDI (1 << 6)
-#define GPIO_RTCK (1 << 7)
-#define GPIO_TMS (1 << 8)
-
-struct interface_gpio_t {
- RESULT(*init)(uint8_t interface_index);
- RESULT(*fini)(uint8_t interface_index);
- RESULT(*config)(uint8_t interface_index, uint32_t pin_mask, uint32_t io,
- uint32_t pull_en_mask, uint32_t input_pull_mask);
- RESULT(*out)(uint8_t interface_index, uint32_t pin_mask, uint32_t value);
- RESULT(*in)(uint8_t interface_index, uint32_t pin_mask, uint32_t *value);
-};
-
-struct interface_delay_t {
- RESULT(*delayms)(uint16_t ms);
- RESULT(*delayus)(uint16_t us);
-};
-
-struct interface_swd_t {
- RESULT(*init)(uint8_t interface_index);
- RESULT(*fini)(uint8_t interface_index);
- RESULT(*config)(uint8_t interface_index, uint8_t trn, uint16_t retry,
- uint16_t dly);
- RESULT(*seqout)(uint8_t interface_index, const uint8_t *data,
- uint16_t bitlen);
- RESULT(*seqin)(uint8_t interface_index, uint8_t *data, uint16_t bitlen);
- RESULT(*transact)(uint8_t interface_index, uint8_t request,
- uint32_t *data, uint8_t *ack);
-};
-
-struct interface_jtag_raw_t {
- RESULT(*init)(uint8_t interface_index);
- RESULT(*fini)(uint8_t interface_index);
- RESULT(*config)(uint8_t interface_index, uint32_t kHz);
- RESULT(*execute)(uint8_t interface_index, uint8_t *tdi, uint8_t *tms,
- uint8_t *tdo, uint32_t bitlen);
-};
-
-struct interface_target_voltage_t {
- RESULT(*get)(uint16_t *voltage);
- RESULT(*set)(uint16_t voltage);
-};
-
-struct versaloon_adaptors_t {
- struct interface_target_voltage_t target_voltage;
- struct interface_gpio_t gpio;
- struct interface_delay_t delay;
- struct interface_swd_t swd;
- struct interface_jtag_raw_t jtag_raw;
- RESULT(*peripheral_commit)(void);
-};
-
-struct versaloon_usb_setting_t {
- uint16_t vid;
- uint16_t pid;
- uint8_t ep_out;
- uint8_t ep_in;
- uint8_t interface;
- char *serialstring;
-
- uint16_t buf_size;
-};
-
-struct versaloon_interface_t {
- RESULT(*init)(void);
- RESULT(*fini)(void);
- struct versaloon_adaptors_t adaptors;
- struct versaloon_usb_setting_t usb_setting;
-};
-
-extern struct versaloon_interface_t versaloon_interface;
-extern libusb_device_handle *versaloon_usb_device_handle;
-
-#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H */
diff --git a/src/jtag/drivers/versaloon/versaloon_include.h b/src/jtag/drivers/versaloon/versaloon_include.h
deleted file mode 100644
index 089056d..0000000
--- a/src/jtag/drivers/versaloon/versaloon_include.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H
-#define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H
-
-/* This file is used to include different header and macros */
-/* according to different platform */
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-
-#define PARAM_CHECK 1
-
-#define sleep_ms(ms) jtag_sleep((ms) * 1000)
-#define dimof(arr) (sizeof(arr) / sizeof((arr)[0]))
-#define TO_STR(name) #name
-
-#define RESULT int
-#define LOG_BUG LOG_ERROR
-
-/* Common error messages */
-#define ERRMSG_NOT_ENOUGH_MEMORY "Lack of memory."
-#define ERRCODE_NOT_ENOUGH_MEMORY ERROR_FAIL
-
-#define ERRMSG_INVALID_VALUE "%d is invalid for %s."
-#define ERRMSG_INVALID_INDEX "Index %d is invalid for %s."
-#define ERRMSG_INVALID_USAGE "Invalid usage of %s"
-#define ERRMSG_INVALID_TARGET "Invalid %s"
-#define ERRMSG_INVALID_PARAMETER "Invalid parameter of %s."
-#define ERRMSG_INVALID_INTERFACE_NUM "invalid inteface %d"
-#define ERRMSG_INVALID_BUFFER "Buffer %s is not valid."
-#define ERRCODE_INVALID_BUFFER ERROR_FAIL
-#define ERRCODE_INVALID_PARAMETER ERROR_FAIL
-
-#define ERRMSG_NOT_SUPPORT_BY "%s is not supported by %s."
-
-#define ERRMSG_FAILURE_OPERATION "Fail to %s."
-#define ERRMSG_FAILURE_OPERATION_MESSAGE "Fail to %s, %s"
-#define ERRCODE_FAILURE_OPERATION ERROR_FAIL
-
-#define GET_U16_MSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 8) | \
- ((*((uint8_t *)(p) + 1)) << 0))
-#define GET_U32_MSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 24) | \
- ((*((uint8_t *)(p) + 1)) << 16) | \
- ((*((uint8_t *)(p) + 2)) << 8) | \
- ((*((uint8_t *)(p) + 3)) << 0))
-#define GET_U16_LSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 0) | \
- ((*((uint8_t *)(p) + 1)) << 8))
-#define GET_U32_LSBFIRST(p) (((*((uint8_t *)(p) + 0)) << 0) | \
- ((*((uint8_t *)(p) + 1)) << 8) | \
- ((*((uint8_t *)(p) + 2)) << 16) | \
- ((*((uint8_t *)(p) + 3)) << 24))
-
-#define SET_U16_MSBFIRST(p, v) \
- do {\
- *((uint8_t *)(p) + 0) = (((uint16_t)(v)) >> 8) & 0xFF;\
- *((uint8_t *)(p) + 1) = (((uint16_t)(v)) >> 0) & 0xFF;\
- } while (0)
-#define SET_U32_MSBFIRST(p, v) \
- do {\
- *((uint8_t *)(p) + 0) = (((uint32_t)(v)) >> 24) & 0xFF;\
- *((uint8_t *)(p) + 1) = (((uint32_t)(v)) >> 16) & 0xFF;\
- *((uint8_t *)(p) + 2) = (((uint32_t)(v)) >> 8) & 0xFF;\
- *((uint8_t *)(p) + 3) = (((uint32_t)(v)) >> 0) & 0xFF;\
- } while (0)
-#define SET_U16_LSBFIRST(p, v) \
- do {\
- *((uint8_t *)(p) + 0) = (((uint16_t)(v)) >> 0) & 0xFF;\
- *((uint8_t *)(p) + 1) = (((uint16_t)(v)) >> 8) & 0xFF;\
- } while (0)
-#define SET_U32_LSBFIRST(p, v) \
- do {\
- *((uint8_t *)(p) + 0) = (((uint32_t)(v)) >> 0) & 0xFF;\
- *((uint8_t *)(p) + 1) = (((uint32_t)(v)) >> 8) & 0xFF;\
- *((uint8_t *)(p) + 2) = (((uint32_t)(v)) >> 16) & 0xFF;\
- *((uint8_t *)(p) + 3) = (((uint32_t)(v)) >> 24) & 0xFF;\
- } while (0)
-
-#define GET_LE_U16(p) GET_U16_LSBFIRST(p)
-#define GET_LE_U32(p) GET_U32_LSBFIRST(p)
-#define GET_BE_U16(p) GET_U16_MSBFIRST(p)
-#define GET_BE_U32(p) GET_U32_MSBFIRST(p)
-#define SET_LE_U16(p, v) SET_U16_LSBFIRST(p, v)
-#define SET_LE_U32(p, v) SET_U32_LSBFIRST(p, v)
-#define SET_BE_U16(p, v) SET_U16_MSBFIRST(p, v)
-#define SET_BE_U32(p, v) SET_U32_MSBFIRST(p, v)
-
-#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H */
diff --git a/src/jtag/drivers/versaloon/versaloon_internal.h b/src/jtag/drivers/versaloon/versaloon_internal.h
deleted file mode 100644
index 497b6b9..0000000
--- a/src/jtag/drivers/versaloon/versaloon_internal.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INTERNAL_H
-#define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INTERNAL_H
-
-#define VERSALOON_PRODUCTSTRING_INDEX 2
-#define VERSALOON_SERIALSTRING_INDEX 3
-
-#define VERSALOON_PRODUCTSTRING "Versaloon"
-
-#define VERSALOON_VID 0x0483
-#define VERSALOON_PID 0xA038
-#define VERSALOON_INP 0x82
-#define VERSALOON_OUTP 0x03
-#define VERSALOON_IFACE 0x00
-
-#define VERSALOON_FULL 1
-#define VERSALOON_MINI 2
-#define VERSALOON_NANO 3
-
-#define VERSALOON_TIMEOUT 5000
-#define VERSALOON_TIMEOUT_LONG 60000
-
-/* USB Commands */
-/* Common Commands */
-#define VERSALOON_COMMON_CMD_START 0x00
-#define VERSALOON_COMMON_CMD_END 0x0F
-
-#define VERSALOON_GET_INFO 0x00
-#define VERSALOON_GET_TVCC 0x01
-#define VERSALOON_GET_HARDWARE 0x02
-#define VERSALOON_GET_OFFLINE_SIZE 0x08
-#define VERSALOON_ERASE_OFFLINE_DATA 0x09
-#define VERSALOON_WRITE_OFFLINE_DATA 0x0A
-#define VERSALOON_GET_OFFLINE_CHECKSUM 0x0B
-#define VERSALOON_FW_UPDATE 0x0F
-#define VERSALOON_FW_UPDATE_KEY 0xAA
-
-/* MCU Command */
-#define VERSALOON_MCU_CMD_START 0x10
-#define VERSALOON_MCU_CMD_END 0x1F
-
-/* USB_TO_XXX Command */
-#define VERSALOON_USB_TO_XXX_CMD_START 0x20
-#define VERSALOON_USB_TO_XXX_CMD_END 0x7F
-
-/* VSLLink Command */
-#define VERSALOON_VSLLINK_CMD_START 0x80
-#define VERSALOON_VSLLINK_CMD_END 0xFF
-
-/* Mass-product */
-#define MP_OK 0x00
-#define MP_FAIL 0x01
-
-#define MP_ISSP 0x11
-
-/* pending struct */
-#define VERSALOON_MAX_PENDING_NUMBER 4096
-typedef RESULT(*versaloon_callback_t)(void *, uint8_t *, uint8_t *);
-struct versaloon_want_pos_t {
- uint16_t offset;
- uint16_t size;
- uint8_t *buff;
- struct versaloon_want_pos_t *next;
-};
-struct versaloon_pending_t {
- uint8_t type;
- uint8_t cmd;
- uint16_t want_data_pos;
- uint16_t want_data_size;
- uint16_t actual_data_size;
- uint8_t *data_buffer;
- uint8_t collect;
- uint32_t id;
- struct versaloon_want_pos_t *pos;
- void *extra_data;
- versaloon_callback_t callback;
-};
-extern struct versaloon_pending_t \
- versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
-extern uint16_t versaloon_pending_idx;
-void versaloon_set_pending_id(uint32_t id);
-void versaloon_set_callback(versaloon_callback_t callback);
-void versaloon_set_extra_data(void *p);
-RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff);
-RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie,
- uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect);
-void versaloon_free_want_pos(void);
-
-RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen);
-extern uint8_t *versaloon_buf;
-extern uint8_t *versaloon_cmd_buf;
-extern uint16_t versaloon_buf_size;
-
-#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INTERNAL_H */
diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c
deleted file mode 100644
index 6f7e9ca..0000000
--- a/src/jtag/drivers/vsllink.c
+++ /dev/null
@@ -1,975 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Simon Qian <SimonQian@SimonQian.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* Versaloon is a programming tool for multiple MCUs.
- * It's distributed under GPLv3.
- * You can find it at http://www.Versaloon.com/.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/interface.h>
-#include <jtag/commands.h>
-#include <jtag/swd.h>
-#include <libusb.h>
-
-#include "versaloon/versaloon_include.h"
-#include "versaloon/versaloon.h"
-
-static int vsllink_tms_offset;
-
-struct pending_scan_result {
- int src_offset;
- int dest_offset;
- int length; /* Number of bits to read */
- struct scan_command *command; /* Corresponding scan command */
- uint8_t *ack;
- uint8_t *buffer;
- bool last; /* indicate the last scan pending */
-};
-
-#define MAX_PENDING_SCAN_RESULTS 256
-
-static int pending_scan_results_length;
-static struct pending_scan_result
- pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
-
-/* Queue command functions */
-static void vsllink_end_state(tap_state_t state);
-static void vsllink_state_move(void);
-static void vsllink_path_move(int num_states, tap_state_t *path);
-static void vsllink_tms(int num_bits, const uint8_t *bits);
-static void vsllink_runtest(int num_cycles);
-static void vsllink_stableclocks(int num_cycles, int tms);
-static void vsllink_scan(bool ir_scan, enum scan_type type,
- uint8_t *buffer, int scan_size, struct scan_command *command);
-static void vsllink_reset(int trst, int srst);
-
-/* VSLLink tap buffer functions */
-static void vsllink_tap_append_step(int tms, int tdi);
-static void vsllink_tap_init(void);
-static int vsllink_tap_execute(void);
-static void vsllink_tap_ensure_pending(int scans);
-static void vsllink_tap_append_scan(int length, uint8_t *buffer,
- struct scan_command *command);
-
-/* VSLLink SWD functions */
-static int_least32_t vsllink_swd_frequency(int_least32_t hz);
-static int vsllink_swd_switch_seq(enum swd_special_seq seq);
-
-/* VSLLink lowlevel functions */
-struct vsllink {
- struct libusb_context *libusb_ctx;
- struct libusb_device_handle *usb_device_handle;
-};
-
-static int vsllink_usb_open(struct vsllink *vsllink);
-static void vsllink_usb_close(struct vsllink *vsllink);
-
-#if defined _DEBUG_JTAG_IO_
-static void vsllink_debug_buffer(uint8_t *buffer, int length);
-#endif
-
-static int tap_length;
-static int tap_buffer_size;
-static uint8_t *tms_buffer;
-static uint8_t *tdi_buffer;
-static uint8_t *tdo_buffer;
-
-static bool swd_mode;
-
-static struct vsllink *vsllink_handle;
-
-static int vsllink_execute_queue(void)
-{
- struct jtag_command *cmd = jtag_command_queue;
- int scan_size;
- enum scan_type type;
- uint8_t *buffer;
-
- DEBUG_JTAG_IO("-------------------------------------"
- " vsllink "
- "-------------------------------------");
-
- while (cmd != NULL) {
- switch (cmd->type) {
- case JTAG_RUNTEST:
- DEBUG_JTAG_IO("runtest %i cycles, end in %s",
- cmd->cmd.runtest->num_cycles,
- tap_state_name(cmd->cmd.runtest->end_state));
-
- vsllink_end_state(cmd->cmd.runtest->end_state);
- vsllink_runtest(cmd->cmd.runtest->num_cycles);
- break;
-
- case JTAG_TLR_RESET:
- DEBUG_JTAG_IO("statemove end in %s",
- tap_state_name(cmd->cmd.statemove->end_state));
-
- vsllink_end_state(cmd->cmd.statemove->end_state);
- vsllink_state_move();
- break;
-
- case JTAG_PATHMOVE:
- DEBUG_JTAG_IO("pathmove: %i states, end in %s",
- cmd->cmd.pathmove->num_states,
- tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
-
- vsllink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
- break;
-
- case JTAG_SCAN:
- DEBUG_JTAG_IO("JTAG Scan...");
-
- vsllink_end_state(cmd->cmd.scan->end_state);
-
- scan_size = jtag_build_buffer(
- cmd->cmd.scan, &buffer);
-
- if (cmd->cmd.scan->ir_scan)
- DEBUG_JTAG_IO(
- "JTAG Scan write IR(%d bits), "
- "end in %s:",
- scan_size,
- tap_state_name(cmd->cmd.scan->end_state));
-
- else
- DEBUG_JTAG_IO(
- "JTAG Scan write DR(%d bits), "
- "end in %s:",
- scan_size,
- tap_state_name(cmd->cmd.scan->end_state));
-
-#ifdef _DEBUG_JTAG_IO_
- vsllink_debug_buffer(buffer,
- DIV_ROUND_UP(scan_size, 8));
-#endif
-
- type = jtag_scan_type(cmd->cmd.scan);
-
- vsllink_scan(cmd->cmd.scan->ir_scan,
- type, buffer, scan_size,
- cmd->cmd.scan);
- break;
-
- case JTAG_RESET:
- DEBUG_JTAG_IO("reset trst: %i srst %i",
- cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
-
- vsllink_tap_execute();
-
- if (cmd->cmd.reset->trst == 1)
- tap_set_state(TAP_RESET);
-
- vsllink_reset(cmd->cmd.reset->trst,
- cmd->cmd.reset->srst);
- break;
-
- case JTAG_SLEEP:
- DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us);
- vsllink_tap_execute();
- jtag_sleep(cmd->cmd.sleep->us);
- break;
-
- case JTAG_STABLECLOCKS:
- DEBUG_JTAG_IO("add %d clocks",
- cmd->cmd.stableclocks->num_cycles);
-
- switch (tap_get_state()) {
- case TAP_RESET:
- /* tms must be '1' to stay
- * n TAP_RESET mode
- */
- scan_size = 1;
- break;
- case TAP_DRSHIFT:
- case TAP_IDLE:
- case TAP_DRPAUSE:
- case TAP_IRSHIFT:
- case TAP_IRPAUSE:
- /* else, tms should be '0' */
- scan_size = 0;
- break;
- /* above stable states are OK */
- default:
- LOG_ERROR("jtag_add_clocks() "
- "in non-stable state \"%s\"",
- tap_state_name(tap_get_state())
- );
- exit(-1);
- }
- vsllink_stableclocks(cmd->cmd.stableclocks->num_cycles, scan_size);
- break;
-
- case JTAG_TMS:
- DEBUG_JTAG_IO("add %d jtag tms",
- cmd->cmd.tms->num_bits);
-
- vsllink_tms(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits);
- break;
-
- default:
- LOG_ERROR("BUG: unknown JTAG command type "
- "encountered: %d", cmd->type);
- exit(-1);
- }
- cmd = cmd->next;
- }
-
- return vsllink_tap_execute();
-}
-
-static int vsllink_speed(int speed)
-{
- if (swd_mode) {
- vsllink_swd_frequency(speed * 1000);
- return ERROR_OK;
- }
-
- versaloon_interface.adaptors.jtag_raw.config(0, (uint16_t)speed);
- return versaloon_interface.adaptors.peripheral_commit();
-}
-
-static int vsllink_khz(int khz, int *jtag_speed)
-{
- *jtag_speed = khz;
-
- return ERROR_OK;
-}
-
-static int vsllink_speed_div(int jtag_speed, int *khz)
-{
- *khz = jtag_speed;
-
- return ERROR_OK;
-}
-
-static void vsllink_free_buffer(void)
-{
- if (tdi_buffer != NULL) {
- free(tdi_buffer);
- tdi_buffer = NULL;
- }
- if (tdo_buffer != NULL) {
- free(tdo_buffer);
- tdo_buffer = NULL;
- }
- if (tms_buffer != NULL) {
- free(tms_buffer);
- tms_buffer = NULL;
- }
-}
-
-static int vsllink_quit(void)
-{
- versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST,
- 0, 0, GPIO_SRST | GPIO_TRST);
- versaloon_interface.adaptors.gpio.fini(0);
-
- if (swd_mode)
- versaloon_interface.adaptors.swd.fini(0);
- else
- versaloon_interface.adaptors.jtag_raw.fini(0);
-
- versaloon_interface.adaptors.peripheral_commit();
- versaloon_interface.fini();
-
- vsllink_free_buffer();
- vsllink_usb_close(vsllink_handle);
-
- free(vsllink_handle);
-
- return ERROR_OK;
-}
-
-static int vsllink_interface_init(void)
-{
- vsllink_handle = malloc(sizeof(struct vsllink));
- if (NULL == vsllink_handle) {
- LOG_ERROR("unable to allocate memory");
- return ERROR_FAIL;
- }
-
- libusb_init(&vsllink_handle->libusb_ctx);
-
- if (ERROR_OK != vsllink_usb_open(vsllink_handle)) {
- LOG_ERROR("Can't find USB JTAG Interface!" \
- "Please check connection and permissions.");
- return ERROR_JTAG_INIT_FAILED;
- }
- LOG_DEBUG("vsllink found on %04X:%04X",
- versaloon_interface.usb_setting.vid,
- versaloon_interface.usb_setting.pid);
- versaloon_usb_device_handle = vsllink_handle->usb_device_handle;
-
- if (ERROR_OK != versaloon_interface.init())
- return ERROR_FAIL;
- if (versaloon_interface.usb_setting.buf_size < 32) {
- versaloon_interface.fini();
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int vsllink_init(void)
-{
- int retval = vsllink_interface_init();
- if (ERROR_OK != retval)
- return retval;
-
- versaloon_interface.adaptors.gpio.init(0);
- versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, 0, GPIO_SRST,
- GPIO_SRST);
- versaloon_interface.adaptors.delay.delayms(100);
- versaloon_interface.adaptors.peripheral_commit();
-
- if (swd_mode) {
- versaloon_interface.adaptors.gpio.config(0, GPIO_TRST, 0,
- GPIO_TRST, GPIO_TRST);
- versaloon_interface.adaptors.swd.init(0);
- vsllink_swd_frequency(jtag_get_speed_khz() * 1000);
- vsllink_swd_switch_seq(JTAG_TO_SWD);
-
- } else {
- /* malloc buffer size for tap */
- tap_buffer_size = versaloon_interface.usb_setting.buf_size / 2 - 32;
- vsllink_free_buffer();
- tdi_buffer = malloc(tap_buffer_size);
- tdo_buffer = malloc(tap_buffer_size);
- tms_buffer = malloc(tap_buffer_size);
- if ((NULL == tdi_buffer) || (NULL == tdo_buffer) || (NULL == tms_buffer)) {
- vsllink_quit();
- return ERROR_FAIL;
- }
-
- versaloon_interface.adaptors.jtag_raw.init(0);
- versaloon_interface.adaptors.jtag_raw.config(0, jtag_get_speed_khz());
- versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST,
- GPIO_TRST, GPIO_SRST, GPIO_SRST);
- }
-
- if (ERROR_OK != versaloon_interface.adaptors.peripheral_commit())
- return ERROR_FAIL;
-
- vsllink_reset(0, 0);
- vsllink_tap_init();
- return ERROR_OK;
-}
-
-/**************************************************************************
- * Queue command implementations */
-
-static void vsllink_end_state(tap_state_t state)
-{
- if (tap_is_state_stable(state))
- tap_set_end_state(state);
- else {
- LOG_ERROR("BUG: %i is not a valid end state", state);
- exit(-1);
- }
-}
-
-/* Goes to the end state. */
-static void vsllink_state_move(void)
-{
- int i;
- uint8_t tms_scan = tap_get_tms_path(tap_get_state(),
- tap_get_end_state());
- uint8_t tms_scan_bits = tap_get_tms_path_len(tap_get_state(),
- tap_get_end_state());
-
- for (i = 0; i < tms_scan_bits; i++)
- vsllink_tap_append_step((tms_scan >> i) & 1, 0);
-
- tap_set_state(tap_get_end_state());
-}
-
-static void vsllink_path_move(int num_states, tap_state_t *path)
-{
- for (int i = 0; i < num_states; i++) {
- if (path[i] == tap_state_transition(tap_get_state(), false))
- vsllink_tap_append_step(0, 0);
- else if (path[i] == tap_state_transition(tap_get_state(), true))
- vsllink_tap_append_step(1, 0);
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(tap_get_state()),
- tap_state_name(path[i]));
- exit(-1);
- }
-
- tap_set_state(path[i]);
- }
-
- tap_set_end_state(tap_get_state());
-}
-
-static void vsllink_tms(int num_bits, const uint8_t *bits)
-{
- for (int i = 0; i < num_bits; i++)
- vsllink_tap_append_step((bits[i / 8] >> (i % 8)) & 1, 0);
-}
-
-static void vsllink_stableclocks(int num_cycles, int tms)
-{
- while (num_cycles > 0) {
- vsllink_tap_append_step(tms, 0);
- num_cycles--;
- }
-}
-
-static void vsllink_runtest(int num_cycles)
-{
- tap_state_t saved_end_state = tap_get_end_state();
-
- if (tap_get_state() != TAP_IDLE) {
- /* enter IDLE state */
- vsllink_end_state(TAP_IDLE);
- vsllink_state_move();
- }
-
- vsllink_stableclocks(num_cycles, 0);
-
- /* post-process */
- /* set end_state */
- vsllink_end_state(saved_end_state);
- if (tap_get_end_state() != tap_get_end_state())
- vsllink_state_move();
-}
-
-static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer,
- int scan_size, struct scan_command *command)
-{
- tap_state_t saved_end_state;
-
- saved_end_state = tap_get_end_state();
-
- /* Move to appropriate scan state */
- vsllink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
-
- if (tap_get_state() != tap_get_end_state())
- vsllink_state_move();
- vsllink_end_state(saved_end_state);
-
- /* Scan */
- vsllink_tap_append_scan(scan_size, buffer, command);
-
- /* Goto Pause and record position to insert tms:0 */
- vsllink_tap_append_step(0, 0);
- vsllink_tms_offset = tap_length;
-
- tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
-
- if (tap_get_state() != tap_get_end_state())
- vsllink_state_move();
-}
-
-static void vsllink_reset(int trst, int srst)
-{
- LOG_DEBUG("trst: %i, srst: %i", trst, srst);
-
- if (!srst)
- versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, 0, GPIO_SRST, GPIO_SRST);
- else
- versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, GPIO_SRST, 0, 0);
-
- if (!swd_mode) {
- if (!trst)
- versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, GPIO_TRST);
- else
- versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, 0);
- }
-
- versaloon_interface.adaptors.peripheral_commit();
-}
-
-COMMAND_HANDLER(vsllink_handle_usb_vid_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0],
- versaloon_interface.usb_setting.vid);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(vsllink_handle_usb_pid_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0],
- versaloon_interface.usb_setting.pid);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(vsllink_handle_usb_serial_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- free(versaloon_interface.usb_setting.serialstring);
-
- if (CMD_ARGC == 1)
- versaloon_interface.usb_setting.serialstring = strdup(CMD_ARGV[0]);
- else
- versaloon_interface.usb_setting.serialstring = NULL;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(vsllink_handle_usb_bulkin_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0],
- versaloon_interface.usb_setting.ep_in);
-
- versaloon_interface.usb_setting.ep_in |= 0x80;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(vsllink_handle_usb_bulkout_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0],
- versaloon_interface.usb_setting.ep_out);
-
- versaloon_interface.usb_setting.ep_out &= ~0x80;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(vsllink_handle_usb_interface_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0],
- versaloon_interface.usb_setting.interface);
- return ERROR_OK;
-}
-
-/**************************************************************************
- * VSLLink tap functions */
-
-static void vsllink_tap_init(void)
-{
- tap_length = 0;
- pending_scan_results_length = 0;
- vsllink_tms_offset = 0;
-}
-
-static void vsllink_tap_ensure_pending(int scans)
-{
- int available_scans =
- MAX_PENDING_SCAN_RESULTS - pending_scan_results_length;
-
- if (scans > available_scans)
- vsllink_tap_execute();
-}
-
-static void vsllink_tap_append_step(int tms, int tdi)
-{
- int index_var = tap_length / 8;
-
- int bit_index = tap_length % 8;
- uint8_t bit = 1 << bit_index;
-
- if (tms)
- tms_buffer[index_var] |= bit;
- else
- tms_buffer[index_var] &= ~bit;
-
- if (tdi)
- tdi_buffer[index_var] |= bit;
- else
- tdi_buffer[index_var] &= ~bit;
-
- tap_length++;
-
- if (tap_buffer_size * 8 <= tap_length)
- vsllink_tap_execute();
-}
-
-static void vsllink_tap_append_scan(int length, uint8_t *buffer,
- struct scan_command *command)
-{
- struct pending_scan_result *pending_scan_result;
- int len_tmp, len_all, i;
-
- len_all = 0;
- while (len_all < length) {
- vsllink_tap_ensure_pending(1);
- pending_scan_result =
- &pending_scan_results_buffer[
- pending_scan_results_length];
-
- if ((length - len_all) > (tap_buffer_size * 8 - tap_length)) {
- /* Use all memory available
- vsllink_tap_append_step will commit automatically */
- len_tmp = tap_buffer_size * 8 - tap_length;
- pending_scan_result->last = false;
- } else {
- len_tmp = length - len_all;
- pending_scan_result->last = true;
- }
- pending_scan_result->src_offset = tap_length;
- pending_scan_result->dest_offset = len_all;
- pending_scan_result->length = len_tmp;
- pending_scan_result->command = command;
- pending_scan_result->buffer = buffer;
- pending_scan_results_length++;
-
- for (i = 0; i < len_tmp; i++) {
- vsllink_tap_append_step(((len_all + i) < length-1
- ? 0 : 1),
- (buffer[(len_all + i)/8]
- >> ((len_all + i)%8)) & 1);
- }
-
- len_all += len_tmp;
- }
-}
-
-static int vsllink_jtag_execute(void)
-{
- int i;
- int result;
-
- if (tap_length <= 0)
- return ERROR_OK;
-
- versaloon_interface.adaptors.jtag_raw.execute(0, tdi_buffer, tms_buffer,
- tdo_buffer, tap_length);
-
- result = versaloon_interface.adaptors.peripheral_commit();
-
- if (result == ERROR_OK) {
- for (i = 0; i < pending_scan_results_length; i++) {
- struct pending_scan_result *pending_scan_result =
- &pending_scan_results_buffer[i];
- uint8_t *buffer = pending_scan_result->buffer;
- int length = pending_scan_result->length;
- int src_first = pending_scan_result->src_offset;
- int dest_first = pending_scan_result->dest_offset;
- bool last = pending_scan_result->last;
-
- struct scan_command *command;
-
- command = pending_scan_result->command;
- buf_set_buf(tdo_buffer, src_first, buffer, dest_first, length);
-
-#ifdef _DEBUG_JTAG_IO_
- DEBUG_JTAG_IO(
- "JTAG scan read(%d bits, from src %d bits to dest %d bits):",
- length, src_first, dest_first);
- vsllink_debug_buffer(buffer + dest_first / 8,
- DIV_ROUND_UP(length, 7));
-#endif
-
- if (last) {
- if (jtag_read_buffer(buffer, command)
- != ERROR_OK) {
- vsllink_tap_init();
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- if (pending_scan_result->buffer != NULL)
- free(pending_scan_result->buffer);
- }
- }
- } else {
- LOG_ERROR("vsllink_jtag_execute failure");
- return ERROR_JTAG_QUEUE_FAILED;
- }
-
- vsllink_tap_init();
-
- return ERROR_OK;
-}
-
-static int vsllink_tap_execute(void)
-{
- if (swd_mode)
- return ERROR_OK;
-
- return vsllink_jtag_execute();
-}
-
-static int vsllink_swd_init(void)
-{
- LOG_INFO("VSLLink SWD mode enabled");
- swd_mode = true;
-
- return ERROR_OK;
-}
-
-static int_least32_t vsllink_swd_frequency(int_least32_t hz)
-{
- const int_least32_t delay2hz[] = {
- 1850000, 235000, 130000, 102000, 85000, 72000
- };
-
- if (hz > 0) {
- uint16_t delay = UINT16_MAX;
-
- for (uint16_t i = 0; i < ARRAY_SIZE(delay2hz); i++) {
- if (hz >= delay2hz[i]) {
- hz = delay2hz[i];
- delay = i;
- break;
- }
- }
-
- if (delay == UINT16_MAX)
- delay = (500000 / hz) - 1;
-
- /* Calculate retry count after a WAIT response. This will give
- * a retry timeout at about ~250 ms. 54 is the number of bits
- * found in a transaction. */
- uint16_t retry_count = 250 * hz / 1000 / 54;
-
- LOG_DEBUG("SWD delay: %d, retry count: %d", delay, retry_count);
-
- versaloon_interface.adaptors.swd.config(0, 2, retry_count, delay);
- }
-
- return hz;
-}
-
-static int vsllink_swd_switch_seq(enum swd_special_seq seq)
-{
- switch (seq) {
- case LINE_RESET:
- LOG_DEBUG("SWD line reset");
- versaloon_interface.adaptors.swd.seqout(0, swd_seq_line_reset,
- swd_seq_line_reset_len);
- break;
- case JTAG_TO_SWD:
- LOG_DEBUG("JTAG-to-SWD");
- versaloon_interface.adaptors.swd.seqout(0, swd_seq_jtag_to_swd,
- swd_seq_jtag_to_swd_len);
- break;
- case SWD_TO_JTAG:
- LOG_DEBUG("SWD-to-JTAG");
- versaloon_interface.adaptors.swd.seqout(0, swd_seq_swd_to_jtag,
- swd_seq_swd_to_jtag_len);
- break;
- default:
- LOG_ERROR("Sequence %d not supported", seq);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static void vsllink_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
-{
- versaloon_interface.adaptors.swd.transact(0, cmd, value, NULL);
-}
-
-static void vsllink_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
-{
- versaloon_interface.adaptors.swd.transact(0, cmd, &value, NULL);
-}
-
-static int vsllink_swd_run_queue(void)
-{
- return versaloon_interface.adaptors.peripheral_commit();
-}
-
-/****************************************************************************
- * VSLLink USB low-level functions */
-
-static int vsllink_check_usb_strings(
- struct libusb_device_handle *usb_device_handle,
- struct libusb_device_descriptor *usb_desc)
-{
- char desc_string[256];
- int retval;
-
- if (NULL != versaloon_interface.usb_setting.serialstring) {
- retval = libusb_get_string_descriptor_ascii(usb_device_handle,
- usb_desc->iSerialNumber, (unsigned char *)desc_string,
- sizeof(desc_string));
- if (retval < 0)
- return ERROR_FAIL;
-
- if (strncmp(desc_string, versaloon_interface.usb_setting.serialstring,
- sizeof(desc_string)))
- return ERROR_FAIL;
- }
-
- retval = libusb_get_string_descriptor_ascii(usb_device_handle,
- usb_desc->iProduct, (unsigned char *)desc_string,
- sizeof(desc_string));
- if (retval < 0)
- return ERROR_FAIL;
-
- if (strstr(desc_string, "Versaloon") == NULL)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int vsllink_usb_open(struct vsllink *vsllink)
-{
- ssize_t num_devices, i;
- libusb_device **usb_devices;
- struct libusb_device_descriptor usb_desc;
- struct libusb_device_handle *usb_device_handle;
- int retval;
-
- num_devices = libusb_get_device_list(vsllink->libusb_ctx, &usb_devices);
-
- if (num_devices <= 0)
- return ERROR_FAIL;
-
- for (i = 0; i < num_devices; i++) {
- libusb_device *device = usb_devices[i];
-
- retval = libusb_get_device_descriptor(device, &usb_desc);
- if (retval != 0)
- continue;
-
- if (usb_desc.idVendor != versaloon_interface.usb_setting.vid ||
- usb_desc.idProduct != versaloon_interface.usb_setting.pid)
- continue;
-
- retval = libusb_open(device, &usb_device_handle);
- if (retval != 0)
- continue;
-
- retval = vsllink_check_usb_strings(usb_device_handle, &usb_desc);
- if (ERROR_OK == retval)
- break;
-
- libusb_close(usb_device_handle);
- }
-
- libusb_free_device_list(usb_devices, 1);
-
- if (i == num_devices)
- return ERROR_FAIL;
-
- retval = libusb_claim_interface(usb_device_handle,
- versaloon_interface.usb_setting.interface);
- if (retval != 0) {
- LOG_ERROR("unable to claim interface");
- libusb_close(usb_device_handle);
- return ERROR_FAIL;
- }
-
- vsllink->usb_device_handle = usb_device_handle;
- return ERROR_OK;
-}
-
-static void vsllink_usb_close(struct vsllink *vsllink)
-{
- libusb_release_interface(vsllink->usb_device_handle,
- versaloon_interface.usb_setting.interface);
- libusb_close(vsllink->usb_device_handle);
-}
-
-#define BYTES_PER_LINE 16
-
-#if defined _DEBUG_JTAG_IO_
-static void vsllink_debug_buffer(uint8_t *buffer, int length)
-{
- char line[81];
- char s[4];
- int i;
- int j;
-
- for (i = 0; i < length; i += BYTES_PER_LINE) {
- snprintf(line, 5, "%04x", i);
- for (j = i; j < i + BYTES_PER_LINE && j < length; j++) {
- snprintf(s, 4, " %02x", buffer[j]);
- strcat(line, s);
- }
- LOG_DEBUG("%s", line);
- }
-}
-#endif /* _DEBUG_JTAG_IO_ */
-
-static const struct command_registration vsllink_command_handlers[] = {
- {
- .name = "vsllink_usb_vid",
- .handler = &vsllink_handle_usb_vid_command,
- .mode = COMMAND_CONFIG,
- },
- {
- .name = "vsllink_usb_pid",
- .handler = &vsllink_handle_usb_pid_command,
- .mode = COMMAND_CONFIG,
- },
- {
- .name = "vsllink_usb_serial",
- .handler = &vsllink_handle_usb_serial_command,
- .mode = COMMAND_CONFIG,
- },
- {
- .name = "vsllink_usb_bulkin",
- .handler = &vsllink_handle_usb_bulkin_command,
- .mode = COMMAND_CONFIG,
- },
- {
- .name = "vsllink_usb_bulkout",
- .handler = &vsllink_handle_usb_bulkout_command,
- .mode = COMMAND_CONFIG,
- },
- {
- .name = "vsllink_usb_interface",
- .handler = &vsllink_handle_usb_interface_command,
- .mode = COMMAND_CONFIG,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const char * const vsllink_transports[] = {"jtag", "swd", NULL};
-
-static const struct swd_driver vsllink_swd_driver = {
- .init = vsllink_swd_init,
- .frequency = vsllink_swd_frequency,
- .switch_seq = vsllink_swd_switch_seq,
- .read_reg = vsllink_swd_read_reg,
- .write_reg = vsllink_swd_write_reg,
- .run = vsllink_swd_run_queue,
-};
-
-struct jtag_interface vsllink_interface = {
- .name = "vsllink",
- .supported = DEBUG_CAP_TMS_SEQ,
- .commands = vsllink_command_handlers,
- .transports = vsllink_transports,
- .swd = &vsllink_swd_driver,
-
- .init = vsllink_init,
- .quit = vsllink_quit,
- .khz = vsllink_khz,
- .speed = vsllink_speed,
- .speed_div = vsllink_speed_div,
- .execute_queue = vsllink_execute_queue,
-};
diff --git a/src/jtag/hla/Makefile.am b/src/jtag/hla/Makefile.am
deleted file mode 100644
index 4fbc70e..0000000
--- a/src/jtag/hla/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-include $(top_srcdir)/common.mk
-
-noinst_LTLIBRARIES = libocdhla.la
-
-libocdhla_la_SOURCES = \
- $(HLFILES)
-
-HLFILES =
-
-if HLADAPTER
-HLFILES += hla_transport.c
-HLFILES += hla_tcl.c
-HLFILES += hla_interface.c
-HLFILES += hla_layout.c
-endif
-
-noinst_HEADERS = \
- hla_interface.h \
- hla_layout.h \
- hla_tcl.h \
- hla_transport.h
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c
deleted file mode 100644
index 9217631..0000000
--- a/src/jtag/hla/hla_interface.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <transport/transport.h>
-#include <helper/time_support.h>
-
-#include <jtag/hla/hla_tcl.h>
-#include <jtag/hla/hla_layout.h>
-#include <jtag/hla/hla_transport.h>
-#include <jtag/hla/hla_interface.h>
-
-#include <target/target.h>
-
-static struct hl_interface_s hl_if = { {0, 0, 0, 0, 0, HL_TRANSPORT_UNKNOWN, false, -1}, 0, 0 };
-
-int hl_interface_open(enum hl_transports tr)
-{
- LOG_DEBUG("hl_interface_open");
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
- if (jtag_reset_config & RESET_SRST_NO_GATING)
- hl_if.param.connect_under_reset = true;
- else
- LOG_WARNING("\'srst_nogate\' reset_config option is required");
- }
-
- /* set transport mode */
- hl_if.param.transport = tr;
-
- int result = hl_if.layout->open(&hl_if);
- if (result != ERROR_OK)
- return result;
-
- return hl_interface_init_reset();
-}
-
-int hl_interface_init_target(struct target *t)
-{
- int res;
-
- LOG_DEBUG("hl_interface_init_target");
-
- /* this is the interface for the current target and we
- * can setup the private pointer in the tap structure
- * if the interface match the tap idcode
- */
- res = hl_if.layout->api->idcode(hl_if.handle, &t->tap->idcode);
-
- if (res != ERROR_OK)
- return res;
-
- unsigned ii, limit = t->tap->expected_ids_cnt;
- int found = 0;
-
- for (ii = 0; ii < limit; ii++) {
- uint32_t expected = t->tap->expected_ids[ii];
-
- /* treat "-expected-id 0" as a "don't-warn" wildcard */
- if (!expected || !t->tap->idcode ||
- (t->tap->idcode == expected)) {
- found = 1;
- break;
- }
- }
-
- if (found == 0) {
- LOG_WARNING("UNEXPECTED idcode: 0x%08" PRIx32, t->tap->idcode);
- for (ii = 0; ii < limit; ii++)
- LOG_ERROR("expected %u of %u: 0x%08" PRIx32, ii + 1, limit,
- t->tap->expected_ids[ii]);
-
- return ERROR_FAIL;
- }
-
- t->tap->priv = &hl_if;
- t->tap->hasidcode = 1;
-
- return ERROR_OK;
-}
-
-static int hl_interface_init(void)
-{
- LOG_DEBUG("hl_interface_init");
-
- /* here we can initialize the layout */
- return hl_layout_init(&hl_if);
-}
-
-static int hl_interface_quit(void)
-{
- LOG_DEBUG("hl_interface_quit");
-
- if (hl_if.layout->api->close)
- hl_if.layout->api->close(hl_if.handle);
-
- return ERROR_OK;
-}
-
-static int hl_interface_execute_queue(void)
-{
- LOG_DEBUG("hl_interface_execute_queue: ignored");
-
- return ERROR_OK;
-}
-
-int hl_interface_init_reset(void)
-{
- /* incase the adapter has not already handled asserting srst
- * we will attempt it again */
- if (hl_if.param.connect_under_reset) {
- jtag_add_reset(0, 1);
- hl_if.layout->api->assert_srst(hl_if.handle, 0);
- } else {
- jtag_add_reset(0, 0);
- }
-
- return ERROR_OK;
-}
-
-static int hl_interface_khz(int khz, int *jtag_speed)
-{
- if (hl_if.layout->api->speed == NULL)
- return ERROR_OK;
-
- *jtag_speed = hl_if.layout->api->speed(hl_if.handle, khz, true);
- return ERROR_OK;
-}
-
-static int hl_interface_speed_div(int speed, int *khz)
-{
- *khz = speed;
- return ERROR_OK;
-}
-
-static int hl_interface_speed(int speed)
-{
- if (hl_if.layout->api->speed == NULL)
- return ERROR_OK;
-
- if (hl_if.handle == NULL) {
- /* pass speed as initial param as interface not open yet */
- hl_if.param.initial_interface_speed = speed;
- return ERROR_OK;
- }
-
- hl_if.layout->api->speed(hl_if.handle, speed, false);
-
- return ERROR_OK;
-}
-
-int hl_interface_override_target(const char **targetname)
-{
- if (hl_if.layout->api->override_target) {
- if (hl_if.layout->api->override_target(*targetname)) {
- *targetname = "hla_target";
- return ERROR_OK;
- } else
- return ERROR_FAIL;
- }
- return ERROR_FAIL;
-}
-
-int hl_interface_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq)
-{
- if (hl_if.layout->api->config_trace)
- return hl_if.layout->api->config_trace(hl_if.handle, enabled, pin_protocol,
- port_size, trace_freq);
- else if (enabled) {
- LOG_ERROR("The selected interface does not support tracing");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-int hl_interface_poll_trace(uint8_t *buf, size_t *size)
-{
- if (hl_if.layout->api->poll_trace)
- return hl_if.layout->api->poll_trace(hl_if.handle, buf, size);
-
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(hl_interface_handle_device_desc_command)
-{
- LOG_DEBUG("hl_interface_handle_device_desc_command");
-
- if (CMD_ARGC == 1) {
- hl_if.param.device_desc = strdup(CMD_ARGV[0]);
- } else {
- LOG_ERROR("expected exactly one argument to hl_device_desc <description>");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(hl_interface_handle_serial_command)
-{
- LOG_DEBUG("hl_interface_handle_serial_command");
-
- if (CMD_ARGC == 1) {
- hl_if.param.serial = strdup(CMD_ARGV[0]);
- } else {
- LOG_ERROR("expected exactly one argument to hl_serial <serial-number>");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(hl_interface_handle_layout_command)
-{
- LOG_DEBUG("hl_interface_handle_layout_command");
-
- if (CMD_ARGC != 1) {
- LOG_ERROR("Need exactly one argument to stlink_layout");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (hl_if.layout) {
- LOG_ERROR("already specified hl_layout %s",
- hl_if.layout->name);
- return (strcmp(hl_if.layout->name, CMD_ARGV[0]) != 0)
- ? ERROR_FAIL : ERROR_OK;
- }
-
- for (const struct hl_layout *l = hl_layout_get_list(); l->name;
- l++) {
- if (strcmp(l->name, CMD_ARGV[0]) == 0) {
- hl_if.layout = l;
- return ERROR_OK;
- }
- }
-
- LOG_ERROR("No adapter layout '%s' found", CMD_ARGV[0]);
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(hl_interface_handle_vid_pid_command)
-{
- LOG_DEBUG("hl_interface_handle_vid_pid_command");
-
- if (CMD_ARGC != 2) {
- LOG_WARNING("ignoring extra IDs in hl_vid_pid (maximum is 1 pair)");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], hl_if.param.vid);
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], hl_if.param.pid);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(interface_handle_hla_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (!hl_if.layout->api->custom_command) {
- LOG_ERROR("The selected adapter doesn't support custom commands");
- return ERROR_FAIL;
- }
-
- hl_if.layout->api->custom_command(hl_if.handle, CMD_ARGV[0]);
-
- return ERROR_OK;
-}
-
-static const struct command_registration hl_interface_command_handlers[] = {
- {
- .name = "hla_device_desc",
- .handler = &hl_interface_handle_device_desc_command,
- .mode = COMMAND_CONFIG,
- .help = "set the a device description of the adapter",
- .usage = "description_string",
- },
- {
- .name = "hla_serial",
- .handler = &hl_interface_handle_serial_command,
- .mode = COMMAND_CONFIG,
- .help = "set the serial number of the adapter",
- .usage = "serial_string",
- },
- {
- .name = "hla_layout",
- .handler = &hl_interface_handle_layout_command,
- .mode = COMMAND_CONFIG,
- .help = "set the layout of the adapter",
- .usage = "layout_name",
- },
- {
- .name = "hla_vid_pid",
- .handler = &hl_interface_handle_vid_pid_command,
- .mode = COMMAND_CONFIG,
- .help = "the vendor and product ID of the adapter",
- .usage = "(vid pid)* ",
- },
- {
- .name = "hla_command",
- .handler = &interface_handle_hla_command,
- .mode = COMMAND_EXEC,
- .help = "execute a custom adapter-specific command",
- .usage = "hla_command <command>",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct jtag_interface hl_interface = {
- .name = "hla",
- .supported = 0,
- .commands = hl_interface_command_handlers,
- .transports = hl_transports,
- .init = hl_interface_init,
- .quit = hl_interface_quit,
- .execute_queue = hl_interface_execute_queue,
- .speed = &hl_interface_speed,
- .khz = &hl_interface_khz,
- .speed_div = &hl_interface_speed_div,
- .config_trace = &hl_interface_config_trace,
- .poll_trace = &hl_interface_poll_trace,
-};
diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h
deleted file mode 100644
index 0992d1c..0000000
--- a/src/jtag/hla/hla_interface.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_HLA_HLA_INTERFACE_H
-#define OPENOCD_JTAG_HLA_HLA_INTERFACE_H
-
-/** */
-struct target;
-/** */
-enum e_hl_transports;
-/** */
-extern const char *hl_transports[];
-
-struct hl_interface_param_s {
- /** */
- const char *device_desc;
- /** */
- const char *serial;
- /** */
- uint16_t vid;
- /** */
- uint16_t pid;
- /** */
- unsigned api;
- /** */
- enum hl_transports transport;
- /** */
- bool connect_under_reset;
- /** Initial interface clock clock speed */
- int initial_interface_speed;
-};
-
-struct hl_interface_s {
- /** */
- struct hl_interface_param_s param;
- /** */
- const struct hl_layout *layout;
- /** */
- void *handle;
-};
-
-/** */
-int hl_interface_open(enum hl_transports tr);
-/** */
-
-int hl_interface_init_target(struct target *t);
-int hl_interface_init_reset(void);
-int hl_interface_override_target(const char **targetname);
-
-#endif /* OPENOCD_JTAG_HLA_HLA_INTERFACE_H */
diff --git a/src/jtag/hla/hla_layout.c b/src/jtag/hla/hla_layout.c
deleted file mode 100644
index c5e3518..0000000
--- a/src/jtag/hla/hla_layout.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <transport/transport.h>
-#include <helper/time_support.h>
-
-#include <jtag/hla/hla_layout.h>
-#include <jtag/hla/hla_tcl.h>
-#include <jtag/hla/hla_transport.h>
-#include <jtag/hla/hla_interface.h>
-
-static int hl_layout_open(struct hl_interface_s *adapter)
-{
- int res;
-
- LOG_DEBUG("hl_layout_open");
-
- adapter->handle = NULL;
-
- res = adapter->layout->api->open(&adapter->param, &adapter->handle);
-
- if (res != ERROR_OK) {
- LOG_DEBUG("failed");
- return res;
- }
-
- return ERROR_OK;
-}
-
-static int hl_layout_close(struct hl_interface_s *adapter)
-{
- return ERROR_OK;
-}
-
-static const struct hl_layout hl_layouts[] = {
- {
- .name = "stlink",
- .open = hl_layout_open,
- .close = hl_layout_close,
- .api = &stlink_usb_layout_api,
- },
- {
- .name = "ti-icdi",
- .open = hl_layout_open,
- .close = hl_layout_close,
- .api = &icdi_usb_layout_api,
- },
- {.name = NULL, /* END OF TABLE */ },
-};
-
-/** */
-const struct hl_layout *hl_layout_get_list(void)
-{
- return hl_layouts;
-}
-
-int hl_layout_init(struct hl_interface_s *adapter)
-{
- LOG_DEBUG("hl_layout_init");
-
- if (adapter->layout == NULL) {
- LOG_ERROR("no layout specified");
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
diff --git a/src/jtag/hla/hla_layout.h b/src/jtag/hla/hla_layout.h
deleted file mode 100644
index 40c1321..0000000
--- a/src/jtag/hla/hla_layout.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_HLA_HLA_LAYOUT_H
-#define OPENOCD_JTAG_HLA_HLA_LAYOUT_H
-
-#include <target/armv7m_trace.h>
-
-/** */
-struct hl_interface_s;
-struct hl_interface_param_s;
-
-/** */
-extern struct hl_layout_api_s stlink_usb_layout_api;
-extern struct hl_layout_api_s icdi_usb_layout_api;
-
-/** */
-struct hl_layout_api_s {
- /** */
- int (*open) (struct hl_interface_param_s *param, void **handle);
- /** */
- int (*close) (void *handle);
- /** */
- int (*reset) (void *handle);
- /** */
- int (*assert_srst) (void *handle, int srst);
- /** */
- int (*run) (void *handle);
- /** */
- int (*halt) (void *handle);
- /** */
- int (*step) (void *handle);
- /** */
- int (*read_regs) (void *handle);
- /** */
- int (*read_reg) (void *handle, int num, uint32_t *val);
- /** */
- int (*write_reg) (void *handle, int num, uint32_t val);
- /** */
- int (*read_mem) (void *handle, uint32_t addr, uint32_t size,
- uint32_t count, uint8_t *buffer);
- /** */
- int (*write_mem) (void *handle, uint32_t addr, uint32_t size,
- uint32_t count, const uint8_t *buffer);
- /** */
- int (*write_debug_reg) (void *handle, uint32_t addr, uint32_t val);
- /**
- * Read the idcode of the target connected to the adapter
- *
- * If the adapter doesn't support idcode retrieval, this callback should
- * store 0 to indicate a wildcard match.
- *
- * @param handle A pointer to the device-specific handle
- * @param idcode Storage for the detected idcode
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*idcode) (void *handle, uint32_t *idcode);
- /** */
- int (*override_target) (const char *targetname);
- /** */
- int (*custom_command) (void *handle, const char *command);
- /** */
- int (*speed)(void *handle, int khz, bool query);
- /**
- * Configure trace parameters for the adapter
- *
- * @param handle A handle to adapter
- * @param enabled Whether to enable trace
- * @param pin_protocol Configured pin protocol
- * @param port_size Trace port width for sync mode
- * @param trace_freq A pointer to the configured trace
- * frequency; if it points to 0, the adapter driver must write
- * its maximum supported rate there
- * @returns ERROR_OK on success, an error code on failure.
- */
- int (*config_trace)(void *handle, bool enabled, enum tpio_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq);
- /**
- * Poll for new trace data
- *
- * @param handle A handle to adapter
- * @param buf A pointer to buffer to store received data
- * @param size A pointer to buffer size; must be filled with
- * the actual amount of bytes written
- *
- * @returns ERROR_OK on success, an error code on failure.
- */
- int (*poll_trace)(void *handle, uint8_t *buf, size_t *size);
- /** */
- enum target_state (*state) (void *fd);
-};
-
-/** */
-struct hl_layout {
- /** */
- char *name;
- /** */
- int (*open) (struct hl_interface_s *adapter);
- /** */
- int (*close) (struct hl_interface_s *adapter);
- /** */
- struct hl_layout_api_s *api;
-};
-
-/** */
-const struct hl_layout *hl_layout_get_list(void);
-/** */
-int hl_layout_init(struct hl_interface_s *adapter);
-
-#endif /* OPENOCD_JTAG_HLA_HLA_LAYOUT_H */
diff --git a/src/jtag/hla/hla_tcl.c b/src/jtag/hla/hla_tcl.c
deleted file mode 100644
index 9378427..0000000
--- a/src/jtag/hla/hla_tcl.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <transport/transport.h>
-#include <helper/time_support.h>
-
-static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
- struct jtag_tap *pTap)
-{
- jim_wide w;
- int e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK) {
- Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
- n->name);
- return e;
- }
-
- unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt;
- uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
- if (new_expected_ids == NULL) {
- Jim_SetResultFormatted(goi->interp, "no memory");
- return JIM_ERR;
- }
-
- memcpy(new_expected_ids, pTap->expected_ids, expected_len);
-
- new_expected_ids[pTap->expected_ids_cnt] = w;
-
- free(pTap->expected_ids);
- pTap->expected_ids = new_expected_ids;
- pTap->expected_ids_cnt++;
-
- return JIM_OK;
-}
-
-#define NTAP_OPT_IRLEN 0
-#define NTAP_OPT_IRMASK 1
-#define NTAP_OPT_IRCAPTURE 2
-#define NTAP_OPT_ENABLED 3
-#define NTAP_OPT_DISABLED 4
-#define NTAP_OPT_EXPECTED_ID 5
-#define NTAP_OPT_VERSION 6
-
-static int jim_hl_newtap_cmd(Jim_GetOptInfo *goi)
-{
- struct jtag_tap *pTap;
- int x;
- int e;
- Jim_Nvp *n;
- char *cp;
- const Jim_Nvp opts[] = {
- { .name = "-irlen", .value = NTAP_OPT_IRLEN },
- { .name = "-irmask", .value = NTAP_OPT_IRMASK },
- { .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE },
- { .name = "-enable", .value = NTAP_OPT_ENABLED },
- { .name = "-disable", .value = NTAP_OPT_DISABLED },
- { .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
- { .name = "-ignore-version", .value = NTAP_OPT_VERSION },
- { .name = NULL, .value = -1},
- };
-
- pTap = calloc(1, sizeof(struct jtag_tap));
- if (!pTap) {
- Jim_SetResultFormatted(goi->interp, "no memory");
- return JIM_ERR;
- }
-
- /*
- * we expect CHIP + TAP + OPTIONS
- * */
- if (goi->argc < 3) {
- Jim_SetResultFormatted(goi->interp,
- "Missing CHIP TAP OPTIONS ....");
- free(pTap);
- return JIM_ERR;
- }
-
- const char *tmp;
- Jim_GetOpt_String(goi, &tmp, NULL);
- pTap->chip = strdup(tmp);
-
- Jim_GetOpt_String(goi, &tmp, NULL);
- pTap->tapname = strdup(tmp);
-
- /* name + dot + name + null */
- x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
- cp = malloc(x);
- sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
- pTap->dotted_name = cp;
-
- LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
- pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);
-
- while (goi->argc) {
- e = Jim_GetOpt_Nvp(goi, opts, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, opts, 0);
- free(cp);
- free(pTap);
- return e;
- }
- LOG_DEBUG("Processing option: %s", n->name);
- switch (n->value) {
- case NTAP_OPT_EXPECTED_ID:
- e = jim_newtap_expected_id(n, goi, pTap);
- if (JIM_OK != e) {
- free(cp);
- free(pTap);
- return e;
- }
- break;
- case NTAP_OPT_IRLEN:
- case NTAP_OPT_IRMASK:
- case NTAP_OPT_IRCAPTURE:
- /* dummy read to ignore the next argument */
- Jim_GetOpt_Wide(goi, NULL);
- break;
- } /* switch (n->value) */
- } /* while (goi->argc) */
-
- /* default is enabled-after-reset */
- pTap->enabled = !pTap->disabled_after_reset;
-
- jtag_tap_init(pTap);
- return JIM_OK;
-}
-
-int jim_hl_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
- return jim_hl_newtap_cmd(&goi);
-}
diff --git a/src/jtag/hla/hla_tcl.h b/src/jtag/hla/hla_tcl.h
deleted file mode 100644
index ac00add..0000000
--- a/src/jtag/hla/hla_tcl.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_HLA_HLA_TCL_H
-#define OPENOCD_JTAG_HLA_HLA_TCL_H
-
-/** */
-int jim_hl_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv);
-
-#endif /* OPENOCD_JTAG_HLA_HLA_TCL_H */
diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c
deleted file mode 100644
index 5a5671d..0000000
--- a/src/jtag/hla/hla_transport.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* project specific includes */
-#include <jtag/interface.h>
-#include <jtag/tcl.h>
-#include <transport/transport.h>
-#include <helper/time_support.h>
-#include <target/target.h>
-#include <jtag/hla/hla_tcl.h>
-#include <jtag/hla/hla_transport.h>
-#include <jtag/hla/hla_interface.h>
-
-COMMAND_HANDLER(hl_transport_jtag_command)
-{
- LOG_DEBUG("hl_transport_jtag_command");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(hl_transport_reset_command)
-{
- return hl_interface_init_reset();
-}
-
-static const struct command_registration
-hl_transport_stlink_subcommand_handlers[] = {
- {
- .name = "newtap",
- .mode = COMMAND_CONFIG,
- .jim_handler = jim_hl_newtap,
- .help = "Create a new TAP instance named basename.tap_type, "
- "and appends it to the scan chain.",
- .usage = "basename tap_type '-irlen' count "
- "['-expected_id' number] ",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration
-hl_transport_jtag_subcommand_handlers[] = {
- {
- .name = "init",
- .mode = COMMAND_ANY,
- .handler = hl_transport_jtag_command,
- .usage = ""
- },
- {
- .name = "arp_init",
- .mode = COMMAND_ANY,
- .handler = hl_transport_jtag_command,
- .usage = ""
- },
- {
- .name = "arp_init-reset",
- .mode = COMMAND_ANY,
- .handler = hl_transport_reset_command,
- .usage = ""
- },
- {
- .name = "tapisenabled",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- },
- {
- .name = "tapenable",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- },
- {
- .name = "tapdisable",
- .mode = COMMAND_EXEC,
- .handler = hl_transport_jtag_command,
- .usage = "",
- },
- {
- .name = "configure",
- .mode = COMMAND_EXEC,
- .handler = hl_transport_jtag_command,
- .usage = "",
- },
- {
- .name = "cget",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_configure,
- },
- {
- .name = "names",
- .mode = COMMAND_ANY,
- .handler = hl_transport_jtag_command,
- .usage = "",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration stlink_transport_command_handlers[] = {
-
- {
- .name = "hla",
- .mode = COMMAND_ANY,
- .help = "perform hl adapter actions",
- .usage = "",
- .chain = hl_transport_stlink_subcommand_handlers,
- },
- {
- .name = "jtag",
- .mode = COMMAND_ANY,
- .usage = "",
- .chain = hl_transport_jtag_subcommand_handlers,
- },
- {
- .name = "jtag_ntrst_delay",
- .mode = COMMAND_ANY,
- .handler = hl_transport_jtag_command,
- .usage = "",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int hl_transport_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL,
- stlink_transport_command_handlers);
-}
-
-static int hl_transport_init(struct command_context *cmd_ctx)
-{
- LOG_DEBUG("hl_transport_init");
- struct target *t = get_current_target(cmd_ctx);
- struct transport *transport;
- enum hl_transports tr;
-
- if (!t) {
- LOG_ERROR("no current target");
- return ERROR_FAIL;
- }
-
- transport = get_current_transport();
-
- if (!transport) {
- LOG_ERROR("no transport selected");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("current transport %s", transport->name);
-
- /* get selected transport as enum */
- tr = HL_TRANSPORT_UNKNOWN;
-
- if (strcmp(transport->name, "hla_swd") == 0)
- tr = HL_TRANSPORT_SWD;
- else if (strcmp(transport->name, "hla_jtag") == 0)
- tr = HL_TRANSPORT_JTAG;
- else if (strcmp(transport->name, "stlink_swim") == 0)
- tr = HL_TRANSPORT_SWIM;
-
- int retval = hl_interface_open(tr);
-
- if (retval != ERROR_OK)
- return retval;
-
- return hl_interface_init_target(t);
-}
-
-static int hl_transport_select(struct command_context *ctx)
-{
- LOG_DEBUG("hl_transport_select");
-
- int retval;
-
- /* NOTE: interface init must already have been done.
- * That works with only C code ... no Tcl glue required.
- */
-
- retval = hl_transport_register_commands(ctx);
-
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static struct transport hl_swd_transport = {
- .name = "hla_swd",
- .select = hl_transport_select,
- .init = hl_transport_init,
- .override_target = hl_interface_override_target,
-};
-
-static struct transport hl_jtag_transport = {
- .name = "hla_jtag",
- .select = hl_transport_select,
- .init = hl_transport_init,
- .override_target = hl_interface_override_target,
-};
-
-static struct transport stlink_swim_transport = {
- .name = "stlink_swim",
- .select = hl_transport_select,
- .init = hl_transport_init,
-};
-
-const char *hl_transports[] = { "hla_swd", "hla_jtag", "stlink_swim", NULL };
-
-static void hl_constructor(void) __attribute__ ((constructor));
-static void hl_constructor(void)
-{
- transport_register(&hl_swd_transport);
- transport_register(&hl_jtag_transport);
- transport_register(&stlink_swim_transport);
-}
diff --git a/src/jtag/hla/hla_transport.h b/src/jtag/hla/hla_transport.h
deleted file mode 100644
index 07eb751..0000000
--- a/src/jtag/hla/hla_transport.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2012 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_HLA_HLA_TRANSPORT_H
-#define OPENOCD_JTAG_HLA_HLA_TRANSPORT_H
-
-enum hl_transports {
- HL_TRANSPORT_UNKNOWN = 0,
- HL_TRANSPORT_SWD,
- HL_TRANSPORT_JTAG,
- HL_TRANSPORT_SWIM
-};
-
-#endif /* OPENOCD_JTAG_HLA_HLA_TRANSPORT_H */
diff --git a/src/jtag/interface.c b/src/jtag/interface.c
deleted file mode 100644
index e12b2ae..0000000
--- a/src/jtag/interface.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag.h"
-#include "interface.h"
-
-/**
- * @see tap_set_state() and tap_get_state() accessors.
- * Actual name is not important since accessors hide it.
- */
-static tap_state_t state_follower = TAP_RESET;
-
-void tap_set_state_impl(tap_state_t new_state)
-{
- /* this is the state we think the TAPs are in now, was cur_state */
- state_follower = new_state;
-}
-
-tap_state_t tap_get_state()
-{
- return state_follower;
-}
-
-/**
- * @see tap_set_end_state() and tap_get_end_state() accessors.
- * Actual name is not important because accessors hide it.
- */
-static tap_state_t end_state_follower = TAP_RESET;
-
-void tap_set_end_state(tap_state_t new_end_state)
-{
- /* this is the state we think the TAPs will be in at completion of the
- * current TAP operation, was end_state
- */
- end_state_follower = new_end_state;
-}
-
-tap_state_t tap_get_end_state()
-{
- return end_state_follower;
-}
-
-int tap_move_ndx(tap_state_t astate)
-{
- /* given a stable state, return the index into the tms_seqs[]
- * array within tap_get_tms_path()
- */
-
- int ndx;
-
- switch (astate) {
- case TAP_RESET:
- ndx = 0;
- break;
- case TAP_IDLE:
- ndx = 1;
- break;
- case TAP_DRSHIFT:
- ndx = 2;
- break;
- case TAP_DRPAUSE:
- ndx = 3;
- break;
- case TAP_IRSHIFT:
- ndx = 4;
- break;
- case TAP_IRPAUSE:
- ndx = 5;
- break;
- default:
- LOG_ERROR("FATAL: unstable state \"%s\" in tap_move_ndx()",
- tap_state_name(astate));
- exit(1);
- }
-
- return ndx;
-}
-
-/* tap_move[i][j]: tap movement command to go from state i to state j
- * encodings of i and j are what tap_move_ndx() reports.
- *
- * DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code
- */
-struct tms_sequences {
- uint8_t bits;
- uint8_t bit_count;
-};
-
-/*
- * These macros allow us to specify TMS state transitions by bits rather than hex bytes.
- * Read the bits from LSBit first to MSBit last (right-to-left).
- */
-#define HEX__(n) 0x##n##LU
-
-#define B8__(x) \
- ((((x) & 0x0000000FLU) ? (1 << 0) : 0) \
- +(((x) & 0x000000F0LU) ? (1 << 1) : 0) \
- +(((x) & 0x00000F00LU) ? (1 << 2) : 0) \
- +(((x) & 0x0000F000LU) ? (1 << 3) : 0) \
- +(((x) & 0x000F0000LU) ? (1 << 4) : 0) \
- +(((x) & 0x00F00000LU) ? (1 << 5) : 0) \
- +(((x) & 0x0F000000LU) ? (1 << 6) : 0) \
- +(((x) & 0xF0000000LU) ? (1 << 7) : 0))
-
-#define B8(bits, count) {((uint8_t)B8__(HEX__(bits))), (count)}
-
-static const struct tms_sequences old_tms_seqs[6][6] = { /* [from_state_ndx][to_state_ndx] */
- /* value clocked to TMS to move from one of six stable states to another.
- * N.B. OOCD clocks TMS from LSB first, so read these right-to-left.
- * N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable.
- * These extra ones cause no TAP state problem, because we go into reset and stay in reset.
- */
-
-/* to state: */
-/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
-{B8(1111111, 7), B8(0000000, 7), B8(0010111, 7), B8(0001010, 7), B8(0011011, 7), B8(0010110, 7)},/* RESET */
-{B8(1111111, 7), B8(0000000, 7), B8(0100101, 7), B8(0000101, 7), B8(0101011, 7), B8(0001011, 7)},/* IDLE */
-{B8(1111111, 7), B8(0110001, 7), B8(0000000, 7), B8(0000001, 7), B8(0001111, 7), B8(0101111, 7)},/* DRSHIFT */
-{B8(1111111, 7), B8(0110000, 7), B8(0100000, 7), B8(0010111, 7), B8(0011110, 7), B8(0101111, 7)},/* DRPAUSE */
-{B8(1111111, 7), B8(0110001, 7), B8(0000111, 7), B8(0010111, 7), B8(0000000, 7), B8(0000001, 7)},/* IRSHIFT */
-{B8(1111111, 7), B8(0110000, 7), B8(0011100, 7), B8(0010111, 7), B8(0011110, 7), B8(0101111, 7)},/* IRPAUSE */
-};
-
-static const struct tms_sequences short_tms_seqs[6][6] = { /* [from_state_ndx][to_state_ndx] */
- /* this is the table submitted by Jeff Williams on 3/30/2009 with this comment:
-
- OK, I added Peter's version of the state table, and it works OK for
- me on MC1322x. I've recreated the jlink portion of patch with this
- new state table. His changes to my state table are pretty minor in
- terms of total transitions, but Peter feels that his version fixes
- some long-standing problems.
- Jeff
-
- I added the bit count into the table, reduced RESET column to 7 bits from 8.
- Dick
-
- state specific comments:
- ------------------------
- *->RESET tried the 5 bit reset and it gave me problems, 7 bits seems to
- work better on ARM9 with ft2232 driver. (Dick)
-
- RESET->DRSHIFT add 1 extra clock cycles in the RESET state before advancing.
- needed on ARM9 with ft2232 driver. (Dick)
- (For a total of *THREE* extra clocks in RESET; NOP.)
-
- RESET->IRSHIFT add 1 extra clock cycles in the RESET state before advancing.
- needed on ARM9 with ft2232 driver. (Dick)
- (For a total of *TWO* extra clocks in RESET; NOP.)
-
- RESET->* always adds one or more clocks in the target state,
- which should be NOPS; except shift states which (as
- noted above) add those clocks in RESET.
-
- The X-to-X transitions always add clocks; from *SHIFT, they go
- via IDLE and thus *DO HAVE SIDE EFFECTS* (capture and update).
-*/
-
-/* to state: */
-/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
-{B8(1111111, 7), B8(0000000, 7), B8(0010111, 7), B8(0001010, 7), B8(0011011, 7), B8(0010110, 7)}, /* RESET */
-{B8(1111111, 7), B8(0000000, 7), B8(001, 3), B8(0101, 4), B8(0011, 4), B8(01011, 5)}, /* IDLE */
-{B8(1111111, 7), B8(011, 3), B8(00111, 5), B8(01, 2), B8(001111, 6), B8(0101111, 7)}, /* DRSHIFT */
-{B8(1111111, 7), B8(011, 3), B8(01, 2), B8(0, 1), B8(001111, 6), B8(0101111, 7)}, /* DRPAUSE */
-{B8(1111111, 7), B8(011, 3), B8(00111, 5), B8(010111, 6), B8(001111, 6), B8(01, 2)}, /* IRSHIFT */
-{B8(1111111, 7), B8(011, 3), B8(00111, 5), B8(010111, 6), B8(01, 2), B8(0, 1)} /* IRPAUSE */
-};
-
-typedef const struct tms_sequences tms_table[6][6];
-
-static tms_table *tms_seqs = &short_tms_seqs;
-
-int tap_get_tms_path(tap_state_t from, tap_state_t to)
-{
- return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bits;
-}
-
-int tap_get_tms_path_len(tap_state_t from, tap_state_t to)
-{
- return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bit_count;
-}
-
-bool tap_is_state_stable(tap_state_t astate)
-{
- bool is_stable;
-
- /* A switch () is used because it is symbol dependent
- * (not value dependent like an array), and can also check bounds.
- */
- switch (astate) {
- case TAP_RESET:
- case TAP_IDLE:
- case TAP_DRSHIFT:
- case TAP_DRPAUSE:
- case TAP_IRSHIFT:
- case TAP_IRPAUSE:
- is_stable = true;
- break;
- default:
- is_stable = false;
- }
-
- return is_stable;
-}
-
-tap_state_t tap_state_transition(tap_state_t cur_state, bool tms)
-{
- tap_state_t new_state;
-
- /* A switch is used because it is symbol dependent and not value dependent
- * like an array. Also it can check for out of range conditions.
- */
-
- if (tms) {
- switch (cur_state) {
- case TAP_RESET:
- new_state = cur_state;
- break;
- case TAP_IDLE:
- case TAP_DRUPDATE:
- case TAP_IRUPDATE:
- new_state = TAP_DRSELECT;
- break;
- case TAP_DRSELECT:
- new_state = TAP_IRSELECT;
- break;
- case TAP_DRCAPTURE:
- case TAP_DRSHIFT:
- new_state = TAP_DREXIT1;
- break;
- case TAP_DREXIT1:
- case TAP_DREXIT2:
- new_state = TAP_DRUPDATE;
- break;
- case TAP_DRPAUSE:
- new_state = TAP_DREXIT2;
- break;
- case TAP_IRSELECT:
- new_state = TAP_RESET;
- break;
- case TAP_IRCAPTURE:
- case TAP_IRSHIFT:
- new_state = TAP_IREXIT1;
- break;
- case TAP_IREXIT1:
- case TAP_IREXIT2:
- new_state = TAP_IRUPDATE;
- break;
- case TAP_IRPAUSE:
- new_state = TAP_IREXIT2;
- break;
- default:
- LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state);
- exit(1);
- break;
- }
- } else {
- switch (cur_state) {
- case TAP_RESET:
- case TAP_IDLE:
- case TAP_DRUPDATE:
- case TAP_IRUPDATE:
- new_state = TAP_IDLE;
- break;
- case TAP_DRSELECT:
- new_state = TAP_DRCAPTURE;
- break;
- case TAP_DRCAPTURE:
- case TAP_DRSHIFT:
- case TAP_DREXIT2:
- new_state = TAP_DRSHIFT;
- break;
- case TAP_DREXIT1:
- case TAP_DRPAUSE:
- new_state = TAP_DRPAUSE;
- break;
- case TAP_IRSELECT:
- new_state = TAP_IRCAPTURE;
- break;
- case TAP_IRCAPTURE:
- case TAP_IRSHIFT:
- case TAP_IREXIT2:
- new_state = TAP_IRSHIFT;
- break;
- case TAP_IREXIT1:
- case TAP_IRPAUSE:
- new_state = TAP_IRPAUSE;
- break;
- default:
- LOG_ERROR("fatal: invalid argument cur_state=%d", cur_state);
- exit(1);
- break;
- }
- }
-
- return new_state;
-}
-
-/* NOTE: do not change these state names. They're documented,
- * and we rely on them to match SVF input (except for "RUN/IDLE").
- */
-static const struct name_mapping {
- enum tap_state symbol;
- const char *name;
-} tap_name_mapping[] = {
- { TAP_RESET, "RESET", },
- { TAP_IDLE, "RUN/IDLE", },
- { TAP_DRSELECT, "DRSELECT", },
- { TAP_DRCAPTURE, "DRCAPTURE", },
- { TAP_DRSHIFT, "DRSHIFT", },
- { TAP_DREXIT1, "DREXIT1", },
- { TAP_DRPAUSE, "DRPAUSE", },
- { TAP_DREXIT2, "DREXIT2", },
- { TAP_DRUPDATE, "DRUPDATE", },
- { TAP_IRSELECT, "IRSELECT", },
- { TAP_IRCAPTURE, "IRCAPTURE", },
- { TAP_IRSHIFT, "IRSHIFT", },
- { TAP_IREXIT1, "IREXIT1", },
- { TAP_IRPAUSE, "IRPAUSE", },
- { TAP_IREXIT2, "IREXIT2", },
- { TAP_IRUPDATE, "IRUPDATE", },
-
- /* only for input: accept standard SVF name */
- { TAP_IDLE, "IDLE", },
-};
-
-const char *tap_state_name(tap_state_t state)
-{
- unsigned i;
-
- for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) {
- if (tap_name_mapping[i].symbol == state)
- return tap_name_mapping[i].name;
- }
- return "???";
-}
-
-tap_state_t tap_state_by_name(const char *name)
-{
- unsigned i;
-
- for (i = 0; i < ARRAY_SIZE(tap_name_mapping); i++) {
- /* be nice to the human */
- if (strcasecmp(name, tap_name_mapping[i].name) == 0)
- return tap_name_mapping[i].symbol;
- }
- /* not found */
- return TAP_INVALID;
-}
-
-#ifdef _DEBUG_JTAG_IO_
-
-#define JTAG_DEBUG_STATE_APPEND(buf, len, bit) \
- do { buf[len] = bit ? '1' : '0'; } while (0)
-#define JTAG_DEBUG_STATE_PRINT(a, b, astr, bstr) \
- DEBUG_JTAG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \
- tap_state_name(a), tap_state_name(b), astr, bstr)
-
-tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
- unsigned tap_bits, tap_state_t next_state)
-{
- const uint8_t *tms_buffer;
- const uint8_t *tdi_buffer;
- unsigned tap_bytes;
- unsigned cur_byte;
- unsigned cur_bit;
-
- unsigned tap_out_bits;
- char tms_str[33];
- char tdi_str[33];
-
- tap_state_t last_state;
-
- /* set startstate (and possibly last, if tap_bits == 0) */
- last_state = next_state;
- DEBUG_JTAG_IO("TAP/SM: START state: %s", tap_state_name(next_state));
-
- tms_buffer = (const uint8_t *)tms_buf;
- tdi_buffer = (const uint8_t *)tdi_buf;
-
- tap_bytes = DIV_ROUND_UP(tap_bits, 8);
- DEBUG_JTAG_IO("TAP/SM: TMS bits: %u (bytes: %u)", tap_bits, tap_bytes);
-
- tap_out_bits = 0;
- for (cur_byte = 0; cur_byte < tap_bytes; cur_byte++) {
- for (cur_bit = 0; cur_bit < 8; cur_bit++) {
- /* make sure we do not run off the end of the buffers */
- unsigned tap_bit = cur_byte * 8 + cur_bit;
- if (tap_bit == tap_bits)
- break;
-
- /* check and save TMS bit */
- tap_bit = !!(tms_buffer[cur_byte] & (1 << cur_bit));
- JTAG_DEBUG_STATE_APPEND(tms_str, tap_out_bits, tap_bit);
-
- /* use TMS bit to find the next TAP state */
- next_state = tap_state_transition(last_state, tap_bit);
-
- /* check and store TDI bit */
- tap_bit = !!(tdi_buffer[cur_byte] & (1 << cur_bit));
- JTAG_DEBUG_STATE_APPEND(tdi_str, tap_out_bits, tap_bit);
-
- /* increment TAP bits */
- tap_out_bits++;
-
- /* Only show TDO bits on state transitions, or */
- /* after some number of bits in the same state. */
- if ((next_state == last_state) && (tap_out_bits < 32))
- continue;
-
- /* terminate strings and display state transition */
- tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
- JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
-
- /* reset state */
- last_state = next_state;
- tap_out_bits = 0;
- }
- }
-
- if (tap_out_bits) {
- /* terminate strings and display state transition */
- tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
- JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
- }
-
- DEBUG_JTAG_IO("TAP/SM: FINAL state: %s", tap_state_name(next_state));
-
- return next_state;
-}
-#endif /* _DEBUG_JTAG_IO_ */
-
-void tap_use_new_tms_table(bool use_new)
-{
- tms_seqs = use_new ? &short_tms_seqs : &old_tms_seqs;
-}
-bool tap_uses_new_tms_table(void)
-{
- return tms_seqs == &short_tms_seqs;
-}
diff --git a/src/jtag/interface.h b/src/jtag/interface.h
deleted file mode 100644
index cdfc676..0000000
--- a/src/jtag/interface.h
+++ /dev/null
@@ -1,335 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_INTERFACE_H
-#define OPENOCD_JTAG_INTERFACE_H
-
-#include <jtag/jtag.h>
-#include <target/armv7m_trace.h>
-
-/* @file
- * The "Cable Helper API" is what the cable drivers can use to help
- * implement their "Cable API". So a Cable Helper API is a set of
- * helper functions used by cable drivers, and this is different from a
- * Cable API. A "Cable API" is what higher level code used to talk to a
- * cable.
- */
-
-
-/** implementation of wrapper function tap_set_state() */
-void tap_set_state_impl(tap_state_t new_state);
-
-/**
- * This function sets the state of a "state follower" which tracks the
- * state of the TAPs connected to the cable. The state follower is
- * hopefully always in the same state as the actual TAPs in the jtag
- * chain, and will be so if there are no bugs in the tracking logic
- * within that cable driver.
- *
- * All the cable drivers call this function to indicate the state they
- * think the TAPs attached to their cables are in. Because this
- * function can also log transitions, it will be helpful to call this
- * function with every transition that the TAPs being manipulated are
- * expected to traverse, not just end points of a multi-step state path.
- *
- * @param new_state The state we think the TAPs are currently in (or
- * are about to enter).
- */
-#if defined(_DEBUG_JTAG_IO_)
-#define tap_set_state(new_state) \
- do { \
- LOG_DEBUG("tap_set_state(%s)", tap_state_name(new_state)); \
- tap_set_state_impl(new_state); \
- } while (0)
-#else
-static inline void tap_set_state(tap_state_t new_state)
-{
- tap_set_state_impl(new_state);
-}
-#endif
-
-/**
- * This function gets the state of the "state follower" which tracks the
- * state of the TAPs connected to the cable. @see tap_set_state @return
- * tap_state_t The state the TAPs are in now.
- */
-tap_state_t tap_get_state(void);
-
-/**
- * This function sets the state of an "end state follower" which tracks
- * the state that any cable driver thinks will be the end (resultant)
- * state of the current TAP SIR or SDR operation.
- *
- * At completion of that TAP operation this value is copied into the
- * state follower via tap_set_state().
- *
- * @param new_end_state The state the TAPs should enter at completion of
- * a pending TAP operation.
- */
-void tap_set_end_state(tap_state_t new_end_state);
-
-/**
- * For more information, @see tap_set_end_state
- * @return tap_state_t - The state the TAPs should be in at completion of the current TAP operation.
- */
-tap_state_t tap_get_end_state(void);
-
-/**
- * This function provides a "bit sequence" indicating what has to be
- * done with TMS during a sequence of seven TAP clock cycles in order to
- * get from state \a "from" to state \a "to".
- *
- * The length of the sequence must be determined with a parallel call to
- * tap_get_tms_path_len().
- *
- * @param from The starting state.
- * @param to The desired final state.
- * @return int The required TMS bit sequence, with the first bit in the
- * sequence at bit 0.
- */
-int tap_get_tms_path(tap_state_t from, tap_state_t to);
-
-/**
- * Function int tap_get_tms_path_len
- * returns the total number of bits that represents a TMS path
- * transition as given by the function tap_get_tms_path().
- *
- * For at least one interface (JLink) it's not OK to simply "pad" TMS
- * sequences to fit a whole byte. (I suspect this is a general TAP
- * problem within OOCD.) Padding TMS causes all manner of instability
- * that's not easily discovered. Using this routine we can apply
- * EXACTLY the state transitions required to make something work - no
- * more - no less.
- *
- * @param from is the starting state
- * @param to is the resultant or final state
- * @return int - the total number of bits in a transition.
- */
-int tap_get_tms_path_len(tap_state_t from, tap_state_t to);
-
-
-/**
- * Function tap_move_ndx
- * when given a stable state, returns an index from 0-5. The index corresponds to a
- * sequence of stable states which are given in this order: <p>
- * { TAP_RESET, TAP_IDLE, TAP_DRSHIFT, TAP_DRPAUSE, TAP_IRSHIFT, TAP_IRPAUSE }
- * <p>
- * This sequence corresponds to look up tables which are used in some of the
- * cable drivers.
- * @param astate is the stable state to find in the sequence. If a non stable
- * state is passed, this may cause the program to output an error message
- * and terminate.
- * @return int - the array (or sequence) index as described above
- */
-int tap_move_ndx(tap_state_t astate);
-
-/**
- * Function tap_is_state_stable
- * returns true if the \a astate is stable.
- */
-bool tap_is_state_stable(tap_state_t astate);
-
-/**
- * Function tap_state_transition
- * takes a current TAP state and returns the next state according to the tms value.
- * @param current_state is the state of a TAP currently.
- * @param tms is either zero or non-zero, just like a real TMS line in a jtag interface.
- * @return tap_state_t - the next state a TAP would enter.
- */
-tap_state_t tap_state_transition(tap_state_t current_state, bool tms);
-
-/** Allow switching between old and new TMS tables. @see tap_get_tms_path */
-void tap_use_new_tms_table(bool use_new);
-/** @returns True if new TMS table is active; false otherwise. */
-bool tap_uses_new_tms_table(void);
-
-#ifdef _DEBUG_JTAG_IO_
-/**
- * @brief Prints verbose TAP state transitions for the given TMS/TDI buffers.
- * @param tms_buf must points to a buffer containing the TMS bitstream.
- * @param tdi_buf must points to a buffer containing the TDI bitstream.
- * @param tap_len must specify the length of the TMS/TDI bitstreams.
- * @param start_tap_state must specify the current TAP state.
- * @returns the final TAP state; pass as @a start_tap_state in following call.
- */
-tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
- unsigned tap_len, tap_state_t start_tap_state);
-#else
-static inline tap_state_t jtag_debug_state_machine(const void *tms_buf,
- const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state)
-{
- return start_tap_state;
-}
-#endif /* _DEBUG_JTAG_IO_ */
-
-/**
- * Represents a driver for a debugging interface.
- *
- * @todo Rename; perhaps "debug_driver". This isn't an interface,
- * it's a driver! Also, not all drivers support JTAG.
- *
- * @todo We need a per-instance structure too, and changes to pass
- * that structure to the driver. Instances can for example be in
- * either SWD or JTAG modes. This will help remove globals, and
- * eventually to cope with systems which have more than one such
- * debugging interface.
- */
-struct jtag_interface {
- /** The name of the JTAG interface driver. */
- const char * const name;
-
- /**
- * Bit vector listing capabilities exposed by this driver.
- */
- unsigned supported;
-#define DEBUG_CAP_TMS_SEQ (1 << 0)
-
- /** transports supported in C code (NULL terminated vector) */
- const char * const *transports;
-
- const struct swd_driver *swd;
-
- /**
- * Execute queued commands.
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*execute_queue)(void);
-
- /**
- * Set the interface speed.
- * @param speed The new interface speed setting.
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*speed)(int speed);
-
- /**
- * The interface driver may register additional commands to expose
- * additional features not covered by the standard command set.
- */
- const struct command_registration *commands;
-
- /**
- * Interface driver must initialize any resources and connect to a
- * JTAG device.
- *
- * quit() is invoked if and only if init() succeeds. quit() is always
- * invoked if init() succeeds. Same as malloc() + free(). Always
- * invoke free() if malloc() succeeds and do not invoke free()
- * otherwise.
- *
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*init)(void);
-
- /**
- * Interface driver must tear down all resources and disconnect from
- * the JTAG device.
- *
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*quit)(void);
-
- /**
- * Returns JTAG maxium speed for KHz. 0 = RTCK. The function returns
- * a failure if it can't support the KHz/RTCK.
- *
- * WARNING!!!! if RTCK is *slow* then think carefully about
- * whether you actually want to support this in the driver.
- * Many target scripts are written to handle the absence of RTCK
- * and use a fallback kHz TCK.
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*khz)(int khz, int *jtag_speed);
-
- /**
- * Calculate the clock frequency (in KHz) for the given @a speed.
- * @param speed The desired interface speed setting.
- * @param khz On return, contains the speed in KHz (0 for RTCK).
- * @returns ERROR_OK on success, or an error code if the
- * interface cannot support the specified speed (KHz or RTCK).
- */
- int (*speed_div)(int speed, int *khz);
-
- /**
- * Read and clear the power dropout flag. Note that a power dropout
- * can be transitionary, easily much less than a ms.
- *
- * To find out if the power is *currently* on, one must invoke this
- * method twice. Once to clear the power dropout flag and a second
- * time to read the current state. The default implementation
- * never reports power dropouts.
- *
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*power_dropout)(int *power_dropout);
-
- /**
- * Read and clear the srst asserted detection flag.
- *
- * Like power_dropout this does *not* read the current
- * state. SRST assertion is transitionary and may be much
- * less than 1ms, so the interface driver must watch for these
- * events until this routine is called.
- *
- * @param srst_asserted On return, indicates whether SRST has
- * been asserted.
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*srst_asserted)(int *srst_asserted);
-
- /**
- * Configure trace parameters for the adapter
- *
- * @param enabled Whether to enable trace
- * @param pin_protocol Configured pin protocol
- * @param port_size Trace port width for sync mode
- * @param trace_freq A pointer to the configured trace
- * frequency; if it points to 0, the adapter driver must write
- * its maximum supported rate there
- * @returns ERROR_OK on success, an error code on failure.
- */
- int (*config_trace)(bool enabled, enum tpio_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq);
-
- /**
- * Poll for new trace data
- *
- * @param buf A pointer to buffer to store received data
- * @param size A pointer to buffer size; must be filled with
- * the actual amount of bytes written
- *
- * @returns ERROR_OK on success, an error code on failure.
- */
- int (*poll_trace)(uint8_t *buf, size_t *size);
-};
-
-extern const char * const jtag_only[];
-
-void adapter_assert_reset(void);
-void adapter_deassert_reset(void);
-int adapter_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol,
- uint32_t port_size, unsigned int *trace_freq);
-int adapter_poll_trace(uint8_t *buf, size_t *size);
-
-#endif /* OPENOCD_JTAG_INTERFACE_H */
diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
deleted file mode 100644
index 64fdd71..0000000
--- a/src/jtag/interfaces.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "interfaces.h"
-
-/** @file
- * This file includes declarations for all built-in jtag interfaces,
- * which are then listed in the jtag_interfaces array.
- *
- * Dynamic loading can be implemented be searching for shared libraries
- * that contain a jtag_interface structure that can added to this list.
- */
-
-#if BUILD_ZY1000 == 1
-extern struct jtag_interface zy1000_interface;
-#elif defined(BUILD_MINIDRIVER_DUMMY)
-extern struct jtag_interface minidummy_interface;
-#else /* standard drivers */
-#if BUILD_PARPORT == 1
-extern struct jtag_interface parport_interface;
-#endif
-#if BUILD_DUMMY == 1
-extern struct jtag_interface dummy_interface;
-#endif
-#if BUILD_FT2232_FTD2XX == 1
-extern struct jtag_interface ft2232_interface;
-#endif
-#if BUILD_FT2232_LIBFTDI == 1
-extern struct jtag_interface ft2232_interface;
-#endif
-#if BUILD_FTDI == 1
-extern struct jtag_interface ftdi_interface;
-#endif
-#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1
-extern struct jtag_interface usb_blaster_interface;
-#endif
-#if BUILD_JTAG_VPI == 1
-extern struct jtag_interface jtag_vpi_interface;
-#endif
-#if BUILD_AMTJTAGACCEL == 1
-extern struct jtag_interface amt_jtagaccel_interface;
-#endif
-#if BUILD_EP93XX == 1
-extern struct jtag_interface ep93xx_interface;
-#endif
-#if BUILD_AT91RM9200 == 1
-extern struct jtag_interface at91rm9200_interface;
-#endif
-#if BUILD_GW16012 == 1
-extern struct jtag_interface gw16012_interface;
-#endif
-#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
-extern struct jtag_interface presto_interface;
-#endif
-#if BUILD_USBPROG == 1
-extern struct jtag_interface usbprog_interface;
-#endif
-#if BUILD_OPENJTAG == 1
-extern struct jtag_interface openjtag_interface;
-#endif
-#if BUILD_JLINK == 1
-extern struct jtag_interface jlink_interface;
-#endif
-#if BUILD_VSLLINK == 1
-extern struct jtag_interface vsllink_interface;
-#endif
-#if BUILD_RLINK == 1
-extern struct jtag_interface rlink_interface;
-#endif
-#if BUILD_ULINK == 1
-extern struct jtag_interface ulink_interface;
-#endif
-#if BUILD_ARMJTAGEW == 1
-extern struct jtag_interface armjtagew_interface;
-#endif
-#if BUILD_BUSPIRATE == 1
-extern struct jtag_interface buspirate_interface;
-#endif
-#if BUILD_REMOTE_BITBANG == 1
-extern struct jtag_interface remote_bitbang_interface;
-#endif
-#if BUILD_HLADAPTER == 1
-extern struct jtag_interface hl_interface;
-#endif
-#if BUILD_OSBDM == 1
-extern struct jtag_interface osbdm_interface;
-#endif
-#if BUILD_OPENDOUS == 1
-extern struct jtag_interface opendous_interface;
-#endif
-#if BUILD_SYSFSGPIO == 1
-extern struct jtag_interface sysfsgpio_interface;
-#endif
-#if BUILD_AICE == 1
-extern struct jtag_interface aice_interface;
-#endif
-#if BUILD_BCM2835GPIO == 1
-extern struct jtag_interface bcm2835gpio_interface;
-#endif
-#if BUILD_CMSIS_DAP == 1
-extern struct jtag_interface cmsis_dap_interface;
-#endif
-#endif /* standard drivers */
-
-/**
- * The list of built-in JTAG interfaces, containing entries for those
- * drivers that were enabled by the @c configure script.
- *
- * The list should be defined to contain either one minidriver interface
- * or some number of standard driver interfaces, never both.
- */
-struct jtag_interface *jtag_interfaces[] = {
-#if BUILD_ZY1000 == 1
- &zy1000_interface,
-#elif defined(BUILD_MINIDRIVER_DUMMY)
- &minidummy_interface,
-#else /* standard drivers */
-#if BUILD_PARPORT == 1
- &parport_interface,
-#endif
-#if BUILD_DUMMY == 1
- &dummy_interface,
-#endif
-#if BUILD_FT2232_FTD2XX == 1
- &ft2232_interface,
-#endif
-#if BUILD_FT2232_LIBFTDI == 1
- &ft2232_interface,
-#endif
-#if BUILD_FTDI == 1
- &ftdi_interface,
-#endif
-#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1
- &usb_blaster_interface,
-#endif
-#if BUILD_JTAG_VPI == 1
- &jtag_vpi_interface,
-#endif
-#if BUILD_AMTJTAGACCEL == 1
- &amt_jtagaccel_interface,
-#endif
-#if BUILD_EP93XX == 1
- &ep93xx_interface,
-#endif
-#if BUILD_AT91RM9200 == 1
- &at91rm9200_interface,
-#endif
-#if BUILD_GW16012 == 1
- &gw16012_interface,
-#endif
-#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
- &presto_interface,
-#endif
-#if BUILD_USBPROG == 1
- &usbprog_interface,
-#endif
-#if BUILD_OPENJTAG == 1
- &openjtag_interface,
-#endif
-#if BUILD_JLINK == 1
- &jlink_interface,
-#endif
-#if BUILD_VSLLINK == 1
- &vsllink_interface,
-#endif
-#if BUILD_RLINK == 1
- &rlink_interface,
-#endif
-#if BUILD_ULINK == 1
- &ulink_interface,
-#endif
-#if BUILD_ARMJTAGEW == 1
- &armjtagew_interface,
-#endif
-#if BUILD_BUSPIRATE == 1
- &buspirate_interface,
-#endif
-#if BUILD_REMOTE_BITBANG == 1
- &remote_bitbang_interface,
-#endif
-#if BUILD_HLADAPTER == 1
- &hl_interface,
-#endif
-#if BUILD_OSBDM == 1
- &osbdm_interface,
-#endif
-#if BUILD_OPENDOUS == 1
- &opendous_interface,
-#endif
-#if BUILD_SYSFSGPIO == 1
- &sysfsgpio_interface,
-#endif
-#if BUILD_AICE == 1
- &aice_interface,
-#endif
-#if BUILD_BCM2835GPIO == 1
- &bcm2835gpio_interface,
-#endif
-#if BUILD_CMSIS_DAP == 1
- &cmsis_dap_interface,
-#endif
-#endif /* standard drivers */
- NULL,
- };
-
-void jtag_interface_modules_load(const char *path)
-{
- /* @todo: implement dynamic module loading for JTAG interface drivers */
-}
diff --git a/src/jtag/interfaces.h b/src/jtag/interfaces.h
deleted file mode 100644
index 02d201b..0000000
--- a/src/jtag/interfaces.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_INTERFACES_H
-#define OPENOCD_JTAG_INTERFACES_H
-
-/** @file
- * Exports the list of JTAG interface drivers, along with routines
- * for loading and unloading them dynamically from shared libraries.
- */
-
-#include <jtag/interface.h>
-
-/** Dynamically load all JTAG interface modules from specified directory. */
-void jtag_interface_modules_load(const char *path);
-
-extern struct jtag_interface *jtag_interfaces[];
-
-#endif /* OPENOCD_JTAG_INTERFACES_H */
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
deleted file mode 100644
index 7702d6c..0000000
--- a/src/jtag/jtag.h
+++ /dev/null
@@ -1,649 +0,0 @@
-/***************************************************************************
-* Copyright (C) 2005 by Dominic Rath *
-* Dominic.Rath@gmx.de *
-* *
-* Copyright (C) 2007-2010 Øyvind Harboe *
-* oyvind.harboe@zylin.com *
-* *
-* This program is free software; you can redistribute it and/or modify *
-* it under the terms of the GNU General Public License as published by *
-* the Free Software Foundation; either version 2 of the License, or *
-* (at your option) any later version. *
-* *
-* This program is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-* GNU General Public License for more details. *
-* *
-* You should have received a copy of the GNU General Public License *
-* along with this program. If not, see <http://www.gnu.org/licenses/>. *
-***************************************************************************/
-
-#ifndef OPENOCD_JTAG_JTAG_H
-#define OPENOCD_JTAG_JTAG_H
-
-#include <helper/binarybuffer.h>
-#include <helper/log.h>
-
-#ifdef _DEBUG_JTAG_IO_
-#define DEBUG_JTAG_IO(expr ...) \
- do { if (1) LOG_DEBUG(expr); } while (0)
-#else
-#define DEBUG_JTAG_IO(expr ...) \
- do { if (0) LOG_DEBUG(expr); } while (0)
-#endif
-
-#ifndef DEBUG_JTAG_IOZ
-#define DEBUG_JTAG_IOZ 64
-#endif
-
-/*-----</Macros>-------------------------------------------------*/
-
-/**
- * Defines JTAG Test Access Port states.
- *
- * These definitions were gleaned from the ARM7TDMI-S Technical
- * Reference Manual and validated against several other ARM core
- * technical manuals.
- *
- * FIXME some interfaces require specific numbers be used, as they
- * are handed-off directly to their hardware implementations.
- * Fix those drivers to map as appropriate ... then pick some
- * sane set of numbers here (where 0/uninitialized == INVALID).
- */
-typedef enum tap_state {
- TAP_INVALID = -1,
-
-#if BUILD_ZY1000
- /* These are the old numbers. Leave as-is for now... */
- TAP_RESET = 0, TAP_IDLE = 8,
- TAP_DRSELECT = 1, TAP_DRCAPTURE = 2, TAP_DRSHIFT = 3, TAP_DREXIT1 = 4,
- TAP_DRPAUSE = 5, TAP_DREXIT2 = 6, TAP_DRUPDATE = 7,
- TAP_IRSELECT = 9, TAP_IRCAPTURE = 10, TAP_IRSHIFT = 11, TAP_IREXIT1 = 12,
- TAP_IRPAUSE = 13, TAP_IREXIT2 = 14, TAP_IRUPDATE = 15,
-
-#else
- /* Proper ARM recommended numbers */
- TAP_DREXIT2 = 0x0,
- TAP_DREXIT1 = 0x1,
- TAP_DRSHIFT = 0x2,
- TAP_DRPAUSE = 0x3,
- TAP_IRSELECT = 0x4,
- TAP_DRUPDATE = 0x5,
- TAP_DRCAPTURE = 0x6,
- TAP_DRSELECT = 0x7,
- TAP_IREXIT2 = 0x8,
- TAP_IREXIT1 = 0x9,
- TAP_IRSHIFT = 0xa,
- TAP_IRPAUSE = 0xb,
- TAP_IDLE = 0xc,
- TAP_IRUPDATE = 0xd,
- TAP_IRCAPTURE = 0xe,
- TAP_RESET = 0x0f,
-
-#endif
-} tap_state_t;
-
-/**
- * Function tap_state_name
- * Returns a string suitable for display representing the JTAG tap_state
- */
-const char *tap_state_name(tap_state_t state);
-
-/** Provides user-friendly name lookup of TAP states. */
-tap_state_t tap_state_by_name(const char *name);
-
-/** The current TAP state of the pending JTAG command queue. */
-extern tap_state_t cmd_queue_cur_state;
-
-/**
- * This structure defines a single scan field in the scan. It provides
- * fields for the field's width and pointers to scan input and output
- * values.
- *
- * In addition, this structure includes a value and mask that is used by
- * jtag_add_dr_scan_check() to validate the value that was scanned out.
- */
-struct scan_field {
- /** The number of bits this field specifies */
- int num_bits;
- /** A pointer to value to be scanned into the device */
- const uint8_t *out_value;
- /** A pointer to a 32-bit memory location for data scanned out */
- uint8_t *in_value;
-
- /** The value used to check the data scanned out. */
- uint8_t *check_value;
- /** The mask to go with check_value */
- uint8_t *check_mask;
-};
-
-struct jtag_tap {
- char *chip;
- char *tapname;
- char *dotted_name;
- int abs_chain_position;
- /** Is this TAP disabled after JTAG reset? */
- bool disabled_after_reset;
- /** Is this TAP currently enabled? */
- bool enabled;
- int ir_length; /**< size of instruction register */
- uint32_t ir_capture_value;
- uint8_t *expected; /**< Capture-IR expected value */
- uint32_t ir_capture_mask;
- uint8_t *expected_mask; /**< Capture-IR expected mask */
- uint32_t idcode; /**< device identification code */
- /** not all devices have idcode,
- * we'll discover this during chain examination */
- bool hasidcode;
-
- /** Array of expected identification codes */
- uint32_t *expected_ids;
- /** Number of expected identification codes */
- uint8_t expected_ids_cnt;
-
- /** Flag saying whether to ignore version field in expected_ids[] */
- bool ignore_version;
-
- /** current instruction */
- uint8_t *cur_instr;
- /** Bypass register selected */
- int bypass;
-
- struct jtag_tap_event_action *event_action;
-
- struct jtag_tap *next_tap;
- /* dap instance if some null if no instance , initialized to 0 by calloc*/
- struct adiv5_dap *dap;
- /* private pointer to support none-jtag specific functions */
- void *priv;
-};
-
-void jtag_tap_init(struct jtag_tap *tap);
-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 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);
-unsigned jtag_tap_count(void);
-
-/*
- * - TRST_ASSERTED triggers two sets of callbacks, after operations to
- * reset the scan chain -- via TMS+TCK signaling, or deasserting the
- * nTRST signal -- are queued:
- *
- * + Callbacks in C code fire first, patching internal state
- * + Then post-reset event scripts fire ... activating JTAG circuits
- * via TCK cycles, exiting SWD mode via TMS sequences, etc
- *
- * During those callbacks, scan chain contents have not been validated.
- * JTAG operations that address a specific TAP (primarily DR/IR scans)
- * must *not* be queued.
- *
- * - TAP_EVENT_SETUP is reported after TRST_ASSERTED, and after the scan
- * chain has been validated. JTAG operations including scans that
- * target specific TAPs may be performed.
- *
- * - TAP_EVENT_ENABLE and TAP_EVENT_DISABLE implement TAP activation and
- * deactivation outside the core using scripted code that understands
- * the specific JTAG router type. They might be triggered indirectly
- * from EVENT_SETUP operations.
- */
-enum jtag_event {
- JTAG_TRST_ASSERTED,
- JTAG_TAP_EVENT_SETUP,
- JTAG_TAP_EVENT_ENABLE,
- JTAG_TAP_EVENT_DISABLE,
-};
-
-struct jtag_tap_event_action {
- /** The event for which this action will be triggered. */
- enum jtag_event event;
- /** The interpreter to use for evaluating the @c body. */
- Jim_Interp *interp;
- /** Contains a script to 'eval' when the @c event is triggered. */
- Jim_Obj *body;
- /* next action in linked list */
- struct jtag_tap_event_action *next;
-};
-
-/**
- * Defines the function signature requide for JTAG event callback
- * functions, which are added with jtag_register_event_callback()
- * and removed jtag_unregister_event_callback().
- * @param event The event to handle.
- * @param prive A pointer to data that was passed to
- * jtag_register_event_callback().
- * @returns Must return ERROR_OK on success, or an error code on failure.
- *
- * @todo Change to return void or define a use for its return code.
- */
-typedef int (*jtag_event_handler_t)(enum jtag_event event, void *priv);
-
-int jtag_register_event_callback(jtag_event_handler_t f, void *x);
-int jtag_unregister_event_callback(jtag_event_handler_t f, void *x);
-
-int jtag_call_event_callbacks(enum jtag_event event);
-
-
-/** @returns The current JTAG speed setting. */
-int jtag_get_speed(int *speed);
-
-/**
- * Given a @a speed setting, use the interface @c speed_div callback to
- * adjust the setting.
- * @param speed The speed setting to convert back to readable KHz.
- * @returns ERROR_OK if the interface has not been initialized or on success;
- * otherwise, the error code produced by the @c speed_div callback.
- */
-int jtag_get_speed_readable(int *speed);
-
-/** Attempt to configure the interface for the specified KHz. */
-int jtag_config_khz(unsigned khz);
-
-/**
- * Attempt to enable RTCK/RCLK. If that fails, fallback to the
- * specified frequency.
- */
-int jtag_config_rclk(unsigned fallback_speed_khz);
-
-/** Retreives the clock speed of the JTAG interface in KHz. */
-unsigned jtag_get_speed_khz(void);
-
-enum reset_types {
- RESET_NONE = 0x0,
- RESET_HAS_TRST = 0x1,
- RESET_HAS_SRST = 0x2,
- RESET_TRST_AND_SRST = 0x3,
- RESET_SRST_PULLS_TRST = 0x4,
- RESET_TRST_PULLS_SRST = 0x8,
- RESET_TRST_OPEN_DRAIN = 0x10,
- RESET_SRST_PUSH_PULL = 0x20,
- RESET_SRST_NO_GATING = 0x40,
- RESET_CNCT_UNDER_SRST = 0x80
-};
-
-enum reset_types jtag_get_reset_config(void);
-void jtag_set_reset_config(enum reset_types type);
-
-void jtag_set_nsrst_delay(unsigned delay);
-unsigned jtag_get_nsrst_delay(void);
-
-void jtag_set_ntrst_delay(unsigned delay);
-unsigned jtag_get_ntrst_delay(void);
-
-void jtag_set_nsrst_assert_width(unsigned delay);
-unsigned jtag_get_nsrst_assert_width(void);
-
-void jtag_set_ntrst_assert_width(unsigned delay);
-unsigned jtag_get_ntrst_assert_width(void);
-
-/** @returns The current state of TRST. */
-int jtag_get_trst(void);
-/** @returns The current state of SRST. */
-int jtag_get_srst(void);
-
-/** Enable or disable data scan verification checking. */
-void jtag_set_verify(bool enable);
-/** @returns True if data scan verification will be performed. */
-bool jtag_will_verify(void);
-
-/** Enable or disable verification of IR scan checking. */
-void jtag_set_verify_capture_ir(bool enable);
-/** @returns True if IR scan verification will be performed. */
-bool jtag_will_verify_capture_ir(void);
-
-/** Initialize debug adapter upon startup. */
-int adapter_init(struct command_context *cmd_ctx);
-
-/** Shutdown the debug adapter upon program exit. */
-int adapter_quit(void);
-
-/** Set ms to sleep after jtag_execute_queue() flushes queue. Debug purposes. */
-void jtag_set_flush_queue_sleep(int ms);
-
-/**
- * Initialize JTAG chain using only a RESET reset. If init fails,
- * try reset + init.
- */
-int jtag_init(struct command_context *cmd_ctx);
-
-/** reset, then initialize JTAG chain */
-int jtag_init_reset(struct command_context *cmd_ctx);
-int jtag_register_commands(struct command_context *cmd_ctx);
-int jtag_init_inner(struct command_context *cmd_ctx);
-
-/**
- * @file
- * The JTAG interface can be implemented with a software or hardware fifo.
- *
- * TAP_DRSHIFT and TAP_IRSHIFT are illegal end states; however,
- * TAP_DRSHIFT/IRSHIFT can be emulated as end states, by using longer
- * scans.
- *
- * Code that is relatively insensitive to the path taken through state
- * machine (as long as it is JTAG compliant) can use @a endstate for
- * jtag_add_xxx_scan(). Otherwise, the pause state must be specified as
- * end state and a subsequent jtag_add_pathmove() must be issued.
- */
-
-/**
- * Generate an IR SCAN with a list of scan fields with one entry for
- * each enabled TAP.
- *
- * If the input field list contains an instruction value for a TAP then
- * that is used otherwise the TAP is set to bypass.
- *
- * TAPs for which no fields are passed are marked as bypassed for
- * subsequent DR SCANs.
- *
- */
-void jtag_add_ir_scan(struct jtag_tap *tap,
- struct scan_field *fields, tap_state_t endstate);
-/**
- * The same as jtag_add_ir_scan except no verification is performed out
- * the output values.
- */
-void jtag_add_ir_scan_noverify(struct jtag_tap *tap,
- const struct scan_field *fields, tap_state_t state);
-/**
- * Scan out the bits in ir scan mode.
- *
- * If in_bits == NULL, discard incoming bits.
- */
-void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
- tap_state_t endstate);
-
-/**
- * Generate a DR SCAN using the fields passed to the function.
- * For connected TAPs, the function checks in_fields and uses fields
- * specified there. For bypassed TAPs, the function generates a dummy
- * 1-bit field. The bypass status of TAPs is set by jtag_add_ir_scan().
- */
-void jtag_add_dr_scan(struct jtag_tap *tap, int num_fields,
- const struct scan_field *fields, tap_state_t endstate);
-/** A version of jtag_add_dr_scan() that uses the check_value/mask fields */
-void jtag_add_dr_scan_check(struct jtag_tap *tap, int num_fields,
- struct scan_field *fields, tap_state_t endstate);
-/**
- * Scan out the bits in ir scan mode.
- *
- * If in_bits == NULL, discard incoming bits.
- */
-void jtag_add_plain_dr_scan(int num_bits,
- const uint8_t *out_bits, uint8_t *in_bits, tap_state_t endstate);
-
-/**
- * Defines the type of data passed to the jtag_callback_t interface.
- * The underlying type must allow storing an @c int or pointer type.
- */
-typedef intptr_t jtag_callback_data_t;
-
-/**
- * Defines a simple JTAG callback that can allow conversions on data
- * scanned in from an interface.
- *
- * This callback should only be used for conversion that cannot fail.
- * For conversion types or checks that can fail, use the more complete
- * variant: jtag_callback_t.
- */
-typedef void (*jtag_callback1_t)(jtag_callback_data_t data0);
-
-/** A simpler version of jtag_add_callback4(). */
-void jtag_add_callback(jtag_callback1_t, jtag_callback_data_t data0);
-
-
-/**
- * Defines the interface of the JTAG callback mechanism. Such
- * callbacks can be executed once the queue has been flushed.
- *
- * The JTAG queue can be executed synchronously or asynchronously.
- * Typically for USB, the queue is executed asynchronously. For
- * low-latency interfaces, the queue may be executed synchronously.
- *
- * The callback mechanism is very general and does not make many
- * assumptions about what the callback does or what its arguments are.
- * These callbacks are typically executed *after* the *entire* JTAG
- * queue has been executed for e.g. USB interfaces, and they are
- * guaranteeed to be invoked in the order that they were queued.
- *
- * If the execution of the queue fails before the callbacks, then --
- * depending on driver implementation -- the callbacks may or may not be
- * invoked.
- *
- * @todo Make that behavior consistent.
- *
- * @param data0 Typically used to point to the data to operate on.
- * Frequently this will be the data clocked in during a shift operation.
- * @param data1 An integer big enough to use as an @c int or a pointer.
- * @param data2 An integer big enough to use as an @c int or a pointer.
- * @param data3 An integer big enough to use as an @c int or a pointer.
- * @returns an error code
- */
-typedef int (*jtag_callback_t)(jtag_callback_data_t data0,
- jtag_callback_data_t data1,
- jtag_callback_data_t data2,
- jtag_callback_data_t data3);
-
-/**
- * Run a TAP_RESET reset where the end state is TAP_RESET,
- * regardless of the start state.
- */
-void jtag_add_tlr(void);
-
-/**
- * Application code *must* assume that interfaces will
- * implement transitions between states with different
- * paths and path lengths through the state diagram. The
- * path will vary across interface and also across versions
- * of the same interface over time. Even if the OpenOCD code
- * is unchanged, the actual path taken may vary over time
- * and versions of interface firmware or PCB revisions.
- *
- * Use jtag_add_pathmove() when specific transition sequences
- * are required.
- *
- * Do not use jtag_add_pathmove() unless you need to, but do use it
- * if you have to.
- *
- * DANGER! If the target is dependent upon a particular sequence
- * of transitions for things to work correctly(e.g. as a workaround
- * for an errata that contradicts the JTAG standard), then pathmove
- * must be used, even if some jtag interfaces happen to use the
- * desired path. Worse, the jtag interface used for testing a
- * particular implementation, could happen to use the "desired"
- * path when transitioning to/from end
- * state.
- *
- * A list of unambigious single clock state transitions, not
- * all drivers can support this, but it is required for e.g.
- * XScale and Xilinx support
- *
- * Note! TAP_RESET must not be used in the path!
- *
- * Note that the first on the list must be reachable
- * via a single transition from the current state.
- *
- * All drivers are required to implement jtag_add_pathmove().
- * However, if the pathmove sequence can not be precisely
- * executed, an interface_jtag_add_pathmove() or jtag_execute_queue()
- * must return an error. It is legal, but not recommended, that
- * a driver returns an error in all cases for a pathmove if it
- * can only implement a few transitions and therefore
- * a partial implementation of pathmove would have little practical
- * application.
- *
- * If an error occurs, jtag_error will contain one of these error codes:
- * - ERROR_JTAG_NOT_STABLE_STATE -- The final state was not stable.
- * - ERROR_JTAG_STATE_INVALID -- The path passed through TAP_RESET.
- * - ERROR_JTAG_TRANSITION_INVALID -- The path includes invalid
- * state transitions.
- */
-void jtag_add_pathmove(int num_states, const tap_state_t *path);
-
-/**
- * jtag_add_statemove() moves from the current state to @a goal_state.
- *
- * @param goal_state The final TAP state.
- * @return ERROR_OK on success, or an error code on failure.
- *
- * Moves from the current state to the goal \a state.
- * Both states must be stable.
- */
-int jtag_add_statemove(tap_state_t goal_state);
-
-/**
- * Goes to TAP_IDLE (if we're not already there), cycle
- * precisely num_cycles in the TAP_IDLE state, after which move
- * to @a endstate (unless it is also TAP_IDLE).
- *
- * @param num_cycles Number of cycles in TAP_IDLE state. This argument
- * may be 0, in which case this routine will navigate to @a endstate
- * via TAP_IDLE.
- * @param endstate The final state.
- */
-void jtag_add_runtest(int num_cycles, tap_state_t endstate);
-
-/**
- * A reset of the TAP state machine can be requested.
- *
- * Whether tms or trst reset is used depends on the capabilities of
- * the target and jtag interface(reset_config command configures this).
- *
- * srst can driver a reset of the TAP state machine and vice
- * versa
- *
- * Application code may need to examine value of jtag_reset_config
- * to determine the proper codepath
- *
- * DANGER! Even though srst drives trst, trst might not be connected to
- * the interface, and it might actually be *harmful* to assert trst in this case.
- *
- * This is why combinations such as "reset_config srst_only srst_pulls_trst"
- * are supported.
- *
- * only req_tlr_or_trst and srst can have a transition for a
- * call as the effects of transitioning both at the "same time"
- * are undefined, but when srst_pulls_trst or vice versa,
- * then trst & srst *must* be asserted together.
- */
-void jtag_add_reset(int req_tlr_or_trst, int srst);
-
-void jtag_add_sleep(uint32_t us);
-
-int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state t);
-
-/**
- * Function jtag_add_clocks
- * first checks that the state in which the clocks are to be issued is
- * stable, then queues up num_cycles clocks for transmission.
- */
-void jtag_add_clocks(int num_cycles);
-
-/**
- * For software FIFO implementations, the queued commands can be executed
- * during this call or earlier. A sw queue might decide to push out
- * some of the jtag_add_xxx() operations once the queue is "big enough".
- *
- * This fn will return an error code if any of the prior jtag_add_xxx()
- * calls caused a failure, e.g. check failure. Note that it does not
- * matter if the operation was executed *before* jtag_execute_queue(),
- * jtag_execute_queue() will still return an error code.
- *
- * All jtag_add_xxx() calls that have in_handler != NULL will have been
- * executed when this fn returns, but if what has been queued only
- * clocks data out, without reading anything back, then JTAG could
- * be running *after* jtag_execute_queue() returns. The API does
- * not define a way to flush a hw FIFO that runs *after*
- * jtag_execute_queue() returns.
- *
- * jtag_add_xxx() commands can either be executed immediately or
- * at some time between the jtag_add_xxx() fn call and jtag_execute_queue().
- */
-int jtag_execute_queue(void);
-
-/** same as jtag_execute_queue() but does not clear the error flag */
-void jtag_execute_queue_noclear(void);
-
-/** @returns the number of times the scan queue has been flushed */
-int jtag_get_flush_queue_count(void);
-
-/** Report Tcl event to all TAPs */
-void jtag_notify_event(enum jtag_event);
-
-/* can be implemented by hw + sw */
-int jtag_power_dropout(int *dropout);
-int jtag_srst_asserted(int *srst_asserted);
-
-/* JTAG support functions */
-
-/**
- * Execute jtag queue and check value with an optional mask.
- * @param field Pointer to scan field.
- * @param value Pointer to scan value.
- * @param mask Pointer to scan mask; may be NULL.
- * @returns Nothing, but calls jtag_set_error() on any error.
- */
-void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask);
-
-void jtag_sleep(uint32_t us);
-
-/*
- * The JTAG subsystem defines a number of error codes,
- * using codes between -100 and -199.
- */
-#define ERROR_JTAG_INIT_FAILED (-100)
-#define ERROR_JTAG_INVALID_INTERFACE (-101)
-#define ERROR_JTAG_NOT_IMPLEMENTED (-102)
-#define ERROR_JTAG_TRST_ASSERTED (-103)
-#define ERROR_JTAG_QUEUE_FAILED (-104)
-#define ERROR_JTAG_NOT_STABLE_STATE (-105)
-#define ERROR_JTAG_DEVICE_ERROR (-107)
-#define ERROR_JTAG_STATE_INVALID (-108)
-#define ERROR_JTAG_TRANSITION_INVALID (-109)
-#define ERROR_JTAG_INIT_SOFT_FAIL (-110)
-
-/**
- * Set the current JTAG core execution error, unless one was set
- * by a previous call previously. Driver or application code must
- * use jtag_error_clear to reset jtag_error once this routine has been
- * called with a non-zero error code.
- */
-void jtag_set_error(int error);
-/**
- * Resets jtag_error to ERROR_OK, returning its previous value.
- * @returns The previous value of @c jtag_error.
- */
-int jtag_error_clear(void);
-
-/**
- * Return true if it's safe for a background polling task to access the
- * JTAG scan chain. Polling may be explicitly disallowed, and is also
- * unsafe while nTRST is active or the JTAG clock is gated off.
- */
-bool is_jtag_poll_safe(void);
-
-/**
- * Return flag reporting whether JTAG polling is disallowed.
- */
-bool jtag_poll_get_enabled(void);
-
-/**
- * Assign flag reporting whether JTAG polling is disallowed.
- */
-void jtag_poll_set_enabled(bool value);
-
-
-/* The minidriver may have inline versions of some of the low
- * level APIs that are used in inner loops. */
-#include <jtag/minidriver.h>
-
-bool transport_is_jtag(void);
-
-int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-
-#endif /* OPENOCD_JTAG_JTAG_H */
diff --git a/src/jtag/minidriver.h b/src/jtag/minidriver.h
deleted file mode 100644
index 688c396..0000000
--- a/src/jtag/minidriver.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_MINIDRIVER_H
-#define OPENOCD_JTAG_MINIDRIVER_H
-
-/**
- * @page jtagminidriver JTAG Mini-Driver
- *
- * The JTAG minidriver interface allows the definition of alternate
- * interface functions, instead of the built-in asynchronous driver
- * module that is used by the standard JTAG interface drivers.
- *
- * In addtion to the functions defined in the @c minidriver.h file, the
- * @c jtag_minidriver.h file must declare the following functions (or
- * define static inline versions of them):
- * - jtag_add_callback
- * - jtag_add_callback4
- *
- * The following core functions are declared in this file for use by
- * the minidriver and do @b not need to be defined by an implementation:
- * - default_interface_jtag_execute_queue()
- */
-
-/* this header will be provided by the minidriver implementation, */
-/* and it may provide additional declarations that must be defined. */
-#include <jtag/minidriver_imp.h>
-
-int interface_jtag_add_ir_scan(struct jtag_tap *active,
- const struct scan_field *fields,
- tap_state_t endstate);
-int interface_jtag_add_plain_ir_scan(
- int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
- tap_state_t endstate);
-
-int interface_jtag_add_dr_scan(struct jtag_tap *active,
- int num_fields, const struct scan_field *fields,
- tap_state_t endstate);
-int interface_jtag_add_plain_dr_scan(
- int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
- tap_state_t endstate);
-
-int interface_jtag_add_tlr(void);
-int interface_jtag_add_pathmove(int num_states, const tap_state_t *path);
-int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
-
-int interface_add_tms_seq(unsigned num_bits,
- const uint8_t *bits, enum tap_state state);
-
-/**
- * This drives the actual srst and trst pins. srst will always be 0
- * if jtag_reset_config & RESET_SRST_PULLS_TRST != 0 and ditto for
- * trst.
- *
- * the higher level jtag_add_reset will invoke jtag_add_tlr() if
- * approperiate
- */
-int interface_jtag_add_reset(int trst, int srst);
-int interface_jtag_add_sleep(uint32_t us);
-int interface_jtag_add_clocks(int num_cycles);
-int interface_jtag_execute_queue(void);
-
-/**
- * Calls the interface callback to execute the queue. This routine
- * is used by the JTAG driver layer and should not be called directly.
- */
-int default_interface_jtag_execute_queue(void);
-
-#endif /* OPENOCD_JTAG_MINIDRIVER_H */
diff --git a/src/jtag/minidriver/minidriver_imp.h b/src/jtag/minidriver/minidriver_imp.h
deleted file mode 100644
index 11d0fae..0000000
--- a/src/jtag/minidriver/minidriver_imp.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H
-#define OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H
-
-#include <jtag/jtag_minidriver.h>
-
-#define jtag_add_callback(callback, in) interface_jtag_add_callback(callback, in)
-
-#define jtag_add_callback4(callback, in, data1, data2, data3) \
- interface_jtag_add_callback4(callback, in, data1, data2, data3)
-
-#endif /* OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H */
diff --git a/src/jtag/minidummy/jtag_minidriver.h b/src/jtag/minidummy/jtag_minidriver.h
deleted file mode 100644
index 1708356..0000000
--- a/src/jtag/minidummy/jtag_minidriver.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007-2008 by Øyvind Harboe *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#define interface_jtag_add_callback(callback, in) callback(in)
-
-#define interface_jtag_add_callback4(callback, in, data1, data2, data3) \
- jtag_set_error(callback(in, data1, data2, data3))
diff --git a/src/jtag/minidummy/minidummy.c b/src/jtag/minidummy/minidummy.c
deleted file mode 100644
index b7c989f..0000000
--- a/src/jtag/minidummy/minidummy.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007-2008 by Øyvind Harboe *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/jtag.h>
-#include <target/embeddedice.h>
-#include <jtag/minidriver.h>
-#include <jtag/interface.h>
-
-struct jtag_interface minidummy_interface = {
- .name = "minidummy",
- .execute_queue = NULL,
- .speed = NULL,
- .commands = NULL,
- .init = NULL,
- .quit = NULL,
- .khz = NULL,
- .speed_div = NULL,
- .power_dropout = NULL,
- .srst_asserted = NULL,
-};
-
-int interface_jtag_execute_queue(void)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_ir_scan(struct jtag_tap *active, const struct scan_field *fields,
- tap_state_t state)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits,
- uint8_t *in_bits, tap_state_t state)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_dr_scan(struct jtag_tap *active, int num_fields,
- const struct scan_field *fields, tap_state_t state)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits,
- uint8_t *in_bits, tap_state_t state)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_tlr()
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_reset(int req_trst, int req_srst)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_clocks(int num_cycles)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_sleep(uint32_t us)
-{
- jtag_sleep(us);
- return ERROR_OK;
-}
-
-int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
-{
- int state_count;
- int tms = 0;
-
- state_count = 0;
-
- tap_state_t cur_state = cmd_queue_cur_state;
-
- while (num_states) {
- if (tap_state_transition(cur_state, false) == path[state_count])
- tms = 0;
- else if (tap_state_transition(cur_state, true) == path[state_count])
- tms = 1;
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(cur_state), tap_state_name(path[state_count]));
- exit(-1);
- }
-
- /* synchronously do the operation here */
-
- cur_state = path[state_count];
- state_count++;
- num_states--;
- }
-
-
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
-{
- /* synchronously do the operation here */
-
- return ERROR_OK;
-}
-
-void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer,
- int little, int count)
-{
- int i;
- for (i = 0; i < count; i++) {
- embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, little));
- buffer += 4;
- }
-}
-
-int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap, uint32_t opcode,
- uint32_t *data, size_t count)
-{
- int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap, \
- uint32_t opcode, uint32_t *data, size_t count);
- return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
-}
diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl
deleted file mode 100644
index d57cafb..0000000
--- a/src/jtag/startup.tcl
+++ /dev/null
@@ -1,163 +0,0 @@
-# Defines basic Tcl procs for OpenOCD JTAG module
-
-# Executed during "init". Can be overridden
-# by board/target/... scripts
-proc jtag_init {} {
- if {[catch {jtag arp_init} err]!=0} {
- # try resetting additionally
- init_reset startup
- }
-}
-
-# This reset logic may be overridden by board/target/... scripts as needed
-# to provide a reset that, if possible, is close to a power-up reset.
-#
-# Exit requirements include: (a) JTAG must be working, (b) the scan
-# chain was validated with "jtag arp_init" (or equivalent), (c) nothing
-# stays in reset. No TAP-specific scans were performed. It's OK if
-# some targets haven't been reset yet; they may need TAP-specific scans.
-#
-# The "mode" values include: halt, init, run (from "reset" command);
-# startup (at OpenOCD server startup, when JTAG may not yet work); and
-# potentially more (for reset types like cold, warm, etc)
-proc init_reset { mode } {
- if {[using_jtag]} {
- jtag arp_init-reset
- }
-}
-
-#########
-
-# TODO: power_restore and power_dropout are currently neither
-# documented nor supported except on ZY1000.
-
-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]
- 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."
-
-proc power_dropout {} {
- echo "Sensed power dropout."
-}
-
-#########
-
-# TODO: srst_deasserted and srst_asserted are currently neither
-# documented nor supported except on ZY1000.
-
-proc srst_deasserted {} {
- echo "Sensed nSRST deasserted, running reset init and halting GDB."
- reset init
-
- # Halt GDB so user can deal with a detected reset.
- #
- # After GDB is halted, then output is no longer forwarded
- # to the GDB console.
- 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."
-
-proc srst_asserted {} {
- echo "Sensed nSRST asserted."
-}
-
-# measure actual JTAG clock
-proc measure_clk {} {
- set start_time [ms];
- set iterations 10000000;
- runtest $iterations;
- echo "Running at more than [expr $iterations.0 / ([ms]-$start_time)] kHz";
-}
-
-add_help_text measure_clk "Runs a test to measure the JTAG clk. Useful with RCLK / RTCK."
-
-proc default_to_jtag { f args } {
- set current_transport [transport select]
- if {[using_jtag]} {
- eval $f $args
- } {
- error "session transport is \"$current_transport\" but your config requires JTAG"
- }
-}
-
-proc jtag args {
- eval default_to_jtag jtag $args
-}
-
-proc jtag_rclk args {
- eval default_to_jtag jtag_rclk $args
-}
-
-proc jtag_ntrst_delay args {
- eval default_to_jtag jtag_ntrst_delay $args
-}
-
-proc jtag_ntrst_assert_width args {
- eval default_to_jtag jtag_ntrst_assert_width $args
-}
-
-# BEGIN MIGRATION AIDS ... these adapter operations originally had
-# JTAG-specific names despite the fact that the operations were not
-# specific to JTAG, or otherewise had troublesome/misleading names.
-#
-# 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
-}
-
-proc jtag_nsrst_delay args {
- echo "DEPRECATED! use 'adapter_nsrst_delay' not 'jtag_nsrst_delay'"
- eval adapter_nsrst_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
-}
-
-# stlink migration helpers
-proc stlink_device_desc args {
- echo "DEPRECATED! use 'hla_device_desc' not 'stlink_device_desc'"
- eval hla_device_desc $args
-}
-
-proc stlink_serial args {
- echo "DEPRECATED! use 'hla_serial' not 'stlink_serial'"
- eval hla_serial $args
-}
-
-proc stlink_layout args {
- echo "DEPRECATED! use 'hla_layout' not 'stlink_layout'"
- eval hla_layout $args
-}
-
-proc stlink_vid_pid args {
- echo "DEPRECATED! use 'hla_vid_pid' not 'stlink_vid_pid'"
- eval hla_vid_pid $args
-}
-
-proc stlink args {
- echo "DEPRECATED! use 'hla' not 'stlink'"
- eval hla $args
-}
-
-# END MIGRATION AIDS
diff --git a/src/jtag/swd.h b/src/jtag/swd.h
deleted file mode 100644
index c888cc0..0000000
--- a/src/jtag/swd.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by David Brownell *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_SWD_H
-#define OPENOCD_JTAG_SWD_H
-
-#include <target/arm_adi_v5.h>
-
-/* Bits in SWD command packets, written from host to target
- * first bit on the wire is START
- */
-#define SWD_CMD_START (1 << 0) /* always set */
-#define SWD_CMD_APnDP (1 << 1) /* set only for AP access */
-#define SWD_CMD_RnW (1 << 2) /* set only for read access */
-#define SWD_CMD_A32 (3 << 3) /* bits A[3:2] of register addr */
-#define SWD_CMD_PARITY (1 << 5) /* parity of APnDP|RnW|A32 */
-#define SWD_CMD_STOP (0 << 6) /* always clear for synch SWD */
-#define SWD_CMD_PARK (1 << 7) /* driven high by host */
-/* followed by TRN, 3-bits of ACK, TRN */
-
-/**
- * Construct a "cmd" byte, in lSB bit order, which swd_driver.read_reg()
- * and swd_driver.write_reg() methods will use directly.
- */
-static inline uint8_t swd_cmd(bool is_read, bool is_ap, uint8_t regnum)
-{
- uint8_t cmd = (is_ap ? SWD_CMD_APnDP : 0)
- | (is_read ? SWD_CMD_RnW : 0)
- | ((regnum & 0xc) << 1);
-
- /* 8 cmd bits 4:1 may be set */
- if (parity_u32(cmd))
- cmd |= SWD_CMD_PARITY;
-
- /* driver handles START, STOP, and TRN */
-
- return cmd;
-}
-
-/* SWD_ACK_* bits are defined in <target/arm_adi_v5.h> */
-
-/**
- * Line reset.
- *
- * Line reset is at least 50 SWCLK cycles with SWDIO driven high, followed
- * by at least one idle (low) cycle.
- */
-static const uint8_t swd_seq_line_reset[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03
-};
-static const unsigned swd_seq_line_reset_len = 51;
-
-/**
- * JTAG-to-SWD sequence.
- *
- * The JTAG-to-SWD sequence is at least 50 TCK/SWCLK cycles with TMS/SWDIO
- * high, putting either interface logic into reset state, followed by a
- * specific 16-bit sequence and finally a line reset in case the SWJ-DP was
- * already in SWD mode.
- */
-static const uint8_t swd_seq_jtag_to_swd[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x9e,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
-};
-static const unsigned swd_seq_jtag_to_swd_len = 118;
-
-/**
- * SWD-to-JTAG sequence.
- *
- * The SWD-to-JTAG sequence is at least 50 TCK/SWCLK cycles with TMS/SWDIO
- * high, putting either interface logic into reset state, followed by a
- * specific 16-bit sequence and finally at least 5 TCK cycles to put the
- * JTAG TAP in TLR.
- */
-static const uint8_t swd_seq_swd_to_jtag[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xff
-};
-static const unsigned swd_seq_swd_to_jtag_len = 71;
-
-/**
- * SWD-to-dormant sequence.
- *
- * This is at least 50 SWCLK cycles with SWDIO high to put the interface
- * in reset state, followed by a specific 16-bit sequence.
- */
-static const uint8_t swd_seq_swd_to_dormant[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x8e, 0x03
-};
-static const unsigned swd_seq_swd_to_dormant_len = 66;
-
-/**
- * Dormant-to-SWD sequence.
- *
- * This is at least 8 TCK/SWCLK cycles with TMS/SWDIO high to abort any ongoing
- * selection alert sequence, followed by a specific 128-bit selection alert
- * sequence, followed by 4 TCK/SWCLK cycles with TMS/SWDIO low, followed by
- * a specific protocol-dependent activation code. For SWD the activation code
- * is an 8-bit sequence. The sequence ends with a line reset.
- */
-static const uint8_t swd_seq_dormant_to_swd[] = {
- 0xff,
- 0x92, 0xf3, 0x09, 0x62, 0x95, 0x2d, 0x85, 0x86,
- 0xe9, 0xaf, 0xdd, 0xe3, 0xa2, 0x0e, 0xbc, 0x19,
- 0x10, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
-};
-static const unsigned swd_seq_dormant_to_swd_len = 199;
-
-enum swd_special_seq {
- LINE_RESET,
- JTAG_TO_SWD,
- SWD_TO_JTAG,
- SWD_TO_DORMANT,
- DORMANT_TO_SWD,
-};
-
-struct swd_driver {
- /**
- * Initialize the debug link so it can perform SWD operations.
- *
- * As an example, this would switch a dual-mode debug adapter
- * into SWD mode and out of JTAG mode.
- *
- * @return ERROR_OK on success, else a negative fault code.
- */
- int (*init)(void);
-
- /**
- * Set the SWCLK frequency of the SWD link.
- *
- * The driver should round the desired value, downwards if possible, to
- * the nearest supported frequency. A negative value should be ignored
- * and can be used to query the current setting. If the driver does not
- * support a variable frequency a fixed, nominal, value should be
- * returned.
- *
- * If the frequency is increased, it must not apply before the currently
- * queued transactions are executed. If the frequency is lowered, it may
- * apply immediately.
- *
- * @param hz The desired frequency in Hz.
- * @return The actual resulting frequency after rounding.
- */
- int_least32_t (*frequency)(int_least32_t hz);
-
- /**
- * Queue a special SWDIO sequence.
- *
- * @param seq The special sequence to generate.
- * @return ERROR_OK if the sequence was queued, negative error if the
- * sequence is unsupported.
- */
- int (*switch_seq)(enum swd_special_seq seq);
-
- /**
- * Queued read of an AP or DP register.
- *
- * @param Command byte with APnDP/RnW/addr/parity bits
- * @param Where to store value to read from register
- * @param ap_delay_hint Number of idle cycles that may be
- * needed after an AP access to avoid WAITs
- */
- void (*read_reg)(uint8_t cmd, uint32_t *value, uint32_t ap_delay_hint);
-
- /**
- * Queued write of an AP or DP register.
- *
- * @param Command byte with APnDP/RnW/addr/parity bits
- * @param Value to be written to the register
- * @param ap_delay_hint Number of idle cycles that may be
- * needed after an AP access to avoid WAITs
- */
- void (*write_reg)(uint8_t cmd, uint32_t value, uint32_t ap_delay_hint);
-
- /**
- * Execute any queued transactions and collect the result.
- *
- * @return ERROR_OK on success, Ack response code on WAIT/FAULT
- * or negative error code on other kinds of failure.
- */
- int (*run)(void);
-
- /**
- * Configures data collection from the Single-wire
- * trace (SWO) signal.
- * @param swo true if SWO data collection should be routed.
- *
- * For example, some debug adapters include a UART which
- * is normally connected to a microcontroller's UART TX,
- * but which may instead be connected to SWO for use in
- * collecting ITM (and possibly ETM) trace data.
- *
- * @return ERROR_OK on success, else a negative fault code.
- */
- int *(*trace)(bool swo);
-};
-
-int swd_init_reset(struct command_context *cmd_ctx);
-void swd_add_reset(int req_srst);
-
-bool transport_is_swd(void);
-
-#endif /* OPENOCD_JTAG_SWD_H */
diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
deleted file mode 100644
index bc6bbf2..0000000
--- a/src/jtag/tcl.c
+++ /dev/null
@@ -1,1387 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag.h"
-#include "swd.h"
-#include "minidriver.h"
-#include "interface.h"
-#include "interfaces.h"
-#include "tcl.h"
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#include <helper/time_support.h>
-
-/**
- * @file
- * Holds support for accessing JTAG-specific mechanisms from TCl scripts.
- */
-
-static const Jim_Nvp nvp_jtag_tap_event[] = {
- { .value = JTAG_TRST_ASSERTED, .name = "post-reset" },
- { .value = JTAG_TAP_EVENT_SETUP, .name = "setup" },
- { .value = JTAG_TAP_EVENT_ENABLE, .name = "tap-enable" },
- { .value = JTAG_TAP_EVENT_DISABLE, .name = "tap-disable" },
-
- { .name = NULL, .value = -1 }
-};
-
-struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
-{
- const char *cp = Jim_GetString(o, NULL);
- struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL;
- if (NULL == cp)
- cp = "(unknown)";
- if (NULL == t)
- Jim_SetResultFormatted(interp, "Tap '%s' could not be found", cp);
- return t;
-}
-
-static bool scan_is_safe(tap_state_t state)
-{
- switch (state) {
- case TAP_RESET:
- case TAP_IDLE:
- case TAP_DRPAUSE:
- case TAP_IRPAUSE:
- return true;
- default:
- return false;
- }
-}
-
-static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args)
-{
- int retval;
- struct scan_field *fields;
- int num_fields;
- int field_count = 0;
- int i, e;
- struct jtag_tap *tap;
- tap_state_t endstate;
-
- /* args[1] = device
- * args[2] = num_bits
- * args[3] = hex string
- * ... repeat num bits and hex string ...
- *
- * .. optionally:
- * args[N-2] = "-endstate"
- * args[N-1] = statename
- */
- if ((argc < 4) || ((argc % 2) != 0)) {
- Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
- return JIM_ERR;
- }
-
- endstate = TAP_IDLE;
-
- script_debug(interp, "drscan", argc, args);
-
- /* validate arguments as numbers */
- e = JIM_OK;
- for (i = 2; i < argc; i += 2) {
- long bits;
- const char *cp;
-
- e = Jim_GetLong(interp, args[i], &bits);
- /* If valid - try next arg */
- if (e == JIM_OK)
- continue;
-
- /* Not valid.. are we at the end? */
- if (((i + 2) != argc)) {
- /* nope, then error */
- return e;
- }
-
- /* it could be: "-endstate FOO"
- * e.g. DRPAUSE so we can issue more instructions
- * before entering RUN/IDLE and executing them.
- */
-
- /* get arg as a string. */
- cp = Jim_GetString(args[i], NULL);
- /* is it the magic? */
- if (0 == strcmp("-endstate", cp)) {
- /* is the statename valid? */
- cp = Jim_GetString(args[i + 1], NULL);
-
- /* see if it is a valid state name */
- endstate = tap_state_by_name(cp);
- if (endstate < 0) {
- /* update the error message */
- Jim_SetResultFormatted(interp, "endstate: %s invalid", cp);
- } else {
- if (!scan_is_safe(endstate))
- LOG_WARNING("drscan with unsafe "
- "endstate \"%s\"", cp);
-
- /* valid - so clear the error */
- e = JIM_OK;
- /* and remove the last 2 args */
- argc -= 2;
- }
- }
-
- /* Still an error? */
- if (e != JIM_OK)
- return e; /* too bad */
- } /* validate args */
-
- assert(e == JIM_OK);
-
- tap = jtag_tap_by_jim_obj(interp, args[1]);
- if (tap == NULL)
- return JIM_ERR;
-
- num_fields = (argc-2)/2;
- if (num_fields <= 0) {
- Jim_SetResultString(interp, "drscan: no scan fields supplied", -1);
- return JIM_ERR;
- }
- fields = malloc(sizeof(struct scan_field) * num_fields);
- for (i = 2; i < argc; i += 2) {
- long bits;
- int len;
- const char *str;
-
- Jim_GetLong(interp, args[i], &bits);
- str = Jim_GetString(args[i + 1], &len);
-
- fields[field_count].num_bits = bits;
- void *t = malloc(DIV_ROUND_UP(bits, 8));
- fields[field_count].out_value = t;
- str_to_buf(str, len, t, bits, 0);
- fields[field_count].in_value = t;
- field_count++;
- }
-
- jtag_add_dr_scan(tap, num_fields, fields, endstate);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- Jim_SetResultString(interp, "drscan: jtag execute failed", -1);
- return JIM_ERR;
- }
-
- field_count = 0;
- Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
- for (i = 2; i < argc; i += 2) {
- long bits;
- char *str;
-
- Jim_GetLong(interp, args[i], &bits);
- str = buf_to_str(fields[field_count].in_value, bits, 16);
- free(fields[field_count].in_value);
-
- Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));
- free(str);
- field_count++;
- }
-
- Jim_SetResult(interp, list);
-
- free(fields);
-
- return JIM_OK;
-}
-
-
-static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *args)
-{
- tap_state_t states[8];
-
- if ((argc < 2) || ((size_t)argc > (ARRAY_SIZE(states) + 1))) {
- Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
- return JIM_ERR;
- }
-
- script_debug(interp, "pathmove", argc, args);
-
- int i;
- for (i = 0; i < argc-1; i++) {
- const char *cp;
- cp = Jim_GetString(args[i + 1], NULL);
- states[i] = tap_state_by_name(cp);
- if (states[i] < 0) {
- /* update the error message */
- Jim_SetResultFormatted(interp, "endstate: %s invalid", cp);
- return JIM_ERR;
- }
- }
-
- if ((jtag_add_statemove(states[0]) != ERROR_OK) || (jtag_execute_queue() != ERROR_OK)) {
- Jim_SetResultString(interp, "pathmove: jtag execute failed", -1);
- return JIM_ERR;
- }
-
- jtag_add_pathmove(argc - 2, states + 1);
-
- if (jtag_execute_queue() != ERROR_OK) {
- Jim_SetResultString(interp, "pathmove: failed", -1);
- return JIM_ERR;
- }
-
- return JIM_OK;
-}
-
-
-static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args)
-{
- script_debug(interp, "flush_count", argc, args);
-
- Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count()));
-
- return JIM_OK;
-}
-
-/* REVISIT Just what about these should "move" ... ?
- * These registrations, into the main JTAG table?
- *
- * There's a minor compatibility issue, these all show up twice;
- * that's not desirable:
- * - jtag drscan ... NOT DOCUMENTED!
- * - drscan ...
- *
- * The "irscan" command (for example) doesn't show twice.
- */
-static const struct command_registration jtag_command_handlers_to_move[] = {
- {
- .name = "drscan",
- .mode = COMMAND_EXEC,
- .jim_handler = Jim_Command_drscan,
- .help = "Execute Data Register (DR) scan for one TAP. "
- "Other TAPs must be in BYPASS mode.",
- .usage = "tap_name [num_bits value]* ['-endstate' state_name]",
- },
- {
- .name = "flush_count",
- .mode = COMMAND_EXEC,
- .jim_handler = Jim_Command_flush_count,
- .help = "Returns the number of times the JTAG queue "
- "has been flushed.",
- },
- {
- .name = "pathmove",
- .mode = COMMAND_EXEC,
- .jim_handler = Jim_Command_pathmove,
- .usage = "start_state state1 [state2 [state3 ...]]",
- .help = "Move JTAG state machine from current state "
- "(start_state) to state1, then state2, state3, etc.",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-
-enum jtag_tap_cfg_param {
- JCFG_EVENT
-};
-
-static Jim_Nvp nvp_config_opts[] = {
- { .name = "-event", .value = JCFG_EVENT },
-
- { .name = NULL, .value = -1 }
-};
-
-static int jtag_tap_configure_event(Jim_GetOptInfo *goi, struct jtag_tap *tap)
-{
- if (goi->argc == 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event <event-name> ...");
- return JIM_ERR;
- }
-
- Jim_Nvp *n;
- int e = Jim_GetOpt_Nvp(goi, nvp_jtag_tap_event, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1);
- return e;
- }
-
- if (goi->isconfigure) {
- if (goi->argc != 1) {
- Jim_WrongNumArgs(goi->interp,
- goi->argc,
- goi->argv,
- "-event <event-name> <event-body>");
- return JIM_ERR;
- }
- } else {
- if (goi->argc != 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event <event-name>");
- return JIM_ERR;
- }
- }
-
- struct jtag_tap_event_action *jteap = tap->event_action;
- /* replace existing event body */
- bool found = false;
- while (jteap) {
- if (jteap->event == (enum jtag_event)n->value) {
- found = true;
- break;
- }
- jteap = jteap->next;
- }
-
- Jim_SetEmptyResult(goi->interp);
-
- if (goi->isconfigure) {
- if (!found)
- jteap = calloc(1, sizeof(*jteap));
- else if (NULL != jteap->body)
- Jim_DecrRefCount(goi->interp, jteap->body);
-
- jteap->interp = goi->interp;
- jteap->event = n->value;
-
- Jim_Obj *o;
- Jim_GetOpt_Obj(goi, &o);
- jteap->body = Jim_DuplicateObj(goi->interp, o);
- Jim_IncrRefCount(jteap->body);
-
- if (!found) {
- /* add to head of event list */
- jteap->next = tap->event_action;
- tap->event_action = jteap;
- }
- } else if (found) {
- jteap->interp = goi->interp;
- Jim_SetResult(goi->interp,
- Jim_DuplicateObj(goi->interp, jteap->body));
- }
- return JIM_OK;
-}
-
-static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, struct jtag_tap *tap)
-{
- /* parse config or cget options */
- while (goi->argc > 0) {
- Jim_SetEmptyResult(goi->interp);
-
- Jim_Nvp *n;
- int e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
- return e;
- }
-
- switch (n->value) {
- case JCFG_EVENT:
- e = jtag_tap_configure_event(goi, tap);
- if (e != JIM_OK)
- return e;
- break;
- default:
- Jim_SetResultFormatted(goi->interp, "unknown event: %s", n->name);
- return JIM_ERR;
- }
- }
-
- return JIM_OK;
-}
-
-static int is_bad_irval(int ir_length, jim_wide w)
-{
- jim_wide v = 1;
-
- v <<= ir_length;
- v -= 1;
- v = ~v;
- return (w & v) != 0;
-}
-
-static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
- struct jtag_tap *pTap)
-{
- jim_wide w;
- int e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK) {
- Jim_SetResultFormatted(goi->interp, "option: %s bad parameter", n->name);
- return e;
- }
-
- uint32_t *p = realloc(pTap->expected_ids,
- (pTap->expected_ids_cnt + 1) * sizeof(uint32_t));
- if (!p) {
- Jim_SetResultFormatted(goi->interp, "no memory");
- return JIM_ERR;
- }
-
- pTap->expected_ids = p;
- pTap->expected_ids[pTap->expected_ids_cnt++] = w;
-
- return JIM_OK;
-}
-
-#define NTAP_OPT_IRLEN 0
-#define NTAP_OPT_IRMASK 1
-#define NTAP_OPT_IRCAPTURE 2
-#define NTAP_OPT_ENABLED 3
-#define NTAP_OPT_DISABLED 4
-#define NTAP_OPT_EXPECTED_ID 5
-#define NTAP_OPT_VERSION 6
-
-static int jim_newtap_ir_param(Jim_Nvp *n, Jim_GetOptInfo *goi,
- struct jtag_tap *pTap)
-{
- jim_wide w;
- int e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK) {
- Jim_SetResultFormatted(goi->interp,
- "option: %s bad parameter", n->name);
- return e;
- }
- switch (n->value) {
- case NTAP_OPT_IRLEN:
- if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value))) {
- LOG_WARNING("%s: huge IR length %d",
- pTap->dotted_name, (int) w);
- }
- pTap->ir_length = w;
- break;
- case NTAP_OPT_IRMASK:
- if (is_bad_irval(pTap->ir_length, w)) {
- LOG_ERROR("%s: IR mask %x too big",
- pTap->dotted_name,
- (int) w);
- return JIM_ERR;
- }
- if ((w & 3) != 3)
- LOG_WARNING("%s: nonstandard IR mask", pTap->dotted_name);
- pTap->ir_capture_mask = w;
- break;
- case NTAP_OPT_IRCAPTURE:
- if (is_bad_irval(pTap->ir_length, w)) {
- LOG_ERROR("%s: IR capture %x too big",
- pTap->dotted_name, (int) w);
- return JIM_ERR;
- }
- if ((w & 3) != 1)
- LOG_WARNING("%s: nonstandard IR value",
- pTap->dotted_name);
- pTap->ir_capture_value = w;
- break;
- default:
- return JIM_ERR;
- }
- return JIM_OK;
-}
-
-static int jim_newtap_cmd(Jim_GetOptInfo *goi)
-{
- struct jtag_tap *pTap;
- int x;
- int e;
- Jim_Nvp *n;
- char *cp;
- const Jim_Nvp opts[] = {
- { .name = "-irlen", .value = NTAP_OPT_IRLEN },
- { .name = "-irmask", .value = NTAP_OPT_IRMASK },
- { .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE },
- { .name = "-enable", .value = NTAP_OPT_ENABLED },
- { .name = "-disable", .value = NTAP_OPT_DISABLED },
- { .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
- { .name = "-ignore-version", .value = NTAP_OPT_VERSION },
- { .name = NULL, .value = -1 },
- };
-
- pTap = calloc(1, sizeof(struct jtag_tap));
- if (!pTap) {
- Jim_SetResultFormatted(goi->interp, "no memory");
- return JIM_ERR;
- }
-
- /*
- * we expect CHIP + TAP + OPTIONS
- * */
- if (goi->argc < 3) {
- Jim_SetResultFormatted(goi->interp, "Missing CHIP TAP OPTIONS ....");
- free(pTap);
- return JIM_ERR;
- }
-
- const char *tmp;
- Jim_GetOpt_String(goi, &tmp, NULL);
- pTap->chip = strdup(tmp);
-
- Jim_GetOpt_String(goi, &tmp, NULL);
- pTap->tapname = strdup(tmp);
-
- /* name + dot + name + null */
- x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
- cp = malloc(x);
- sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
- pTap->dotted_name = cp;
-
- LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
- pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);
-
- if (!transport_is_jtag()) {
- /* SWD doesn't require any JTAG tap parameters */
- pTap->enabled = true;
- jtag_tap_init(pTap);
- return JIM_OK;
- }
-
- /* IEEE specifies that the two LSBs of an IR scan are 01, so make
- * that the default. The "-ircapture" and "-irmask" options are only
- * needed to cope with nonstandard TAPs, or to specify more bits.
- */
- pTap->ir_capture_mask = 0x03;
- pTap->ir_capture_value = 0x01;
-
- while (goi->argc) {
- e = Jim_GetOpt_Nvp(goi, opts, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, opts, 0);
- free(cp);
- free(pTap);
- return e;
- }
- LOG_DEBUG("Processing option: %s", n->name);
- switch (n->value) {
- case NTAP_OPT_ENABLED:
- pTap->disabled_after_reset = false;
- break;
- case NTAP_OPT_DISABLED:
- pTap->disabled_after_reset = true;
- break;
- case NTAP_OPT_EXPECTED_ID:
- e = jim_newtap_expected_id(n, goi, pTap);
- if (JIM_OK != e) {
- free(cp);
- free(pTap);
- return e;
- }
- break;
- case NTAP_OPT_IRLEN:
- case NTAP_OPT_IRMASK:
- case NTAP_OPT_IRCAPTURE:
- e = jim_newtap_ir_param(n, goi, pTap);
- if (JIM_OK != e) {
- free(cp);
- free(pTap);
- return e;
- }
- break;
- case NTAP_OPT_VERSION:
- pTap->ignore_version = true;
- break;
- } /* switch (n->value) */
- } /* while (goi->argc) */
-
- /* default is enabled-after-reset */
- pTap->enabled = !pTap->disabled_after_reset;
-
- /* Did all the required option bits get cleared? */
- if (pTap->ir_length != 0) {
- jtag_tap_init(pTap);
- return JIM_OK;
- }
-
- Jim_SetResultFormatted(goi->interp,
- "newtap: %s missing IR length",
- pTap->dotted_name);
- jtag_tap_free(pTap);
- return JIM_ERR;
-}
-
-static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
-{
- struct jtag_tap_event_action *jteap;
-
- for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) {
- if (jteap->event != e)
- continue;
-
- Jim_Nvp *nvp = Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e);
- LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
- tap->dotted_name, e, nvp->name,
- Jim_GetString(jteap->body, NULL));
-
- if (Jim_EvalObj(jteap->interp, jteap->body) != JIM_OK) {
- Jim_MakeErrorMessage(jteap->interp);
- LOG_USER("%s", Jim_GetString(Jim_GetResult(jteap->interp), NULL));
- continue;
- }
-
- switch (e) {
- case JTAG_TAP_EVENT_ENABLE:
- case JTAG_TAP_EVENT_DISABLE:
- /* NOTE: we currently assume the handlers
- * can't fail. Right here is where we should
- * really be verifying the scan chains ...
- */
- tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
- LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
- tap->enabled ? "enabled" : "disabled");
- break;
- default:
- break;
- }
- }
-}
-
-static int jim_jtag_arp_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
- if (goi.argc != 0) {
- Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
- return JIM_ERR;
- }
- struct command_context *context = current_command_context(interp);
- int e = jtag_init_inner(context);
- if (e != ERROR_OK) {
- Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e);
- Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
- Jim_FreeNewObj(goi.interp, eObj);
- return JIM_ERR;
- }
- return JIM_OK;
-}
-
-static int jim_jtag_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- int e = ERROR_OK;
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
- if (goi.argc != 0) {
- Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
- return JIM_ERR;
- }
- struct command_context *context = current_command_context(interp);
- if (transport_is_jtag())
- e = jtag_init_reset(context);
- else if (transport_is_swd())
- e = swd_init_reset(context);
-
- if (e != ERROR_OK) {
- Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e);
- Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
- Jim_FreeNewObj(goi.interp, eObj);
- return JIM_ERR;
- }
- return JIM_OK;
-}
-
-int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
- return jim_newtap_cmd(&goi);
-}
-
-static bool jtag_tap_enable(struct jtag_tap *t)
-{
- if (t->enabled)
- return false;
- jtag_tap_handle_event(t, JTAG_TAP_EVENT_ENABLE);
- if (!t->enabled)
- return false;
-
- /* FIXME add JTAG sanity checks, w/o TLR
- * - scan chain length grew by one (this)
- * - IDs and IR lengths are as expected
- */
- jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE);
- return true;
-}
-static bool jtag_tap_disable(struct jtag_tap *t)
-{
- if (!t->enabled)
- return false;
- jtag_tap_handle_event(t, JTAG_TAP_EVENT_DISABLE);
- if (t->enabled)
- return false;
-
- /* FIXME add JTAG sanity checks, w/o TLR
- * - scan chain length shrank by one (this)
- * - IDs and IR lengths are as expected
- */
- jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE);
- return true;
-}
-
-int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
- if (goi.argc != 1) {
- Jim_SetResultFormatted(goi.interp, "usage: %s <name>", cmd_name);
- return JIM_ERR;
- }
-
- struct jtag_tap *t;
-
- t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]);
- if (t == NULL)
- return JIM_ERR;
-
- if (strcasecmp(cmd_name, "tapisenabled") == 0) {
- /* do nothing, just return the value */
- } else if (strcasecmp(cmd_name, "tapenable") == 0) {
- if (!jtag_tap_enable(t)) {
- LOG_WARNING("failed to enable tap %s", t->dotted_name);
- return JIM_ERR;
- }
- } else if (strcasecmp(cmd_name, "tapdisable") == 0) {
- if (!jtag_tap_disable(t)) {
- LOG_WARNING("failed to disable tap %s", t->dotted_name);
- return JIM_ERR;
- }
- } else {
- LOG_ERROR("command '%s' unknown", cmd_name);
- return JIM_ERR;
- }
- bool e = t->enabled;
- Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
- return JIM_OK;
-}
-
-int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
- goi.isconfigure = !strcmp(cmd_name, "configure");
- if (goi.argc < 2 + goi.isconfigure) {
- Jim_WrongNumArgs(goi.interp, 0, NULL,
- "<tap_name> <attribute> ...");
- return JIM_ERR;
- }
-
- struct jtag_tap *t;
-
- Jim_Obj *o;
- Jim_GetOpt_Obj(&goi, &o);
- t = jtag_tap_by_jim_obj(goi.interp, o);
- if (t == NULL)
- return JIM_ERR;
-
- return jtag_tap_configure_cmd(&goi, t);
-}
-
-static int jim_jtag_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
- if (goi.argc != 0) {
- Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
- return JIM_ERR;
- }
- Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
- struct jtag_tap *tap;
-
- for (tap = jtag_all_taps(); tap; tap = tap->next_tap) {
- Jim_ListAppendElement(goi.interp,
- Jim_GetResult(goi.interp),
- Jim_NewStringObj(goi.interp,
- tap->dotted_name, -1));
- }
- return JIM_OK;
-}
-
-COMMAND_HANDLER(handle_jtag_init_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- static bool jtag_initialized;
- if (jtag_initialized) {
- LOG_INFO("'jtag init' has already been called");
- return ERROR_OK;
- }
- jtag_initialized = true;
-
- LOG_DEBUG("Initializing jtag devices...");
- return jtag_init(CMD_CTX);
-}
-
-static const struct command_registration jtag_subcommand_handlers[] = {
- {
- .name = "init",
- .mode = COMMAND_ANY,
- .handler = handle_jtag_init_command,
- .help = "initialize jtag scan chain",
- .usage = ""
- },
- {
- .name = "arp_init",
- .mode = COMMAND_ANY,
- .jim_handler = jim_jtag_arp_init,
- .help = "Validates JTAG scan chain against the list of "
- "declared TAPs using just the four standard JTAG "
- "signals.",
- },
- {
- .name = "arp_init-reset",
- .mode = COMMAND_ANY,
- .jim_handler = jim_jtag_arp_init_reset,
- .help = "Uses TRST and SRST to try resetting everything on "
- "the JTAG scan chain, then performs 'jtag arp_init'."
- },
- {
- .name = "newtap",
- .mode = COMMAND_CONFIG,
- .jim_handler = jim_jtag_newtap,
- .help = "Create a new TAP instance named basename.tap_type, "
- "and appends it to the scan chain.",
- .usage = "basename tap_type '-irlen' count "
- "['-enable'|'-disable'] "
- "['-expected_id' number] "
- "['-ignore-version'] "
- "['-ircapture' number] "
- "['-mask' number] ",
- },
- {
- .name = "tapisenabled",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- .help = "Returns a Tcl boolean (0/1) indicating whether "
- "the TAP is enabled (1) or not (0).",
- .usage = "tap_name",
- },
- {
- .name = "tapenable",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- .help = "Try to enable the specified TAP using the "
- "'tap-enable' TAP event.",
- .usage = "tap_name",
- },
- {
- .name = "tapdisable",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_tap_enabler,
- .help = "Try to disable the specified TAP using the "
- "'tap-disable' TAP event.",
- .usage = "tap_name",
- },
- {
- .name = "configure",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_configure,
- .help = "Provide a Tcl handler for the specified "
- "TAP event.",
- .usage = "tap_name '-event' event_name handler",
- },
- {
- .name = "cget",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_jtag_configure,
- .help = "Return any Tcl handler for the specified "
- "TAP event.",
- .usage = "tap_name '-event' event_name",
- },
- {
- .name = "names",
- .mode = COMMAND_ANY,
- .jim_handler = jim_jtag_names,
- .help = "Returns list of all JTAG tap names.",
- },
- {
- .chain = jtag_command_handlers_to_move,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-void jtag_notify_event(enum jtag_event event)
-{
- struct jtag_tap *tap;
-
- for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
- jtag_tap_handle_event(tap, event);
-}
-
-
-COMMAND_HANDLER(handle_scan_chain_command)
-{
- struct jtag_tap *tap;
- char expected_id[12];
-
- tap = jtag_all_taps();
- command_print(CMD_CTX,
- " TapName Enabled IdCode Expected IrLen IrCap IrMask");
- command_print(CMD_CTX,
- "-- ------------------- -------- ---------- ---------- ----- ----- ------");
-
- while (tap) {
- uint32_t expected, expected_mask, ii;
-
- snprintf(expected_id, sizeof expected_id, "0x%08x",
- (unsigned)((tap->expected_ids_cnt > 0)
- ? tap->expected_ids[0]
- : 0));
- if (tap->ignore_version)
- expected_id[2] = '*';
-
- expected = buf_get_u32(tap->expected, 0, tap->ir_length);
- expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
-
- command_print(CMD_CTX,
- "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x",
- tap->abs_chain_position,
- tap->dotted_name,
- tap->enabled ? 'Y' : 'n',
- (unsigned int)(tap->idcode),
- expected_id,
- (unsigned int)(tap->ir_length),
- (unsigned int)(expected),
- (unsigned int)(expected_mask));
-
- for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
- snprintf(expected_id, sizeof expected_id, "0x%08x",
- (unsigned) tap->expected_ids[ii]);
- if (tap->ignore_version)
- expected_id[2] = '*';
-
- command_print(CMD_CTX,
- " %s",
- expected_id);
- }
-
- tap = tap->next_tap;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_jtag_ntrst_delay_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (CMD_ARGC == 1) {
- unsigned delay;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
-
- jtag_set_ntrst_delay(delay);
- }
- command_print(CMD_CTX, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay());
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_jtag_ntrst_assert_width_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (CMD_ARGC == 1) {
- unsigned delay;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], delay);
-
- jtag_set_ntrst_assert_width(delay);
- }
- command_print(CMD_CTX, "jtag_ntrst_assert_width: %u", jtag_get_ntrst_assert_width());
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_jtag_rclk_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int retval = ERROR_OK;
- if (CMD_ARGC == 1) {
- unsigned khz = 0;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz);
-
- retval = jtag_config_rclk(khz);
- if (ERROR_OK != retval)
- return retval;
- }
-
- int cur_khz = jtag_get_speed_khz();
- retval = jtag_get_speed_readable(&cur_khz);
- if (ERROR_OK != retval)
- return retval;
-
- if (cur_khz)
- command_print(CMD_CTX, "RCLK not supported - fallback to %d kHz", cur_khz);
- else
- command_print(CMD_CTX, "RCLK - adaptive");
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_jtag_reset_command)
-{
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int trst = -1;
- if (CMD_ARGV[0][0] == '1')
- trst = 1;
- else if (CMD_ARGV[0][0] == '0')
- trst = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int srst = -1;
- if (CMD_ARGV[1][0] == '1')
- srst = 1;
- else if (CMD_ARGV[1][0] == '0')
- srst = 0;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (adapter_init(CMD_CTX) != ERROR_OK)
- return ERROR_JTAG_INIT_FAILED;
-
- jtag_add_reset(trst, srst);
- return jtag_execute_queue();
-}
-
-COMMAND_HANDLER(handle_runtest_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned num_clocks;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num_clocks);
-
- jtag_add_runtest(num_clocks, TAP_IDLE);
- return jtag_execute_queue();
-}
-
-/*
- * For "irscan" or "drscan" commands, the "end" (really, "next") state
- * should be stable ... and *NOT* a shift state, otherwise free-running
- * jtag clocks could change the values latched by the update state.
- * Not surprisingly, this is the same constraint as SVF; the "irscan"
- * and "drscan" commands are a write-only subset of what SVF provides.
- */
-
-COMMAND_HANDLER(handle_irscan_command)
-{
- int i;
- struct scan_field *fields;
- struct jtag_tap *tap = NULL;
- tap_state_t endstate;
-
- if ((CMD_ARGC < 2) || (CMD_ARGC % 2))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* optional "-endstate" "statename" at the end of the arguments,
- * so that e.g. IRPAUSE can let us load the data register before
- * entering RUN/IDLE to execute the instruction we load here.
- */
- endstate = TAP_IDLE;
-
- if (CMD_ARGC >= 4) {
- /* have at least one pair of numbers.
- * is last pair the magic text? */
- if (strcmp("-endstate", CMD_ARGV[CMD_ARGC - 2]) == 0) {
- endstate = tap_state_by_name(CMD_ARGV[CMD_ARGC - 1]);
- if (endstate == TAP_INVALID)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (!scan_is_safe(endstate))
- LOG_WARNING("unstable irscan endstate \"%s\"",
- CMD_ARGV[CMD_ARGC - 1]);
- CMD_ARGC -= 2;
- }
- }
-
- int num_fields = CMD_ARGC / 2;
- if (num_fields > 1) {
- /* we really should be looking at plain_ir_scan if we want
- * anything more fancy.
- */
- LOG_ERROR("Specify a single value for tap");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- fields = calloc(num_fields, sizeof(*fields));
-
- int retval;
- for (i = 0; i < num_fields; i++) {
- tap = jtag_tap_by_string(CMD_ARGV[i*2]);
- if (tap == NULL) {
- free(fields);
- command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[i*2]);
-
- return ERROR_FAIL;
- }
- int field_size = tap->ir_length;
- fields[i].num_bits = field_size;
- uint8_t *v = malloc(DIV_ROUND_UP(field_size, 8));
-
- uint64_t value;
- retval = parse_u64(CMD_ARGV[i * 2 + 1], &value);
- if (ERROR_OK != retval)
- goto error_return;
- buf_set_u64(v, 0, field_size, value);
- fields[i].out_value = v;
- fields[i].in_value = NULL;
- }
-
- /* did we have an endstate? */
- jtag_add_ir_scan(tap, fields, endstate);
-
- retval = jtag_execute_queue();
-
-error_return:
- for (i = 0; i < num_fields; i++) {
- if (NULL != fields[i].out_value)
- free((void *)fields[i].out_value);
- }
-
- free(fields);
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_verify_ircapture_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 1) {
- bool enable;
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
- jtag_set_verify_capture_ir(enable);
- }
-
- const char *status = jtag_will_verify_capture_ir() ? "enabled" : "disabled";
- command_print(CMD_CTX, "verify Capture-IR is %s", status);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_verify_jtag_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 1) {
- bool enable;
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
- jtag_set_verify(enable);
- }
-
- const char *status = jtag_will_verify() ? "enabled" : "disabled";
- command_print(CMD_CTX, "verify jtag capture is %s", status);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_tms_sequence_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 1) {
- bool use_new_table;
- if (strcmp(CMD_ARGV[0], "short") == 0)
- use_new_table = true;
- else if (strcmp(CMD_ARGV[0], "long") == 0)
- use_new_table = false;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- tap_use_new_tms_table(use_new_table);
- }
-
- command_print(CMD_CTX, "tms sequence is %s",
- tap_uses_new_tms_table() ? "short" : "long");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_jtag_flush_queue_sleep)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int sleep_ms;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], sleep_ms);
-
- jtag_set_flush_queue_sleep(sleep_ms);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_wait_srst_deassert)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int timeout_ms;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], timeout_ms);
- if ((timeout_ms <= 0) || (timeout_ms > 100000)) {
- LOG_ERROR("Timeout must be an integer between 0 and 100000");
- return ERROR_FAIL;
- }
-
- LOG_USER("Waiting for srst assert + deassert for at most %dms", timeout_ms);
- int asserted_yet;
- int64_t then = timeval_ms();
- while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) {
- if ((timeval_ms() - then) > timeout_ms) {
- LOG_ERROR("Timed out");
- return ERROR_FAIL;
- }
- if (asserted_yet)
- break;
- }
- while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) {
- if ((timeval_ms() - then) > timeout_ms) {
- LOG_ERROR("Timed out");
- return ERROR_FAIL;
- }
- if (!asserted_yet)
- break;
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration jtag_command_handlers[] = {
-
- {
- .name = "jtag_flush_queue_sleep",
- .handler = handle_jtag_flush_queue_sleep,
- .mode = COMMAND_ANY,
- .help = "For debug purposes(simulate long delays of interface) "
- "to test performance or change in behavior. Default 0ms.",
- .usage = "[sleep in ms]",
- },
- {
- .name = "jtag_rclk",
- .handler = handle_jtag_rclk_command,
- .mode = COMMAND_ANY,
- .help = "With an argument, change to to use adaptive clocking "
- "if possible; else to use the fallback speed. "
- "With or without argument, display current setting.",
- .usage = "[fallback_speed_khz]",
- },
- {
- .name = "jtag_ntrst_delay",
- .handler = handle_jtag_ntrst_delay_command,
- .mode = COMMAND_ANY,
- .help = "delay after deasserting trst in ms",
- .usage = "[milliseconds]",
- },
- {
- .name = "jtag_ntrst_assert_width",
- .handler = handle_jtag_ntrst_assert_width_command,
- .mode = COMMAND_ANY,
- .help = "delay after asserting trst in ms",
- .usage = "[milliseconds]",
- },
- {
- .name = "scan_chain",
- .handler = handle_scan_chain_command,
- .mode = COMMAND_ANY,
- .help = "print current scan chain configuration",
- .usage = ""
- },
- {
- .name = "jtag_reset",
- .handler = handle_jtag_reset_command,
- .mode = COMMAND_EXEC,
- .help = "Set reset line values. Value '1' is active, "
- "value '0' is inactive.",
- .usage = "trst_active srst_active",
- },
- {
- .name = "runtest",
- .handler = handle_runtest_command,
- .mode = COMMAND_EXEC,
- .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.",
- .usage = "num_cycles"
- },
- {
- .name = "irscan",
- .handler = handle_irscan_command,
- .mode = COMMAND_EXEC,
- .help = "Execute Instruction Register (DR) 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]",
- },
- {
- .name = "verify_ircapture",
- .handler = handle_verify_ircapture_command,
- .mode = COMMAND_ANY,
- .help = "Display or assign flag controlling whether to "
- "verify values captured during Capture-IR.",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "verify_jtag",
- .handler = handle_verify_jtag_command,
- .mode = COMMAND_ANY,
- .help = "Display or assign flag controlling whether to "
- "verify values captured during IR and DR scans.",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "tms_sequence",
- .handler = handle_tms_sequence_command,
- .mode = COMMAND_ANY,
- .help = "Display or change what style TMS sequences to use "
- "for JTAG state transitions: short (default) or "
- "long. Only for working around JTAG bugs.",
- /* Specifically for working around DRIVER bugs... */
- .usage = "['short'|'long']",
- },
- {
- .name = "wait_srst_deassert",
- .handler = handle_wait_srst_deassert,
- .mode = COMMAND_ANY,
- .help = "Wait for an SRST deassert. "
- "Useful for cases where you need something to happen within ms "
- "of an srst deassert. Timeout in ms ",
- .usage = "ms",
- },
- {
- .name = "jtag",
- .mode = COMMAND_ANY,
- .help = "perform jtag tap actions",
- .usage = "",
-
- .chain = jtag_subcommand_handlers,
- },
- {
- .chain = jtag_command_handlers_to_move,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int jtag_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, jtag_command_handlers);
-}
diff --git a/src/jtag/tcl.h b/src/jtag/tcl.h
deleted file mode 100644
index 932b47a..0000000
--- a/src/jtag/tcl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 SoftPLC Corporation *
- * http://softplc.com *
- * dick@softplc.com *
- * *
- * Copyright (C) 2009 Zachary T Welch *
- * zw@superlucidity.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_JTAG_TCL_H
-#define OPENOCD_JTAG_TCL_H
-
-int jim_jtag_configure(Jim_Interp *interp, int argc,
- Jim_Obj * const *argv);
-int jim_jtag_tap_enabler(Jim_Interp *interp, int argc,
- Jim_Obj * const *argv);
-
-#endif /* OPENOCD_JTAG_TCL_H */
diff --git a/src/jtag/zy1000/jtag_minidriver.h b/src/jtag/zy1000/jtag_minidriver.h
deleted file mode 100644
index 7d1ede5..0000000
--- a/src/jtag/zy1000/jtag_minidriver.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007-2010 by Øyvind Harboe *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* used to test manual mode */
-#define TEST_MANUAL() 0
-#define VERBOSE(a)
-
-#if BUILD_ZY1000_MASTER
-
-#define ZY1000_PEEK(a, b) do {b = *((volatile uint32_t *)(a)); } while (0)
-#define ZY1000_POKE(a, b) do {*((volatile uint32_t *)(a)) = b; } while (0)
-extern volatile void *zy1000_jtag_master;
-#define ZY1000_JTAG_BASE ((unsigned long)zy1000_jtag_master)
-
-#else
-
-/* redirect this to TCP/IP */
-#define ZY1000_JTAG_BASE 0
-extern void zy1000_tcpout(uint32_t address, uint32_t data);
-extern uint32_t zy1000_tcpin(uint32_t address);
-#define ZY1000_PEEK(a, b) b = zy1000_tcpin(a)
-#define ZY1000_POKE(a, b) zy1000_tcpout(a, b)
-
-#endif
-
-#if BUILD_ZY1000_MASTER
-/* FIFO empty? */
-static inline void waitIdle(void)
-{
- uint32_t empty;
- do {
- ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
- } while ((empty & 0x100) == 0);
-}
-
-static inline void zy1000_flush_readqueue(void)
-{
- /* Not used w/hardware fifo */
-}
-static inline void zy1000_flush_callbackqueue(void)
-{
- /* Not used w/hardware fifo */
-}
-#else
-extern void waitIdle(void);
-void zy1000_flush_readqueue(void);
-void zy1000_flush_callbackqueue(void);
-void zy1000_jtag_add_callback4(jtag_callback_t callback,
- jtag_callback_data_t data0,
- jtag_callback_data_t data1,
- jtag_callback_data_t data2,
- jtag_callback_data_t data3);
-void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0);
-#endif
-
-static inline void waitQueue(void)
-{
-/* waitIdle(); */
-}
-
-static inline void sampleShiftRegister(void)
-{
-#if 0
- uint32_t dummy;
- waitIdle();
- ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, dummy);
-#endif
-}
-
-static inline void setCurrentState(enum tap_state state)
-{
- uint32_t a;
- a = state;
- int repeat = 0;
- if (state == TAP_RESET) {
- /* The FPGA nor we know the current state of the CPU TAP */
- /* controller. This will move it to TAP for sure. */
- /* */
- /* 5 should be enough here, 7 is what OpenOCD uses */
- repeat = 7;
- }
- waitQueue();
- sampleShiftRegister();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | a);
-
-}
-
-/*
- * Enter state and cause repeat transitions *out* of that state. So if the endState != state, then
- * the transition from state to endState counts as a transition out of state.
- */
-static inline void shiftValueInner(const enum tap_state state,
- const enum tap_state endState,
- int repeat,
- uint32_t value)
-{
- uint32_t a, b;
- a = state;
- b = endState;
- waitQueue();
- sampleShiftRegister();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value);
-#if 1
-#if TEST_MANUAL()
- if ((state == TAP_DRSHIFT) && (endState != TAP_DRSHIFT)) {
- int i;
- setCurrentState(state);
- for (i = 0; i < repeat; i++) {
- int tms;
- tms = 0;
- if ((i == repeat-1) && (state != endState))
- tms = 1;
- /* shift out value */
- waitIdle();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, (((value >> i)&1) << 1) | tms);
- }
- waitIdle();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
- waitIdle();
- /* ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT); // set this state and things
- * break => expected */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRPAUSE); /* set this and things will
- * work => expected. Not
- * setting this is not
- * sufficient to make things
- * break. */
- setCurrentState(endState);
- } else
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
-
-#else
- /* fast version */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
-#endif
-#else
- /* maximum debug version */
- if ((repeat > 0) && ((state == TAP_DRSHIFT) || (state == TAP_SI))) {
- int i;
- /* sample shift register for every bit. */
- for (i = 0; i < repeat-1; i++) {
- sampleShiftRegister();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> i);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | a);
- }
- sampleShiftRegister();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> (repeat-1));
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | b);
- } else {
- sampleShiftRegister();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
- }
- sampleShiftRegister();
-#endif
-}
-
-#if BUILD_ZY1000_MASTER
-#define interface_jtag_add_callback(callback, in) callback(in)
-#define interface_jtag_add_callback4(callback, in, data1, data2, \
- data3) jtag_set_error(callback(in, data1, data2, data3))
-#else
-#define interface_jtag_add_callback(callback, in) zy1000_jtag_add_callback(callback, in)
-#define interface_jtag_add_callback4(callback, in, data1, data2, data3) zy1000_jtag_add_callback4( \
- callback, \
- in, \
- data1, \
- data2, \
- data3)
-#endif
diff --git a/src/jtag/zy1000/zy1000.c b/src/jtag/zy1000/zy1000.c
deleted file mode 100644
index 67d9907..0000000
--- a/src/jtag/zy1000/zy1000.c
+++ /dev/null
@@ -1,1252 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007-2010 by Øyvind Harboe *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* This file supports the zy1000 debugger:
- *
- * http://www.ultsol.com/index.php/component/content/article/8/33-zylin-zy1000-jtag-probe
- *
- * The zy1000 is a standalone debugger that has a web interface and
- * requires no drivers on the developer host as all communication
- * is via TCP/IP. The zy1000 gets it performance(~400-700kBytes/s
- * DCC downloads @ 16MHz target) as it has an FPGA to hardware
- * accelerate the JTAG commands, while offering *very* low latency
- * between OpenOCD and the FPGA registers.
- *
- * The disadvantage of the zy1000 is that it has a feeble CPU compared to
- * a PC(ca. 50-500 DMIPS depending on how one counts it), whereas a PC
- * is on the order of 10000 DMIPS(i.e. at a factor of 20-200).
- *
- * The zy1000 revc hardware is using an Altera Nios CPU, whereas the
- * revb is using ARM7 + Xilinx.
- *
- * See Zylin web pages or contact Zylin for more information.
- *
- * The reason this code is in OpenOCD rather than OpenOCD linked with the
- * ZY1000 code is that OpenOCD is the long road towards getting
- * libopenocd into place. libopenocd will support both low performance,
- * low latency systems(embedded) and high performance high latency
- * systems(PCs).
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <pthread.h>
-
-#include <target/embeddedice.h>
-#include <jtag/minidriver.h>
-#include <jtag/interface.h>
-#include <time.h>
-#include <helper/time_support.h>
-
-#include <netinet/tcp.h>
-
-/* Assume we're connecting to a revc w/60MHz clock. */
-#define ZYLIN_KHZ 60000
-
-/* The software needs to check if it's in RCLK mode or not */
-static bool zy1000_rclk;
-
-static int zy1000_khz(int khz, int *jtag_speed)
-{
- if (khz == 0)
- *jtag_speed = 0;
- else {
- int speed;
- /* Round speed up to nearest divisor.
- *
- * E.g. 16000kHz
- * (64000 + 15999) / 16000 = 4
- * (4 + 1) / 2 = 2
- * 2 * 2 = 4
- *
- * 64000 / 4 = 16000
- *
- * E.g. 15999
- * (64000 + 15998) / 15999 = 5
- * (5 + 1) / 2 = 3
- * 3 * 2 = 6
- *
- * 64000 / 6 = 10666
- *
- */
- speed = (ZYLIN_KHZ + (khz - 1)) / khz;
- speed = (speed + 1) / 2;
- speed *= 2;
- if (speed > 8190) {
- /* maximum dividend */
- speed = 8190;
- }
- *jtag_speed = speed;
- }
- return ERROR_OK;
-}
-
-static int zy1000_speed_div(int speed, int *khz)
-{
- if (speed == 0)
- *khz = 0;
- else
- *khz = ZYLIN_KHZ / speed;
-
- return ERROR_OK;
-}
-
-static bool readPowerDropout(void)
-{
- uint32_t state;
- /* sample and clear power dropout */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x80);
- ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, state);
- bool powerDropout;
- powerDropout = (state & 0x80) != 0;
- return powerDropout;
-}
-
-
-static bool readSRST(void)
-{
- uint32_t state;
- /* sample and clear SRST sensing */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000040);
- ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, state);
- bool srstAsserted;
- srstAsserted = (state & 0x40) != 0;
- return srstAsserted;
-}
-
-static int zy1000_srst_asserted(int *srst_asserted)
-{
- *srst_asserted = readSRST();
- return ERROR_OK;
-}
-
-static int zy1000_power_dropout(int *dropout)
-{
- *dropout = readPowerDropout();
- return ERROR_OK;
-}
-
-/* Wait for SRST to assert or deassert */
-static void waitSRST(bool asserted)
-{
- bool first = true;
- int64_t start = 0;
- int64_t total = 0;
- const char *mode = asserted ? "assert" : "deassert";
-
- for (;; ) {
- bool srstAsserted = readSRST();
- if ((asserted && srstAsserted) || (!asserted && !srstAsserted)) {
- if (total > 1)
- LOG_USER("SRST took %dms to %s", (int)total, mode);
- break;
- }
-
- if (first) {
- first = false;
- start = timeval_ms();
- }
-
- total = timeval_ms() - start;
-
- keep_alive();
-
- if (total > 5000) {
- LOG_ERROR("SRST took too long to %s: %" PRId64 "ms", mode, total);
- break;
- }
- }
-}
-
-void zy1000_reset(int trst, int srst)
-{
- LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst);
-
- /* flush the JTAG FIFO. Not flushing the queue before messing with
- * reset has such interesting bugs as causing hard to reproduce
- * RCLK bugs as RCLK will stop responding when TRST is asserted
- */
- waitIdle();
-
- if (!srst)
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000001);
- else {
- /* Danger!!! if clk != 0 when in
- * idle in TAP_IDLE, reset halt on str912 will fail.
- */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000001);
-
- waitSRST(true);
- }
-
- if (!trst)
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000002);
- else {
- /* assert reset */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x00000002);
- }
-
- if (trst || (srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) {
- /* we're now in the RESET state until trst is deasserted */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_RESET);
- } else {
- /* We'll get RCLK failure when we assert TRST, so clear any false positives here */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x400);
- }
-
- /* wait for srst to float back up */
- if ((!srst && ((jtag_get_reset_config() & RESET_TRST_PULLS_SRST) == 0)) ||
- (!srst && !trst && (jtag_get_reset_config() & RESET_TRST_PULLS_SRST)))
- waitSRST(false);
-}
-
-int zy1000_speed(int speed)
-{
- /* flush JTAG master FIFO before setting speed */
- waitIdle();
-
- zy1000_rclk = false;
-
- if (speed == 0) {
- /*0 means RCLK*/
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x100);
- zy1000_rclk = true;
- LOG_DEBUG("jtag_speed using RCLK");
- } else {
- if (speed > 8190 || speed < 2) {
- LOG_USER(
- "valid ZY1000 jtag_speed=[8190,2]. With divisor is %dkHz / even values between 8190-2, i.e. min %dHz, max %dMHz",
- ZYLIN_KHZ,
- (ZYLIN_KHZ * 1000) / 8190,
- ZYLIN_KHZ / (2 * 1000));
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- int khz;
- speed &= ~1;
- zy1000_speed_div(speed, &khz);
- LOG_USER("jtag_speed %d => JTAG clk=%d kHz", speed, khz);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x100);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x1c, speed);
- }
- return ERROR_OK;
-}
-
-static bool savePower;
-
-static void setPower(bool power)
-{
- savePower = power;
- if (power)
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x8);
- else
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x8);
-}
-
-COMMAND_HANDLER(handle_power_command)
-{
- switch (CMD_ARGC) {
- case 1: {
- bool enable;
- COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
- setPower(enable);
- /* fall through */
- }
- case 0:
- LOG_INFO("Target power %s", savePower ? "on" : "off");
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-#if !BUILD_ZY1000_MASTER
-static char *tcp_server = "notspecified";
-static int jim_zy1000_server(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- if (argc != 2)
- return JIM_ERR;
-
- tcp_server = strdup(Jim_GetString(argv[1], NULL));
-
- return JIM_OK;
-}
-#endif
-
-static int zylinjtag_Jim_Command_powerstatus(Jim_Interp *interp,
- int argc,
- Jim_Obj * const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "powerstatus");
- return JIM_ERR;
- }
-
- bool dropout = readPowerDropout();
-
- Jim_SetResult(interp, Jim_NewIntObj(interp, dropout));
-
- return JIM_OK;
-}
-
-int zy1000_quit(void)
-{
-
- return ERROR_OK;
-}
-
-int interface_jtag_execute_queue(void)
-{
- uint32_t empty;
-
- waitIdle();
-
- /* We must make sure to write data read back to memory location before we return
- * from this fn
- */
- zy1000_flush_readqueue();
-
- /* and handle any callbacks... */
- zy1000_flush_callbackqueue();
-
- if (zy1000_rclk) {
- /* Only check for errors when using RCLK to speed up
- * jtag over TCP/IP
- */
- ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
- /* clear JTAG error register */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x400);
-
- if ((empty&0x400) != 0) {
- LOG_WARNING("RCLK timeout");
- /* the error is informative only as we don't want to break the firmware if there
- * is a false positive.
- */
- /* return ERROR_FAIL; */
- }
- }
- return ERROR_OK;
-}
-
-static void writeShiftValue(uint8_t *data, int bits);
-
-/* here we shuffle N bits out/in */
-static inline void scanBits(const uint8_t *out_value,
- uint8_t *in_value,
- int num_bits,
- bool pause_now,
- tap_state_t shiftState,
- tap_state_t end_state)
-{
- tap_state_t pause_state = shiftState;
- for (int j = 0; j < num_bits; j += 32) {
- int k = num_bits - j;
- if (k > 32) {
- k = 32;
- /* we have more to shift out */
- } else if (pause_now) {
- /* this was the last to shift out this time */
- pause_state = end_state;
- }
-
- /* we have (num_bits + 7)/8 bytes of bits to toggle out. */
- /* bits are pushed out LSB to MSB */
- uint32_t value;
- value = 0;
- if (out_value != NULL) {
- for (int l = 0; l < k; l += 8)
- value |= out_value[(j + l)/8]<<l;
- }
- /* mask away unused bits for easier debugging */
- if (k < 32)
- value &= ~(((uint32_t)0xffffffff) << k);
- else {
- /* Shifting by >= 32 is not defined by the C standard
- * and will in fact shift by &0x1f bits on nios */
- }
-
- shiftValueInner(shiftState, pause_state, k, value);
-
- if (in_value != NULL)
- writeShiftValue(in_value + (j/8), k);
- }
-}
-
-static inline void scanFields(int num_fields,
- const struct scan_field *fields,
- tap_state_t shiftState,
- tap_state_t end_state)
-{
- for (int i = 0; i < num_fields; i++) {
- scanBits(fields[i].out_value,
- fields[i].in_value,
- fields[i].num_bits,
- (i == num_fields-1),
- shiftState,
- end_state);
- }
-}
-
-int interface_jtag_add_ir_scan(struct jtag_tap *active,
- const struct scan_field *fields,
- tap_state_t state)
-{
- int scan_size = 0;
- struct jtag_tap *tap, *nextTap;
- tap_state_t pause_state = TAP_IRSHIFT;
-
- for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) {
- nextTap = jtag_tap_next_enabled(tap);
- if (nextTap == NULL)
- pause_state = state;
- scan_size = tap->ir_length;
-
- /* search the list */
- if (tap == active) {
- scanFields(1, fields, TAP_IRSHIFT, pause_state);
- /* update device information */
- buf_cpy(fields[0].out_value, tap->cur_instr, scan_size);
-
- tap->bypass = 0;
- } else {
- /* if a device isn't listed, set it to BYPASS */
- assert(scan_size <= 32);
- shiftValueInner(TAP_IRSHIFT, pause_state, scan_size, 0xffffffff);
-
- /* Optimization code will check what the cur_instr is set to, so
- * we must set it to bypass value.
- */
- buf_set_ones(tap->cur_instr, tap->ir_length);
-
- tap->bypass = 1;
- }
- }
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_plain_ir_scan(int num_bits,
- const uint8_t *out_bits,
- uint8_t *in_bits,
- tap_state_t state)
-{
- scanBits(out_bits, in_bits, num_bits, true, TAP_IRSHIFT, state);
- return ERROR_OK;
-}
-
-int interface_jtag_add_dr_scan(struct jtag_tap *active,
- int num_fields,
- const struct scan_field *fields,
- tap_state_t state)
-{
- struct jtag_tap *tap, *nextTap;
- tap_state_t pause_state = TAP_DRSHIFT;
- for (tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = nextTap) {
- nextTap = jtag_tap_next_enabled(tap);
- if (nextTap == NULL)
- pause_state = state;
-
- /* Find a range of fields to write to this tap */
- if (tap == active) {
- assert(!tap->bypass);
-
- scanFields(num_fields, fields, TAP_DRSHIFT, pause_state);
- } else {
- /* Shift out a 0 for disabled tap's */
- assert(tap->bypass);
- shiftValueInner(TAP_DRSHIFT, pause_state, 1, 0);
- }
- }
- return ERROR_OK;
-}
-
-int interface_jtag_add_plain_dr_scan(int num_bits,
- const uint8_t *out_bits,
- uint8_t *in_bits,
- tap_state_t state)
-{
- scanBits(out_bits, in_bits, num_bits, true, TAP_DRSHIFT, state);
- return ERROR_OK;
-}
-
-int interface_jtag_add_tlr()
-{
- setCurrentState(TAP_RESET);
- return ERROR_OK;
-}
-
-int interface_jtag_add_reset(int req_trst, int req_srst)
-{
- zy1000_reset(req_trst, req_srst);
- return ERROR_OK;
-}
-
-static int zy1000_jtag_add_clocks(int num_cycles, tap_state_t state, tap_state_t clockstate)
-{
- /* num_cycles can be 0 */
- setCurrentState(clockstate);
-
- /* execute num_cycles, 32 at the time. */
- int i;
- for (i = 0; i < num_cycles; i += 32) {
- int num;
- num = 32;
- if (num_cycles-i < num)
- num = num_cycles-i;
- shiftValueInner(clockstate, clockstate, num, 0);
- }
-
-#if !TEST_MANUAL()
- /* finish in end_state */
- setCurrentState(state);
-#else
- tap_state_t t = TAP_IDLE;
- /* test manual drive code on any target */
- int tms;
- uint8_t tms_scan = tap_get_tms_path(t, state);
- int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
-
- for (i = 0; i < tms_count; i++) {
- tms = (tms_scan >> i) & 1;
- waitIdle();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, tms);
- }
- waitIdle();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, state);
-#endif
-
- return ERROR_OK;
-}
-
-int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
-{
- return zy1000_jtag_add_clocks(num_cycles, state, TAP_IDLE);
-}
-
-int interface_jtag_add_clocks(int num_cycles)
-{
- return zy1000_jtag_add_clocks(num_cycles, cmd_queue_cur_state, cmd_queue_cur_state);
-}
-
-int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
-{
- /*wait for the fifo to be empty*/
- waitIdle();
-
- for (unsigned i = 0; i < num_bits; i++) {
- int tms;
-
- if (((seq[i/8] >> (i % 8)) & 1) == 0)
- tms = 0;
- else
- tms = 1;
-
- waitIdle();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, tms);
- }
-
- waitIdle();
- if (state != TAP_INVALID)
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, state);
- else {
- /* this would be normal if
- * we are switching to SWD mode */
- }
- return ERROR_OK;
-}
-
-int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
-{
- int state_count;
- int tms = 0;
-
- state_count = 0;
-
- tap_state_t cur_state = cmd_queue_cur_state;
-
- uint8_t seq[16];
- memset(seq, 0, sizeof(seq));
- assert(num_states < (int)((sizeof(seq) * 8)));
-
- while (num_states) {
- if (tap_state_transition(cur_state, false) == path[state_count])
- tms = 0;
- else if (tap_state_transition(cur_state, true) == path[state_count])
- tms = 1;
- else {
- LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
- tap_state_name(cur_state), tap_state_name(path[state_count]));
- exit(-1);
- }
-
- seq[state_count/8] = seq[state_count/8] | (tms << (state_count % 8));
-
- cur_state = path[state_count];
- state_count++;
- num_states--;
- }
-
- return interface_add_tms_seq(state_count, seq, cur_state);
-}
-
-static void jtag_pre_post_bits(struct jtag_tap *tap, int *pre, int *post)
-{
- /* bypass bits before and after */
- int pre_bits = 0;
- int post_bits = 0;
-
- bool found = false;
- struct jtag_tap *cur_tap, *nextTap;
- for (cur_tap = jtag_tap_next_enabled(NULL); cur_tap != NULL; cur_tap = nextTap) {
- nextTap = jtag_tap_next_enabled(cur_tap);
- if (cur_tap == tap)
- found = true;
- else {
- if (found)
- post_bits++;
- else
- pre_bits++;
- }
- }
- *pre = pre_bits;
- *post = post_bits;
-}
-
-void embeddedice_write_dcc(struct jtag_tap *tap,
- int reg_addr,
- const uint8_t *buffer,
- int little,
- int count)
-{
-#if 0
- int i;
- for (i = 0; i < count; i++) {
- embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer,
- little));
- buffer += 4;
- }
-#else
- int pre_bits;
- int post_bits;
- jtag_pre_post_bits(tap, &pre_bits, &post_bits);
-
- if ((pre_bits > 32) || (post_bits + 6 > 32)) {
- int i;
- for (i = 0; i < count; i++) {
- embeddedice_write_reg_inner(tap, reg_addr,
- fast_target_buffer_get_u32(buffer, little));
- buffer += 4;
- }
- } else {
- int i;
- for (i = 0; i < count; i++) {
- /* Fewer pokes means we get to use the FIFO more efficiently */
- shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0);
- shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32,
- fast_target_buffer_get_u32(buffer, little));
- /* Danger! here we need to exit into the TAP_IDLE state to make
- * DCC pick up this value.
- */
- shiftValueInner(TAP_DRSHIFT, TAP_IDLE, 6 + post_bits,
- (reg_addr | (1 << 5)));
- buffer += 4;
- }
- }
-#endif
-}
-
-int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
- uint32_t opcode,
- const uint32_t *data,
- size_t count)
-{
- /* bypass bits before and after */
- int pre_bits;
- int post_bits;
- jtag_pre_post_bits(tap, &pre_bits, &post_bits);
- post_bits += 2;
-
- if ((pre_bits > 32) || (post_bits > 32)) {
- int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *,
- uint32_t, const uint32_t *, size_t);
- return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
- } else {
- static const uint8_t zero;
-
- /* FIX!!!!!! the target_write_memory() API started this nasty problem
- * with unaligned uint32_t * pointers... */
- const uint8_t *t = (const uint8_t *)data;
-
- while (--count > 0) {
-#if 1
- /* Danger! This code doesn't update cmd_queue_cur_state, so
- * invoking jtag_add_pathmove() before jtag_add_dr_scan() after
- * this loop would fail!
- */
- shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, pre_bits, 0);
-
- uint32_t value;
- value = *t++;
- value |= (*t++<<8);
- value |= (*t++<<16);
- value |= (*t++<<24);
-
- shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, value);
- /* minimum 2 bits */
- shiftValueInner(TAP_DRSHIFT, TAP_DRPAUSE, post_bits, 0);
-
- /* copy & paste from arm11_dbgtap.c */
- /* TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT,
- * TAP_DRCAPTURE, TAP_DRSHIFT */
- /* KLUDGE! we have to flush the fifo or the Nios CPU locks up.
- * This is probably a bug in the Avalon bus(cross clocking bridge?)
- * or in the jtag registers module.
- */
- waitIdle();
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 1);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
- /* we don't have to wait for the queue to empty here */
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT);
- waitIdle();
-#else
- static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = {
- TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE,
- TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
- };
-
- struct scan_field fields[2] = {
- { .num_bits = 32, .out_value = t },
- { .num_bits = 2, .out_value = &zero },
- };
- t += 4;
-
- jtag_add_dr_scan(tap,
- 2,
- fields,
- TAP_IDLE);
-
- jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
- arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay);
-#endif
- }
-
- struct scan_field fields[2] = {
- { .num_bits = 32, .out_value = t },
- { .num_bits = 2, .out_value = &zero },
- };
-
- /* This will happen on the last iteration updating cmd_queue_cur_state
- * so we don't have to track it during the common code path
- */
- jtag_add_dr_scan(tap,
- 2,
- fields,
- TAP_IDLE);
-
- return jtag_execute_queue();
- }
-}
-
-static const struct command_registration zy1000_commands[] = {
- {
- .name = "power",
- .handler = handle_power_command,
- .mode = COMMAND_ANY,
- .help = "Turn power switch to target on/off. "
- "With no arguments, prints status.",
- .usage = "('on'|'off)",
- },
-#if !BUILD_ZY1000_MASTER
- {
- .name = "zy1000_server",
- .mode = COMMAND_ANY,
- .jim_handler = jim_zy1000_server,
- .help = "Tcpip address for ZY1000 server.",
- .usage = "address",
- },
-#endif
- {
- .name = "powerstatus",
- .mode = COMMAND_ANY,
- .jim_handler = zylinjtag_Jim_Command_powerstatus,
- .help = "Returns power status of target",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-#if !BUILD_ZY1000_MASTER
-
-static int tcp_ip = -1;
-
-/* Write large packets if we can */
-static size_t out_pos;
-static uint8_t out_buffer[16384];
-static size_t in_pos;
-static size_t in_write;
-static uint8_t in_buffer[16384];
-
-static bool flush_writes(void)
-{
- bool ok = (write(tcp_ip, out_buffer, out_pos) == (int)out_pos);
- out_pos = 0;
- return ok;
-}
-
-static bool writeLong(uint32_t l)
-{
- int i;
- for (i = 0; i < 4; i++) {
- uint8_t c = (l >> (i*8))&0xff;
- out_buffer[out_pos++] = c;
- if (out_pos >= sizeof(out_buffer)) {
- if (!flush_writes())
- return false;
- }
- }
- return true;
-}
-
-static bool readLong(uint32_t *out_data)
-{
- uint32_t data = 0;
- int i;
- for (i = 0; i < 4; i++) {
- uint8_t c;
- if (in_pos == in_write) {
- /* If we have some data that we can send, send them before
- * we wait for more data
- */
- if (out_pos > 0) {
- if (!flush_writes())
- return false;
- }
-
- /* read more */
- int t;
- t = read(tcp_ip, in_buffer, sizeof(in_buffer));
- if (t < 1)
- return false;
- in_write = (size_t) t;
- in_pos = 0;
- }
- c = in_buffer[in_pos++];
-
- data |= (c << (i*8));
- }
- *out_data = data;
- return true;
-}
-
-enum ZY1000_CMD {
- ZY1000_CMD_POKE = 0x0,
- ZY1000_CMD_PEEK = 0x8,
- ZY1000_CMD_SLEEP = 0x1,
- ZY1000_CMD_WAITIDLE = 2
-};
-
-#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
-#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
-
-/* We initialize this late since we need to know the server address
- * first.
- */
-static void tcpip_open(void)
-{
- if (tcp_ip >= 0)
- return;
-
- struct sockaddr_in echoServAddr;/* Echo server address */
-
- /* Create a reliable, stream socket using TCP */
- tcp_ip = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (tcp_ip < 0) {
- fprintf(stderr, "Failed to connect to zy1000 server\n");
- exit(-1);
- }
-
- /* Construct the server address structure */
- memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
- echoServAddr.sin_family = AF_INET; /* Internet address family */
- echoServAddr.sin_addr.s_addr = inet_addr(tcp_server); /* Server IP address */
- echoServAddr.sin_port = htons(7777); /* Server port */
-
- /* Establish the connection to the echo server */
- if (connect(tcp_ip, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) {
- fprintf(stderr, "Failed to connect to zy1000 server\n");
- exit(-1);
- }
-
- int flag = 1;
- setsockopt(tcp_ip, /* socket affected */
- IPPROTO_TCP, /* set option at TCP level */
- TCP_NODELAY, /* name of option */
- (char *)&flag, /* the cast is historical cruft */
- sizeof(int)); /* length of option value */
-
-}
-
-/* send a poke */
-void zy1000_tcpout(uint32_t address, uint32_t data)
-{
- tcpip_open();
- if (!writeLong((ZY1000_CMD_POKE << 24) | address) || !writeLong(data)) {
- fprintf(stderr, "Could not write to zy1000 server\n");
- exit(-1);
- }
-}
-
-/* By sending the wait to the server, we avoid a readback
- * of status. Radically improves performance for this operation
- * with long ping times.
- */
-void waitIdle(void)
-{
- tcpip_open();
- if (!writeLong((ZY1000_CMD_WAITIDLE << 24))) {
- fprintf(stderr, "Could not write to zy1000 server\n");
- exit(-1);
- }
-}
-
-uint32_t zy1000_tcpin(uint32_t address)
-{
- tcpip_open();
-
- zy1000_flush_readqueue();
-
- uint32_t data;
- if (!writeLong((ZY1000_CMD_PEEK << 24) | address) || !readLong(&data)) {
- fprintf(stderr, "Could not read from zy1000 server\n");
- exit(-1);
- }
- return data;
-}
-
-int interface_jtag_add_sleep(uint32_t us)
-{
- tcpip_open();
- if (!writeLong((ZY1000_CMD_SLEEP << 24)) || !writeLong(us)) {
- fprintf(stderr, "Could not read from zy1000 server\n");
- exit(-1);
- }
- return ERROR_OK;
-}
-
-/* queue a readback */
-#define readqueue_size 16384
-static struct {
- uint8_t *dest;
- int bits;
-} readqueue[readqueue_size];
-
-static int readqueue_pos;
-
-/* flush the readqueue, this means reading any data that
- * we're expecting and store them into the final position
- */
-void zy1000_flush_readqueue(void)
-{
- if (readqueue_pos == 0) {
- /* simply debugging by allowing easy breakpoints when there
- * is something to do. */
- return;
- }
- int i;
- tcpip_open();
- for (i = 0; i < readqueue_pos; i++) {
- uint32_t value;
- if (!readLong(&value)) {
- fprintf(stderr, "Could not read from zy1000 server\n");
- exit(-1);
- }
-
- uint8_t *in_value = readqueue[i].dest;
- int k = readqueue[i].bits;
-
- /* we're shifting in data to MSB, shift data to be aligned for returning the value */
- value >>= 32-k;
-
- for (int l = 0; l < k; l += 8)
- in_value[l/8] = (value >> l)&0xff;
- }
- readqueue_pos = 0;
-}
-
-/* By queuing the callback's we avoid flushing the
- * read queue until jtag_execute_queue(). This can
- * reduce latency dramatically for cases where
- * callbacks are used extensively.
-*/
-#define callbackqueue_size 128
-static struct callbackentry {
- jtag_callback_t callback;
- jtag_callback_data_t data0;
- jtag_callback_data_t data1;
- jtag_callback_data_t data2;
- jtag_callback_data_t data3;
-} callbackqueue[callbackqueue_size];
-
-static int callbackqueue_pos;
-
-void zy1000_jtag_add_callback4(jtag_callback_t callback,
- jtag_callback_data_t data0,
- jtag_callback_data_t data1,
- jtag_callback_data_t data2,
- jtag_callback_data_t data3)
-{
- if (callbackqueue_pos >= callbackqueue_size)
- zy1000_flush_callbackqueue();
-
- callbackqueue[callbackqueue_pos].callback = callback;
- callbackqueue[callbackqueue_pos].data0 = data0;
- callbackqueue[callbackqueue_pos].data1 = data1;
- callbackqueue[callbackqueue_pos].data2 = data2;
- callbackqueue[callbackqueue_pos].data3 = data3;
- callbackqueue_pos++;
-
- /* KLUDGE!
- * make callbacks synchronous for now as minidriver requires callback
- * to be synchronous.
- *
- * We can get away with making read and writes asynchronous so we
- * don't completely kill performance.
- */
- zy1000_flush_callbackqueue();
-}
-
-static int zy1000_jtag_convert_to_callback4(jtag_callback_data_t data0,
- jtag_callback_data_t data1,
- jtag_callback_data_t data2,
- jtag_callback_data_t data3)
-{
- ((jtag_callback1_t)data1)(data0);
- return ERROR_OK;
-}
-
-void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
-{
- zy1000_jtag_add_callback4(zy1000_jtag_convert_to_callback4,
- data0,
- (jtag_callback_data_t)callback,
- 0,
- 0);
-}
-
-void zy1000_flush_callbackqueue(void)
-{
- /* we have to flush the read queue so we have access to
- the data the callbacks will use
- */
- zy1000_flush_readqueue();
- int i;
- for (i = 0; i < callbackqueue_pos; i++) {
- struct callbackentry *entry = &callbackqueue[i];
- jtag_set_error(entry->callback(entry->data0, entry->data1, entry->data2,
- entry->data3));
- }
- callbackqueue_pos = 0;
-}
-
-static void writeShiftValue(uint8_t *data, int bits)
-{
- waitIdle();
-
- if (!writeLong((ZY1000_CMD_PEEK << 24) | (ZY1000_JTAG_BASE + 0xc))) {
- fprintf(stderr, "Could not read from zy1000 server\n");
- exit(-1);
- }
-
- if (readqueue_pos >= readqueue_size)
- zy1000_flush_readqueue();
-
- readqueue[readqueue_pos].dest = data;
- readqueue[readqueue_pos].bits = bits;
- readqueue_pos++;
-
- /* KLUDGE!!! minidriver requires readqueue to be synchronous */
- zy1000_flush_readqueue();
-}
-
-#else
-
-static void writeShiftValue(uint8_t *data, int bits)
-{
- uint32_t value;
- waitIdle();
- ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, value);
- VERBOSE(LOG_INFO("getShiftValue %08x", value));
-
- /* data in, LSB to MSB */
- /* we're shifting in data to MSB, shift data to be aligned for returning the value */
- value >>= 32 - bits;
-
- for (int l = 0; l < bits; l += 8)
- data[l/8] = (value >> l)&0xff;
-}
-
-#endif
-
-#if BUILD_ZY1000_MASTER
-
-#ifdef WATCHDOG_BASE
-/* If we connect to port 8888 we must send a char every 10s or the board resets itself */
-static void watchdog_server(cyg_addrword_t data)
-{
- int so_reuseaddr_option = 1;
-
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd == -1) {
- LOG_ERROR("error creating socket: %s", strerror(errno));
- exit(-1);
- }
-
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &so_reuseaddr_option,
- sizeof(int));
-
- struct sockaddr_in sin;
- unsigned int address_size;
- address_size = sizeof(sin);
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons(8888);
-
- if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
- LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
- exit(-1);
- }
-
- if (listen(fd, 1) == -1) {
- LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
- exit(-1);
- }
-
-
- for (;; ) {
- int watchdog_ip = accept(fd, (struct sockaddr *) &sin, &address_size);
-
- /* Start watchdog, must be reset every 10 seconds. */
- HAL_WRITE_UINT32(WATCHDOG_BASE + 4, 4);
-
- if (watchdog_ip < 0) {
- LOG_ERROR("couldn't open watchdog socket: %s", strerror(errno));
- exit(-1);
- }
-
- int flag = 1;
- setsockopt(watchdog_ip, /* socket affected */
- IPPROTO_TCP, /* set option at TCP level */
- TCP_NODELAY, /* name of option */
- (char *)&flag, /* the cast is historical cruft */
- sizeof(int)); /* length of option value */
-
-
- char buf;
- for (;; ) {
- if (read(watchdog_ip, &buf, 1) == 1) {
- /* Reset timer */
- HAL_WRITE_UINT32(WATCHDOG_BASE + 8, 0x1234);
- /* Echo so we can telnet in and see that resetting works */
- write(watchdog_ip, &buf, 1);
- } else {
- /* Stop tickling the watchdog, the CPU will reset in < 10 seconds
- * now.
- */
- return;
- }
-
- }
-
- /* Never reached */
- }
-}
-#endif
-
-#endif
-
-#if BUILD_ZY1000_MASTER
-int interface_jtag_add_sleep(uint32_t us)
-{
- jtag_sleep(us);
- return ERROR_OK;
-}
-#endif
-
-#if BUILD_ZY1000_MASTER
-volatile void *zy1000_jtag_master;
-#include <sys/mman.h>
-#endif
-
-int zy1000_init(void)
-{
-#if BUILD_ZY1000_MASTER
- int fd = open("/dev/mem", O_RDWR | O_SYNC);
- if (fd == -1) {
- LOG_ERROR("No access to /dev/mem");
- return ERROR_FAIL;
- }
-#ifndef REGISTERS_BASE
-#define REGISTERS_BASE 0x9002000
-#define REGISTERS_SPAN 128
-#endif
-
- zy1000_jtag_master = mmap(0,
- REGISTERS_SPAN,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fd,
- REGISTERS_BASE);
-
- if (zy1000_jtag_master == (void *) -1) {
- close(fd);
- LOG_ERROR("No access to /dev/mem");
- return ERROR_FAIL;
- }
-#endif
-
- ZY1000_POKE(ZY1000_JTAG_BASE + 0x10, 0x30); /* Turn on LED1 & LED2 */
-
- setPower(true); /* on by default */
-
- /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */
- zy1000_reset(0, 0);
-
- return ERROR_OK;
-}
-
-struct jtag_interface zy1000_interface = {
- .name = "ZY1000",
- .supported = DEBUG_CAP_TMS_SEQ,
- .execute_queue = NULL,
- .speed = zy1000_speed,
- .commands = zy1000_commands,
- .init = zy1000_init,
- .quit = zy1000_quit,
- .khz = zy1000_khz,
- .speed_div = zy1000_speed_div,
- .power_dropout = zy1000_power_dropout,
- .srst_asserted = zy1000_srst_asserted,
-};
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 83e60d8..0000000
--- a/src/main.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "openocd.h"
-
-/* This is the main entry for developer PC hosted OpenOCD.
- *
- * OpenOCD can also be used as a library that is linked with
- * another application(not mainstream yet, but possible), e.g.
- * w/as an embedded application.
- *
- * Those applications will have their own main() implementation
- * and use bits and pieces from openocd.c. */
-
-int main(int argc, char *argv[])
-{
- /* disable buffering otherwise piping to logs causes problems work */
- setvbuf(stdout, NULL, _IONBF, 0);
- setvbuf(stderr, NULL, _IONBF, 0);
-
- return openocd_main(argc, argv);
-}
diff --git a/src/openocd.c b/src/openocd.c
deleted file mode 100644
index b5bb44b..0000000
--- a/src/openocd.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 Richard Missenden *
- * richard.missenden@googlemail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "openocd.h"
-#include <jtag/driver.h>
-#include <jtag/jtag.h>
-#include <transport/transport.h>
-#include <helper/ioutil.h>
-#include <helper/util.h>
-#include <helper/configuration.h>
-#include <flash/nor/core.h>
-#include <flash/nand/core.h>
-#include <pld/pld.h>
-#include <flash/mflash.h>
-
-#include <server/server.h>
-#include <server/gdb_server.h>
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#define OPENOCD_VERSION \
- "Open On-Chip Debugger " VERSION RELSTR " (" PKGBLDDATE ")"
-
-static const char openocd_startup_tcl[] = {
-#include "startup_tcl.inc"
-0 /* Terminate with zero */
-};
-
-/* Give scripts and TELNET a way to find out what version this is */
-static int jim_version_command(Jim_Interp *interp, int argc,
- Jim_Obj * const *argv)
-{
- if (argc > 2)
- return JIM_ERR;
- const char *str = "";
- char *version_str;
- version_str = OPENOCD_VERSION;
-
- if (argc == 2)
- str = Jim_GetString(argv[1], NULL);
-
- if (strcmp("git", str) == 0)
- version_str = GITVERSION;
-
- Jim_SetResult(interp, Jim_NewStringObj(interp, version_str, -1));
-
- return JIM_OK;
-}
-
-static int log_target_callback_event_handler(struct target *target,
- enum target_event event,
- void *priv)
-{
- switch (event) {
- case TARGET_EVENT_GDB_START:
- target->display = 0;
- break;
- case TARGET_EVENT_GDB_END:
- target->display = 1;
- break;
- case TARGET_EVENT_HALTED:
- if (target->display) {
- /* do not display information when debugger caused the halt */
- target_arch_state(target);
- }
- break;
- default:
- break;
- }
-
- return ERROR_OK;
-}
-
-static bool init_at_startup = true;
-
-COMMAND_HANDLER(handle_noinit_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
- init_at_startup = false;
- return ERROR_OK;
-}
-
-/* OpenOCD can't really handle failure of this command. Patches welcome! :-) */
-COMMAND_HANDLER(handle_init_command)
-{
-
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int retval;
- static int initialized;
- if (initialized)
- return ERROR_OK;
-
- initialized = 1;
-
- retval = command_run_line(CMD_CTX, "target init");
- if (ERROR_OK != retval)
- return ERROR_FAIL;
-
- retval = adapter_init(CMD_CTX);
- if (retval != ERROR_OK) {
- /* we must be able to set up the debug adapter */
- return retval;
- }
-
- LOG_DEBUG("Debug Adapter init complete");
-
- /* "transport init" verifies the expected devices are present;
- * for JTAG, it checks the list of configured TAPs against
- * what's discoverable, possibly with help from the platform's
- * JTAG event handlers. (which require COMMAND_EXEC)
- */
- command_context_mode(CMD_CTX, COMMAND_EXEC);
-
- retval = command_run_line(CMD_CTX, "transport init");
- if (ERROR_OK != retval)
- return ERROR_FAIL;
-
- LOG_DEBUG("Examining targets...");
- if (target_examine() != ERROR_OK)
- LOG_DEBUG("target examination failed");
-
- command_context_mode(CMD_CTX, COMMAND_CONFIG);
-
- if (command_run_line(CMD_CTX, "flash init") != ERROR_OK)
- return ERROR_FAIL;
-
- if (command_run_line(CMD_CTX, "mflash init") != ERROR_OK)
- return ERROR_FAIL;
-
- if (command_run_line(CMD_CTX, "nand init") != ERROR_OK)
- return ERROR_FAIL;
-
- if (command_run_line(CMD_CTX, "pld init") != ERROR_OK)
- return ERROR_FAIL;
- command_context_mode(CMD_CTX, COMMAND_EXEC);
-
- /* initialize telnet subsystem */
- gdb_target_add_all(all_targets);
-
- target_register_event_callback(log_target_callback_event_handler, CMD_CTX);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_add_script_search_dir_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- add_script_search_dir(CMD_ARGV[0]);
-
- return ERROR_OK;
-}
-
-static const struct command_registration openocd_command_handlers[] = {
- {
- .name = "version",
- .jim_handler = jim_version_command,
- .mode = COMMAND_ANY,
- .help = "show program version",
- },
- {
- .name = "noinit",
- .handler = &handle_noinit_command,
- .mode = COMMAND_CONFIG,
- .help = "Prevent 'init' from being called at startup.",
- .usage = ""
- },
- {
- .name = "init",
- .handler = &handle_init_command,
- .mode = COMMAND_ANY,
- .help = "Initializes configured targets and servers. "
- "Changes command mode from CONFIG to EXEC. "
- "Unless 'noinit' is called, this command is "
- "called automatically at the end of startup.",
- .usage = ""
- },
- {
- .name = "add_script_search_dir",
- .handler = &handle_add_script_search_dir_command,
- .mode = COMMAND_ANY,
- .help = "dir to search for config files and scripts",
- .usage = "<directory>"
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int openocd_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, openocd_command_handlers);
-}
-
-struct command_context *global_cmd_ctx;
-
-/* NB! this fn can be invoked outside this file for non PC hosted builds
- * NB! do not change to 'static'!!!!
- */
-struct command_context *setup_command_handler(Jim_Interp *interp)
-{
- log_init();
- LOG_DEBUG("log_init: complete");
-
- struct command_context *cmd_ctx = command_init(openocd_startup_tcl, interp);
-
- /* register subsystem commands */
- typedef int (*command_registrant_t)(struct command_context *cmd_ctx_value);
- static const command_registrant_t command_registrants[] = {
- &openocd_register_commands,
- &server_register_commands,
- &gdb_register_commands,
- &log_register_commands,
- &transport_register_commands,
- &interface_register_commands,
- &target_register_commands,
- &flash_register_commands,
- &nand_register_commands,
- &pld_register_commands,
- &mflash_register_commands,
- NULL
- };
- for (unsigned i = 0; NULL != command_registrants[i]; i++) {
- int retval = (*command_registrants[i])(cmd_ctx);
- if (ERROR_OK != retval) {
- command_done(cmd_ctx);
- return NULL;
- }
- }
- LOG_DEBUG("command registration: complete");
-
- LOG_OUTPUT(OPENOCD_VERSION "\n"
- "Licensed under GNU GPL v2\n");
-
- global_cmd_ctx = cmd_ctx;
-
- return cmd_ctx;
-}
-
-/** OpenOCD runtime meat that can become single-thread in future. It parse
- * commandline, reads configuration, sets up the target and starts server loop.
- * Commandline arguments are passed into this function from openocd_main().
- */
-static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ctx)
-{
- int ret;
-
- if (parse_cmdline_args(cmd_ctx, argc, argv) != ERROR_OK)
- return ERROR_FAIL;
-
- if (server_preinit() != ERROR_OK)
- return ERROR_FAIL;
-
- ret = parse_config_file(cmd_ctx);
- if (ret == ERROR_COMMAND_CLOSE_CONNECTION)
- return ERROR_OK;
- else if (ret != ERROR_OK)
- return ERROR_FAIL;
-
- ret = server_init(cmd_ctx);
- if (ERROR_OK != ret)
- return ERROR_FAIL;
-
- if (init_at_startup) {
- ret = command_run_line(cmd_ctx, "init");
- if (ERROR_OK != ret)
- return ERROR_FAIL;
- }
-
- ret = server_loop(cmd_ctx);
-
- int last_signal = server_quit();
- if (last_signal != ERROR_OK)
- return last_signal;
-
- if (ret != ERROR_OK)
- return ERROR_FAIL;
- return ERROR_OK;
-}
-
-/* normally this is the main() function entry, but if OpenOCD is linked
- * into application, then this fn will not be invoked, but rather that
- * application will have it's own implementation of main(). */
-int openocd_main(int argc, char *argv[])
-{
- int ret;
-
- /* initialize commandline interface */
- struct command_context *cmd_ctx;
-
- cmd_ctx = setup_command_handler(NULL);
-
- if (util_init(cmd_ctx) != ERROR_OK)
- return EXIT_FAILURE;
-
- if (ioutil_init(cmd_ctx) != ERROR_OK)
- return EXIT_FAILURE;
-
- LOG_OUTPUT("For bug reports, read\n\t"
- "http://openocd.org/doc/doxygen/bugs.html"
- "\n");
-
- command_context_mode(cmd_ctx, COMMAND_CONFIG);
- command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
-
- /* Start the executable meat that can evolve into thread in future. */
- ret = openocd_thread(argc, argv, cmd_ctx);
-
- unregister_all_commands(cmd_ctx, NULL);
-
- /* free commandline interface */
- command_done(cmd_ctx);
-
- adapter_quit();
-
- if (ERROR_FAIL == ret)
- return EXIT_FAILURE;
- else if (ERROR_OK != ret)
- exit_on_signal(ret);
-
- return ret;
-}
diff --git a/src/openocd.h b/src/openocd.h
deleted file mode 100644
index 543ac3c..0000000
--- a/src/openocd.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
- * Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_OPENOCD_H
-#define OPENOCD_OPENOCD_H
-
-/**
- * Different applications can define this entry point to override
- * the default openocd main function. On most systems, this will be
- * defined in src/openocd.c.
- * @param argc normally passed from main()
- * @param argv normally passed from main()
- * @returns return code for main()
- */
-int openocd_main(int argc, char *argv[]);
-
-#endif /* OPENOCD_OPENOCD_H */
diff --git a/src/pld/Makefile.am b/src/pld/Makefile.am
deleted file mode 100644
index 93b79f4..0000000
--- a/src/pld/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-include $(top_srcdir)/common.mk
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libpld.la
-noinst_HEADERS = pld.h xilinx_bit.h virtex2.h
-libpld_la_SOURCES = pld.c xilinx_bit.c virtex2.c
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/pld/pld.c b/src/pld/pld.c
deleted file mode 100644
index 5210b97..0000000
--- a/src/pld/pld.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pld.h"
-#include <helper/log.h>
-#include <helper/time_support.h>
-
-
-/* pld drivers
- */
-extern struct pld_driver virtex2_pld;
-
-static struct pld_driver *pld_drivers[] = {
- &virtex2_pld,
- NULL,
-};
-
-static struct pld_device *pld_devices;
-
-struct pld_device *get_pld_device_by_num(int num)
-{
- struct pld_device *p;
- int i = 0;
-
- for (p = pld_devices; p; p = p->next) {
- if (i++ == num)
- return p;
- }
-
- return NULL;
-}
-
-/* pld device <driver> [driver_options ...]
- */
-COMMAND_HANDLER(handle_pld_device_command)
-{
- int i;
- int found = 0;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- for (i = 0; pld_drivers[i]; i++) {
- if (strcmp(CMD_ARGV[0], pld_drivers[i]->name) == 0) {
- struct pld_device *p, *c;
-
- /* register pld specific commands */
- int retval;
- if (pld_drivers[i]->commands) {
- retval = register_commands(CMD_CTX, NULL,
- pld_drivers[i]->commands);
- if (ERROR_OK != retval) {
- LOG_ERROR("couldn't register '%s' commands", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
- }
-
- c = malloc(sizeof(struct pld_device));
- c->driver = pld_drivers[i];
- c->next = NULL;
-
- retval = CALL_COMMAND_HANDLER(
- pld_drivers[i]->pld_device_command, c);
- if (ERROR_OK != retval) {
- LOG_ERROR("'%s' driver rejected pld device",
- CMD_ARGV[0]);
- free(c);
- return ERROR_OK;
- }
-
- /* put pld device in linked list */
- if (pld_devices) {
- /* find last pld device */
- for (p = pld_devices; p && p->next; p = p->next)
- ;
- if (p)
- p->next = c;
- } else
- pld_devices = c;
-
- found = 1;
- }
- }
-
- /* no matching pld driver found */
- if (!found) {
- LOG_ERROR("pld driver '%s' not found", CMD_ARGV[0]);
- exit(-1);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_pld_devices_command)
-{
- struct pld_device *p;
- int i = 0;
-
- if (!pld_devices) {
- command_print(CMD_CTX, "no pld devices configured");
- return ERROR_OK;
- }
-
- for (p = pld_devices; p; p = p->next)
- command_print(CMD_CTX, "#%i: %s", i++, p->driver->name);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_pld_load_command)
-{
- int retval;
- struct timeval start, end, duration;
- struct pld_device *p;
-
- gettimeofday(&start, NULL);
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned dev_id;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
- p = get_pld_device_by_num(dev_id);
- if (!p) {
- command_print(CMD_CTX, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- retval = p->driver->load(p, CMD_ARGV[1]);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX, "failed loading file %s to pld device %u",
- CMD_ARGV[1], dev_id);
- switch (retval) {
- }
- return retval;
- } else {
- gettimeofday(&end, NULL);
- timeval_subtract(&duration, &end, &start);
-
- command_print(CMD_CTX, "loaded file %s to pld device %u in %jis %jius",
- CMD_ARGV[1], dev_id,
- (intmax_t)duration.tv_sec, (intmax_t)duration.tv_usec);
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration pld_exec_command_handlers[] = {
- {
- .name = "devices",
- .handler = handle_pld_devices_command,
- .mode = COMMAND_EXEC,
- .help = "list configured pld devices",
- },
- {
- .name = "load",
- .handler = handle_pld_load_command,
- .mode = COMMAND_EXEC,
- .help = "load configuration file into PLD",
- .usage = "pld_num filename",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int pld_init(struct command_context *cmd_ctx)
-{
- if (!pld_devices)
- return ERROR_OK;
-
- struct command *parent = command_find_in_context(cmd_ctx, "pld");
- return register_commands(cmd_ctx, parent, pld_exec_command_handlers);
-}
-
-COMMAND_HANDLER(handle_pld_init_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- static bool pld_initialized;
- if (pld_initialized) {
- LOG_INFO("'pld init' has already been called");
- return ERROR_OK;
- }
- pld_initialized = true;
-
- LOG_DEBUG("Initializing PLDs...");
- return pld_init(CMD_CTX);
-}
-
-static const struct command_registration pld_config_command_handlers[] = {
- {
- .name = "device",
- .mode = COMMAND_CONFIG,
- .handler = handle_pld_device_command,
- .help = "configure a PLD device",
- .usage = "driver_name [driver_args ... ]",
- },
- {
- .name = "init",
- .mode = COMMAND_CONFIG,
- .handler = handle_pld_init_command,
- .help = "initialize PLD devices",
- .usage = ""
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration pld_command_handler[] = {
- {
- .name = "pld",
- .mode = COMMAND_ANY,
- .help = "programmable logic device commands",
- .usage = "",
- .chain = pld_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-int pld_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, pld_command_handler);
-}
diff --git a/src/pld/pld.h b/src/pld/pld.h
deleted file mode 100644
index 3178fd4..0000000
--- a/src/pld/pld.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_PLD_PLD_H
-#define OPENOCD_PLD_PLD_H
-
-#include <helper/command.h>
-
-struct pld_device;
-
-#define __PLD_DEVICE_COMMAND(name) \
- COMMAND_HELPER(name, struct pld_device *pld)
-
-struct pld_driver {
- const char *name;
- __PLD_DEVICE_COMMAND((*pld_device_command));
- const struct command_registration *commands;
- int (*load)(struct pld_device *pld_device, const char *filename);
-};
-
-#define PLD_DEVICE_COMMAND_HANDLER(name) \
- static __PLD_DEVICE_COMMAND(name)
-
-struct pld_device {
- struct pld_driver *driver;
- void *driver_priv;
- struct pld_device *next;
-};
-
-int pld_register_commands(struct command_context *cmd_ctx);
-
-struct pld_device *get_pld_device_by_num(int num);
-
-#define ERROR_PLD_DEVICE_INVALID (-1000)
-#define ERROR_PLD_FILE_LOAD_FAILED (-1001)
-
-#endif /* OPENOCD_PLD_PLD_H */
diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c
deleted file mode 100644
index 4e385e9..0000000
--- a/src/pld/virtex2.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "virtex2.h"
-#include "xilinx_bit.h"
-#include "pld.h"
-
-static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr)
-{
- if (tap == NULL)
- return ERROR_FAIL;
-
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
- struct scan_field field;
-
- field.num_bits = tap->ir_length;
- void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_instr);
- field.in_value = NULL;
-
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- free(t);
- }
-
- return ERROR_OK;
-}
-
-static int virtex2_send_32(struct pld_device *pld_device,
- int num_words, uint32_t *words)
-{
- struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
- struct scan_field scan_field;
- uint8_t *values;
- int i;
-
- values = malloc(num_words * 4);
-
- scan_field.num_bits = num_words * 32;
- scan_field.out_value = values;
- scan_field.in_value = NULL;
-
- for (i = 0; i < num_words; i++)
- buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
-
- virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
-
- jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE);
-
- free(values);
-
- return ERROR_OK;
-}
-
-static inline void virtexflip32(jtag_callback_data_t arg)
-{
- uint8_t *in = (uint8_t *)arg;
- *((uint32_t *)arg) = flip_u32(le_to_h_u32(in), 32);
-}
-
-static int virtex2_receive_32(struct pld_device *pld_device,
- int num_words, uint32_t *words)
-{
- struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
- struct scan_field scan_field;
-
- scan_field.num_bits = 32;
- scan_field.out_value = NULL;
- scan_field.in_value = NULL;
-
- virtex2_set_instr(virtex2_info->tap, 0x4); /* CFG_OUT */
-
- while (num_words--) {
- scan_field.in_value = (uint8_t *)words;
-
- jtag_add_dr_scan(virtex2_info->tap, 1, &scan_field, TAP_DRPAUSE);
-
- jtag_add_callback(virtexflip32, (jtag_callback_data_t)words);
-
- words++;
- }
-
- return ERROR_OK;
-}
-
-static int virtex2_read_stat(struct pld_device *pld_device, uint32_t *status)
-{
- uint32_t data[5];
-
- jtag_add_tlr();
-
- data[0] = 0xaa995566; /* synch word */
- data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
- data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
- data[3] = 0x20000000; /* NOOP */
- data[4] = 0x20000000; /* NOOP */
- virtex2_send_32(pld_device, 5, data);
-
- virtex2_receive_32(pld_device, 1, status);
-
- jtag_execute_queue();
-
- LOG_DEBUG("status: 0x%8.8" PRIx32 "", *status);
-
- return ERROR_OK;
-}
-
-static int virtex2_load(struct pld_device *pld_device, const char *filename)
-{
- struct virtex2_pld_device *virtex2_info = pld_device->driver_priv;
- struct xilinx_bit_file bit_file;
- int retval;
- unsigned int i;
- struct scan_field field;
-
- field.in_value = NULL;
-
- retval = xilinx_read_bit_file(&bit_file, filename);
- if (retval != ERROR_OK)
- return retval;
-
- virtex2_set_instr(virtex2_info->tap, 0xb); /* JPROG_B */
- jtag_execute_queue();
- jtag_add_sleep(1000);
-
- virtex2_set_instr(virtex2_info->tap, 0x5); /* CFG_IN */
- jtag_execute_queue();
-
- for (i = 0; i < bit_file.length; i++)
- bit_file.data[i] = flip_u32(bit_file.data[i], 8);
-
- field.num_bits = bit_file.length * 8;
- field.out_value = bit_file.data;
-
- jtag_add_dr_scan(virtex2_info->tap, 1, &field, TAP_DRPAUSE);
- jtag_execute_queue();
-
- jtag_add_tlr();
-
- if (!(virtex2_info->no_jstart))
- virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
- jtag_add_runtest(13, TAP_IDLE);
- virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
- virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
- if (!(virtex2_info->no_jstart))
- virtex2_set_instr(virtex2_info->tap, 0xc); /* JSTART */
- jtag_add_runtest(13, TAP_IDLE);
- virtex2_set_instr(virtex2_info->tap, 0x3f); /* BYPASS */
- jtag_execute_queue();
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(virtex2_handle_read_stat_command)
-{
- struct pld_device *device;
- uint32_t status;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned dev_id;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], dev_id);
- device = get_pld_device_by_num(dev_id);
- if (!device) {
- command_print(CMD_CTX, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
- return ERROR_OK;
- }
-
- virtex2_read_stat(device, &status);
-
- command_print(CMD_CTX, "virtex2 status register: 0x%8.8" PRIx32 "", status);
-
- return ERROR_OK;
-}
-
-PLD_DEVICE_COMMAND_HANDLER(virtex2_pld_device_command)
-{
- struct jtag_tap *tap;
-
- struct virtex2_pld_device *virtex2_info;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- tap = jtag_tap_by_string(CMD_ARGV[1]);
- if (tap == NULL) {
- command_print(CMD_CTX, "Tap: %s does not exist", CMD_ARGV[1]);
- return ERROR_OK;
- }
-
- virtex2_info = malloc(sizeof(struct virtex2_pld_device));
- virtex2_info->tap = tap;
-
- virtex2_info->no_jstart = 0;
- if (CMD_ARGC >= 3)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], virtex2_info->no_jstart);
-
- pld->driver_priv = virtex2_info;
-
- return ERROR_OK;
-}
-
-static const struct command_registration virtex2_exec_command_handlers[] = {
- {
- .name = "read_stat",
- .mode = COMMAND_EXEC,
- .handler = virtex2_handle_read_stat_command,
- .help = "read status register",
- .usage = "pld_num",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration virtex2_command_handler[] = {
- {
- .name = "virtex2",
- .mode = COMMAND_ANY,
- .help = "Virtex-II specific commands",
- .usage = "",
- .chain = virtex2_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct pld_driver virtex2_pld = {
- .name = "virtex2",
- .commands = virtex2_command_handler,
- .pld_device_command = &virtex2_pld_device_command,
- .load = &virtex2_load,
-};
diff --git a/src/pld/virtex2.h b/src/pld/virtex2.h
deleted file mode 100644
index d6d922e..0000000
--- a/src/pld/virtex2.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_PLD_VIRTEX2_H
-#define OPENOCD_PLD_VIRTEX2_H
-
-#include <jtag/jtag.h>
-
-struct virtex2_pld_device {
- struct jtag_tap *tap;
- int no_jstart;
-};
-
-#endif /* OPENOCD_PLD_VIRTEX2_H */
diff --git a/src/pld/xilinx_bit.c b/src/pld/xilinx_bit.c
deleted file mode 100644
index a975a7a..0000000
--- a/src/pld/xilinx_bit.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xilinx_bit.h"
-#include "pld.h"
-#include <helper/log.h>
-
-#include <sys/stat.h>
-
-
-static int read_section(FILE *input_file, int length_size, char section,
- uint32_t *buffer_length, uint8_t **buffer)
-{
- uint8_t length_buffer[4];
- int length;
- char section_char;
- int read_count;
-
- if ((length_size != 2) && (length_size != 4)) {
- LOG_ERROR("BUG: length_size neither 2 nor 4");
- return ERROR_PLD_FILE_LOAD_FAILED;
- }
-
- read_count = fread(&section_char, 1, 1, input_file);
- if (read_count != 1)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- if (section_char != section)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- read_count = fread(length_buffer, 1, length_size, input_file);
- if (read_count != length_size)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- if (length_size == 4)
- length = be_to_h_u32(length_buffer);
- else /* (length_size == 2) */
- length = be_to_h_u16(length_buffer);
-
- if (buffer_length)
- *buffer_length = length;
-
- *buffer = malloc(length);
-
- read_count = fread(*buffer, 1, length, input_file);
- if (read_count != length)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- return ERROR_OK;
-}
-
-int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename)
-{
- FILE *input_file;
- struct stat input_stat;
- int read_count;
-
- if (!filename || !bit_file)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (stat(filename, &input_stat) == -1) {
- LOG_ERROR("couldn't stat() %s: %s", filename, strerror(errno));
- return ERROR_PLD_FILE_LOAD_FAILED;
- }
-
- if (S_ISDIR(input_stat.st_mode)) {
- LOG_ERROR("%s is a directory", filename);
- return ERROR_PLD_FILE_LOAD_FAILED;
- }
-
- if (input_stat.st_size == 0) {
- LOG_ERROR("Empty file %s", filename);
- return ERROR_PLD_FILE_LOAD_FAILED;
- }
-
- input_file = fopen(filename, "rb");
- if (input_file == NULL) {
- LOG_ERROR("couldn't open %s: %s", filename, strerror(errno));
- return ERROR_PLD_FILE_LOAD_FAILED;
- }
-
- read_count = fread(bit_file->unknown_header, 1, 13, input_file);
- if (read_count != 13) {
- LOG_ERROR("couldn't read unknown_header from file '%s'", filename);
- return ERROR_PLD_FILE_LOAD_FAILED;
- }
-
- if (read_section(input_file, 2, 'a', NULL, &bit_file->source_file) != ERROR_OK)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- if (read_section(input_file, 2, 'b', NULL, &bit_file->part_name) != ERROR_OK)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- if (read_section(input_file, 2, 'c', NULL, &bit_file->date) != ERROR_OK)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- if (read_section(input_file, 2, 'd', NULL, &bit_file->time) != ERROR_OK)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- if (read_section(input_file, 4, 'e', &bit_file->length, &bit_file->data) != ERROR_OK)
- return ERROR_PLD_FILE_LOAD_FAILED;
-
- LOG_DEBUG("bit_file: %s %s %s,%s %" PRIi32 "", bit_file->source_file, bit_file->part_name,
- bit_file->date, bit_file->time, bit_file->length);
-
- fclose(input_file);
-
- return ERROR_OK;
-}
diff --git a/src/pld/xilinx_bit.h b/src/pld/xilinx_bit.h
deleted file mode 100644
index 1a35c3b..0000000
--- a/src/pld/xilinx_bit.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_PLD_XILINX_BIT_H
-#define OPENOCD_PLD_XILINX_BIT_H
-
-struct xilinx_bit_file {
- uint8_t unknown_header[13];
- uint8_t *source_file;
- uint8_t *part_name;
- uint8_t *date;
- uint8_t *time;
- uint32_t length;
- uint8_t *data;
-};
-
-int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename);
-
-#endif /* OPENOCD_PLD_XILINX_BIT_H */
diff --git a/src/rtos/ChibiOS.c b/src/rtos/ChibiOS.c
deleted file mode 100644
index 00e9df7..0000000
--- a/src/rtos/ChibiOS.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by Matthias Blaicher *
- * Matthias Blaicher - matthias@blaicher.com *
- * *
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include "target/target.h"
-#include "target/target_type.h"
-#include "target/armv7m.h"
-#include "target/cortex_m.h"
-#include "rtos.h"
-#include "helper/log.h"
-#include "helper/types.h"
-#include "rtos_chibios_stackings.h"
-
-/**
- * @brief ChibiOS/RT memory signature record.
- *
- * @details Definition copied from os/kernel/include/chregistry.h of ChibiOS/RT.
- */
-struct ChibiOS_chdebug {
- char ch_identifier[4]; /**< @brief Always set to "main". */
- uint8_t ch_zero; /**< @brief Must be zero. */
- uint8_t ch_size; /**< @brief Size of this structure. */
- uint16_t ch_version; /**< @brief Encoded ChibiOS/RT version. */
- uint8_t ch_ptrsize; /**< @brief Size of a pointer. */
- uint8_t ch_timesize; /**< @brief Size of a @p systime_t. */
- uint8_t ch_threadsize; /**< @brief Size of a @p Thread struct. */
- uint8_t cf_off_prio; /**< @brief Offset of @p p_prio field. */
- uint8_t cf_off_ctx; /**< @brief Offset of @p p_ctx field. */
- uint8_t cf_off_newer; /**< @brief Offset of @p p_newer field. */
- uint8_t cf_off_older; /**< @brief Offset of @p p_older field. */
- uint8_t cf_off_name; /**< @brief Offset of @p p_name field. */
- uint8_t cf_off_stklimit; /**< @brief Offset of @p p_stklimit
- field. */
- uint8_t cf_off_state; /**< @brief Offset of @p p_state field. */
- uint8_t cf_off_flags; /**< @brief Offset of @p p_flags field. */
- uint8_t cf_off_refs; /**< @brief Offset of @p p_refs field. */
- uint8_t cf_off_preempt; /**< @brief Offset of @p p_preempt
- field. */
- uint8_t cf_off_time; /**< @brief Offset of @p p_time field. */
-};
-
-#define GET_CH_KERNEL_MAJOR(codedVersion) ((codedVersion >> 11) & 0x1f)
-#define GET_CH_KERNEL_MINOR(codedVersion) ((codedVersion >> 6) & 0x1f)
-#define GET_CH_KERNEL_PATCH(codedVersion) ((codedVersion >> 0) & 0x3f)
-
-/**
- * @brief ChibiOS thread states.
- */
-static const char * const ChibiOS_thread_states[] = {
- "READY", "CURRENT", "SUSPENDED", "WTSEM", "WTMTX", "WTCOND", "SLEEPING",
- "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "WTQUEUE",
- "FINAL"
-};
-
-#define CHIBIOS_NUM_STATES (sizeof(ChibiOS_thread_states)/sizeof(char *))
-
-/* Maximum ChibiOS thread name. There is no real limit set by ChibiOS but 64
- * chars ought to be enough.
- */
-#define CHIBIOS_THREAD_NAME_STR_SIZE (64)
-
-struct ChibiOS_params {
- const char *target_name;
-
- struct ChibiOS_chdebug *signature;
- const struct rtos_register_stacking *stacking_info;
-};
-
-static struct ChibiOS_params ChibiOS_params_list[] = {
- {
- "cortex_m", /* target_name */
- 0,
- NULL, /* stacking_info */
- },
- {
- "hla_target", /* target_name */
- 0,
- NULL, /* stacking_info */
- }
-};
-#define CHIBIOS_NUM_PARAMS ((int)(sizeof(ChibiOS_params_list)/sizeof(struct ChibiOS_params)))
-
-static int ChibiOS_detect_rtos(struct target *target);
-static int ChibiOS_create(struct target *target);
-static int ChibiOS_update_threads(struct rtos *rtos);
-static int ChibiOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
-static int ChibiOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
-
-struct rtos_type ChibiOS_rtos = {
- .name = "ChibiOS",
-
- .detect_rtos = ChibiOS_detect_rtos,
- .create = ChibiOS_create,
- .update_threads = ChibiOS_update_threads,
- .get_thread_reg_list = ChibiOS_get_thread_reg_list,
- .get_symbol_list_to_lookup = ChibiOS_get_symbol_list_to_lookup,
-};
-
-
-/* In ChibiOS/RT 3.0 the rlist structure has become part of a system
- * data structure ch. We declare both symbols as optional and later
- * use whatever is available.
- */
-
-enum ChibiOS_symbol_values {
- ChibiOS_VAL_rlist = 0,
- ChibiOS_VAL_ch = 1,
- ChibiOS_VAL_ch_debug = 2
-};
-
-static symbol_table_elem_t ChibiOS_symbol_list[] = {
- { "rlist", 0, true}, /* Thread ready list */
- { "ch", 0, true}, /* System data structure */
- { "ch_debug", 0, false}, /* Memory Signature containing offsets of fields in rlist */
- { NULL, 0, false}
-};
-
-/* Offset of the rlist structure within the system data structure (ch) */
-#define CH_RLIST_OFFSET 0x00
-
-static int ChibiOS_update_memory_signature(struct rtos *rtos)
-{
- int retval;
- struct ChibiOS_params *param;
- struct ChibiOS_chdebug *signature;
-
- param = (struct ChibiOS_params *) rtos->rtos_specific_params;
-
- /* Free existing memory description.*/
- if (param->signature) {
- free(param->signature);
- param->signature = 0;
- }
-
- signature = malloc(sizeof(*signature));
- if (!signature) {
- LOG_ERROR("Could not allocate space for ChibiOS/RT memory signature");
- return -1;
- }
-
- retval = target_read_buffer(rtos->target,
- rtos->symbols[ChibiOS_VAL_ch_debug].address,
- sizeof(*signature),
- (uint8_t *) signature);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read ChibiOS/RT memory signature from target");
- goto errfree;
- }
-
- if (strncmp(signature->ch_identifier, "main", 4) != 0) {
- LOG_ERROR("Memory signature identifier does not contain magic bytes.");
- goto errfree;
- }
-
- if (signature->ch_size < sizeof(*signature)) {
- LOG_ERROR("ChibiOS/RT memory signature claims to be smaller "
- "than expected");
- goto errfree;
- }
-
- if (signature->ch_size > sizeof(*signature)) {
- LOG_WARNING("ChibiOS/RT memory signature claims to be bigger than"
- " expected. Assuming compatibility...");
- }
-
- /* Convert endianness of version field */
- const uint8_t *versionTarget = (const uint8_t *)
- &signature->ch_version;
- signature->ch_version = rtos->target->endianness == TARGET_LITTLE_ENDIAN ?
- le_to_h_u32(versionTarget) : be_to_h_u32(versionTarget);
-
- const uint16_t ch_version = signature->ch_version;
- LOG_INFO("Successfully loaded memory map of ChibiOS/RT target "
- "running version %i.%i.%i", GET_CH_KERNEL_MAJOR(ch_version),
- GET_CH_KERNEL_MINOR(ch_version), GET_CH_KERNEL_PATCH(ch_version));
-
- /* Currently, we have the inherent assumption that all address pointers
- * are 32 bit wide. */
- if (signature->ch_ptrsize != sizeof(uint32_t)) {
- LOG_ERROR("ChibiOS/RT target memory signature claims an address"
- "width unequal to 32 bits!");
- free(signature);
- return -1;
- }
-
- param->signature = signature;
- return 0;
-
-errfree:
- /* Error reading the ChibiOS memory structure */
- free(signature);
- param->signature = 0;
- return -1;
-}
-
-
-static int ChibiOS_update_stacking(struct rtos *rtos)
-{
- /* Sometimes the stacking can not be determined only by looking at the
- * target name but only a runtime.
- *
- * For example, this is the case for Cortex-M4 targets and ChibiOS which
- * only stack the FPU registers if it is enabled during ChibiOS build.
- *
- * Terminating which stacking is used is target depending.
- *
- * Assumptions:
- * - Once ChibiOS is actually initialized, the stacking is fixed.
- * - During startup code, the FPU might not be initialized and the
- * detection might fail.
- * - Since no threads are running during startup, the problem is solved
- * by delaying stacking detection until there are more threads
- * available than the current execution. In which case
- * ChibiOS_get_thread_reg_list is called.
- */
- int retval;
-
- if (!rtos->rtos_specific_params)
- return -1;
-
- struct ChibiOS_params *param;
- param = (struct ChibiOS_params *) rtos->rtos_specific_params;
-
- /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4 */
- struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
- if (is_armv7m(armv7m_target)) {
- if (armv7m_target->fp_feature == FPv4_SP) {
- /* Found ARM v7m target which includes a FPU */
- uint32_t cpacr;
-
- retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read CPACR register to check FPU state");
- return -1;
- }
-
- /* Check if CP10 and CP11 are set to full access.
- * In ChibiOS this is done in ResetHandler() in crt0.c */
- if (cpacr & 0x00F00000) {
- LOG_DEBUG("Enabled FPU detected.");
- param->stacking_info = &rtos_chibios_arm_v7m_stacking_w_fpu;
- return 0;
- }
- }
-
- /* Found ARM v7m target with no or disabled FPU */
- param->stacking_info = &rtos_chibios_arm_v7m_stacking;
- return 0;
- }
-
- return -1;
-}
-
-static int ChibiOS_update_threads(struct rtos *rtos)
-{
- int retval;
- const struct ChibiOS_params *param;
- int tasks_found = 0;
- int rtos_valid = -1;
-
- if (!rtos->rtos_specific_params)
- return -1;
-
- if (!rtos->symbols) {
- LOG_ERROR("No symbols for ChibiOS");
- return -3;
- }
-
- param = (const struct ChibiOS_params *) rtos->rtos_specific_params;
- /* Update the memory signature saved in the target memory */
- if (!param->signature) {
- retval = ChibiOS_update_memory_signature(rtos);
- if (retval != ERROR_OK) {
- LOG_ERROR("Reading the memory signature of ChibiOS/RT failed");
- return retval;
- }
- }
-
- /* wipe out previous thread details if any */
- rtos_free_threadlist(rtos);
-
- /* ChibiOS does not save the current thread count. We have to first
- * parse the double linked thread list to check for errors and the number of
- * threads. */
- const uint32_t rlist = rtos->symbols[ChibiOS_VAL_rlist].address ?
- rtos->symbols[ChibiOS_VAL_rlist].address :
- rtos->symbols[ChibiOS_VAL_ch].address + CH_RLIST_OFFSET /* ChibiOS3 */;
- const struct ChibiOS_chdebug *signature = param->signature;
- uint32_t current;
- uint32_t previous;
- uint32_t older;
-
- current = rlist;
- previous = rlist;
- while (1) {
- retval = target_read_u32(rtos->target,
- current + signature->cf_off_newer, &current);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read next ChibiOS thread");
- return retval;
- }
- /* Could be NULL if the kernel is not initialized yet or if the
- * registry is corrupted. */
- if (current == 0) {
- LOG_ERROR("ChibiOS registry integrity check failed, NULL pointer");
-
- rtos_valid = 0;
- break;
- }
- /* Fetch previous thread in the list as a integrity check. */
- retval = target_read_u32(rtos->target,
- current + signature->cf_off_older, &older);
- if ((retval != ERROR_OK) || (older == 0) || (older != previous)) {
- LOG_ERROR("ChibiOS registry integrity check failed, "
- "double linked list violation");
- rtos_valid = 0;
- break;
- }
- /* Check for full iteration of the linked list. */
- if (current == rlist)
- break;
- tasks_found++;
- previous = current;
- }
- if (!rtos_valid) {
- /* No RTOS, there is always at least the current execution, though */
- LOG_INFO("Only showing current execution because of a broken "
- "ChibiOS thread registry.");
-
- const char tmp_thread_name[] = "Current Execution";
- const char tmp_thread_extra_info[] = "No RTOS thread";
-
- rtos->thread_details = malloc(
- sizeof(struct thread_detail));
- rtos->thread_details->threadid = 1;
- rtos->thread_details->exists = true;
-
- rtos->thread_details->extra_info_str = malloc(
- sizeof(tmp_thread_extra_info));
- strcpy(rtos->thread_details->extra_info_str, tmp_thread_extra_info);
-
- rtos->thread_details->thread_name_str = malloc(
- sizeof(tmp_thread_name));
- strcpy(rtos->thread_details->thread_name_str, tmp_thread_name);
-
- rtos->current_thread = 1;
- rtos->thread_count = 1;
- return ERROR_OK;
- }
-
- /* create space for new thread details */
- rtos->thread_details = malloc(
- sizeof(struct thread_detail) * tasks_found);
- if (!rtos->thread_details) {
- LOG_ERROR("Could not allocate space for thread details");
- return -1;
- }
-
- rtos->thread_count = tasks_found;
- /* Loop through linked list. */
- struct thread_detail *curr_thrd_details = rtos->thread_details;
- while (curr_thrd_details < rtos->thread_details + tasks_found) {
- uint32_t name_ptr = 0;
- char tmp_str[CHIBIOS_THREAD_NAME_STR_SIZE];
-
- retval = target_read_u32(rtos->target,
- current + signature->cf_off_newer, &current);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read next ChibiOS thread");
- return -6;
- }
-
- /* Check for full iteration of the linked list. */
- if (current == rlist)
- break;
-
- /* Save the thread pointer */
- curr_thrd_details->threadid = current;
-
- /* read the name pointer */
- retval = target_read_u32(rtos->target,
- current + signature->cf_off_name, &name_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read ChibiOS thread name pointer from target");
- return retval;
- }
-
- /* Read the thread name */
- retval = target_read_buffer(rtos->target, name_ptr,
- CHIBIOS_THREAD_NAME_STR_SIZE,
- (uint8_t *)&tmp_str);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread name from ChibiOS target");
- return retval;
- }
- tmp_str[CHIBIOS_THREAD_NAME_STR_SIZE - 1] = '\x00';
-
- if (tmp_str[0] == '\x00')
- strcpy(tmp_str, "No Name");
-
- curr_thrd_details->thread_name_str = malloc(
- strlen(tmp_str) + 1);
- strcpy(curr_thrd_details->thread_name_str, tmp_str);
-
- /* State info */
- uint8_t threadState;
- const char *state_desc;
-
- retval = target_read_u8(rtos->target,
- current + signature->cf_off_state, &threadState);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread state from ChibiOS target");
- return retval;
- }
-
-
- if (threadState < CHIBIOS_NUM_STATES)
- state_desc = ChibiOS_thread_states[threadState];
- else
- state_desc = "Unknown state";
-
- curr_thrd_details->extra_info_str = malloc(strlen(
- state_desc)+1);
- strcpy(curr_thrd_details->extra_info_str, state_desc);
-
- curr_thrd_details->exists = true;
-
- curr_thrd_details++;
- }
-
- uint32_t current_thrd;
- /* NOTE: By design, cf_off_name equals readylist_current_offset */
- retval = target_read_u32(rtos->target,
- rlist + signature->cf_off_name,
- &current_thrd);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read current Thread from ChibiOS target");
- return retval;
- }
- rtos->current_thread = current_thrd;
-
- return 0;
-}
-
-static int ChibiOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
-{
- int retval;
- const struct ChibiOS_params *param;
- uint32_t stack_ptr = 0;
-
- *hex_reg_list = NULL;
- if ((rtos == NULL) || (thread_id == 0) ||
- (rtos->rtos_specific_params == NULL))
- return -1;
-
- param = (const struct ChibiOS_params *) rtos->rtos_specific_params;
-
- if (!param->signature)
- return -1;
-
- /* Update stacking if it can only be determined from runtime information */
- if ((param->stacking_info == 0) &&
- (ChibiOS_update_stacking(rtos) != ERROR_OK)) {
- LOG_ERROR("Failed to determine exact stacking for the target type %s", rtos->target->type->name);
- return -1;
- }
-
- /* Read the stack pointer */
- retval = target_read_u32(rtos->target,
- thread_id + param->signature->cf_off_ctx, &stack_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading stack frame from ChibiOS thread");
- return retval;
- }
-
- return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
-}
-
-static int ChibiOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- *symbol_list = malloc(sizeof(ChibiOS_symbol_list));
-
- if (*symbol_list == NULL)
- return ERROR_FAIL;
-
- memcpy(*symbol_list, ChibiOS_symbol_list, sizeof(ChibiOS_symbol_list));
- return 0;
-}
-
-static int ChibiOS_detect_rtos(struct target *target)
-{
- if ((target->rtos->symbols != NULL) &&
- ((target->rtos->symbols[ChibiOS_VAL_rlist].address != 0) ||
- (target->rtos->symbols[ChibiOS_VAL_ch].address != 0))) {
-
- if (target->rtos->symbols[ChibiOS_VAL_ch_debug].address == 0) {
- LOG_INFO("It looks like the target may be running ChibiOS "
- "without ch_debug.");
- return 0;
- }
-
- /* looks like ChibiOS with memory map enabled.*/
- return 1;
- }
-
- return 0;
-}
-
-static int ChibiOS_create(struct target *target)
-{
- int i = 0;
- while ((i < CHIBIOS_NUM_PARAMS) &&
- (0 != strcmp(ChibiOS_params_list[i].target_name, target->type->name))) {
- i++;
- }
- if (i >= CHIBIOS_NUM_PARAMS) {
- LOG_WARNING("Could not find target \"%s\" in ChibiOS compatibility "
- "list", target->type->name);
- return -1;
- }
-
- target->rtos->rtos_specific_params = (void *) &ChibiOS_params_list[i];
- return 0;
-}
diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c
deleted file mode 100644
index 52cebad..0000000
--- a/src/rtos/FreeRTOS.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include "target/target.h"
-#include "target/target_type.h"
-#include "rtos.h"
-#include "helper/log.h"
-#include "helper/types.h"
-#include "rtos_standard_stackings.h"
-#include "target/armv7m.h"
-#include "target/cortex_m.h"
-
-
-
-#define FREERTOS_MAX_PRIORITIES 63
-
-#define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
-
-struct FreeRTOS_params {
- const char *target_name;
- const unsigned char thread_count_width;
- const unsigned char pointer_width;
- const unsigned char list_next_offset;
- const unsigned char list_width;
- const unsigned char list_elem_next_offset;
- const unsigned char list_elem_content_offset;
- const unsigned char thread_stack_offset;
- const unsigned char thread_name_offset;
- const struct rtos_register_stacking *stacking_info_cm3;
- const struct rtos_register_stacking *stacking_info_cm4f;
- const struct rtos_register_stacking *stacking_info_cm4f_fpu;
-};
-
-static const struct FreeRTOS_params FreeRTOS_params_list[] = {
- {
- "cortex_m", /* target_name */
- 4, /* thread_count_width; */
- 4, /* pointer_width; */
- 16, /* list_next_offset; */
- 20, /* list_width; */
- 8, /* list_elem_next_offset; */
- 12, /* list_elem_content_offset */
- 0, /* thread_stack_offset; */
- 52, /* thread_name_offset; */
- &rtos_standard_Cortex_M3_stacking, /* stacking_info */
- &rtos_standard_Cortex_M4F_stacking,
- &rtos_standard_Cortex_M4F_FPU_stacking,
- },
- {
- "hla_target", /* target_name */
- 4, /* thread_count_width; */
- 4, /* pointer_width; */
- 16, /* list_next_offset; */
- 20, /* list_width; */
- 8, /* list_elem_next_offset; */
- 12, /* list_elem_content_offset */
- 0, /* thread_stack_offset; */
- 52, /* thread_name_offset; */
- &rtos_standard_Cortex_M3_stacking, /* stacking_info */
- &rtos_standard_Cortex_M4F_stacking,
- &rtos_standard_Cortex_M4F_FPU_stacking,
- },
- {
- "nds32_v3", /* target_name */
- 4, /* thread_count_width; */
- 4, /* pointer_width; */
- 16, /* list_next_offset; */
- 20, /* list_width; */
- 8, /* list_elem_next_offset; */
- 12, /* list_elem_content_offset */
- 0, /* thread_stack_offset; */
- 52, /* thread_name_offset; */
- &rtos_standard_NDS32_N1068_stacking, /* stacking_info */
- &rtos_standard_Cortex_M4F_stacking,
- &rtos_standard_Cortex_M4F_FPU_stacking,
- },
-};
-
-#define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
-
-static int FreeRTOS_detect_rtos(struct target *target);
-static int FreeRTOS_create(struct target *target);
-static int FreeRTOS_update_threads(struct rtos *rtos);
-static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
-static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
-
-struct rtos_type FreeRTOS_rtos = {
- .name = "FreeRTOS",
-
- .detect_rtos = FreeRTOS_detect_rtos,
- .create = FreeRTOS_create,
- .update_threads = FreeRTOS_update_threads,
- .get_thread_reg_list = FreeRTOS_get_thread_reg_list,
- .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
-};
-
-enum FreeRTOS_symbol_values {
- FreeRTOS_VAL_pxCurrentTCB = 0,
- FreeRTOS_VAL_pxReadyTasksLists = 1,
- FreeRTOS_VAL_xDelayedTaskList1 = 2,
- FreeRTOS_VAL_xDelayedTaskList2 = 3,
- FreeRTOS_VAL_pxDelayedTaskList = 4,
- FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
- FreeRTOS_VAL_xPendingReadyList = 6,
- FreeRTOS_VAL_xTasksWaitingTermination = 7,
- FreeRTOS_VAL_xSuspendedTaskList = 8,
- FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
- FreeRTOS_VAL_uxTopUsedPriority = 10,
-};
-
-struct symbols {
- const char *name;
- bool optional;
-};
-
-static const struct symbols FreeRTOS_symbol_list[] = {
- { "pxCurrentTCB", false },
- { "pxReadyTasksLists", false },
- { "xDelayedTaskList1", false },
- { "xDelayedTaskList2", false },
- { "pxDelayedTaskList", false },
- { "pxOverflowDelayedTaskList", false },
- { "xPendingReadyList", false },
- { "xTasksWaitingTermination", true }, /* Only if INCLUDE_vTaskDelete */
- { "xSuspendedTaskList", true }, /* Only if INCLUDE_vTaskSuspend */
- { "uxCurrentNumberOfTasks", false },
- { "uxTopUsedPriority", true }, /* Unavailable since v7.5.3 */
- { NULL, false }
-};
-
-/* TODO: */
-/* this is not safe for little endian yet */
-/* may be problems reading if sizes are not 32 bit long integers. */
-/* test mallocs for failure */
-
-static int FreeRTOS_update_threads(struct rtos *rtos)
-{
- int i = 0;
- int retval;
- int tasks_found = 0;
- const struct FreeRTOS_params *param;
-
- if (rtos->rtos_specific_params == NULL)
- return -1;
-
- param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
-
- if (rtos->symbols == NULL) {
- LOG_ERROR("No symbols for FreeRTOS");
- return -3;
- }
-
- if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) {
- LOG_ERROR("Don't have the number of threads in FreeRTOS");
- return -2;
- }
-
- int thread_list_size = 0;
- retval = target_read_buffer(rtos->target,
- rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
- param->thread_count_width,
- (uint8_t *)&thread_list_size);
- LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64 ", value %d\r\n",
- rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
- thread_list_size);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read FreeRTOS thread count from target");
- return retval;
- }
-
- /* wipe out previous thread details if any */
- rtos_free_threadlist(rtos);
-
- /* read the current thread */
- retval = target_read_buffer(rtos->target,
- rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
- param->pointer_width,
- (uint8_t *)&rtos->current_thread);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading current thread in FreeRTOS thread list");
- return retval;
- }
- LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
- rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
- rtos->current_thread);
-
- if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
- /* Either : No RTOS threads - there is always at least the current execution though */
- /* OR : No current thread - all threads suspended - show the current execution
- * of idling */
- char tmp_str[] = "Current Execution";
- thread_list_size++;
- tasks_found++;
- rtos->thread_details = malloc(
- sizeof(struct thread_detail) * thread_list_size);
- if (!rtos->thread_details) {
- LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
- return ERROR_FAIL;
- }
- rtos->thread_details->threadid = 1;
- rtos->thread_details->exists = true;
- rtos->thread_details->extra_info_str = NULL;
- rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
- strcpy(rtos->thread_details->thread_name_str, tmp_str);
-
- if (thread_list_size == 1) {
- rtos->thread_count = 1;
- return ERROR_OK;
- }
- } else {
- /* create space for new thread details */
- rtos->thread_details = malloc(
- sizeof(struct thread_detail) * thread_list_size);
- if (!rtos->thread_details) {
- LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
- return ERROR_FAIL;
- }
- }
-
- /* Find out how many lists are needed to be read from pxReadyTasksLists, */
- if (rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address == 0) {
- LOG_ERROR("FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around");
- return ERROR_FAIL;
- }
- int64_t max_used_priority = 0;
- retval = target_read_buffer(rtos->target,
- rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
- param->pointer_width,
- (uint8_t *)&max_used_priority);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64 ", value %" PRId64 "\r\n",
- rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
- max_used_priority);
- if (max_used_priority > FREERTOS_MAX_PRIORITIES) {
- LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64 "",
- max_used_priority);
- return ERROR_FAIL;
- }
-
- symbol_address_t *list_of_lists =
- malloc(sizeof(symbol_address_t) *
- (max_used_priority+1 + 5));
- if (!list_of_lists) {
- LOG_ERROR("Error allocating memory for %" PRId64 " priorities", max_used_priority);
- return ERROR_FAIL;
- }
-
- int num_lists;
- for (num_lists = 0; num_lists <= max_used_priority; num_lists++)
- list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address +
- num_lists * param->list_width;
-
- list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address;
- list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address;
- list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address;
- list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address;
- list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
-
- for (i = 0; i < num_lists; i++) {
- if (list_of_lists[i] == 0)
- continue;
-
- /* Read the number of threads in this list */
- int64_t list_thread_count = 0;
- retval = target_read_buffer(rtos->target,
- list_of_lists[i],
- param->thread_count_width,
- (uint8_t *)&list_thread_count);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
- free(list_of_lists);
- return retval;
- }
- LOG_DEBUG("FreeRTOS: Read thread count for list %d at 0x%" PRIx64 ", value %" PRId64 "\r\n",
- i, list_of_lists[i], list_thread_count);
-
- if (list_thread_count == 0)
- continue;
-
- /* Read the location of first list item */
- uint64_t prev_list_elem_ptr = -1;
- uint64_t list_elem_ptr = 0;
- retval = target_read_buffer(rtos->target,
- list_of_lists[i] + param->list_next_offset,
- param->pointer_width,
- (uint8_t *)&list_elem_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
- free(list_of_lists);
- return retval;
- }
- LOG_DEBUG("FreeRTOS: Read first item for list %d at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
- i, list_of_lists[i] + param->list_next_offset, list_elem_ptr);
-
- while ((list_thread_count > 0) && (list_elem_ptr != 0) &&
- (list_elem_ptr != prev_list_elem_ptr) &&
- (tasks_found < thread_list_size)) {
- /* Get the location of the thread structure. */
- rtos->thread_details[tasks_found].threadid = 0;
- retval = target_read_buffer(rtos->target,
- list_elem_ptr + param->list_elem_content_offset,
- param->pointer_width,
- (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
- free(list_of_lists);
- return retval;
- }
- LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
- list_elem_ptr + param->list_elem_content_offset,
- rtos->thread_details[tasks_found].threadid);
-
- /* get thread name */
-
- #define FREERTOS_THREAD_NAME_STR_SIZE (200)
- char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
-
- /* Read the thread name */
- retval = target_read_buffer(rtos->target,
- rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
- FREERTOS_THREAD_NAME_STR_SIZE,
- (uint8_t *)&tmp_str);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
- free(list_of_lists);
- return retval;
- }
- tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
- LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64 ", value \"%s\"\r\n",
- rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
- tmp_str);
-
- if (tmp_str[0] == '\x00')
- strcpy(tmp_str, "No Name");
-
- rtos->thread_details[tasks_found].thread_name_str =
- malloc(strlen(tmp_str)+1);
- strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
- rtos->thread_details[tasks_found].exists = true;
-
- if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
- char running_str[] = "Running";
- rtos->thread_details[tasks_found].extra_info_str = malloc(
- sizeof(running_str));
- strcpy(rtos->thread_details[tasks_found].extra_info_str,
- running_str);
- } else
- rtos->thread_details[tasks_found].extra_info_str = NULL;
-
- tasks_found++;
- list_thread_count--;
-
- prev_list_elem_ptr = list_elem_ptr;
- list_elem_ptr = 0;
- retval = target_read_buffer(rtos->target,
- prev_list_elem_ptr + param->list_elem_next_offset,
- param->pointer_width,
- (uint8_t *)&list_elem_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
- free(list_of_lists);
- return retval;
- }
- LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
- prev_list_elem_ptr + param->list_elem_next_offset,
- list_elem_ptr);
- }
- }
-
- free(list_of_lists);
- rtos->thread_count = tasks_found;
- return 0;
-}
-
-static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
-{
- int retval;
- const struct FreeRTOS_params *param;
- int64_t stack_ptr = 0;
-
- *hex_reg_list = NULL;
- if (rtos == NULL)
- return -1;
-
- if (thread_id == 0)
- return -2;
-
- if (rtos->rtos_specific_params == NULL)
- return -1;
-
- param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
-
- /* Read the stack pointer */
- retval = target_read_buffer(rtos->target,
- thread_id + param->thread_stack_offset,
- param->pointer_width,
- (uint8_t *)&stack_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading stack frame from FreeRTOS thread");
- return retval;
- }
- LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
- thread_id + param->thread_stack_offset,
- stack_ptr);
-
- /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
- int cm4_fpu_enabled = 0;
- struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
- if (is_armv7m(armv7m_target)) {
- if (armv7m_target->fp_feature == FPv4_SP) {
- /* Found ARM v7m target which includes a FPU */
- uint32_t cpacr;
-
- retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read CPACR register to check FPU state");
- return -1;
- }
-
- /* Check if CP10 and CP11 are set to full access. */
- if (cpacr & 0x00F00000) {
- /* Found target with enabled FPU */
- cm4_fpu_enabled = 1;
- }
- }
- }
-
- if (cm4_fpu_enabled == 1) {
- /* Read the LR to decide between stacking with or without FPU */
- uint32_t LR_svc = 0;
- retval = target_read_buffer(rtos->target,
- stack_ptr + 0x20,
- param->pointer_width,
- (uint8_t *)&LR_svc);
- if (retval != ERROR_OK) {
- LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
- return retval;
- }
- if ((LR_svc & 0x10) == 0)
- return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f_fpu, stack_ptr, hex_reg_list);
- else
- return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f, stack_ptr, hex_reg_list);
- } else
- return rtos_generic_stack_read(rtos->target, param->stacking_info_cm3, stack_ptr, hex_reg_list);
-}
-
-static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- unsigned int i;
- *symbol_list = calloc(
- ARRAY_SIZE(FreeRTOS_symbol_list), sizeof(symbol_table_elem_t));
-
- for (i = 0; i < ARRAY_SIZE(FreeRTOS_symbol_list); i++) {
- (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i].name;
- (*symbol_list)[i].optional = FreeRTOS_symbol_list[i].optional;
- }
-
- return 0;
-}
-
-#if 0
-
-static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
-{
- return 0;
-}
-
-static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_id, char **info)
-{
- int retval;
- const struct FreeRTOS_params *param;
-
- if (rtos == NULL)
- return -1;
-
- if (thread_id == 0)
- return -2;
-
- if (rtos->rtos_specific_params == NULL)
- return -3;
-
- param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
-
-#define FREERTOS_THREAD_NAME_STR_SIZE (200)
- char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
-
- /* Read the thread name */
- retval = target_read_buffer(rtos->target,
- thread_id + param->thread_name_offset,
- FREERTOS_THREAD_NAME_STR_SIZE,
- (uint8_t *)&tmp_str);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
- return retval;
- }
- tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
-
- if (tmp_str[0] == '\x00')
- strcpy(tmp_str, "No Name");
-
- *info = malloc(strlen(tmp_str)+1);
- strcpy(*info, tmp_str);
- return 0;
-}
-
-#endif
-
-static int FreeRTOS_detect_rtos(struct target *target)
-{
- if ((target->rtos->symbols != NULL) &&
- (target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) {
- /* looks like FreeRTOS */
- return 1;
- }
- return 0;
-}
-
-static int FreeRTOS_create(struct target *target)
-{
- int i = 0;
- while ((i < FREERTOS_NUM_PARAMS) &&
- (0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) {
- i++;
- }
- if (i >= FREERTOS_NUM_PARAMS) {
- LOG_ERROR("Could not find target in FreeRTOS compatibility list");
- return -1;
- }
-
- target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i];
- return 0;
-}
diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
deleted file mode 100644
index a7dab00..0000000
--- a/src/rtos/Makefile.am
+++ /dev/null
@@ -1,32 +0,0 @@
-# ***************************************************************************
-# * Copyright (C) 2011 by Broadcom Corporation *
-# * Evan Hunter - ehunter@broadcom.com *
-# * *
-# * This program is free software; you can redistribute it and/or modify *
-# * it under the terms of the GNU General Public License as published by *
-# * the Free Software Foundation; either version 2 of the License, or *
-# * (at your option) any later version. *
-# * *
-# * This program is distributed in the hope that it will be useful, *
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
-# * GNU General Public License for more details. *
-# * *
-# * You should have received a copy of the GNU General Public License *
-# * along with this program. If not, see <http://www.gnu.org/licenses/>. *
-# ***************************************************************************
-
-include $(top_srcdir)/common.mk
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = librtos.la
-noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h riscv_debug.h
-librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c riscv_debug.c
-
-librtos_la_CFLAGS =
-if IS_MINGW
-# FD_* macros are sloppy with their signs on MinGW32 platform
-librtos_la_CFLAGS += -Wno-sign-compare
-endif
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/rtos/ThreadX.c b/src/rtos/ThreadX.c
deleted file mode 100644
index 8267b9f..0000000
--- a/src/rtos/ThreadX.c
+++ /dev/null
@@ -1,617 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include "target/target.h"
-#include "target/target_type.h"
-#include "rtos.h"
-#include "helper/log.h"
-#include "helper/types.h"
-#include "rtos_standard_stackings.h"
-
-static const struct rtos_register_stacking *get_stacking_info(const struct rtos *rtos, int64_t stack_ptr);
-static const struct rtos_register_stacking *get_stacking_info_arm926ejs(const struct rtos *rtos, int64_t stack_ptr);
-
-static int is_thread_id_valid(const struct rtos *rtos, int64_t thread_id);
-static int is_thread_id_valid_arm926ejs(const struct rtos *rtos, int64_t thread_id);
-
-static int ThreadX_detect_rtos(struct target *target);
-static int ThreadX_create(struct target *target);
-static int ThreadX_update_threads(struct rtos *rtos);
-static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
-static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
-
-
-
-struct ThreadX_thread_state {
- int value;
- const char *desc;
-};
-
-static const struct ThreadX_thread_state ThreadX_thread_states[] = {
- { 0, "Ready" },
- { 1, "Completed" },
- { 2, "Terminated" },
- { 3, "Suspended" },
- { 4, "Sleeping" },
- { 5, "Waiting - Queue" },
- { 6, "Waiting - Semaphore" },
- { 7, "Waiting - Event flag" },
- { 8, "Waiting - Memory" },
- { 9, "Waiting - Memory" },
- { 10, "Waiting - I/O" },
- { 11, "Waiting - Filesystem" },
- { 12, "Waiting - Network" },
- { 13, "Waiting - Mutex" },
-};
-
-#define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
-
-#define ARM926EJS_REGISTERS_SIZE_SOLICITED (11 * 4)
-static const struct stack_register_offset rtos_threadx_arm926ejs_stack_offsets_solicited[] = {
- { -1, 32 }, /* r0 */
- { -1, 32 }, /* r1 */
- { -1, 32 }, /* r2 */
- { -1, 32 }, /* r3 */
- { 0x08, 32 }, /* r4 */
- { 0x0C, 32 }, /* r5 */
- { 0x10, 32 }, /* r6 */
- { 0x14, 32 }, /* r7 */
- { 0x18, 32 }, /* r8 */
- { 0x1C, 32 }, /* r9 */
- { 0x20, 32 }, /* r10 */
- { 0x24, 32 }, /* r11 */
- { -1, 32 }, /* r12 */
- { -2, 32 }, /* sp (r13) */
- { 0x28, 32 }, /* lr (r14) */
- { -1, 32 }, /* pc (r15) */
- /*{ -1, 32 },*/ /* lr (r14) */
- /*{ 0x28, 32 },*/ /* pc (r15) */
- { 0x04, 32 }, /* xPSR */
-};
-#define ARM926EJS_REGISTERS_SIZE_INTERRUPT (17 * 4)
-static const struct stack_register_offset rtos_threadx_arm926ejs_stack_offsets_interrupt[] = {
- { 0x08, 32 }, /* r0 */
- { 0x0C, 32 }, /* r1 */
- { 0x10, 32 }, /* r2 */
- { 0x14, 32 }, /* r3 */
- { 0x18, 32 }, /* r4 */
- { 0x1C, 32 }, /* r5 */
- { 0x20, 32 }, /* r6 */
- { 0x24, 32 }, /* r7 */
- { 0x28, 32 }, /* r8 */
- { 0x2C, 32 }, /* r9 */
- { 0x30, 32 }, /* r10 */
- { 0x34, 32 }, /* r11 */
- { 0x38, 32 }, /* r12 */
- { -2, 32 }, /* sp (r13) */
- { 0x3C, 32 }, /* lr (r14) */
- { 0x40, 32 }, /* pc (r15) */
- { 0x04, 32 }, /* xPSR */
-};
-
-const struct rtos_register_stacking rtos_threadx_arm926ejs_stacking[] = {
-{
- ARM926EJS_REGISTERS_SIZE_SOLICITED, /* stack_registers_size */
- -1, /* stack_growth_direction */
- 17, /* num_output_registers */
- NULL, /* stack_alignment */
- rtos_threadx_arm926ejs_stack_offsets_solicited /* register_offsets */
-},
-{
- ARM926EJS_REGISTERS_SIZE_INTERRUPT, /* stack_registers_size */
- -1, /* stack_growth_direction */
- 17, /* num_output_registers */
- NULL, /* stack_alignment */
- rtos_threadx_arm926ejs_stack_offsets_interrupt /* register_offsets */
-},
-};
-
-struct ThreadX_params {
- const char *target_name;
- unsigned char pointer_width;
- unsigned char thread_stack_offset;
- unsigned char thread_name_offset;
- unsigned char thread_state_offset;
- unsigned char thread_next_offset;
- const struct rtos_register_stacking *stacking_info;
- size_t stacking_info_nb;
- const struct rtos_register_stacking* (*fn_get_stacking_info)(const struct rtos *rtos, int64_t stack_ptr);
- int (*fn_is_thread_id_valid)(const struct rtos *rtos, int64_t thread_id);
-};
-
-static const struct ThreadX_params ThreadX_params_list[] = {
- {
- "cortex_m", /* target_name */
- 4, /* pointer_width; */
- 8, /* thread_stack_offset; */
- 40, /* thread_name_offset; */
- 48, /* thread_state_offset; */
- 136, /* thread_next_offset */
- &rtos_standard_Cortex_M3_stacking, /* stacking_info */
- 1, /* stacking_info_nb */
- NULL, /* fn_get_stacking_info */
- NULL, /* fn_is_thread_id_valid */
- },
- {
- "cortex_r4", /* target_name */
- 4, /* pointer_width; */
- 8, /* thread_stack_offset; */
- 40, /* thread_name_offset; */
- 48, /* thread_state_offset; */
- 136, /* thread_next_offset */
- &rtos_standard_Cortex_R4_stacking, /* stacking_info */
- 1, /* stacking_info_nb */
- NULL, /* fn_get_stacking_info */
- NULL, /* fn_is_thread_id_valid */
- },
- {
- "arm926ejs", /* target_name */
- 4, /* pointer_width; */
- 8, /* thread_stack_offset; */
- 40, /* thread_name_offset; */
- 48, /* thread_state_offset; */
- 136, /* thread_next_offset */
- rtos_threadx_arm926ejs_stacking, /* stacking_info */
- 2, /* stacking_info_nb */
- get_stacking_info_arm926ejs, /* fn_get_stacking_info */
- is_thread_id_valid_arm926ejs, /* fn_is_thread_id_valid */
- },
-};
-
-#define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
-
-enum ThreadX_symbol_values {
- ThreadX_VAL_tx_thread_current_ptr = 0,
- ThreadX_VAL_tx_thread_created_ptr = 1,
- ThreadX_VAL_tx_thread_created_count = 2,
-};
-
-static const char * const ThreadX_symbol_list[] = {
- "_tx_thread_current_ptr",
- "_tx_thread_created_ptr",
- "_tx_thread_created_count",
- NULL
-};
-
-const struct rtos_type ThreadX_rtos = {
- .name = "ThreadX",
-
- .detect_rtos = ThreadX_detect_rtos,
- .create = ThreadX_create,
- .update_threads = ThreadX_update_threads,
- .get_thread_reg_list = ThreadX_get_thread_reg_list,
- .get_symbol_list_to_lookup = ThreadX_get_symbol_list_to_lookup,
-};
-
-static const struct rtos_register_stacking *get_stacking_info(const struct rtos *rtos, int64_t stack_ptr)
-{
- const struct ThreadX_params *param = (const struct ThreadX_params *) rtos->rtos_specific_params;
-
- if (param->fn_get_stacking_info != NULL)
- return param->fn_get_stacking_info(rtos, stack_ptr);
-
- return param->stacking_info + 0;
-}
-
-static int is_thread_id_valid(const struct rtos *rtos, int64_t thread_id)
-{
- const struct ThreadX_params *param;
-
- if (rtos->rtos_specific_params == NULL)
- return 0; /* invalid */
-
- param = (const struct ThreadX_params *) rtos->rtos_specific_params;
-
- if (param->fn_is_thread_id_valid != NULL)
- return param->fn_is_thread_id_valid(rtos, thread_id);
-
- return (thread_id != 0);
-}
-
-static const struct rtos_register_stacking *get_stacking_info_arm926ejs(const struct rtos *rtos, int64_t stack_ptr)
-{
- const struct ThreadX_params *param = (const struct ThreadX_params *) rtos->rtos_specific_params;
- int retval;
- uint32_t flag;
-
- retval = target_read_buffer(rtos->target,
- stack_ptr,
- sizeof(flag),
- (uint8_t *)&flag);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading stack data from ThreadX thread: stack_ptr=0x%" PRIx64, stack_ptr);
- return NULL;
- }
-
- if (flag == 0) {
- LOG_DEBUG(" solicited stack");
- return param->stacking_info + 0;
- } else {
- LOG_DEBUG(" interrupt stack: %u", flag);
- return param->stacking_info + 1;
- }
-}
-
-static int is_thread_id_valid_arm926ejs(const struct rtos *rtos, int64_t thread_id)
-{
- return (thread_id != 0 && thread_id != 1);
-}
-
-static int ThreadX_update_threads(struct rtos *rtos)
-{
- int retval;
- int tasks_found = 0;
- int thread_list_size = 0;
- const struct ThreadX_params *param;
-
- if (rtos == NULL)
- return -1;
-
- if (rtos->rtos_specific_params == NULL)
- return -3;
-
- param = (const struct ThreadX_params *) rtos->rtos_specific_params;
-
- if (rtos->symbols == NULL) {
- LOG_ERROR("No symbols for ThreadX");
- return -4;
- }
-
- if (rtos->symbols[ThreadX_VAL_tx_thread_created_count].address == 0) {
- LOG_ERROR("Don't have the number of threads in ThreadX");
- return -2;
- }
-
- /* read the number of threads */
- retval = target_read_buffer(rtos->target,
- rtos->symbols[ThreadX_VAL_tx_thread_created_count].address,
- 4,
- (uint8_t *)&thread_list_size);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read ThreadX thread count from target");
- return retval;
- }
-
- /* wipe out previous thread details if any */
- rtos_free_threadlist(rtos);
-
- /* read the current thread id */
- retval = target_read_buffer(rtos->target,
- rtos->symbols[ThreadX_VAL_tx_thread_current_ptr].address,
- 4,
- (uint8_t *)&rtos->current_thread);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read ThreadX current thread from target");
- return retval;
- }
-
- if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
- /* Either : No RTOS threads - there is always at least the current execution though */
- /* OR : No current thread - all threads suspended - show the current execution
- * of idling */
- char tmp_str[] = "Current Execution";
- thread_list_size++;
- tasks_found++;
- rtos->thread_details = malloc(
- sizeof(struct thread_detail) * thread_list_size);
- rtos->thread_details->threadid = 1;
- rtos->thread_details->exists = true;
- rtos->thread_details->extra_info_str = NULL;
- rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
- strcpy(rtos->thread_details->thread_name_str, tmp_str);
-
- if (thread_list_size == 0) {
- rtos->thread_count = 1;
- return ERROR_OK;
- }
- } else {
- /* create space for new thread details */
- rtos->thread_details = malloc(
- sizeof(struct thread_detail) * thread_list_size);
- }
-
- /* Read the pointer to the first thread */
- int64_t thread_ptr = 0;
- retval = target_read_buffer(rtos->target,
- rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address,
- param->pointer_width,
- (uint8_t *)&thread_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read ThreadX thread location from target");
- return retval;
- }
-
- /* loop over all threads */
- int64_t prev_thread_ptr = 0;
- while ((thread_ptr != prev_thread_ptr) && (tasks_found < thread_list_size)) {
-
- #define THREADX_THREAD_NAME_STR_SIZE (200)
- char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
- unsigned int i = 0;
- int64_t name_ptr = 0;
-
- /* Save the thread pointer */
- rtos->thread_details[tasks_found].threadid = thread_ptr;
-
- /* read the name pointer */
- retval = target_read_buffer(rtos->target,
- thread_ptr + param->thread_name_offset,
- param->pointer_width,
- (uint8_t *)&name_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read ThreadX thread name pointer from target");
- return retval;
- }
-
- /* Read the thread name */
- retval =
- target_read_buffer(rtos->target,
- name_ptr,
- THREADX_THREAD_NAME_STR_SIZE,
- (uint8_t *)&tmp_str);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread name from ThreadX target");
- return retval;
- }
- tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
-
- if (tmp_str[0] == '\x00')
- strcpy(tmp_str, "No Name");
-
- rtos->thread_details[tasks_found].thread_name_str =
- malloc(strlen(tmp_str)+1);
- strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
-
- /* Read the thread status */
- int64_t thread_status = 0;
- retval = target_read_buffer(rtos->target,
- thread_ptr + param->thread_state_offset,
- 4,
- (uint8_t *)&thread_status);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread state from ThreadX target");
- return retval;
- }
-
- for (i = 0; (i < THREADX_NUM_STATES) &&
- (ThreadX_thread_states[i].value != thread_status); i++) {
- /* empty */
- }
-
- const char *state_desc;
- if (i < THREADX_NUM_STATES)
- state_desc = ThreadX_thread_states[i].desc;
- else
- state_desc = "Unknown state";
-
- rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
- state_desc)+1);
- strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
-
- rtos->thread_details[tasks_found].exists = true;
-
- tasks_found++;
- prev_thread_ptr = thread_ptr;
-
- /* Get the location of the next thread structure. */
- thread_ptr = 0;
- retval = target_read_buffer(rtos->target,
- prev_thread_ptr + param->thread_next_offset,
- param->pointer_width,
- (uint8_t *) &thread_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading next thread pointer in ThreadX thread list");
- return retval;
- }
- }
-
- rtos->thread_count = tasks_found;
-
- return 0;
-}
-
-static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
-{
- int retval;
- const struct ThreadX_params *param;
-
- *hex_reg_list = NULL;
-
- if (rtos == NULL)
- return -1;
-
- if (!is_thread_id_valid(rtos, thread_id))
- return -2;
-
- if (rtos->rtos_specific_params == NULL)
- return -3;
-
- param = (const struct ThreadX_params *) rtos->rtos_specific_params;
-
- /* Read the stack pointer */
- int64_t stack_ptr = 0;
- retval = target_read_buffer(rtos->target,
- thread_id + param->thread_stack_offset,
- param->pointer_width,
- (uint8_t *)&stack_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading stack frame from ThreadX thread");
- return retval;
- }
-
- LOG_INFO("thread: 0x%" PRIx64 ", stack_ptr=0x%" PRIx64, (uint64_t)thread_id, (uint64_t)stack_ptr);
-
- if (stack_ptr == 0) {
- LOG_ERROR("null stack pointer in thread");
- return -5;
- }
-
- const struct rtos_register_stacking *stacking_info =
- get_stacking_info(rtos, stack_ptr);
-
- if (stacking_info == NULL) {
- LOG_ERROR("Unknown stacking info for thread id=0x%" PRIx64, (uint64_t)thread_id);
- return -6;
- }
-
- return rtos_generic_stack_read(rtos->target, stacking_info, stack_ptr, hex_reg_list);
-}
-
-static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- unsigned int i;
- *symbol_list = calloc(
- ARRAY_SIZE(ThreadX_symbol_list), sizeof(symbol_table_elem_t));
-
- for (i = 0; i < ARRAY_SIZE(ThreadX_symbol_list); i++)
- (*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
-
- return 0;
-}
-
-static int ThreadX_detect_rtos(struct target *target)
-{
- if ((target->rtos->symbols != NULL) &&
- (target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0)) {
- /* looks like ThreadX */
- return 1;
- }
- return 0;
-}
-
-#if 0
-
-static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
-{
- return 0;
-}
-
-static int ThreadX_get_thread_detail(struct rtos *rtos,
- threadid_t thread_id,
- struct thread_detail *detail)
-{
- unsigned int i = 0;
- int retval;
-
-#define THREADX_THREAD_NAME_STR_SIZE (200)
- char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
-
- const struct ThreadX_params *param;
-
- if (rtos == NULL)
- return -1;
-
- if (thread_id == 0)
- return -2;
-
- if (rtos->rtos_specific_params == NULL)
- return -3;
-
- param = (const struct ThreadX_params *) rtos->rtos_specific_params;
-
- if (rtos->symbols == NULL) {
- LOG_ERROR("No symbols for ThreadX");
- return -3;
- }
-
- detail->threadid = thread_id;
-
- int64_t name_ptr = 0;
- /* read the name pointer */
- retval = target_read_buffer(rtos->target,
- thread_id + param->thread_name_offset,
- param->pointer_width,
- (uint8_t *)&name_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read ThreadX thread name pointer from target");
- return retval;
- }
-
- /* Read the thread name */
- retval = target_read_buffer(rtos->target,
- name_ptr,
- THREADX_THREAD_NAME_STR_SIZE,
- (uint8_t *)&tmp_str);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread name from ThreadX target");
- return retval;
- }
- tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
-
- if (tmp_str[0] == '\x00')
- strcpy(tmp_str, "No Name");
-
- detail->thread_name_str = malloc(strlen(tmp_str)+1);
-
- /* Read the thread status */
- int64_t thread_status = 0;
- retval =
- target_read_buffer(rtos->target,
- thread_id + param->thread_state_offset,
- 4,
- (uint8_t *)&thread_status);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread state from ThreadX target");
- return retval;
- }
-
- for (i = 0; (i < THREADX_NUM_STATES) &&
- (ThreadX_thread_states[i].value != thread_status); i++) {
- /* empty */
- }
-
- char *state_desc;
- if (i < THREADX_NUM_STATES)
- state_desc = ThreadX_thread_states[i].desc;
- else
- state_desc = "Unknown state";
-
- detail->extra_info_str = malloc(strlen(state_desc)+1);
-
- detail->exists = true;
-
- return 0;
-}
-
-#endif
-
-static int ThreadX_create(struct target *target)
-{
- int i = 0;
- while ((i < THREADX_NUM_PARAMS) &&
- (0 != strcmp(ThreadX_params_list[i].target_name, target->type->name))) {
- i++;
- }
- if (i >= THREADX_NUM_PARAMS) {
- LOG_ERROR("Could not find target in ThreadX compatibility list");
- return -1;
- }
-
- target->rtos->rtos_specific_params = (void *) &ThreadX_params_list[i];
- target->rtos->current_thread = 0;
- target->rtos->thread_details = NULL;
- return 0;
-}
diff --git a/src/rtos/eCos.c b/src/rtos/eCos.c
deleted file mode 100644
index e38e11f..0000000
--- a/src/rtos/eCos.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include "target/target.h"
-#include "target/target_type.h"
-#include "rtos.h"
-#include "helper/log.h"
-#include "helper/types.h"
-#include "rtos_ecos_stackings.h"
-
-static int eCos_detect_rtos(struct target *target);
-static int eCos_create(struct target *target);
-static int eCos_update_threads(struct rtos *rtos);
-static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
-static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
-
-struct eCos_thread_state {
- int value;
- const char *desc;
-};
-
-static const struct eCos_thread_state eCos_thread_states[] = {
- { 0, "Ready" },
- { 1, "Sleeping" },
- { 2, "Countsleep" },
- { 4, "Suspended" },
- { 8, "Creating" },
- { 16, "Exited" }
-};
-
-#define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
-
-struct eCos_params {
- const char *target_name;
- unsigned char pointer_width;
- unsigned char thread_stack_offset;
- unsigned char thread_name_offset;
- unsigned char thread_state_offset;
- unsigned char thread_next_offset;
- unsigned char thread_uniqueid_offset;
- const struct rtos_register_stacking *stacking_info;
-};
-
-static const struct eCos_params eCos_params_list[] = {
- {
- "cortex_m", /* target_name */
- 4, /* pointer_width; */
- 0x0c, /* thread_stack_offset; */
- 0x9c, /* thread_name_offset; */
- 0x3c, /* thread_state_offset; */
- 0xa0, /* thread_next_offset */
- 0x4c, /* thread_uniqueid_offset */
- &rtos_eCos_Cortex_M3_stacking /* stacking_info */
- }
-};
-
-#define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
-
-enum eCos_symbol_values {
- eCos_VAL_thread_list = 0,
- eCos_VAL_current_thread_ptr = 1
-};
-
-static const char * const eCos_symbol_list[] = {
- "Cyg_Thread::thread_list",
- "Cyg_Scheduler_Base::current_thread",
- NULL
-};
-
-const struct rtos_type eCos_rtos = {
- .name = "eCos",
-
- .detect_rtos = eCos_detect_rtos,
- .create = eCos_create,
- .update_threads = eCos_update_threads,
- .get_thread_reg_list = eCos_get_thread_reg_list,
- .get_symbol_list_to_lookup = eCos_get_symbol_list_to_lookup,
-
-};
-
-static int eCos_update_threads(struct rtos *rtos)
-{
- int retval;
- int tasks_found = 0;
- int thread_list_size = 0;
- const struct eCos_params *param;
-
- if (rtos == NULL)
- return -1;
-
- if (rtos->rtos_specific_params == NULL)
- return -3;
-
- param = (const struct eCos_params *) rtos->rtos_specific_params;
-
- if (rtos->symbols == NULL) {
- LOG_ERROR("No symbols for eCos");
- return -4;
- }
-
- if (rtos->symbols[eCos_VAL_thread_list].address == 0) {
- LOG_ERROR("Don't have the thread list head");
- return -2;
- }
-
- /* wipe out previous thread details if any */
- rtos_free_threadlist(rtos);
-
- /* determine the number of current threads */
- uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
- uint32_t thread_index;
- target_read_buffer(rtos->target,
- thread_list_head,
- param->pointer_width,
- (uint8_t *) &thread_index);
- uint32_t first_thread = thread_index;
- do {
- thread_list_size++;
- retval = target_read_buffer(rtos->target,
- thread_index + param->thread_next_offset,
- param->pointer_width,
- (uint8_t *) &thread_index);
- if (retval != ERROR_OK)
- return retval;
- } while (thread_index != first_thread);
-
- /* read the current thread id */
- uint32_t current_thread_addr;
- retval = target_read_buffer(rtos->target,
- rtos->symbols[eCos_VAL_current_thread_ptr].address,
- 4,
- (uint8_t *)&current_thread_addr);
- if (retval != ERROR_OK)
- return retval;
- rtos->current_thread = 0;
- retval = target_read_buffer(rtos->target,
- current_thread_addr + param->thread_uniqueid_offset,
- 2,
- (uint8_t *)&rtos->current_thread);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read eCos current thread from target");
- return retval;
- }
-
- if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
- /* Either : No RTOS threads - there is always at least the current execution though */
- /* OR : No current thread - all threads suspended - show the current execution
- * of idling */
- char tmp_str[] = "Current Execution";
- thread_list_size++;
- tasks_found++;
- rtos->thread_details = malloc(
- sizeof(struct thread_detail) * thread_list_size);
- rtos->thread_details->threadid = 1;
- rtos->thread_details->exists = true;
- rtos->thread_details->extra_info_str = NULL;
- rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
- strcpy(rtos->thread_details->thread_name_str, tmp_str);
-
- if (thread_list_size == 0) {
- rtos->thread_count = 1;
- return ERROR_OK;
- }
- } else {
- /* create space for new thread details */
- rtos->thread_details = malloc(
- sizeof(struct thread_detail) * thread_list_size);
- }
-
- /* loop over all threads */
- thread_index = first_thread;
- do {
-
- #define ECOS_THREAD_NAME_STR_SIZE (200)
- char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
- unsigned int i = 0;
- uint32_t name_ptr = 0;
- uint32_t prev_thread_ptr;
-
- /* Save the thread pointer */
- uint16_t thread_id;
- retval = target_read_buffer(rtos->target,
- thread_index + param->thread_uniqueid_offset,
- 2,
- (uint8_t *)&thread_id);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read eCos thread id from target");
- return retval;
- }
- rtos->thread_details[tasks_found].threadid = thread_id;
-
- /* read the name pointer */
- retval = target_read_buffer(rtos->target,
- thread_index + param->thread_name_offset,
- param->pointer_width,
- (uint8_t *)&name_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read eCos thread name pointer from target");
- return retval;
- }
-
- /* Read the thread name */
- retval =
- target_read_buffer(rtos->target,
- name_ptr,
- ECOS_THREAD_NAME_STR_SIZE,
- (uint8_t *)&tmp_str);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread name from eCos target");
- return retval;
- }
- tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
-
- if (tmp_str[0] == '\x00')
- strcpy(tmp_str, "No Name");
-
- rtos->thread_details[tasks_found].thread_name_str =
- malloc(strlen(tmp_str)+1);
- strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
-
- /* Read the thread status */
- int64_t thread_status = 0;
- retval = target_read_buffer(rtos->target,
- thread_index + param->thread_state_offset,
- 4,
- (uint8_t *)&thread_status);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading thread state from eCos target");
- return retval;
- }
-
- for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
- /*
- * empty
- */
- }
-
- const char *state_desc;
- if (i < ECOS_NUM_STATES)
- state_desc = eCos_thread_states[i].desc;
- else
- state_desc = "Unknown state";
-
- rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
- state_desc)+1);
- strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
-
- rtos->thread_details[tasks_found].exists = true;
-
- tasks_found++;
- prev_thread_ptr = thread_index;
-
- /* Get the location of the next thread structure. */
- thread_index = rtos->symbols[eCos_VAL_thread_list].address;
- retval = target_read_buffer(rtos->target,
- prev_thread_ptr + param->thread_next_offset,
- param->pointer_width,
- (uint8_t *) &thread_index);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading next thread pointer in eCos thread list");
- return retval;
- }
- } while (thread_index != first_thread);
-
- rtos->thread_count = tasks_found;
- return 0;
-}
-
-static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
-{
- int retval;
- const struct eCos_params *param;
-
- *hex_reg_list = NULL;
-
- if (rtos == NULL)
- return -1;
-
- if (thread_id == 0)
- return -2;
-
- if (rtos->rtos_specific_params == NULL)
- return -3;
-
- param = (const struct eCos_params *) rtos->rtos_specific_params;
-
- /* Find the thread with that thread id */
- uint16_t id = 0;
- uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
- uint32_t thread_index;
- target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
- (uint8_t *)&thread_index);
- bool done = false;
- while (!done) {
- retval = target_read_buffer(rtos->target,
- thread_index + param->thread_uniqueid_offset,
- 2,
- (uint8_t *)&id);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading unique id from eCos thread");
- return retval;
- }
-
- if (id == thread_id) {
- done = true;
- break;
- }
- target_read_buffer(rtos->target,
- thread_index + param->thread_next_offset,
- param->pointer_width,
- (uint8_t *) &thread_index);
- }
-
- if (done) {
- /* Read the stack pointer */
- int64_t stack_ptr = 0;
- retval = target_read_buffer(rtos->target,
- thread_index + param->thread_stack_offset,
- param->pointer_width,
- (uint8_t *)&stack_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading stack frame from eCos thread");
- return retval;
- }
-
- return rtos_generic_stack_read(rtos->target,
- param->stacking_info,
- stack_ptr,
- hex_reg_list);
- }
-
- return -1;
-}
-
-static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- unsigned int i;
- *symbol_list = calloc(
- ARRAY_SIZE(eCos_symbol_list), sizeof(symbol_table_elem_t));
-
- for (i = 0; i < ARRAY_SIZE(eCos_symbol_list); i++)
- (*symbol_list)[i].symbol_name = eCos_symbol_list[i];
-
- return 0;
-}
-
-static int eCos_detect_rtos(struct target *target)
-{
- if ((target->rtos->symbols != NULL) &&
- (target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
- /* looks like eCos */
- return 1;
- }
- return 0;
-}
-
-static int eCos_create(struct target *target)
-{
- int i = 0;
- while ((i < ECOS_NUM_PARAMS) &&
- (0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
- i++;
- }
- if (i >= ECOS_NUM_PARAMS) {
- LOG_ERROR("Could not find target in eCos compatibility list");
- return -1;
- }
-
- target->rtos->rtos_specific_params = (void *) &eCos_params_list[i];
- target->rtos->current_thread = 0;
- target->rtos->thread_details = NULL;
- return 0;
-}
diff --git a/src/rtos/embKernel.c b/src/rtos/embKernel.c
deleted file mode 100644
index ceb313f..0000000
--- a/src/rtos/embKernel.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include "target/target.h"
-#include "target/target_type.h"
-#include "rtos.h"
-#include "helper/log.h"
-#include "helper/types.h"
-#include "rtos_embkernel_stackings.h"
-
-#define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
-
-static int embKernel_detect_rtos(struct target *target);
-static int embKernel_create(struct target *target);
-static int embKernel_update_threads(struct rtos *rtos);
-static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
-static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
-
-struct rtos_type embKernel_rtos = {
- .name = "embKernel",
- .detect_rtos = embKernel_detect_rtos,
- .create = embKernel_create,
- .update_threads = embKernel_update_threads,
- .get_thread_reg_list =
- embKernel_get_thread_reg_list,
- .get_symbol_list_to_lookup = embKernel_get_symbol_list_to_lookup,
-};
-
-enum {
- SYMBOL_ID_sCurrentTask = 0,
- SYMBOL_ID_sListReady = 1,
- SYMBOL_ID_sListSleep = 2,
- SYMBOL_ID_sListSuspended = 3,
- SYMBOL_ID_sMaxPriorities = 4,
- SYMBOL_ID_sCurrentTaskCount = 5,
-};
-
-static const char * const embKernel_symbol_list[] = {
- "Rtos::sCurrentTask",
- "Rtos::sListReady",
- "Rtos::sListSleep",
- "Rtos::sListSuspended",
- "Rtos::sMaxPriorities",
- "Rtos::sCurrentTaskCount",
- NULL };
-
-struct embKernel_params {
- const char *target_name;
- const unsigned char pointer_width;
- const unsigned char thread_count_width;
- const unsigned char rtos_list_size;
- const unsigned char thread_stack_offset;
- const unsigned char thread_name_offset;
- const unsigned char thread_priority_offset;
- const unsigned char thread_priority_width;
- const unsigned char iterable_next_offset;
- const unsigned char iterable_task_owner_offset;
- const struct rtos_register_stacking *stacking_info;
-};
-
-static const struct embKernel_params embKernel_params_list[] = {
- {
- "cortex_m", /* target_name */
- 4, /* pointer_width */
- 4, /* thread_count_width */
- 8, /*rtos_list_size */
- 0, /*thread_stack_offset */
- 4, /*thread_name_offset */
- 8, /*thread_priority_offset */
- 4, /*thread_priority_width */
- 4, /*iterable_next_offset */
- 12, /*iterable_task_owner_offset */
- &rtos_embkernel_Cortex_M_stacking, /* stacking_info*/
- },
- { "hla_target", /* target_name */
- 4, /* pointer_width */
- 4, /* thread_count_width */
- 8, /*rtos_list_size */
- 0, /*thread_stack_offset */
- 4, /*thread_name_offset */
- 8, /*thread_priority_offset */
- 4, /*thread_priority_width */
- 4, /*iterable_next_offset */
- 12, /*iterable_task_owner_offset */
- &rtos_embkernel_Cortex_M_stacking, /* stacking_info */
- }
-};
-
-static int embKernel_detect_rtos(struct target *target)
-{
- if (target->rtos->symbols != NULL) {
- if (target->rtos->symbols[SYMBOL_ID_sCurrentTask].address != 0)
- return 1;
- }
- return 0;
-}
-
-static int embKernel_create(struct target *target)
-{
- size_t i = 0;
- while ((i < ARRAY_SIZE(embKernel_params_list)) &&
- (0 != strcmp(embKernel_params_list[i].target_name, target->type->name)))
- i++;
-
- if (i >= ARRAY_SIZE(embKernel_params_list)) {
- LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
- "list", target->type->name);
- return -1;
- }
-
- target->rtos->rtos_specific_params = (void *) &embKernel_params_list[i];
- return 0;
-}
-
-static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embKernel_params *param,
- 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,
- (uint8_t *) &task);
- if (retval != ERROR_OK)
- return retval;
- details->threadid = (threadid_t) task;
- details->exists = true;
-
- int64_t name_ptr = 0;
- retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width,
- (uint8_t *) &name_ptr);
- if (retval != ERROR_OK)
- return retval;
-
- details->thread_name_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
- if (name_ptr) {
- retval = target_read_buffer(rtos->target, name_ptr, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE,
- (uint8_t *) details->thread_name_str);
- if (retval != ERROR_OK)
- return retval;
- details->thread_name_str[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE - 1] = 0;
- } else {
- snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task);
- }
-
- int64_t priority = 0;
- retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width,
- (uint8_t *) &priority);
- if (retval != ERROR_OK)
- return retval;
- details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
- if (task == rtos->current_thread) {
- snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, Running",
- (unsigned int) priority);
- } else {
- snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, %s", (unsigned int) priority,
- state_str);
- }
-
- LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
- (unsigned int)task, details->thread_name_str);
- return 0;
-}
-
-static int embKernel_update_threads(struct rtos *rtos)
-{
- /* int i = 0; */
- int retval;
- const struct embKernel_params *param;
-
- if (rtos == NULL)
- return -1;
-
- if (rtos->rtos_specific_params == NULL)
- return -3;
-
- if (rtos->symbols == NULL) {
- LOG_ERROR("No symbols for embKernel");
- return -4;
- }
-
- if (rtos->symbols[SYMBOL_ID_sCurrentTask].address == 0) {
- LOG_ERROR("Don't have the thread list head");
- return -2;
- }
-
- /* wipe out previous thread details if any */
- rtos_free_threadlist(rtos);
-
- param = (const struct embKernel_params *) rtos->rtos_specific_params;
-
- retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTask].address, param->pointer_width,
- (uint8_t *) &rtos->current_thread);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading current thread in embKernel thread list");
- return retval;
- }
-
- int64_t max_used_priority = 0;
- retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sMaxPriorities].address, param->pointer_width,
- (uint8_t *) &max_used_priority);
- if (retval != ERROR_OK)
- return retval;
-
- int thread_list_size = 0;
- retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTaskCount].address,
- param->thread_count_width, (uint8_t *) &thread_list_size);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read embKernel thread count from target");
- return retval;
- }
-
- /* create space for new thread details */
- rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
- if (!rtos->thread_details) {
- LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
- return ERROR_FAIL;
- }
-
- int threadIdx = 0;
- /* Look for ready tasks */
- for (int pri = 0; pri < max_used_priority; pri++) {
- /* Get first item in queue */
- int64_t iterable = 0;
- retval = target_read_buffer(rtos->target,
- rtos->symbols[SYMBOL_ID_sListReady].address + (pri * param->rtos_list_size), param->pointer_width,
- (uint8_t *) &iterable);
- if (retval != ERROR_OK)
- return retval;
- for (; iterable && threadIdx < thread_list_size; threadIdx++) {
- /* Get info from this iterable item */
- retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Ready");
- if (retval != ERROR_OK)
- return retval;
- /* Get next iterable item */
- retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
- (uint8_t *) &iterable);
- if (retval != ERROR_OK)
- return retval;
- }
- }
- /* Look for sleeping tasks */
- int64_t iterable = 0;
- retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSleep].address, param->pointer_width,
- (uint8_t *) &iterable);
- if (retval != ERROR_OK)
- return retval;
- for (; iterable && threadIdx < thread_list_size; threadIdx++) {
- /*Get info from this iterable item */
- retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Sleeping");
- if (retval != ERROR_OK)
- return retval;
- /*Get next iterable item */
- retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
- (uint8_t *) &iterable);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* Look for suspended tasks */
- iterable = 0;
- retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSuspended].address, param->pointer_width,
- (uint8_t *) &iterable);
- if (retval != ERROR_OK)
- return retval;
- for (; iterable && threadIdx < thread_list_size; threadIdx++) {
- /* Get info from this iterable item */
- retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Suspended");
- if (retval != ERROR_OK)
- return retval;
- /*Get next iterable item */
- retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
- (uint8_t *) &iterable);
- if (retval != ERROR_OK)
- return retval;
- }
-
- rtos->thread_count = 0;
- rtos->thread_count = threadIdx;
- LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx);
- return 0;
-}
-
-static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
-{
- int retval;
- const struct embKernel_params *param;
- int64_t stack_ptr = 0;
-
- *hex_reg_list = NULL;
- if (rtos == NULL)
- return -1;
-
- if (thread_id == 0)
- return -2;
-
- if (rtos->rtos_specific_params == NULL)
- return -1;
-
- param = (const struct embKernel_params *) rtos->rtos_specific_params;
-
- /* Read the stack pointer */
- retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width,
- (uint8_t *) &stack_ptr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error reading stack frame from embKernel thread");
- return retval;
- }
-
- return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
-}
-
-static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- unsigned int i;
- *symbol_list = calloc(ARRAY_SIZE(embKernel_symbol_list), sizeof(symbol_table_elem_t));
-
- for (i = 0; i < ARRAY_SIZE(embKernel_symbol_list); i++)
- (*symbol_list)[i].symbol_name = embKernel_symbol_list[i];
-
- return 0;
-}
-
diff --git a/src/rtos/linux.c b/src/rtos/linux.c
deleted file mode 100644
index 8c150af..0000000
--- a/src/rtos/linux.c
+++ /dev/null
@@ -1,1594 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by STEricsson *
- * Heythem Bouhaja heythem.bouhaja@stericsson.com : creation *
- * Michel JAOUEN michel.jaouen@stericsson.com : adaptation to rtos *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include "target/target.h"
-#include "target/target_type.h"
-#include "helper/log.h"
-#include "helper/types.h"
-#include "rtos.h"
-#include "rtos_standard_stackings.h"
-#include <target/register.h>
-#include "server/gdb_server.h"
-
-#define LINUX_USER_KERNEL_BORDER 0xc0000000
-#include "linux_header.h"
-#define PHYS
-#define MAX_THREADS 200
-/* specific task */
-struct linux_os {
- const char *name;
- uint32_t init_task_addr;
- int thread_count;
- int threadid_count;
- int preupdtate_threadid_count;
- int nr_cpus;
- int threads_lookup;
- int threads_needs_update;
- struct current_thread *current_threads;
- struct threads *thread_list;
- /* virt2phys parameter */
- uint32_t phys_mask;
- uint32_t phys_base;
-};
-
-struct current_thread {
- int64_t threadid;
- int32_t core_id;
-#ifdef PID_CHECK
- uint32_t pid;
-#endif
- uint32_t TS;
- struct current_thread *next;
-};
-
-struct threads {
- char name[17];
- uint32_t base_addr; /* address to read magic */
- uint32_t state; /* magic value : filled only at creation */
- uint32_t pid; /* linux pid : id for identifying a thread */
- uint32_t oncpu; /* content cpu number in current thread */
- uint32_t asid; /* filled only at creation */
- int64_t threadid;
- int status; /* dead = 1 alive = 2 current = 3 alive and current */
- /* value that should not change during the live of a thread ? */
- uint32_t thread_info_addr; /* contain latest thread_info_addr computed */
- /* retrieve from thread_info */
- struct cpu_context *context;
- struct threads *next;
-};
-
-struct cpu_context {
- uint32_t R4;
- uint32_t R5;
- uint32_t R6;
- uint32_t R7;
- uint32_t R8;
- uint32_t R9;
- uint32_t IP;
- uint32_t FP;
- uint32_t SP;
- uint32_t PC;
- uint32_t preempt_count;
-};
-struct cpu_context *cpu_context_read(struct target *target, uint32_t base_addr,
- uint32_t *info_addr);
-static int insert_into_threadlist(struct target *target, struct threads *t);
-
-static int linux_os_create(struct target *target);
-
-static int linux_os_dummy_update(struct rtos *rtos)
-{
- /* update is done only when thread request come
- * too many thread to do it on each stop */
- return 0;
-}
-
-static int linux_compute_virt2phys(struct target *target, uint32_t address)
-{
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- uint32_t pa = 0;
- int retval = target->type->virt2phys(target, address, &pa);
- if (retval != ERROR_OK) {
- LOG_ERROR("Cannot compute linux virt2phys translation");
- /* fixes default address */
- linux_os->phys_base = 0;
- return ERROR_FAIL;
- }
-
- linux_os->init_task_addr = address;
- address = address & linux_os->phys_mask;
- linux_os->phys_base = pa - address;
- return ERROR_OK;
-}
-
-static int linux_read_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count,
- uint8_t *buffer)
-{
-#ifdef PHYS
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- uint32_t pa = (address & linux_os->phys_mask) + linux_os->phys_base;
-#endif
- if (address < 0xc000000) {
- LOG_ERROR("linux awareness : address in user space");
- return ERROR_FAIL;
- }
-#ifdef PHYS
- target_read_phys_memory(target, pa, size, count, buffer);
-#endif
- target_read_memory(target, address, size, count, buffer);
- return ERROR_OK;
-}
-
-static char *reg_converter(char *buffer, void *reg, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- buffer += sprintf(buffer, "%02x", ((uint8_t *) reg)[i]);
-
- return buffer;
-}
-
-int fill_buffer(struct target *target, uint32_t addr, uint8_t *buffer)
-{
-
- if ((addr & 0xfffffffc) != addr)
- LOG_INFO("unaligned address %" PRIx32 "!!", addr);
-
- int retval = linux_read_memory(target, addr, 4, 1, buffer);
- return retval;
-
-}
-
-uint32_t get_buffer(struct target *target, const uint8_t *buffer)
-{
- uint32_t value = 0;
- const uint8_t *value_ptr = buffer;
- value = target_buffer_get_u32(target, value_ptr);
- return value;
-}
-
-static int linux_os_thread_reg_list(struct rtos *rtos,
- int64_t thread_id, char **hex_reg_list)
-{
- struct target *target = rtos->target;
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- int i = 0;
- struct current_thread *tmp = linux_os->current_threads;
- struct current_thread *next;
- char *hex_string;
- int found = 0;
- int retval;
- /* check if a current thread is requested */
- next = tmp;
-
- do {
- if (next->threadid == thread_id)
- found = 1;
- else
- next = next->next;
- } while ((found == 0) && (next != tmp) && (next != NULL));
-
- if (found == 1) {
- /* search target to perfom the access */
- struct reg **reg_list;
- int reg_list_size, reg_packet_size = 0;
- struct target_list *head;
- head = target->head;
- found = 0;
- do {
- if (head->target->coreid == next->core_id) {
-
- target = head->target;
- found = 1;
- } else
- head = head->next;
-
- } while ((head != (struct target_list *)NULL) && (found == 0));
-
- if (found == 0) {
- LOG_ERROR
- (
- "current thread %" PRIx64 ": no target to perform access of core id %" PRIx32,
- thread_id,
- next->core_id);
- return ERROR_FAIL;
- }
-
- /*LOG_INFO("thread %lx current on core %x",thread_id,
- * target->coreid);*/
- retval =
- target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
- REG_CLASS_GENERAL);
-
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < reg_list_size; i++)
- reg_packet_size += reg_list[i]->size;
-
- assert(reg_packet_size > 0);
-
- *hex_reg_list = malloc(DIV_ROUND_UP(reg_packet_size, 8) * 2);
-
- hex_string = *hex_reg_list;
-
- for (i = 0; i < reg_list_size; i++) {
- if (!reg_list[i]->valid)
- reg_list[i]->type->get(reg_list[i]);
-
- hex_string = reg_converter(hex_string,
- reg_list[i]->value,
- (reg_list[i]->size) / 8);
- }
-
- free(reg_list);
-
- } else {
- struct threads *temp = linux_os->thread_list;
- *hex_reg_list = calloc(1, 500 * sizeof(char));
- hex_string = *hex_reg_list;
-
- for (i = 0; i < 16; i++)
- hex_string += sprintf(hex_string, "%02x", 0);
-
- while ((temp != NULL) &&
- (temp->threadid != target->rtos->current_threadid))
- temp = temp->next;
-
- if (temp != NULL) {
- if (temp->context == NULL)
- temp->context = cpu_context_read(target,
- temp->
- base_addr,
- &temp->
- thread_info_addr);
-
- hex_string =
- reg_converter(hex_string, &temp->context->R4, 4);
- hex_string =
- reg_converter(hex_string, &temp->context->R5, 4);
- hex_string =
- reg_converter(hex_string, &temp->context->R6, 4);
- hex_string =
- reg_converter(hex_string, &temp->context->R7, 4);
- hex_string =
- reg_converter(hex_string, &temp->context->R8, 4);
- hex_string =
- reg_converter(hex_string, &temp->context->R9, 4);
-
- for (i = 0; i < 4; i++) /*R10 = 0x0 */
- hex_string += sprintf(hex_string, "%02x", 0);
-
- hex_string =
- reg_converter(hex_string, &temp->context->FP, 4);
- hex_string =
- reg_converter(hex_string, &temp->context->IP, 4);
- hex_string =
- reg_converter(hex_string, &temp->context->SP, 4);
-
- for (i = 0; i < 4; i++)
- hex_string += sprintf(hex_string, "%02x", 0);
-
- hex_string =
- reg_converter(hex_string, &temp->context->PC, 4);
-
- for (i = 0; i < 100; i++) /*100 */
- hex_string += sprintf(hex_string, "%02x", 0);
-
- uint32_t cpsr = 0x00000000;
- reg_converter(hex_string, &cpsr, 4);
- }
- }
- return ERROR_OK;
-}
-
-static int linux_os_detect(struct target *target)
-{
- LOG_INFO("should no be called");
- return 0;
-}
-
-static int linux_os_smp_init(struct target *target);
-static int linux_os_clean(struct target *target);
-#define INIT_TASK 0
-static const char * const linux_symbol_list[] = {
- "init_task",
- NULL
-};
-
-static int linux_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- unsigned int i;
- *symbol_list = (symbol_table_elem_t *)
- calloc(ARRAY_SIZE(linux_symbol_list), sizeof(symbol_table_elem_t));
-
- for (i = 0; i < ARRAY_SIZE(linux_symbol_list); i++)
- (*symbol_list)[i].symbol_name = linux_symbol_list[i];
-
- return 0;
-}
-
-static char *linux_ps_command(struct target *target);
-
-const struct rtos_type Linux_os = {
- .name = "linux",
- .detect_rtos = linux_os_detect,
- .create = linux_os_create,
- .smp_init = linux_os_smp_init,
- .update_threads = linux_os_dummy_update,
- .get_thread_reg_list = linux_os_thread_reg_list,
- .get_symbol_list_to_lookup = linux_get_symbol_list_to_lookup,
- .clean = linux_os_clean,
- .ps_command = linux_ps_command,
-};
-
-static int linux_thread_packet(struct connection *connection, char const *packet,
- int packet_size);
-static void linux_identify_current_threads(struct target *target);
-
-#ifdef PID_CHECK
-int fill_task_pid(struct target *target, struct threads *t)
-{
- uint32_t pid_addr = t->base_addr + PID;
- uint8_t buffer[4];
- int retval = fill_buffer(target, pid_addr, buffer);
-
- if (retval == ERROR_OK) {
- uint32_t val = get_buffer(target, buffer);
- t->pid = val;
- } else
- LOG_ERROR("fill_task_pid: unable to read memory");
-
- return retval;
-}
-#endif
-
-int fill_task(struct target *target, struct threads *t)
-{
- int retval;
- uint32_t pid_addr = t->base_addr + PID;
- uint32_t mem_addr = t->base_addr + MEM;
- uint32_t on_cpu = t->base_addr + ONCPU;
- uint8_t *buffer = calloc(1, 4);
- retval = fill_buffer(target, t->base_addr, buffer);
-
- if (retval == ERROR_OK) {
- uint32_t val = get_buffer(target, buffer);
- t->state = val;
- } else
- LOG_ERROR("fill_task: unable to read memory");
-
- retval = fill_buffer(target, pid_addr, buffer);
-
- if (retval == ERROR_OK) {
- uint32_t val = get_buffer(target, buffer);
- t->pid = val;
- } else
- LOG_ERROR("fill task: unable to read memory");
-
- retval = fill_buffer(target, on_cpu, buffer);
-
- if (retval == ERROR_OK) {
- uint32_t val = get_buffer(target, buffer);
- t->oncpu = val;
- } else
- LOG_ERROR("fill task: unable to read memory");
-
- retval = fill_buffer(target, mem_addr, buffer);
-
- if (retval == ERROR_OK) {
- uint32_t val = get_buffer(target, buffer);
-
- if (val != 0) {
- uint32_t asid_addr = val + MM_CTX;
- retval = fill_buffer(target, asid_addr, buffer);
-
- if (retval == ERROR_OK) {
- val = get_buffer(target, buffer);
- t->asid = val;
- } else
- LOG_ERROR
- ("fill task: unable to read memory -- ASID");
- } else
- t->asid = 0;
- } else
- LOG_ERROR("fill task: unable to read memory");
-
- free(buffer);
-
- return retval;
-}
-
-int get_name(struct target *target, struct threads *t)
-{
- int retval;
- uint32_t full_name[4];
- uint32_t comm = t->base_addr + COMM;
- int i;
-
- for (i = 0; i < 17; i++)
- t->name[i] = 0;
-
- retval = linux_read_memory(target, comm, 4, 4, (uint8_t *) full_name);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("get_name: unable to read memory\n");
- return ERROR_FAIL;
- }
-
- uint32_t raw_name = target_buffer_get_u32(target,
- (const uint8_t *)
- &full_name[0]);
- t->name[3] = raw_name >> 24;
- t->name[2] = raw_name >> 16;
- t->name[1] = raw_name >> 8;
- t->name[0] = raw_name;
- raw_name =
- target_buffer_get_u32(target, (const uint8_t *)&full_name[1]);
- t->name[7] = raw_name >> 24;
- t->name[6] = raw_name >> 16;
- t->name[5] = raw_name >> 8;
- t->name[4] = raw_name;
- raw_name =
- target_buffer_get_u32(target, (const uint8_t *)&full_name[2]);
- t->name[11] = raw_name >> 24;
- t->name[10] = raw_name >> 16;
- t->name[9] = raw_name >> 8;
- t->name[8] = raw_name;
- raw_name =
- target_buffer_get_u32(target, (const uint8_t *)&full_name[3]);
- t->name[15] = raw_name >> 24;
- t->name[14] = raw_name >> 16;
- t->name[13] = raw_name >> 8;
- t->name[12] = raw_name;
- return ERROR_OK;
-
-}
-
-int get_current(struct target *target, int create)
-{
- struct target_list *head;
- head = target->head;
- uint8_t *buf;
- uint32_t val;
- uint32_t ti_addr;
- uint8_t *buffer = calloc(1, 4);
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- struct current_thread *ctt = linux_os->current_threads;
-
- /* invalid current threads content */
- while (ctt != NULL) {
- ctt->threadid = -1;
- ctt->TS = 0xdeadbeef;
- ctt = ctt->next;
- }
-
- while (head != (struct target_list *)NULL) {
- struct reg **reg_list;
- int reg_list_size;
- int retval;
-
- if (target_get_gdb_reg_list(head->target, &reg_list,
- &reg_list_size, REG_CLASS_GENERAL) != ERROR_OK) {
- free(buffer);
- return ERROR_TARGET_FAILURE;
- }
-
- if (!reg_list[13]->valid)
- reg_list[13]->type->get(reg_list[13]);
-
- buf = reg_list[13]->value;
- val = get_buffer(target, buf);
- ti_addr = (val & 0xffffe000);
- uint32_t TS_addr = ti_addr + 0xc;
- retval = fill_buffer(target, TS_addr, buffer);
-
- if (retval == ERROR_OK) {
- uint32_t TS = get_buffer(target, buffer);
- uint32_t cpu, on_cpu = TS + ONCPU;
- retval = fill_buffer(target, on_cpu, buffer);
-
- if (retval == ERROR_OK) {
- /*uint32_t cpu = get_buffer(target, buffer);*/
- struct current_thread *ct =
- linux_os->current_threads;
- cpu = head->target->coreid;
-
- while ((ct != NULL) && (ct->core_id != (int32_t) cpu))
- ct = ct->next;
-
- if ((ct != NULL) && (ct->TS == 0xdeadbeef))
- ct->TS = TS;
- else
- LOG_ERROR
- ("error in linux current thread update");
-
- if (create && ct) {
- struct threads *t;
- t = calloc(1, sizeof(struct threads));
- t->base_addr = ct->TS;
- fill_task(target, t);
- get_name(target, t);
- t->oncpu = cpu;
- insert_into_threadlist(target, t);
- t->status = 3;
- t->thread_info_addr = 0xdeadbeef;
- ct->threadid = t->threadid;
- linux_os->thread_count++;
-#ifdef PID_CHECK
- ct->pid = t->pid;
-#endif
- /*LOG_INFO("Creation of current thread %s",t->name);*/
- }
- }
- }
-
- free(reg_list);
- head = head->next;
- }
-
- free(buffer);
-
- return ERROR_OK;
-}
-
-struct cpu_context *cpu_context_read(struct target *target, uint32_t base_addr,
- uint32_t *thread_info_addr_old)
-{
- struct cpu_context *context = calloc(1, sizeof(struct cpu_context));
- uint32_t preempt_count_addr = 0;
- uint32_t registers[10];
- uint8_t *buffer = calloc(1, 4);
- uint32_t stack = base_addr + QAT;
- uint32_t thread_info_addr = 0;
- uint32_t thread_info_addr_update = 0;
- int retval = ERROR_FAIL;
- context->R4 = 0xdeadbeef;
- context->R5 = 0xdeadbeef;
- context->R6 = 0xdeadbeef;
- context->R7 = 0xdeadbeef;
- context->R8 = 0xdeadbeef;
- context->R9 = 0xdeadbeef;
- context->IP = 0xdeadbeef;
- context->FP = 0xdeadbeef;
- context->SP = 0xdeadbeef;
- context->PC = 0xdeadbeef;
-retry:
-
- if (*thread_info_addr_old == 0xdeadbeef) {
- retval = fill_buffer(target, stack, buffer);
-
- if (retval == ERROR_OK)
- thread_info_addr = get_buffer(target, buffer);
- else
- LOG_ERROR("cpu_context: unable to read memory");
-
- thread_info_addr_update = thread_info_addr;
- } else
- thread_info_addr = *thread_info_addr_old;
-
- preempt_count_addr = thread_info_addr + PREEMPT;
- retval = fill_buffer(target, preempt_count_addr, buffer);
-
- if (retval == ERROR_OK)
- context->preempt_count = get_buffer(target, buffer);
- else {
- if (*thread_info_addr_old != 0xdeadbeef) {
- LOG_ERROR
- ("cpu_context: cannot read at thread_info_addr");
-
- if (*thread_info_addr_old < LINUX_USER_KERNEL_BORDER)
- LOG_INFO
- ("cpu_context : thread_info_addr in userspace!!!");
-
- *thread_info_addr_old = 0xdeadbeef;
- goto retry;
- }
-
- LOG_ERROR("cpu_context: unable to read memory");
- }
-
- thread_info_addr += CPU_CONT;
-
- retval = linux_read_memory(target, thread_info_addr, 4, 10,
- (uint8_t *) registers);
-
- if (retval != ERROR_OK) {
- free(buffer);
- LOG_ERROR("cpu_context: unable to read memory\n");
- return context;
- }
-
- context->R4 =
- target_buffer_get_u32(target, (const uint8_t *)&registers[0]);
- context->R5 =
- target_buffer_get_u32(target, (const uint8_t *)&registers[1]);
- context->R6 =
- target_buffer_get_u32(target, (const uint8_t *)&registers[2]);
- context->R7 =
- target_buffer_get_u32(target, (const uint8_t *)&registers[3]);
- context->R8 =
- target_buffer_get_u32(target, (const uint8_t *)&registers[4]);
- context->R9 =
- target_buffer_get_u32(target, (const uint8_t *)&registers[5]);
- context->IP =
- target_buffer_get_u32(target, (const uint8_t *)&registers[6]);
- context->FP =
- target_buffer_get_u32(target, (const uint8_t *)&registers[7]);
- context->SP =
- target_buffer_get_u32(target, (const uint8_t *)&registers[8]);
- context->PC =
- target_buffer_get_u32(target, (const uint8_t *)&registers[9]);
-
- if (*thread_info_addr_old == 0xdeadbeef)
- *thread_info_addr_old = thread_info_addr_update;
-
- free(buffer);
-
- return context;
-}
-
-uint32_t next_task(struct target *target, struct threads *t)
-{
- uint8_t *buffer = calloc(1, 4);
- uint32_t next_addr = t->base_addr + NEXT;
- int retval = fill_buffer(target, next_addr, buffer);
-
- if (retval == ERROR_OK) {
- uint32_t val = get_buffer(target, buffer);
- val = val - NEXT;
- free(buffer);
- return val;
- } else
- LOG_ERROR("next task: unable to read memory");
-
- free(buffer);
-
- return 0;
-}
-
-struct current_thread *add_current_thread(struct current_thread *currents,
- struct current_thread *ct)
-{
- ct->next = NULL;
-
- if (currents == NULL) {
- currents = ct;
- return currents;
- } else {
- struct current_thread *temp = currents;
-
- while (temp->next != NULL)
- temp = temp->next;
-
- temp->next = ct;
- return currents;
- }
-}
-
-struct threads *liste_del_task(struct threads *task_list, struct threads **t,
- struct threads *prev)
-{
- LOG_INFO("del task %" PRId64, (*t)->threadid);
- prev->next = (*t)->next;
-
- if (prev == task_list)
- task_list = prev;
-
- /* free content of threads */
- if ((*t)->context)
- free((*t)->context);
-
- free(*t);
- *t = prev;
- return task_list;
-}
-
-struct threads *liste_add_task(struct threads *task_list, struct threads *t,
- struct threads **last)
-{
- t->next = NULL;
-
- if (*last == NULL)
- if (task_list == NULL) {
- task_list = t;
- return task_list;
- } else {
- struct threads *temp = task_list;
-
- while (temp->next != NULL)
- temp = temp->next;
-
- temp->next = t;
- *last = t;
- return task_list;
- } else {
- (*last)->next = t;
- *last = t;
- return task_list;
- }
-}
-
-#ifdef PID_CHECK
-static int current_pid(struct linux_os *linux_os, uint32_t pid)
-#else
-static int current_base_addr(struct linux_os *linux_os, uint32_t base_addr)
-#endif
-{
- struct current_thread *ct = linux_os->current_threads;
-#ifdef PID_CHECK
-
- while ((ct != NULL) && (ct->pid != pid))
-#else
- while ((ct != NULL) && (ct->TS != base_addr))
-#endif
- ct = ct->next;
-#ifdef PID_CHECK
- if ((ct != NULL) && (ct->pid == pid))
-#else
- if ((ct != NULL) && (ct->TS == base_addr))
-#endif
- return 1;
-
- return 0;
-}
-
-int linux_get_tasks(struct target *target, int context)
-{
- int loop = 0;
- int retval = 0;
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- linux_os->thread_list = NULL;
- linux_os->thread_count = 0;
-
- if (linux_os->init_task_addr == 0xdeadbeef) {
- LOG_INFO("no init symbol\n");
- return ERROR_FAIL;
- }
-
- int64_t start = timeval_ms();
-
- struct threads *t = calloc(1, sizeof(struct threads));
- struct threads *last = NULL;
- t->base_addr = linux_os->init_task_addr;
- /* retrieve the thread id , currently running in the different smp core */
- get_current(target, 1);
-
- while (((t->base_addr != linux_os->init_task_addr) &&
- (t->base_addr != 0)) || (loop == 0)) {
- loop++;
- fill_task(target, t);
- retval = get_name(target, t);
-
- if (loop > MAX_THREADS) {
- free(t);
- LOG_INFO("more than %d threads !!", MAX_THREADS);
- return ERROR_FAIL;
- }
-
- if (retval != ERROR_OK) {
- free(t);
- return ERROR_FAIL;
- }
-
- /* check that this thread is not one the current threads already
- * created */
-#ifdef PID_CHECK
-
- if (!current_pid(linux_os, t->pid)) {
-#else
- if (!current_base_addr(linux_os, t->base_addr)) {
-#endif
- t->threadid = linux_os->threadid_count;
- t->status = 1;
- linux_os->threadid_count++;
-
- linux_os->thread_list =
- liste_add_task(linux_os->thread_list, t, &last);
- /* no interest to fill the context if it is a current thread. */
- linux_os->thread_count++;
- t->thread_info_addr = 0xdeadbeef;
-
- if (context)
- t->context =
- cpu_context_read(target, t->base_addr,
- &t->thread_info_addr);
- } else {
- /*LOG_INFO("thread %s is a current thread already created",t->name); */
- free(t);
- }
-
- uint32_t base_addr = next_task(target, t);
- t = calloc(1, sizeof(struct threads));
- t->base_addr = base_addr;
- }
-
- linux_os->threads_lookup = 1;
- linux_os->threads_needs_update = 0;
- linux_os->preupdtate_threadid_count = linux_os->threadid_count - 1;
- /* check that all current threads have been identified */
-
- LOG_INFO("complete time %" PRId64 ", thread mean %" PRId64 "\n",
- (timeval_ms() - start),
- (timeval_ms() - start) / linux_os->threadid_count);
-
- LOG_INFO("threadid count %d", linux_os->threadid_count);
- free(t);
-
- return ERROR_OK;
-}
-
-static int clean_threadlist(struct target *target)
-{
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- struct threads *old, *temp = linux_os->thread_list;
-
- while (temp != NULL) {
- old = temp;
-
- if (temp->context)
- free(temp->context);
-
- temp = temp->next;
- free(old);
- }
-
- return ERROR_OK;
-}
-
-static int linux_os_clean(struct target *target)
-{
- struct linux_os *os_linux = (struct linux_os *)
- target->rtos->rtos_specific_params;
- clean_threadlist(target);
- os_linux->init_task_addr = 0xdeadbeef;
- os_linux->name = "linux";
- os_linux->thread_list = NULL;
- os_linux->thread_count = 0;
- os_linux->nr_cpus = 0;
- os_linux->threads_lookup = 0;
- os_linux->threads_needs_update = 0;
- os_linux->threadid_count = 1;
- return ERROR_OK;
-}
-
-static int insert_into_threadlist(struct target *target, struct threads *t)
-{
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- struct threads *temp = linux_os->thread_list;
- t->threadid = linux_os->threadid_count;
- linux_os->threadid_count++;
- t->status = 1;
- t->next = NULL;
-
- if (temp == NULL)
- linux_os->thread_list = t;
- else {
- while (temp->next != NULL)
- temp = temp->next;
-
- t->next = NULL;
- temp->next = t;
- }
-
- return ERROR_OK;
-}
-
-static void linux_identify_current_threads(struct target *target)
-{
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- struct threads *thread_list = linux_os->thread_list;
- struct current_thread *ct = linux_os->current_threads;
- struct threads *t = NULL;
-
- while ((ct != NULL)) {
- if (ct->threadid == -1) {
-
- /* un-identified thread */
- int found = 0;
- t = calloc(1, sizeof(struct threads));
- t->base_addr = ct->TS;
-#ifdef PID_CHECK
-
- if (fill_task_pid(target, t) != ERROR_OK) {
-error_handling:
- free(t);
- LOG_ERROR
- ("linux identify_current_threads: unable to read pid");
- return;
- }
-#endif
-
- /* search in the list of threads if pid
- already present */
- while ((thread_list != NULL) && (found == 0)) {
-#ifdef PID_CHECK
- if (thread_list->pid == t->pid) {
-#else
- if (thread_list->base_addr == t->base_addr) {
-#endif
- free(t);
- t = thread_list;
- found = 1;
- }
- thread_list = thread_list->next;
- }
-
- if (!found) {
- /* it is a new thread */
- if (fill_task(target, t) != ERROR_OK)
- goto error_handling;
-
- get_name(target, t);
- insert_into_threadlist(target, t);
- t->thread_info_addr = 0xdeadbeef;
- }
-
- t->status = 3;
- ct->threadid = t->threadid;
-#ifdef PID_CHECK
- ct->pid = t->pid;
-#endif
- linux_os->thread_count++;
-#if 0
- if (found == 0)
- LOG_INFO("current thread core %x identified %s",
- ct->core_id, t->name);
- else
- LOG_INFO("current thread core %x, reused %s",
- ct->core_id, t->name);
-#endif
- }
-#if 0
- else {
- struct threads tmp;
- tmp.base_addr = ct->TS;
- get_name(target, &tmp);
- LOG_INFO("current thread core %x , already identified %s !!!",
- ct->core_id, tmp.name);
- }
-#endif
- ct = ct->next;
- }
-
- return;
-#ifndef PID_CHECK
-error_handling:
- free(t);
- LOG_ERROR("unable to read pid");
- return;
-
-#endif
-}
-
-static int linux_task_update(struct target *target, int context)
-{
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- struct threads *thread_list = linux_os->thread_list;
- int retval;
- int loop = 0;
- linux_os->thread_count = 0;
-
- /*thread_list = thread_list->next; skip init_task*/
- while (thread_list != NULL) {
- thread_list->status = 0; /*setting all tasks to dead state*/
-
- if (thread_list->context) {
- free(thread_list->context);
- thread_list->context = NULL;
- }
-
- thread_list = thread_list->next;
- }
-
- int found = 0;
-
- if (linux_os->init_task_addr == 0xdeadbeef) {
- LOG_INFO("no init symbol\n");
- return ERROR_FAIL;
- }
- int64_t start = timeval_ms();
- struct threads *t = calloc(1, sizeof(struct threads));
- uint32_t previous = 0xdeadbeef;
- t->base_addr = linux_os->init_task_addr;
- retval = get_current(target, 0);
- /*check that all current threads have been identified */
- linux_identify_current_threads(target);
-
- while (((t->base_addr != linux_os->init_task_addr) &&
- (t->base_addr != previous)) || (loop == 0)) {
- /* for avoiding any permanent loop for any reason possibly due to
- * target */
- loop++;
- previous = t->base_addr;
- /* read only pid */
-#ifdef PID_CHECK
- retval = fill_task_pid(target, t);
-#endif
-
- if (retval != ERROR_OK) {
- free(t);
- return ERROR_FAIL;
- }
-
- thread_list = linux_os->thread_list;
-
- while (thread_list != NULL) {
-#ifdef PID_CHECK
- if (t->pid == thread_list->pid) {
-#else
- if (t->base_addr == thread_list->base_addr) {
-#endif
- if (!thread_list->status) {
-#ifdef PID_CHECK
- if (t->base_addr != thread_list->base_addr)
- LOG_INFO("thread base_addr has changed !!");
-#endif
- /* this is not a current thread */
- thread_list->base_addr = t->base_addr;
- thread_list->status = 1;
-
- /* we don 't update this field any more */
-
- /*thread_list->state = t->state;
- thread_list->oncpu = t->oncpu;
- thread_list->asid = t->asid;
- */
- if (context)
- thread_list->context =
- cpu_context_read(target,
- thread_list->
- base_addr,
- &thread_list->
- thread_info_addr);
- } else {
- /* it is a current thread no need to read context */
- }
-
- linux_os->thread_count++;
- found = 1;
- break;
- } else {
- found = 0;
- thread_list = thread_list->next;
- }
- }
-
- if (found == 0) {
- uint32_t base_addr;
- fill_task(target, t);
- get_name(target, t);
- retval = insert_into_threadlist(target, t);
- t->thread_info_addr = 0xdeadbeef;
-
- if (context)
- t->context =
- cpu_context_read(target, t->base_addr,
- &t->thread_info_addr);
-
- base_addr = next_task(target, t);
- t = calloc(1, sizeof(struct threads));
- t->base_addr = base_addr;
- linux_os->thread_count++;
- } else
- t->base_addr = next_task(target, t);
- }
-
- LOG_INFO("update thread done %" PRId64 ", mean%" PRId64 "\n",
- (timeval_ms() - start), (timeval_ms() - start) / loop);
- free(t);
- linux_os->threads_needs_update = 0;
- return ERROR_OK;
-}
-
-int linux_gdb_thread_packet(struct target *target,
- struct connection *connection, char const *packet,
- int packet_size)
-{
- int retval;
- struct linux_os *linux_os =
- (struct linux_os *)target->rtos->rtos_specific_params;
-
- if (linux_os->init_task_addr == 0xdeadbeef) {
- /* it has not been initialized */
- LOG_INFO("received thread request without init task address");
- gdb_put_packet(connection, "l", 1);
- return ERROR_OK;
- }
-
- retval = linux_get_tasks(target, 1);
-
- if (retval != ERROR_OK)
- return ERROR_TARGET_FAILURE;
-
- char *out_str = calloc(1, 350 * sizeof(int64_t));
- char *tmp_str = out_str;
- tmp_str += sprintf(tmp_str, "m");
- struct threads *temp = linux_os->thread_list;
-
- while (temp != NULL) {
- tmp_str += sprintf(tmp_str, "%016" PRIx64, temp->threadid);
- temp = temp->next;
- if (temp)
- tmp_str += sprintf(tmp_str, ",");
- }
-
- gdb_put_packet(connection, out_str, strlen(out_str));
- free(out_str);
- return ERROR_OK;
-}
-
-int linux_gdb_thread_update(struct target *target,
- struct connection *connection, char const *packet,
- int packet_size)
-{
- int found = 0;
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- struct threads *temp = linux_os->thread_list;
-
- while (temp != NULL) {
- if (temp->threadid == linux_os->preupdtate_threadid_count + 1) {
- /*LOG_INFO("FOUND");*/
- found = 1;
- break;
- } else
- temp = temp->next;
- }
-
- if (found == 1) {
- /*LOG_INFO("INTO GDB THREAD UPDATE FOUNDING START TASK");*/
- char *out_strr = calloc(1, 350 * sizeof(int64_t));
- char *tmp_strr = out_strr;
- tmp_strr += sprintf(tmp_strr, "m");
- /*LOG_INFO("CHAR MALLOC & M DONE");*/
- tmp_strr += sprintf(tmp_strr, "%016" PRIx64, temp->threadid);
-
- temp = temp->next;
-
- while (temp != NULL) {
- /*LOG_INFO("INTO GDB THREAD UPDATE WHILE");*/
- tmp_strr += sprintf(tmp_strr, ",");
- tmp_strr +=
- sprintf(tmp_strr, "%016" PRIx64, temp->threadid);
- temp = temp->next;
- }
-
- /*tmp_str[0] = 0;*/
- gdb_put_packet(connection, out_strr, strlen(out_strr));
- linux_os->preupdtate_threadid_count =
- linux_os->threadid_count - 1;
- free(out_strr);
- } else
- gdb_put_packet(connection, "l", 1);
-
- return ERROR_OK;
-}
-
-int linux_thread_extra_info(struct target *target,
- struct connection *connection, char const *packet,
- int packet_size)
-{
- int64_t threadid = 0;
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
- /*LOG_INFO("lookup extra info for thread %" SCNx64, threadid);*/
- struct threads *temp = linux_os->thread_list;
-
- while (temp != NULL) {
- if (temp->threadid == threadid) {
- char *pid = " PID: ";
- char *pid_current = "*PID: ";
- char *name = "NAME: ";
- int str_size = strlen(pid) + strlen(name);
- char *tmp_str = calloc(1, str_size + 50);
- char *tmp_str_ptr = tmp_str;
-
- /* discriminate current task */
- if (temp->status == 3)
- tmp_str_ptr += sprintf(tmp_str_ptr, "%s",
- pid_current);
- else
- tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid);
-
- tmp_str_ptr +=
- sprintf(tmp_str_ptr, "%d", (int)temp->pid);
- tmp_str_ptr += sprintf(tmp_str_ptr, "%s", " | ");
- sprintf(tmp_str_ptr, "%s", name);
- sprintf(tmp_str_ptr, "%s", temp->name);
- char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1);
- int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1);
- gdb_put_packet(connection, hex_str, pkt_len);
- free(hex_str);
- free(tmp_str);
- return ERROR_OK;
- }
-
- temp = temp->next;
- }
-
- LOG_INFO("thread not found");
- return ERROR_OK;
-}
-
-int linux_gdb_T_packet(struct connection *connection,
- struct target *target, char const *packet, int packet_size)
-{
- int64_t threadid;
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- int retval = ERROR_OK;
- sscanf(packet, "T%" SCNx64, &threadid);
-
- if (linux_os->threads_needs_update == 0) {
- struct threads *temp = linux_os->thread_list;
- struct threads *prev = linux_os->thread_list;
-
- while (temp != NULL) {
- if (temp->threadid == threadid) {
- if (temp->status != 0) {
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- } else {
- /* delete item in the list */
- linux_os->thread_list =
- liste_del_task(linux_os->
- thread_list, &temp,
- prev);
- linux_os->thread_count--;
- gdb_put_packet(connection, "E01", 3);
- return ERROR_OK;
- }
- }
-
- /* for deletion */
- prev = temp;
- temp = temp->next;
- }
-
- LOG_INFO("gdb requested status on non existing thread");
- gdb_put_packet(connection, "E01", 3);
- return ERROR_OK;
-
- } else {
- retval = linux_task_update(target, 1);
- struct threads *temp = linux_os->thread_list;
-
- while (temp != NULL) {
- if (temp->threadid == threadid) {
- if (temp->status == 1) {
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- } else {
- gdb_put_packet(connection, "E01", 3);
- return ERROR_OK;
- }
- }
-
- temp = temp->next;
- }
- }
-
- return retval;
-}
-
-int linux_gdb_h_packet(struct connection *connection,
- struct target *target, char const *packet, int packet_size)
-{
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- struct current_thread *ct = linux_os->current_threads;
-
- /* select to display the current thread of the selected target */
- while ((ct != NULL) && (ct->core_id != target->coreid))
- ct = ct->next;
-
- int64_t current_gdb_thread_rq;
-
- if (linux_os->threads_lookup == 1) {
- if ((ct != NULL) && (ct->threadid == -1)) {
- ct = linux_os->current_threads;
-
- while ((ct != NULL) && (ct->threadid == -1))
- ct = ct->next;
- }
-
- if (ct == NULL) {
- /* no current thread can be identified
- * any way with smp */
- LOG_INFO("no current thread identified");
- /* attempt to display the name of the 2 threads identified with
- * get_current */
- struct threads t;
- ct = linux_os->current_threads;
-
- while ((ct != NULL) && (ct->threadid == -1)) {
- t.base_addr = ct->TS;
- get_name(target, &t);
- LOG_INFO("name of unidentified thread %s",
- t.name);
- ct = ct->next;
- }
-
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- }
-
- if (packet[1] == 'g') {
- sscanf(packet, "Hg%16" SCNx64, &current_gdb_thread_rq);
-
- if (current_gdb_thread_rq == 0) {
- target->rtos->current_threadid = ct->threadid;
- gdb_put_packet(connection, "OK", 2);
- } else {
- target->rtos->current_threadid =
- current_gdb_thread_rq;
- gdb_put_packet(connection, "OK", 2);
- }
- } else if (packet[1] == 'c') {
- sscanf(packet, "Hc%16" SCNx64, &current_gdb_thread_rq);
-
- if ((current_gdb_thread_rq == 0) ||
- (current_gdb_thread_rq == ct->threadid)) {
- target->rtos->current_threadid = ct->threadid;
- gdb_put_packet(connection, "OK", 2);
- } else
- gdb_put_packet(connection, "E01", 3);
- }
- } else
- gdb_put_packet(connection, "OK", 2);
-
- return ERROR_OK;
-}
-
-static int linux_thread_packet(struct connection *connection, char const *packet,
- int packet_size)
-{
- int retval = ERROR_OK;
- struct current_thread *ct;
- struct target *target = get_target_from_connection(connection);
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
-
- switch (packet[0]) {
- case 'T': /* Is thread alive?*/
-
- linux_gdb_T_packet(connection, target, packet, packet_size);
- break;
- case 'H': /* Set current thread */
- /* ( 'c' for step and continue, 'g' for all other operations )*/
- /*LOG_INFO(" H packet received '%s'", packet);*/
- linux_gdb_h_packet(connection, target, packet, packet_size);
- break;
- case 'q':
-
- if (strncmp(packet, "qSymbol", 7) == 0) {
- if (rtos_qsymbol(connection, packet, packet_size) == 1) {
- linux_compute_virt2phys(target,
- target->rtos->
- symbols[INIT_TASK].
- address);
- }
-
- break;
- } else if (strncmp(packet, "qfThreadInfo", 12) == 0) {
- if (linux_os->thread_list == NULL) {
- retval = linux_gdb_thread_packet(target,
- connection,
- packet,
- packet_size);
- break;
- } else {
- retval = linux_gdb_thread_update(target,
- connection,
- packet,
- packet_size);
- break;
- }
- } else if (strncmp(packet, "qsThreadInfo", 12) == 0) {
- gdb_put_packet(connection, "l", 1);
- break;
- } else if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) {
- linux_thread_extra_info(target, connection, packet,
- packet_size);
- break;
- } else {
- retval = GDB_THREAD_PACKET_NOT_CONSUMED;
- break;
- }
-
- case 'Q':
- /* previously response was : thread not found
- * gdb_put_packet(connection, "E01", 3); */
- retval = GDB_THREAD_PACKET_NOT_CONSUMED;
- break;
- case 'c':
- case 's': {
- if (linux_os->threads_lookup == 1) {
- ct = linux_os->current_threads;
-
- while ((ct != NULL) && (ct->core_id) != target->coreid)
- ct = ct->next;
-
- if ((ct != NULL) && (ct->threadid == -1)) {
- ct = linux_os->current_threads;
-
- while ((ct != NULL) && (ct->threadid == -1))
- ct = ct->next;
- }
-
- if ((ct != NULL) && (ct->threadid !=
- target->rtos->
- current_threadid)
- && (target->rtos->current_threadid != -1))
- LOG_WARNING("WARNING! current GDB thread do not match" \
- "current thread running." \
- "Switch thread in GDB to threadid %d",
- (int)ct->threadid);
-
- LOG_INFO("threads_needs_update = 1");
- linux_os->threads_needs_update = 1;
- }
- }
-
- /* if a packet handler returned an error, exit input loop */
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int linux_os_smp_init(struct target *target)
-{
- struct target_list *head;
- /* keep only target->rtos */
- struct rtos *rtos = target->rtos;
- struct linux_os *os_linux =
- (struct linux_os *)rtos->rtos_specific_params;
- struct current_thread *ct;
- head = target->head;
-
- while (head != (struct target_list *)NULL) {
- if (head->target->rtos != rtos) {
- struct linux_os *smp_os_linux =
- (struct linux_os *)head->target->rtos->
- rtos_specific_params;
- /* remap smp target on rtos */
- free(head->target->rtos);
- head->target->rtos = rtos;
- /* reuse allocated ct */
- ct = smp_os_linux->current_threads;
- ct->threadid = -1;
- ct->TS = 0xdeadbeef;
- ct->core_id = head->target->coreid;
- os_linux->current_threads =
- add_current_thread(os_linux->current_threads, ct);
- os_linux->nr_cpus++;
- free(smp_os_linux);
- }
-
- head = head->next;
- }
-
- return ERROR_OK;
-}
-
-static int linux_os_create(struct target *target)
-{
- struct linux_os *os_linux = calloc(1, sizeof(struct linux_os));
- struct current_thread *ct = calloc(1, sizeof(struct current_thread));
- LOG_INFO("linux os creation\n");
- os_linux->init_task_addr = 0xdeadbeef;
- os_linux->name = "linux";
- os_linux->thread_list = NULL;
- os_linux->thread_count = 0;
- target->rtos->current_threadid = -1;
- os_linux->nr_cpus = 1;
- os_linux->threads_lookup = 0;
- os_linux->threads_needs_update = 0;
- os_linux->threadid_count = 1;
- os_linux->current_threads = NULL;
- target->rtos->rtos_specific_params = os_linux;
- ct->core_id = target->coreid;
- ct->threadid = -1;
- ct->TS = 0xdeadbeef;
- os_linux->current_threads =
- add_current_thread(os_linux->current_threads, ct);
- /* overload rtos thread default handler */
- target->rtos->gdb_thread_packet = linux_thread_packet;
- /* initialize a default virt 2 phys translation */
- os_linux->phys_mask = ~0xc0000000;
- os_linux->phys_base = 0x0;
- return JIM_OK;
-}
-
-static char *linux_ps_command(struct target *target)
-{
- struct linux_os *linux_os = (struct linux_os *)
- target->rtos->rtos_specific_params;
- int retval = ERROR_OK;
- char *display;
-
- if (linux_os->threads_lookup == 0)
- retval = linux_get_tasks(target, 1);
- else {
- if (linux_os->threads_needs_update != 0)
- retval = linux_task_update(target, 0);
- }
-
- if (retval == ERROR_OK) {
- struct threads *temp = linux_os->thread_list;
- char *tmp;
- LOG_INFO("allocation for %d threads line",
- linux_os->thread_count);
- display = calloc((linux_os->thread_count + 2) * 80, 1);
-
- if (!display)
- goto error;
-
- tmp = display;
- tmp += sprintf(tmp, "PID\t\tCPU\t\tASID\t\tNAME\n");
- tmp += sprintf(tmp, "---\t\t---\t\t----\t\t----\n");
-
- while (temp != NULL) {
- if (temp->status) {
- if (temp->context)
- tmp +=
- sprintf(tmp,
- "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n",
- temp->pid, temp->oncpu,
- temp->asid, temp->name);
- else
- tmp +=
- sprintf(tmp,
- "%" PRId32 "\t\t%" PRId32 "\t\t%" PRIx32 "\t\t%s\n",
- temp->pid, temp->oncpu,
- temp->asid, temp->name);
- }
-
- temp = temp->next;
- }
-
- return display;
- }
-
-error:
- display = calloc(40, 1);
- sprintf(display, "linux_ps_command failed\n");
- return display;
-}
diff --git a/src/rtos/linux_header.h b/src/rtos/linux_header.h
deleted file mode 100644
index a2b408e..0000000
--- a/src/rtos/linux_header.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef OPENOCD_RTOS_LINUX_HEADER_H
-#define OPENOCD_RTOS_LINUX_HEADER_H
-
-/* gdb script to update the header file
- according to kernel version and build option
- before executing function awareness
- kernel symbol must be loaded : symbol vmlinux
-
-define awareness
- set logging off
- set logging file linux_header.h
- set logging on
-
- printf "#define QAT %p\n",&((struct task_struct *)(0))->stack
- set $a=&((struct list_head *)(0))->next
- set $a=(int)$a+(int)&((struct task_struct *)(0))->tasks
- printf "#define NEXT %p\n",$a
- printf "#define COMM %p\n",&((struct task_struct *)(0))->comm
- printf "#define MEM %p\n",&((struct task_struct *)(0))->mm
- printf "#define ONCPU %p\n",&((struct task_struct *)(0))->on_cpu
- printf "#define PID %p\n",&((struct task_struct *)(0))->pid
- printf "#define CPU_CONT %p\n",&((struct thread_info *)(0))->cpu_context
- printf "#define PREEMPT %p\n",&((struct thread_info *)(0))->preempt_count
- printf "#define MM_CTX %p\n",&((struct mm_struct *)(0))->context
- end
-*/
-#define QAT 0x4
-#define NEXT 0x1b0
-#define COMM 0x2d4
-#define MEM 0x1cc
-#define ONCPU 0x18
-#define PID 0x1f4
-#define CPU_CONT 0x1c
-#define PREEMPT 0x4
-#define MM_CTX 0x160
-
-#endif /* OPENOCD_RTOS_LINUX_HEADER_H */
diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c
deleted file mode 100644
index b8095a0..0000000
--- a/src/rtos/mqx.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2014 by Marian Cingel *
- * cingel.marian@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdint.h>
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include "target/target.h"
-#include "target/target_type.h"
-#include "rtos.h"
-#include "helper/log.h"
-#include "helper/types.h"
-#include "rtos_mqx_stackings.h"
-
-/* constants */
-#define MQX_THREAD_NAME_LENGTH (255)
-#define MQX_KERNEL_OFFSET_TDLIST (0x0108)
-#define MQX_KERNEL_OFFSET_SYSTEM_TASK (0x0050)
-#define MQX_KERNEL_OFFSET_ACTIVE_TASK (0x001C)
-#define MQX_KERNEL_OFFSET_CAPABILITY (0x0000)
-#define MQX_QUEUE_OFFSET_SIZE (0x0008)
-#define MQX_TASK_OFFSET_STATE (0x0008)
-#define MQX_TASK_OFFSET_ID (0x000c)
-#define MQX_TASK_OFFSET_TEMPLATE (0x0068)
-#define MQX_TASK_OFFSET_STACK (0x0014)
-#define MQX_TASK_OFFSET_TDLIST (0x006C)
-#define MQX_TASK_OFFSET_NEXT (0x0000)
-#define MQX_TASK_TEMPLATE_OFFSET_NAME (0x0010)
-#define MQX_TASK_OFFSET_ERROR_CODE (0x005C)
-#define MQX_TASK_STATE_MASK (0xFFF)
-
-/* types */
-enum mqx_symbols {
- mqx_VAL_mqx_kernel_data,
- mqx_VAL_MQX_init_struct,
-};
-
-enum mqx_arch {
- mqx_arch_cortexm,
-};
-
-struct mqx_params {
- const char *target_name;
- const enum mqx_arch target_arch;
- const struct rtos_register_stacking *stacking_info;
-};
-
-struct mqx_state {
- uint32_t state;
- char *name;
-};
-
-/* local data */
-static const struct mqx_state mqx_states[] = {
- { 0x0002, "READY" },
- { 0x0003, "BLOCKED" },
- { 0x0005, "RCV_SPECIFIC_BLOCKED" },
- { 0x0007, "RCV_ANY_BLOCKED" },
- { 0x0009, "DYING" },
- { 0x000B, "UNHANDLED_INT_BLOCKED" },
- { 0x000D, "SEND_BLOCKED" },
- { 0x000F, "BREAKPOINT_BLOCKED" },
- { 0x0211, "IO_BLOCKED" },
- { 0x0021, "SEM_BLOCKED" },
- { 0x0223, "MUTEX_BLOCKED" },
- { 0x0025, "EVENT_BLOCKED" },
- { 0x0229, "TASK_QUEUE_BLOCKED" },
- { 0x042B, "LWSEM_BLOCKED" },
- { 0x042D, "LWEVENT_BLOCKED" },
-};
-
-static const char * const mqx_symbol_list[] = {
- "_mqx_kernel_data",
- "MQX_init_struct",
- NULL
-};
-
-static const struct mqx_params mqx_params_list[] = {
- { "cortex_m", mqx_arch_cortexm, &rtos_mqx_arm_v7m_stacking },
-};
-
-/*
- * Perform simple address check to avoid bus fault.
- */
-static int mqx_valid_address_check(
- struct rtos *rtos,
- uint32_t address
-)
-{
- 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;
-
- /* Cortex-M address range */
- if (arch_type == mqx_arch_cortexm) {
- if (
- /* code and sram area */
- (address && address <= 0x3FFFFFFFu) ||
- /* external ram area*/
- (address >= 0x6000000u && address <= 0x9FFFFFFFu)
- ) {
- return ERROR_OK;
- }
- return ERROR_FAIL;
- }
- LOG_ERROR("MQX RTOS - unknown architecture %s", targetname);
- return ERROR_FAIL;
-}
-
-/*
- * Wrapper of 'target_read_buffer' fn.
- * Include address check.
- */
-static int mqx_target_read_buffer(
- struct target *target,
- uint32_t address,
- uint32_t size,
- uint8_t *buffer
-)
-{
- int status = mqx_valid_address_check(target->rtos, address);
- if (status != ERROR_OK) {
- LOG_WARNING("MQX RTOS - target address 0x%" PRIx32 " is not allowed to read", address);
- return status;
- }
- status = target_read_buffer(target, address, size, buffer);
- if (status != ERROR_OK) {
- LOG_ERROR("MQX RTOS - reading target address 0x%" PRIx32" failed", address);
- return status;
- }
- return ERROR_OK;
-}
-
-/*
- * Get symbol address if present
- */
-static int mqx_get_symbol(
- struct rtos *rtos,
- enum mqx_symbols symbol,
- void *result
-)
-{
- /* TODO: additional check ?? */
- (*(int *)result) = (uint32_t)rtos->symbols[symbol].address;
- return ERROR_OK;
-}
-
-/*
- * Get value of struct member by passing
- * member offset, width and name (debug purpose)
- */
-static int mqx_get_member(
- struct rtos *rtos,
- const uint32_t base_address,
- int32_t member_offset,
- int32_t member_width,
- const char *member_name,
- void *result
-)
-{
- int status = ERROR_FAIL;
- status = mqx_target_read_buffer(
- rtos->target, base_address + member_offset, member_width, result
- );
- if (status != ERROR_OK)
- LOG_WARNING("MQX RTOS - cannot read \"%s\" at address 0x%" PRIx32,
- member_name, (uint32_t)(base_address + member_offset));
- return status;
-}
-
-/*
- * Check whether scheduler started
- */
-static int mqx_is_scheduler_running(
- struct rtos *rtos
-)
-{
- uint32_t kernel_data_symbol = 0;
- uint32_t kernel_data_addr = 0;
- uint32_t system_td_addr = 0;
- uint32_t active_td_addr = 0;
- uint32_t capability_value = 0;
-
- /* get '_mqx_kernel_data' symbol */
- if (ERROR_OK != mqx_get_symbol(
- rtos, mqx_VAL_mqx_kernel_data, &kernel_data_symbol
- )) {
- return ERROR_FAIL;
- }
- /* get '_mqx_kernel_data' */
- if (ERROR_OK != mqx_get_member(
- rtos, kernel_data_symbol, 0, 4,
- "_mqx_kernel_data", &kernel_data_addr
- )) {
- return ERROR_FAIL;
- }
- /* return if '_mqx_kernel_data' is NULL or default 0xFFFFFFFF */
- if (0 == kernel_data_addr || (uint32_t)(-1) == kernel_data_addr)
- return ERROR_FAIL;
- /* get kernel_data->ADDRESSING_CAPABILITY */
- if (ERROR_OK != mqx_get_member(
- rtos, kernel_data_addr, MQX_KERNEL_OFFSET_CAPABILITY, 4,
- "kernel_data->ADDRESSING_CAPABILITY", (void *)&capability_value
- )) {
- return ERROR_FAIL;
- }
- /* check first member, the '_mqx_kernel_data->ADDRESSING_CAPABILITY'.
- it supose to be set to value 8 */
- if (capability_value != 8) {
- LOG_WARNING("MQX RTOS - value of '_mqx_kernel_data->ADDRESSING_CAPABILITY' contains invalid value");
- return ERROR_FAIL;
- }
- /* get active ptr */
- if (ERROR_OK != mqx_get_member(
- rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4,
- "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
- )) {
- return ERROR_FAIL;
- }
- /* active task is system task, scheduler has not not run yet */
- system_td_addr = kernel_data_addr + MQX_KERNEL_OFFSET_SYSTEM_TASK;
- if (active_td_addr == system_td_addr) {
- LOG_WARNING("MQX RTOS - scheduler does not run");
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-/*
- * API function, return 1 if MQX is present
- */
-static int mqx_detect_rtos(
- struct target *target
-)
-{
- if (
- (target->rtos->symbols != NULL) &&
- (target->rtos->symbols[mqx_VAL_mqx_kernel_data].address != 0)
- ) {
- return 1;
- }
- return 0;
-}
-
-/*
- * API function, pass MQX extra info to context data
- */
-static int mqx_create(
- struct target *target
-)
-{
- /* check target name against supported architectures */
- int mqx_params_list_num = (sizeof(mqx_params_list)/sizeof(struct mqx_params));
- for (int i = 0; i < mqx_params_list_num; i++) {
- if (0 == strcmp(mqx_params_list[i].target_name, target->type->name)) {
- target->rtos->rtos_specific_params = (void *)&mqx_params_list[i];
- /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */
- return 0;
- }
- }
- LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target->type->name);
- return -1;
-}
-
-/*
- * API function, update list of threads
- */
-static int mqx_update_threads(
- struct rtos *rtos
-)
-{
- uint32_t task_queue_addr = 0;
- uint32_t kernel_data_addr = 0;
- uint16_t task_queue_size = 0;
- uint32_t active_td_addr = 0;
-
- if (!rtos->rtos_specific_params)
- return -3;
-
- if (!rtos->symbols)
- return -4;
-
- /* clear old data */
- rtos_free_threadlist(rtos);
- /* check scheduler */
- if (ERROR_OK != mqx_is_scheduler_running(rtos))
- return ERROR_FAIL;
- /* get kernel_data symbol */
- if (ERROR_OK != mqx_get_symbol(
- rtos, mqx_VAL_mqx_kernel_data, &kernel_data_addr
- )) {
- return ERROR_FAIL;
- }
- /* read kernel_data */
- if (ERROR_OK != mqx_get_member(
- rtos, kernel_data_addr, 0, 4, "_mqx_kernel_data", &kernel_data_addr
- )) {
- return ERROR_FAIL;
- }
- /* get task queue address */
- task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST;
- /* get task queue size */
- if (ERROR_OK != mqx_get_member(
- rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2,
- "kernel_data->TD_LIST.SIZE", &task_queue_size
- )) {
- return ERROR_FAIL;
- }
- /* get active ptr */
- if (ERROR_OK != mqx_get_member(
- rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4,
- "kernel_data->ACTIVE_PTR", (void *)&active_td_addr
- )) {
- return ERROR_FAIL;
- }
-
- /* setup threads info */
- rtos->thread_count = task_queue_size;
- rtos->current_thread = 0;
- rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
- if (NULL == rtos->thread_details)
- return ERROR_FAIL;
-
- /* loop over each task and setup thread details,
- the current_taskpool_addr is set to queue head
- NOTE: debugging functions task create/destroy
- might cause to show invalid data.
- */
- for (
- uint32_t i = 0, taskpool_addr = task_queue_addr;
- i < (uint32_t)rtos->thread_count;
- i++
- ) {
- uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1];
- uint32_t task_addr = 0, task_template = 0, task_state = 0;
- uint32_t task_name_addr = 0, task_id = 0, task_errno = 0;
- uint32_t state_index = 0, state_max = 0;
- uint32_t extra_info_length = 0;
- char *state_name = "unknown state";
-
- /* set current taskpool address */
- if (ERROR_OK != mqx_get_member(
- rtos, taskpool_addr, MQX_TASK_OFFSET_NEXT, 4,
- "td_struct_ptr->NEXT", &taskpool_addr
- )) {
- return ERROR_FAIL;
- }
- /* get task address from taskpool */
- task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST;
- /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
- if (ERROR_OK != mqx_get_member(
- rtos, task_addr, MQX_TASK_OFFSET_TEMPLATE, 4,
- "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template
- )) {
- return ERROR_FAIL;
- }
- /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
- if (ERROR_OK != mqx_get_member(
- rtos, task_template, MQX_TASK_TEMPLATE_OFFSET_NAME, 4,
- "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr
- )) {
- return ERROR_FAIL;
- }
- /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
- if (ERROR_OK != mqx_get_member(
- rtos, task_name_addr, 0, MQX_THREAD_NAME_LENGTH,
- "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name
- )) {
- return ERROR_FAIL;
- }
- /* always terminate last character by force,
- otherwise openocd might fail if task_name
- has corrupted data */
- task_name[MQX_THREAD_NAME_LENGTH] = '\0';
- /* get value of 'td_struct_ptr->TASK_ID' */
- if (ERROR_OK != mqx_get_member(
- rtos, task_addr, MQX_TASK_OFFSET_ID, 4,
- "td_struct_ptr->TASK_ID", &task_id
- )) {
- return ERROR_FAIL;
- }
- /* get task errno */
- if (ERROR_OK != mqx_get_member(
- rtos, task_addr, MQX_TASK_OFFSET_ERROR_CODE, 4,
- "td_struct_ptr->TASK_ERROR_CODE", &task_errno
- )) {
- return ERROR_FAIL;
- }
- /* get value of 'td_struct_ptr->STATE' */
- if (ERROR_OK != mqx_get_member(
- rtos, task_addr, MQX_TASK_OFFSET_STATE, 4,
- "td_struct_ptr->STATE", &task_state
- )) {
- return ERROR_FAIL;
- }
- task_state &= MQX_TASK_STATE_MASK;
- /* and search for defined state */
- state_max = (sizeof(mqx_states)/sizeof(struct mqx_state));
- for (state_index = 0; (state_index < state_max); state_index++) {
- if (mqx_states[state_index].state == task_state) {
- state_name = mqx_states[state_index].name;
- break;
- }
- }
-
- /* setup thread details struct */
- rtos->thread_details[i].threadid = task_id;
- rtos->thread_details[i].exists = true;
- /* set thread name */
- rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1);
- if (NULL == rtos->thread_details[i].thread_name_str)
- return ERROR_FAIL;
- strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name);
- /* set thread extra info
- * - task state
- * - task address
- * - task errno
- * calculate length as:
- * state length + address length + errno length + formatter length
- */
- extra_info_length += strlen((void *)state_name) + 8 + 8 + 8;
- rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1);
- if (NULL == rtos->thread_details[i].extra_info_str)
- return ERROR_FAIL;
- snprintf(
- rtos->thread_details[i].extra_info_str, extra_info_length, "%s : 0x%"PRIx32 " : %" PRIu32,
- state_name, task_addr, task_errno
- );
- /* set active thread */
- if (active_td_addr == task_addr)
- rtos->current_thread = task_id;
- }
- return ERROR_OK;
-}
-
-/*
- * API function, get info of selected thread
- */
-static int mqx_get_thread_reg_list(
- struct rtos *rtos,
- int64_t thread_id,
- char **hex_reg_list
-)
-{
- int64_t stack_ptr = 0;
- uint32_t my_task_addr = 0;
- uint32_t task_queue_addr = 0;
- uint32_t task_queue_size = 0;
- uint32_t kernel_data_addr = 0;
-
- *hex_reg_list = NULL;
- if (thread_id == 0) {
- LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id);
- return ERROR_FAIL;
- }
- if (ERROR_OK != mqx_is_scheduler_running(rtos))
- return ERROR_FAIL;
- /* get kernel_data symbol */
- if (ERROR_OK != mqx_get_symbol(
- rtos, mqx_VAL_mqx_kernel_data, &kernel_data_addr
- )) {
- return ERROR_FAIL;
- }
- /* read kernel_data */
- if (ERROR_OK != mqx_get_member(
- rtos, kernel_data_addr, 0, 4, "_mqx_kernel_data", &kernel_data_addr
- )) {
- return ERROR_FAIL;
- }
- /* get task queue address */
- task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST;
- /* get task queue size */
- if (ERROR_OK != mqx_get_member(
- rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2,
- "kernel_data->TD_LIST.SIZE", &task_queue_size
- )) {
- return ERROR_FAIL;
- }
- /* search for taskid */
- for (
- uint32_t i = 0, taskpool_addr = task_queue_addr;
- i < (uint32_t)rtos->thread_count;
- i++
- ) {
- uint32_t tmp_address = 0, task_addr = 0;
- uint32_t task_id = 0;
- /* set current taskpool address */
- tmp_address = taskpool_addr;
- if (ERROR_OK != mqx_get_member(
- rtos, tmp_address, MQX_TASK_OFFSET_NEXT, 4,
- "td_struct_ptr->NEXT", &taskpool_addr
- )) {
- return ERROR_FAIL;
- }
- /* get task address from taskpool */
- task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST;
- /* get value of td_struct->TASK_ID */
- if (ERROR_OK != mqx_get_member(
- rtos, task_addr, MQX_TASK_OFFSET_ID, 4,
- "td_struct_ptr->TASK_ID", &task_id
- )) {
- return ERROR_FAIL;
- }
- /* found taskid, break */
- if (task_id == thread_id) {
- my_task_addr = task_addr;
- break;
- }
- }
- if (!my_task_addr) {
- LOG_ERROR("MQX_RTOS - threadid %" PRId64 " does not match any task", thread_id);
- return ERROR_FAIL;
- }
- /* get task stack head address */
- if (ERROR_OK != mqx_get_member(
- rtos, my_task_addr, MQX_TASK_OFFSET_STACK, 4, "task->STACK_PTR", &stack_ptr
- )) {
- return ERROR_FAIL;
- }
- return rtos_generic_stack_read(
- rtos->target, ((struct mqx_params *)rtos->rtos_specific_params)->stacking_info, stack_ptr, hex_reg_list
- );
-}
-
-/* API function, export list of required symbols */
-static int mqx_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- *symbol_list = calloc(ARRAY_SIZE(mqx_symbol_list), sizeof(symbol_table_elem_t));
- if (NULL == *symbol_list)
- return ERROR_FAIL;
- /* export required symbols */
- for (int i = 0; i < (int)(ARRAY_SIZE(mqx_symbol_list)); i++)
- (*symbol_list)[i].symbol_name = mqx_symbol_list[i];
- return ERROR_OK;
-}
-
-struct rtos_type mqx_rtos = {
- .name = "mqx",
- .detect_rtos = mqx_detect_rtos,
- .create = mqx_create,
- .update_threads = mqx_update_threads,
- .get_thread_reg_list = mqx_get_thread_reg_list,
- .get_symbol_list_to_lookup = mqx_get_symbol_list_to_lookup,
-};
diff --git a/src/rtos/riscv_debug.c b/src/rtos/riscv_debug.c
deleted file mode 100644
index 181d471..0000000
--- a/src/rtos/riscv_debug.c
+++ /dev/null
@@ -1,280 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "riscv_debug.h"
-#include "target/target.h"
-#include "target/riscv/riscv.h"
-#include "rtos.h"
-#include "server/gdb_server.h"
-
-static int riscv_update_threads(struct rtos *rtos);
-static int riscv_gdb_thread_packet(struct connection *connection, const char *packet, int packet_size);
-
-static int riscv_detect_rtos(struct target *target)
-{
- LOG_ERROR("riscv_detect_rtos() unimplemented");
- return -1;
-}
-
-static int riscv_create_rtos(struct target *target)
-{
- LOG_DEBUG("RISC-V Debug 'RTOS' created: this doesn't meat you're running an RTOS, just that you have multi-hart support on RISC-V");
-
- struct riscv_rtos *r = calloc(1, sizeof(*r));
- target->rtos->rtos_specific_params = r;
-#if 0
- r->target_hartid = 0;
- r->target_any_hart = true;
- r->target_every_hart = true;
-#endif
-
- target->rtos->current_threadid = 1;
- target->rtos->current_thread = 1;
- riscv_update_threads(target->rtos);
-
- target->rtos->gdb_thread_packet = riscv_gdb_thread_packet;
-
- return JIM_OK;
-}
-
-static int riscv_update_threads(struct rtos *rtos)
-{
- LOG_DEBUG("Updating the RISC-V Hart List");
-
- /* Figures out how many harts there are on the system. */
- int hart_count = riscv_count_harts(rtos->target);
- if (rtos->thread_count != hart_count) {
- rtos_free_threadlist(rtos);
- rtos->thread_count = hart_count;
- rtos->thread_details = calloc(rtos->thread_count, sizeof(*rtos->thread_details));
- for (int i = 0; i < rtos->thread_count; ++i) {
- LOG_DEBUG(" Setting up Hart %d", i);
- rtos->thread_details[i].threadid = i + 1;
- rtos->thread_details[i].exists = true;
- if (asprintf(&rtos->thread_details[i].thread_name_str, "Hart %d", i) < 0)
- LOG_ERROR("riscv_update_threads() failed asprintf");
- if (asprintf(&rtos->thread_details[i].extra_info_str, "RV64") < 0)
- LOG_ERROR("riscv_update_threads() failed asprintf");
- }
- }
- return JIM_OK;
-}
-
-static int riscv_gdb_thread_packet(struct connection *connection, const char *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- struct rtos *rtos = target->rtos;
- struct riscv_rtos *r = (struct riscv_rtos *)(target->rtos->rtos_specific_params);
-
- char *packet_stttrr = malloc(packet_size + 1);
- memset(packet_stttrr, '\0', packet_size + 1);
- memcpy(packet_stttrr, packet, packet_size);
- LOG_DEBUG("riscv_gdb_thread_packet(%s)", packet_stttrr);
-
- switch (packet[0]) {
- case 'q':
- if (strncmp(packet, "qfThreadInfo", 12) == 0) {
- riscv_update_threads(target->rtos);
- r->qs_thread_info_offset = 1;
-
- char m[16];
- snprintf(m, 16, "m%08x", (int)rtos->thread_details[0].threadid);
- gdb_put_packet(connection, m, strlen(m));
- return ERROR_OK;
- }
-
- if (strncmp(packet, "qsThreadInfo", 12) == 0) {
- if (r->qs_thread_info_offset >= rtos->thread_count) {
- gdb_put_packet(connection, "l", 1);
- return ERROR_OK;
- }
-
- int tid = r->qs_thread_info_offset++;
- char m[16];
- snprintf(m, 16, "m%08x", (int)rtos->thread_details[tid].threadid);
- gdb_put_packet(connection, m, strlen(m));
- return ERROR_OK;
- }
-
- if (strncmp(packet, "qAttached", 9) == 0) {
- gdb_put_packet(connection, "1", 1);
- return ERROR_OK;
- }
-
- if (strncmp(packet, "qThreadExtraInfo", 16) == 0) {
- char tid_str[32];
- memcpy(tid_str, packet + 17, packet_size - 17);
- tid_str[packet_size - 17] = '\0';
- char *end;
- int tid = strtol(tid_str, &end, 16);
- if (*end != '\0') {
- LOG_ERROR("Got qThreadExtraInfo with non-numeric TID: '%s'", tid_str);
- gdb_put_packet(connection, NULL, 0);
- return ERROR_FAIL;
- }
-
- char m[16];
- snprintf(m, 16, "hart %d", tid);
- char h[33];
- h[0] = '\0';
- for (size_t i = 0; i < strlen(m); ++i) {
- char byte[3];
- snprintf(byte, 3, "%02x", m[i]);
- strncat(h, byte, 32);
- }
- gdb_put_packet(connection, h, strlen(h));
- return ERROR_OK;
- }
-
- return GDB_THREAD_PACKET_NOT_CONSUMED;
-
- case 'Q':
- return GDB_THREAD_PACKET_NOT_CONSUMED;
-
- case 'H':
- /* ‘H op thread-id’
- *
- * Set thread for subsequent operations (‘m’, ‘M’, ‘g’, ‘G’,
- * et.al.). Depending on the operation to be performed, op
- * should be ‘c’ for step and continue operations (note that
- * this is deprecated, supporting the ‘vCont’ command is a
- * better option), and ‘g’ for other operations. The thread
- * designator thread-id has the format and interpretation
- * described in thread-id syntax.
- *
- * Reply:
- * ‘OK’ for success
- * ‘E NN’ for an error
- */
- {
- char tid_str[32];
- memcpy(tid_str, packet + 2, packet_size - 2);
- tid_str[packet_size - 2] = '\0';
- char *entptr;
- int tid = strtol(tid_str, &entptr, 16);
- if (*entptr != '\0') {
- LOG_ERROR("Got H packet, but without integer: %s", tid_str);
- return GDB_THREAD_PACKET_NOT_CONSUMED;
- }
-
- riscv_enable_rtos(target);
- switch (tid) {
- case 0:
- case -1:
- riscv_set_all_rtos_harts(target);
- break;
- default:
- riscv_set_rtos_hartid(target, tid - 1);
- break;
- }
-
- switch (packet[1]) {
- case 'g':
- case 'c':
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- default:
- LOG_ERROR("Unknown H packet subtype %2x\n", packet[1]);
- gdb_put_packet(connection, NULL, 0);
- return ERROR_FAIL;
- }
- }
-
- case 'T':
- {
- char tid_str[32];
- memcpy(tid_str, packet + 1, packet_size - 1);
- tid_str[packet_size - 1] = '\0';
- char *end;
- int tid = strtol(tid_str, &end, 16);
- if (*end != '\0') {
- LOG_ERROR("T packet with non-numeric tid %s", tid_str);
- gdb_put_packet(connection, NULL, 0);
- return ERROR_FAIL;
- }
-
- riscv_enable_rtos(target);
- riscv_update_threads(target->rtos);
- if (tid <= target->rtos->thread_count) {
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- } else {
- gdb_put_packet(connection, "E00", 3);
- return ERROR_OK;
- }
- }
-
-
- case 'c':
- case 's':
- target->state = TARGET_HALTED;
- return JIM_OK;
-
- case 'R':
- {
- char *packet_str = malloc(packet_size + 1);
- memset(packet_str, '\0', packet_size + 1);
- memcpy(packet_str, packet, packet_size);
- LOG_WARNING("riscv_gdb_thread_packet(%s): unimplemented", packet_str);
- gdb_put_packet(connection, NULL, 0);
- return JIM_OK;
- }
- default:
- LOG_ERROR("Unknown packet of type 0x%2.2x", packet[0]);
- gdb_put_packet(connection, NULL, 0);
- return JIM_OK;
- }
-}
-
-static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
-{
- LOG_DEBUG("Updating RISC-V regiser list for hart %d", (int)(thread_id - 1));
-
-#if 0
- LOG_ERROR(" Not actually updating");
- *hex_reg_list = 0;
- return JIM_OK;
-#endif
-
- size_t n_regs = 32;
- size_t xlen = 64;
- size_t reg_chars = xlen / 8 * 2;
-
- ssize_t hex_reg_list_length = n_regs * reg_chars + 2;
- *hex_reg_list = malloc(hex_reg_list_length);
- *hex_reg_list[0] = '\0';
- for (size_t i = 0; i < n_regs; ++i) {
- if (riscv_has_register(rtos->target, thread_id, i)) {
- uint64_t reg_value = riscv_get_register(rtos->target, thread_id - 1, i);
- for (size_t byte = 0; byte < xlen / 8; ++byte) {
- uint8_t reg_byte = reg_value >> (byte * 8);
- char hex[3];
- snprintf(hex, 3, "%02x", reg_byte);
- strncat(*hex_reg_list, hex, hex_reg_list_length);
- }
- } else {
- for (size_t byte = 0; byte < xlen / 8; ++byte)
- strncat(*hex_reg_list, "xx", hex_reg_list_length);
- }
- }
- return JIM_OK;
-}
-
-static int riscv_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
-{
- *symbol_list = calloc(1, sizeof(symbol_table_elem_t));
- (*symbol_list)[0].symbol_name = NULL;
- (*symbol_list)[0].optional = false;
- return JIM_OK;
-}
-
-const struct rtos_type riscv_rtos =
-{
- .name = "riscv",
- .detect_rtos = riscv_detect_rtos,
- .create = riscv_create_rtos,
- .update_threads = riscv_update_threads,
- .get_thread_reg_list = riscv_get_thread_reg_list,
- .get_symbol_list_to_lookup = riscv_get_symbol_list_to_lookup,
-};
diff --git a/src/rtos/riscv_debug.h b/src/rtos/riscv_debug.h
deleted file mode 100644
index bcc7411..0000000
--- a/src/rtos/riscv_debug.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef RTOS__RISCV_H
-#define RTOS__RISCV_H
-
-struct riscv_rtos {
- /* The index into the thread list used to handle */
- int qs_thread_info_offset;
-};
-
-#endif
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
deleted file mode 100644
index 76443b6..0000000
--- a/src/rtos/rtos.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-#include "target/target.h"
-#include "helper/log.h"
-#include "helper/binarybuffer.h"
-#include "server/gdb_server.h"
-
-/* RTOSs */
-extern struct rtos_type FreeRTOS_rtos;
-extern struct rtos_type ThreadX_rtos;
-extern struct rtos_type eCos_rtos;
-extern struct rtos_type Linux_os;
-extern struct rtos_type ChibiOS_rtos;
-extern struct rtos_type embKernel_rtos;
-extern struct rtos_type mqx_rtos;
-extern struct rtos_type riscv_rtos;
-
-static struct rtos_type *rtos_types[] = {
- &ThreadX_rtos,
- &FreeRTOS_rtos,
- &eCos_rtos,
- &Linux_os,
- &ChibiOS_rtos,
- &embKernel_rtos,
- &mqx_rtos,
- &riscv_rtos,
- NULL
-};
-
-int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
-
-int rtos_smp_init(struct target *target)
-{
- if (target->rtos->type->smp_init)
- return target->rtos->type->smp_init(target);
- return ERROR_TARGET_INIT_FAILED;
-}
-
-static int os_alloc(struct target *target, struct rtos_type *ostype)
-{
- struct rtos *os = target->rtos = calloc(1, sizeof(struct rtos));
-
- if (!os)
- return JIM_ERR;
-
- os->type = ostype;
- os->current_threadid = -1;
- os->current_thread = 0;
- os->symbols = NULL;
- os->target = target;
-
- /* RTOS drivers can override the packet handler in _create(). */
- os->gdb_thread_packet = rtos_thread_packet;
-
- return JIM_OK;
-}
-
-static void os_free(struct target *target)
-{
- if (!target->rtos)
- return;
-
- if (target->rtos->symbols)
- free(target->rtos->symbols);
-
- free(target->rtos);
- target->rtos = NULL;
-}
-
-static int os_alloc_create(struct target *target, struct rtos_type *ostype)
-{
- int ret = os_alloc(target, ostype);
-
- if (JIM_OK == ret) {
- ret = target->rtos->type->create(target);
- if (ret != JIM_OK)
- os_free(target);
- }
-
- return ret;
-}
-
-int rtos_create(Jim_GetOptInfo *goi, struct target *target)
-{
- int x;
- const char *cp;
- struct Jim_Obj *res;
-
- if (!goi->isconfigure && goi->argc != 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
- return JIM_ERR;
- }
-
- os_free(target);
-
- Jim_GetOpt_String(goi, &cp, NULL);
-
- if (0 == strcmp(cp, "auto")) {
- /* Auto detect tries to look up all symbols for each RTOS,
- * and runs the RTOS driver's _detect() function when GDB
- * finds all symbols for any RTOS. See rtos_qsymbol(). */
- target->rtos_auto_detect = true;
-
- /* rtos_qsymbol() will iterate over all RTOSes. Allocate
- * target->rtos here, and set it to the first RTOS type. */
- return os_alloc(target, rtos_types[0]);
- }
-
- for (x = 0; rtos_types[x]; x++)
- if (0 == strcmp(cp, rtos_types[x]->name))
- return os_alloc_create(target, rtos_types[x]);
-
- Jim_SetResultFormatted(goi->interp, "Unknown RTOS type %s, try one of: ", cp);
- res = Jim_GetResult(goi->interp);
- for (x = 0; rtos_types[x]; x++)
- Jim_AppendStrings(goi->interp, res, rtos_types[x]->name, ", ", NULL);
- Jim_AppendStrings(goi->interp, res, " or auto", NULL);
-
- return JIM_ERR;
-}
-
-int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- if (target->rtos == NULL)
- return rtos_thread_packet(connection, packet, packet_size); /* thread not
- *found*/
- return target->rtos->gdb_thread_packet(connection, packet, packet_size);
-}
-
-static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
-{
- symbol_table_elem_t *s;
-
- if (!os->symbols)
- os->type->get_symbol_list_to_lookup(&os->symbols);
-
- if (!cur_symbol[0])
- return &os->symbols[0];
-
- for (s = os->symbols; s->symbol_name; s++)
- if (!strcmp(s->symbol_name, cur_symbol)) {
- s->address = cur_addr;
- s++;
- return s;
- }
-
- return NULL;
-}
-
-/* searches for 'symbol' in the lookup table for 'os' and returns TRUE,
- * if 'symbol' is not declared optional */
-static bool is_symbol_mandatory(const struct rtos *os, const char *symbol)
-{
- for (symbol_table_elem_t *s = os->symbols; s->symbol_name; ++s) {
- if (!strcmp(s->symbol_name, symbol))
- return !s->optional;
- }
- return false;
-}
-
-/* rtos_qsymbol() processes and replies to all qSymbol packets from GDB.
- *
- * GDB sends a qSymbol:: packet (empty address, empty name) to notify
- * that it can now answer qSymbol::hexcodedname queries, to look up symbols.
- *
- * If the qSymbol packet has no address that means GDB did not find the
- * symbol, in which case auto-detect will move on to try the next RTOS.
- *
- * rtos_qsymbol() then calls the next_symbol() helper function, which
- * iterates over symbol names for the current RTOS until it finds the
- * symbol in the received GDB packet, and then returns the next entry
- * in the list of symbols.
- *
- * If GDB replied about the last symbol for the RTOS and the RTOS was
- * specified explicitly, then no further symbol lookup is done. When
- * auto-detecting, the RTOS driver _detect() function must return success.
- *
- * rtos_qsymbol() returns 1 if an RTOS has been detected, or 0 otherwise.
- */
-int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size)
-{
- int rtos_detected = 0;
- uint64_t addr = 0;
- size_t reply_len;
- char reply[GDB_BUFFER_SIZE], cur_sym[GDB_BUFFER_SIZE / 2] = "";
- symbol_table_elem_t *next_sym = NULL;
- struct target *target = get_target_from_connection(connection);
- struct rtos *os = target->rtos;
-
- reply_len = sprintf(reply, "OK");
-
- if (!os)
- goto done;
-
- /* Decode any symbol name in the packet*/
- int len = unhexify(cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1));
- cur_sym[len] = 0;
-
- if ((strcmp(packet, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */
- (!sscanf(packet, "qSymbol:%" SCNx64 ":", &addr)) && /* GDB did not find an address for a symbol */
- is_symbol_mandatory(os, cur_sym)) { /* the symbol is mandatory for this RTOS */
-
- /* GDB could not find an address for the previous symbol */
- if (!target->rtos_auto_detect) {
- LOG_WARNING("RTOS %s not detected. (GDB could not find symbol \'%s\')", os->type->name, cur_sym);
- goto done;
- } else {
- /* Autodetecting RTOS - try next RTOS */
- if (!rtos_try_next(target)) {
- LOG_WARNING("No RTOS could be auto-detected!");
- goto done;
- }
-
- /* Next RTOS selected - invalidate current symbol */
- cur_sym[0] = '\x00';
- }
- }
- next_sym = next_symbol(os, cur_sym, addr);
-
- if (!next_sym->symbol_name) {
- /* No more symbols need looking up */
-
- if (!target->rtos_auto_detect) {
- rtos_detected = 1;
- goto done;
- }
-
- if (os->type->detect_rtos(target)) {
- LOG_INFO("Auto-detected RTOS: %s", os->type->name);
- rtos_detected = 1;
- goto done;
- } else {
- LOG_WARNING("No RTOS could be auto-detected!");
- goto done;
- }
- }
-
- if (8 + (strlen(next_sym->symbol_name) * 2) + 1 > sizeof(reply)) {
- LOG_ERROR("ERROR: RTOS symbol '%s' name is too long for GDB!", next_sym->symbol_name);
- goto done;
- }
-
- reply_len = snprintf(reply, sizeof(reply), "qSymbol:");
- reply_len += hexify(reply + reply_len, next_sym->symbol_name, 0, sizeof(reply) - reply_len);
-
-done:
- gdb_put_packet(connection, reply, reply_len);
- return rtos_detected;
-}
-
-int rtos_thread_packet(struct connection *connection, char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
-
- if (strncmp(packet, "qThreadExtraInfo,", 17) == 0) {
- if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) &&
- (target->rtos->thread_count != 0)) {
- threadid_t threadid = 0;
- int found = -1;
- sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
-
- if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
- int thread_num;
- for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
- if (target->rtos->thread_details[thread_num].threadid == threadid) {
- if (target->rtos->thread_details[thread_num].exists)
- found = thread_num;
- }
- }
- }
- if (found == -1) {
- gdb_put_packet(connection, "E01", 3); /* thread not found */
- return ERROR_OK;
- }
-
- struct thread_detail *detail = &target->rtos->thread_details[found];
-
- int str_size = 0;
- if (detail->thread_name_str != NULL)
- str_size += strlen(detail->thread_name_str);
- if (detail->extra_info_str != NULL)
- str_size += strlen(detail->extra_info_str);
-
- char *tmp_str = calloc(str_size + 4, sizeof(char));
- char *tmp_str_ptr = tmp_str;
-
- if (detail->thread_name_str != NULL)
- tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str);
- if (detail->extra_info_str != NULL) {
- if (tmp_str_ptr != tmp_str)
- tmp_str_ptr += sprintf(tmp_str_ptr, " : ");
- tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->extra_info_str);
- }
-
- assert(strlen(tmp_str) ==
- (size_t) (tmp_str_ptr - tmp_str));
-
- char *hex_str = malloc(strlen(tmp_str) * 2 + 1);
- int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1);
-
- gdb_put_packet(connection, hex_str, pkt_len);
- free(hex_str);
- free(tmp_str);
- return ERROR_OK;
-
- }
- gdb_put_packet(connection, "", 0);
- return ERROR_OK;
- } else if (strncmp(packet, "qSymbol", 7) == 0) {
- if (rtos_qsymbol(connection, packet, packet_size) == 1) {
- target->rtos_auto_detect = false;
- target->rtos->type->create(target);
- target->rtos->type->update_threads(target->rtos);
- }
- return ERROR_OK;
- } else if (strncmp(packet, "qfThreadInfo", 12) == 0) {
- int i;
- if (target->rtos != NULL) {
- if (target->rtos->thread_count == 0) {
- gdb_put_packet(connection, "l", 1);
- } else {
- /*thread id are 16 char +1 for ',' */
- char *out_str = malloc(17 * target->rtos->thread_count + 1);
- char *tmp_str = out_str;
- for (i = 0; i < target->rtos->thread_count; i++) {
- tmp_str += sprintf(tmp_str, "%c%016" PRIx64, i == 0 ? 'm' : ',',
- target->rtos->thread_details[i].threadid);
- }
- gdb_put_packet(connection, out_str, strlen(out_str));
- free(out_str);
- }
- } else
- gdb_put_packet(connection, "l", 1);
-
- return ERROR_OK;
- } else if (strncmp(packet, "qsThreadInfo", 12) == 0) {
- gdb_put_packet(connection, "l", 1);
- return ERROR_OK;
- } else if (strncmp(packet, "qAttached", 9) == 0) {
- gdb_put_packet(connection, "1", 1);
- return ERROR_OK;
- } else if (strncmp(packet, "qOffsets", 8) == 0) {
- char offsets[] = "Text=0;Data=0;Bss=0";
- gdb_put_packet(connection, offsets, sizeof(offsets)-1);
- return ERROR_OK;
- } else if (strncmp(packet, "qCRC:", 5) == 0) {
- /* make sure we check this before "qC" packet below
- * otherwise it gets incorrectly handled */
- return GDB_THREAD_PACKET_NOT_CONSUMED;
- } else if (strncmp(packet, "qC", 2) == 0) {
- if (target->rtos != NULL) {
- char buffer[19];
- int size;
- size = snprintf(buffer, 19, "QC%016" PRIx64, target->rtos->current_thread);
- gdb_put_packet(connection, buffer, size);
- } else
- gdb_put_packet(connection, "QC0", 3);
- return ERROR_OK;
- } else if (packet[0] == 'T') { /* Is thread alive? */
- threadid_t threadid;
- int found = -1;
- sscanf(packet, "T%" SCNx64, &threadid);
- if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
- int thread_num;
- for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
- if (target->rtos->thread_details[thread_num].threadid == threadid) {
- if (target->rtos->thread_details[thread_num].exists)
- found = thread_num;
- }
- }
- }
- if (found != -1)
- gdb_put_packet(connection, "OK", 2); /* thread alive */
- else
- gdb_put_packet(connection, "E01", 3); /* thread not found */
- return ERROR_OK;
- } else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
- * all other operations ) */
- if ((packet[1] == 'g') && (target->rtos != NULL)) {
- sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid);
- LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64 "\r\n",
- target->rtos->current_threadid);
- }
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- }
-
- return GDB_THREAD_PACKET_NOT_CONSUMED;
-}
-
-int rtos_get_gdb_reg_list(struct connection *connection)
-{
- struct target *target = get_target_from_connection(connection);
- int64_t current_threadid = target->rtos->current_threadid;
- if ((target->rtos != NULL) && (current_threadid != -1) &&
- (current_threadid != 0) &&
- ((current_threadid != target->rtos->current_thread) ||
- (target->smp))) { /* in smp several current thread are possible */
- char *hex_reg_list;
-
- LOG_INFO("RTOS: getting register list for thread 0x%" PRIx64
- ", target->rtos->current_thread=0x%" PRIx64 "\r\n",
- current_threadid,
- target->rtos->current_thread);
-
- target->rtos->type->get_thread_reg_list(target->rtos,
- current_threadid,
- &hex_reg_list);
-
- if (hex_reg_list != NULL) {
- gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
- free(hex_reg_list);
- return ERROR_OK;
- }
- }
- return ERROR_FAIL;
-}
-
-int rtos_generic_stack_read(struct target *target,
- const struct rtos_register_stacking *stacking,
- int64_t stack_ptr,
- char **hex_reg_list)
-{
- int list_size = 0;
- char *tmp_str_ptr;
- int64_t new_stack_ptr;
- int i;
- int retval;
-
- if (stack_ptr == 0) {
- LOG_ERROR("Error: null stack pointer in thread");
- return -5;
- }
- /* Read the stack */
- uint8_t *stack_data = malloc(stacking->stack_registers_size);
- uint32_t address = stack_ptr;
-
- if (stacking->stack_growth_direction == 1)
- address -= stacking->stack_registers_size;
- retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data);
- if (retval != ERROR_OK) {
- free(stack_data);
- LOG_ERROR("Error reading stack frame from thread");
- return retval;
- }
- LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32, address);
-
-#if 0
- LOG_OUTPUT("Stack Data :");
- for (i = 0; i < stacking->stack_registers_size; i++)
- LOG_OUTPUT("%02X", stack_data[i]);
- LOG_OUTPUT("\r\n");
-#endif
- for (i = 0; i < stacking->num_output_registers; i++)
- list_size += stacking->register_offsets[i].width_bits/8;
- *hex_reg_list = malloc(list_size*2 + 1);
- tmp_str_ptr = *hex_reg_list;
- if (stacking->calculate_process_stack != NULL) {
- new_stack_ptr = stacking->calculate_process_stack(target,
- stack_data, stacking, stack_ptr);
- } else {
- new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
- stacking->stack_registers_size;
- }
- for (i = 0; i < stacking->num_output_registers; i++) {
- int j;
- for (j = 0; j < stacking->register_offsets[i].width_bits/8; j++) {
- if (stacking->register_offsets[i].offset == -1)
- tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", 0);
- else if (stacking->register_offsets[i].offset == -2)
- tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
- ((uint8_t *)&new_stack_ptr)[j]);
- else
- tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
- stack_data[stacking->register_offsets[i].offset + j]);
- }
- }
- free(stack_data);
-/* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
- return ERROR_OK;
-}
-
-int rtos_try_next(struct target *target)
-{
- struct rtos *os = target->rtos;
- struct rtos_type **type = rtos_types;
-
- if (!os)
- return 0;
-
- while (*type && os->type != *type)
- type++;
-
- if (!*type || !*(++type))
- return 0;
-
- os->type = *type;
- if (os->symbols) {
- free(os->symbols);
- os->symbols = NULL;
- }
-
- return 1;
-}
-
-int rtos_update_threads(struct target *target)
-{
- if ((target->rtos != NULL) && (target->rtos->type != NULL))
- target->rtos->type->update_threads(target->rtos);
- return ERROR_OK;
-}
-
-void rtos_free_threadlist(struct rtos *rtos)
-{
- if (rtos->thread_details) {
- int j;
-
- for (j = 0; j < rtos->thread_count; j++) {
- struct thread_detail *current_thread = &rtos->thread_details[j];
- free(current_thread->thread_name_str);
- free(current_thread->extra_info_str);
- }
- free(rtos->thread_details);
- rtos->thread_details = NULL;
- rtos->thread_count = 0;
- }
-}
diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h
deleted file mode 100644
index 70c1193..0000000
--- a/src/rtos/rtos.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_RTOS_RTOS_H
-#define OPENOCD_RTOS_RTOS_H
-
-#include "server/server.h"
-#include <jim-nvp.h>
-
-typedef int64_t threadid_t;
-typedef int64_t symbol_address_t;
-
-struct reg;
-
-/**
- * Table should be terminated by an element with NULL in symbol_name
- */
-typedef struct symbol_table_elem_struct {
- const char *symbol_name;
- symbol_address_t address;
- bool optional;
-} symbol_table_elem_t;
-
-struct thread_detail {
- threadid_t threadid;
- bool exists;
- char *thread_name_str;
- char *extra_info_str;
-};
-
-struct rtos {
- const struct rtos_type *type;
-
- symbol_table_elem_t *symbols;
- struct target *target;
- /* add a context variable instead of global variable */
- int64_t current_threadid;
- threadid_t current_thread;
- struct thread_detail *thread_details;
- int thread_count;
- int (*gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size);
- void *rtos_specific_params;
-};
-
-struct rtos_type {
- const char *name;
- int (*detect_rtos)(struct target *target);
- int (*create)(struct target *target);
- int (*smp_init)(struct target *target);
- int (*update_threads)(struct rtos *rtos);
- int (*get_thread_reg_list)(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
- int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]);
- int (*clean)(struct target *target);
- char * (*ps_command)(struct target *target);
-};
-
-struct stack_register_offset {
- signed short offset; /* offset in bytes from stack head, or -1 to indicate
- * register is not stacked, or -2 to indicate this is the
- * stack pointer register */
- unsigned short width_bits;
-};
-
-struct rtos_register_stacking {
- unsigned char stack_registers_size;
- signed char stack_growth_direction;
- unsigned char num_output_registers;
- /* Some targets require evaluating the stack to determine the
- * actual stack pointer for a process. If this field is NULL,
- * just use stacking->stack_registers_size * stack_growth_direction
- * to calculate adjustment.
- */
- int64_t (*calculate_process_stack)(struct target *target,
- const uint8_t *stack_data,
- const struct rtos_register_stacking *stacking,
- int64_t stack_ptr);
- const struct stack_register_offset *register_offsets;
-};
-
-#define GDB_THREAD_PACKET_NOT_CONSUMED (-40)
-
-int rtos_create(Jim_GetOptInfo *goi, struct target *target);
-int rtos_generic_stack_read(struct target *target,
- const struct rtos_register_stacking *stacking,
- int64_t stack_ptr,
- char **hex_reg_list);
-int rtos_try_next(struct target *target);
-int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size);
-int rtos_get_gdb_reg_list(struct connection *connection);
-int rtos_update_threads(struct target *target);
-void rtos_free_threadlist(struct rtos *rtos);
-int rtos_smp_init(struct target *target);
-/* function for handling symbol access */
-int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size);
-
-#endif /* OPENOCD_RTOS_RTOS_H */
diff --git a/src/rtos/rtos_chibios_stackings.c b/src/rtos/rtos_chibios_stackings.c
deleted file mode 100644
index 3651c49..0000000
--- a/src/rtos/rtos_chibios_stackings.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by Matthias Blaicher *
- * Matthias Blaicher - matthias@blaicher.com *
- * *
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-#include "target/armv7m.h"
-
-static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
- { -1, 32 }, /* r0 */
- { -1, 32 }, /* r1 */
- { -1, 32 }, /* r2 */
- { -1, 32 }, /* r3 */
- { 0x00, 32 }, /* r4 */
- { 0x04, 32 }, /* r5 */
- { 0x08, 32 }, /* r6 */
- { 0x0c, 32 }, /* r7 */
- { 0x10, 32 }, /* r8 */
- { 0x14, 32 }, /* r9 */
- { 0x18, 32 }, /* r10 */
- { 0x1c, 32 }, /* r11 */
- { -1, 32 }, /* r12 */
- { -2, 32 }, /* sp */
- { -1, 32 }, /* lr */
- { 0x20, 32 }, /* pc */
- { -1, 32 }, /* xPSR */
-};
-
-const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking = {
- 0x24, /* stack_registers_size */
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- NULL, /* stack_alignment */
- rtos_chibios_arm_v7m_stack_offsets /* register_offsets */
-};
-
-static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets_w_fpu[ARMV7M_NUM_CORE_REGS] = {
- { -1, 32 }, /* r0 */
- { -1, 32 }, /* r1 */
- { -1, 32 }, /* r2 */
- { -1, 32 }, /* r3 */
- { 0x40, 32 }, /* r4 */
- { 0x44, 32 }, /* r5 */
- { 0x48, 32 }, /* r6 */
- { 0x4c, 32 }, /* r7 */
- { 0x50, 32 }, /* r8 */
- { 0x54, 32 }, /* r9 */
- { 0x58, 32 }, /* r10 */
- { 0x5c, 32 }, /* r11 */
- { -1, 32 }, /* r12 */
- { -2, 32 }, /* sp */
- { -1, 32 }, /* lr */
- { 0x60, 32 }, /* pc */
- { -1, 32 }, /* xPSR */
-};
-
-const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking_w_fpu = {
- 0x64, /* stack_registers_size */
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- NULL, /* stack_alignment */
- rtos_chibios_arm_v7m_stack_offsets_w_fpu /* register_offsets */
-};
diff --git a/src/rtos/rtos_chibios_stackings.h b/src/rtos/rtos_chibios_stackings.h
deleted file mode 100644
index 130aaa1..0000000
--- a/src/rtos/rtos_chibios_stackings.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H
-#define OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-
-extern const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking;
-extern const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking_w_fpu;
-
-#endif /* OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H */
diff --git a/src/rtos/rtos_ecos_stackings.c b/src/rtos/rtos_ecos_stackings.c
deleted file mode 100644
index 43d97a6..0000000
--- a/src/rtos/rtos_ecos_stackings.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-#include "rtos_standard_stackings.h"
-#include "target/armv7m.h"
-
-static const struct stack_register_offset rtos_eCos_Cortex_M3_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
- { 0x0c, 32 }, /* r0 */
- { 0x10, 32 }, /* r1 */
- { 0x14, 32 }, /* r2 */
- { 0x18, 32 }, /* r3 */
- { 0x1c, 32 }, /* r4 */
- { 0x20, 32 }, /* r5 */
- { 0x24, 32 }, /* r6 */
- { 0x28, 32 }, /* r7 */
- { 0x2c, 32 }, /* r8 */
- { 0x30, 32 }, /* r9 */
- { 0x34, 32 }, /* r10 */
- { 0x38, 32 }, /* r11 */
- { 0x3c, 32 }, /* r12 */
- { -2, 32 }, /* sp */
- { -1, 32 }, /* lr */
- { 0x40, 32 }, /* pc */
- { -1, 32 }, /* xPSR */
-};
-
-const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking = {
- 0x44, /* stack_registers_size */
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- rtos_generic_stack_align8, /* stack_alignment */
- rtos_eCos_Cortex_M3_stack_offsets /* register_offsets */
-};
diff --git a/src/rtos/rtos_ecos_stackings.h b/src/rtos/rtos_ecos_stackings.h
deleted file mode 100644
index 951f7de..0000000
--- a/src/rtos/rtos_ecos_stackings.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H
-#define OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-
-extern const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking;
-
-#endif /* OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H */
diff --git a/src/rtos/rtos_embkernel_stackings.c b/src/rtos/rtos_embkernel_stackings.c
deleted file mode 100644
index 2a30629..0000000
--- a/src/rtos/rtos_embkernel_stackings.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-#include "target/armv7m.h"
-#include "rtos_standard_stackings.h"
-
-static const struct stack_register_offset rtos_embkernel_Cortex_M_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
- { 0x24, 32 }, /* r0 */
- { 0x28, 32 }, /* r1 */
- { 0x2c, 32 }, /* r2 */
- { 0x30, 32 }, /* r3 */
- { 0x00, 32 }, /* r4 */
- { 0x04, 32 }, /* r5 */
- { 0x08, 32 }, /* r6 */
- { 0x0c, 32 }, /* r7 */
- { 0x10, 32 }, /* r8 */
- { 0x14, 32 }, /* r9 */
- { 0x18, 32 }, /* r10 */
- { 0x1c, 32 }, /* r11 */
- { 0x34, 32 }, /* r12 */
- { -2, 32 }, /* sp */
- { 0x38, 32 }, /* lr */
- { 0x3c, 32 }, /* pc */
- { 0x40, 32 }, /* xPSR */
-};
-
-const struct rtos_register_stacking rtos_embkernel_Cortex_M_stacking = {
- 0x40, /* stack_registers_size */
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- rtos_generic_stack_align8, /* stack_alignment */
- rtos_embkernel_Cortex_M_stack_offsets /* register_offsets */
-};
-
-
diff --git a/src/rtos/rtos_embkernel_stackings.h b/src/rtos/rtos_embkernel_stackings.h
deleted file mode 100644
index 89a0c2f..0000000
--- a/src/rtos/rtos_embkernel_stackings.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H
-#define OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-
-extern const struct rtos_register_stacking rtos_embkernel_Cortex_M_stacking;
-
-#endif /* OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H */
diff --git a/src/rtos/rtos_mqx_stackings.c b/src/rtos/rtos_mqx_stackings.c
deleted file mode 100644
index 5db2f8e..0000000
--- a/src/rtos/rtos_mqx_stackings.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2014 by Marian Cingel *
- * cingel.marian@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-#include "target/armv7m.h"
-
-
-/*
- * standard exception stack
- * ( stack base, higher memory address )
- * - xpsr - 0x48
- * - pc - 0x44
- * - lr - 0x40
- * - r12 - 0x3C
- * - r3 - 0x38
- * - r2 - 0x34
- * - r1 - 0x30
- * - r0 - 0x2C
- * extended stack in svc_pending handler
- * - lr - 0x28
- * - r11 - 0x24
- * - r10 - 0x20
- * - r9 - 0x1C
- * - r8 - 0x18
- * - r7 - 0x14
- * - r6 - 0x10
- * - r5 - 0x0C
- * - r4 - 0x08
- * - BASEPRI - 0x04
- * - SHPR3 - 0x00 ( contains pend_svc exception priority )
- * ( stack head, lower address, stored in 'task->STACK_PTR' )
- */
-
-static const struct stack_register_offset rtos_mqx_arm_v7m_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
- { 0x2C, 32 }, /* r0 */
- { 0x30, 32 }, /* r1 */
- { 0x34, 32 }, /* r2 */
- { 0x38, 32 }, /* r3 */
- { 0x08, 32 }, /* r4 */
- { 0x0C, 32 }, /* r5 */
- { 0x10, 32 }, /* r6 */
- { 0x14, 32 }, /* r7 */
- { 0x18, 32 }, /* r8 */
- { 0x1C, 32 }, /* r9 */
- { 0x20, 32 }, /* r10 */
- { 0x24, 32 }, /* r11 */
- { 0x3C, 32 }, /* r12 */
- { -2 , 32 }, /* sp */
- { 0x28, 32 }, /* lr */
- { 0x44, 32 }, /* pc */
- { 0x48, 32 }, /* xPSR */
-};
-
-const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking = {
- 0x4C, /* stack_registers_size, calculate offset base address */
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- NULL, /* stack_alignment */
- rtos_mqx_arm_v7m_stack_offsets /* register_offsets */
-};
-
diff --git a/src/rtos/rtos_mqx_stackings.h b/src/rtos/rtos_mqx_stackings.h
deleted file mode 100644
index 6ebd287..0000000
--- a/src/rtos/rtos_mqx_stackings.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2014 by Marian Cingel *
- * cingel.marian@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_RTOS_RTOS_MQX_STACKINGS_H
-#define OPENOCD_RTOS_RTOS_MQX_STACKINGS_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-
-extern const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking;
-
-#endif /* OPENOCD_RTOS_RTOS_MQX_STACKINGS_H */
diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c
deleted file mode 100644
index 0176c01..0000000
--- a/src/rtos/rtos_standard_stackings.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-#include "target/armv7m.h"
-
-static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
- { 0x20, 32 }, /* r0 */
- { 0x24, 32 }, /* r1 */
- { 0x28, 32 }, /* r2 */
- { 0x2c, 32 }, /* r3 */
- { 0x00, 32 }, /* r4 */
- { 0x04, 32 }, /* r5 */
- { 0x08, 32 }, /* r6 */
- { 0x0c, 32 }, /* r7 */
- { 0x10, 32 }, /* r8 */
- { 0x14, 32 }, /* r9 */
- { 0x18, 32 }, /* r10 */
- { 0x1c, 32 }, /* r11 */
- { 0x30, 32 }, /* r12 */
- { -2, 32 }, /* sp */
- { 0x34, 32 }, /* lr */
- { 0x38, 32 }, /* pc */
- { 0x3c, 32 }, /* xPSR */
-};
-
-static const struct stack_register_offset rtos_standard_Cortex_M4F_stack_offsets[] = {
- { 0x24, 32 }, /* r0 */
- { 0x28, 32 }, /* r1 */
- { 0x2c, 32 }, /* r2 */
- { 0x30, 32 }, /* r3 */
- { 0x00, 32 }, /* r4 */
- { 0x04, 32 }, /* r5 */
- { 0x08, 32 }, /* r6 */
- { 0x0c, 32 }, /* r7 */
- { 0x10, 32 }, /* r8 */
- { 0x14, 32 }, /* r9 */
- { 0x18, 32 }, /* r10 */
- { 0x1c, 32 }, /* r11 */
- { 0x34, 32 }, /* r12 */
- { -2, 32 }, /* sp */
- { 0x38, 32 }, /* lr */
- { 0x3c, 32 }, /* pc */
- { 0x40, 32 }, /* xPSR */
-};
-
-static const struct stack_register_offset rtos_standard_Cortex_M4F_FPU_stack_offsets[] = {
- { 0x64, 32 }, /* r0 */
- { 0x68, 32 }, /* r1 */
- { 0x6c, 32 }, /* r2 */
- { 0x70, 32 }, /* r3 */
- { 0x00, 32 }, /* r4 */
- { 0x04, 32 }, /* r5 */
- { 0x08, 32 }, /* r6 */
- { 0x0c, 32 }, /* r7 */
- { 0x10, 32 }, /* r8 */
- { 0x14, 32 }, /* r9 */
- { 0x18, 32 }, /* r10 */
- { 0x1c, 32 }, /* r11 */
- { 0x74, 32 }, /* r12 */
- { -2, 32 }, /* sp */
- { 0x78, 32 }, /* lr */
- { 0x7c, 32 }, /* pc */
- { 0x80, 32 }, /* xPSR */
-};
-
-
-static const struct stack_register_offset rtos_standard_Cortex_R4_stack_offsets[] = {
- { 0x08, 32 }, /* r0 (a1) */
- { 0x0c, 32 }, /* r1 (a2) */
- { 0x10, 32 }, /* r2 (a3) */
- { 0x14, 32 }, /* r3 (a4) */
- { 0x18, 32 }, /* r4 (v1) */
- { 0x1c, 32 }, /* r5 (v2) */
- { 0x20, 32 }, /* r6 (v3) */
- { 0x24, 32 }, /* r7 (v4) */
- { 0x28, 32 }, /* r8 (a1) */
- { 0x2c, 32 }, /* r9 (sb) */
- { 0x30, 32 }, /* r10 (sl) */
- { 0x34, 32 }, /* r11 (fp) */
- { 0x38, 32 }, /* r12 (ip) */
- { -2, 32 }, /* sp */
- { 0x3c, 32 }, /* lr */
- { 0x40, 32 }, /* pc */
- { -1, 96 }, /* FPA1 */
- { -1, 96 }, /* FPA2 */
- { -1, 96 }, /* FPA3 */
- { -1, 96 }, /* FPA4 */
- { -1, 96 }, /* FPA5 */
- { -1, 96 }, /* FPA6 */
- { -1, 96 }, /* FPA7 */
- { -1, 96 }, /* FPA8 */
- { -1, 32 }, /* FPS */
- { 0x04, 32 }, /* CSPR */
-};
-
-static const struct stack_register_offset rtos_standard_NDS32_N1068_stack_offsets[] = {
- { 0x88, 32 }, /* R0 */
- { 0x8C, 32 }, /* R1 */
- { 0x14, 32 }, /* R2 */
- { 0x18, 32 }, /* R3 */
- { 0x1C, 32 }, /* R4 */
- { 0x20, 32 }, /* R5 */
- { 0x24, 32 }, /* R6 */
- { 0x28, 32 }, /* R7 */
- { 0x2C, 32 }, /* R8 */
- { 0x30, 32 }, /* R9 */
- { 0x34, 32 }, /* R10 */
- { 0x38, 32 }, /* R11 */
- { 0x3C, 32 }, /* R12 */
- { 0x40, 32 }, /* R13 */
- { 0x44, 32 }, /* R14 */
- { 0x48, 32 }, /* R15 */
- { 0x4C, 32 }, /* R16 */
- { 0x50, 32 }, /* R17 */
- { 0x54, 32 }, /* R18 */
- { 0x58, 32 }, /* R19 */
- { 0x5C, 32 }, /* R20 */
- { 0x60, 32 }, /* R21 */
- { 0x64, 32 }, /* R22 */
- { 0x68, 32 }, /* R23 */
- { 0x6C, 32 }, /* R24 */
- { 0x70, 32 }, /* R25 */
- { 0x74, 32 }, /* R26 */
- { 0x78, 32 }, /* R27 */
- { 0x7C, 32 }, /* R28 */
- { 0x80, 32 }, /* R29 */
- { 0x84, 32 }, /* R30 (LP) */
- { 0x00, 32 }, /* R31 (SP) */
- { 0x04, 32 }, /* PSW */
- { 0x08, 32 }, /* IPC */
- { 0x0C, 32 }, /* IPSW */
- { 0x10, 32 }, /* IFC_LP */
-};
-
-static int64_t rtos_generic_stack_align(struct target *target,
- const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
- int64_t stack_ptr, int align)
-{
- int64_t new_stack_ptr;
- int64_t aligned_stack_ptr;
- new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
- stacking->stack_registers_size;
- aligned_stack_ptr = new_stack_ptr & ~((int64_t)align - 1);
- if (aligned_stack_ptr != new_stack_ptr &&
- stacking->stack_growth_direction == -1) {
- /* If we have a downward growing stack, the simple alignment code
- * above results in a wrong result (since it rounds down to nearest
- * alignment). We want to round up so add an extra align.
- */
- aligned_stack_ptr += (int64_t)align;
- }
- return aligned_stack_ptr;
-}
-
-int64_t rtos_generic_stack_align8(struct target *target,
- const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
- int64_t stack_ptr)
-{
- return rtos_generic_stack_align(target, stack_data,
- stacking, stack_ptr, 8);
-}
-
-/* The Cortex-M3 will indicate that an alignment adjustment
- * has been done on the stack by setting bit 9 of the stacked xPSR
- * register. In this case, we can just add an extra 4 bytes to get
- * to the program stack. Note that some places in the ARM documentation
- * make this a little unclear but the padding takes place before the
- * normal exception stacking - so xPSR is always available at a fixed
- * location.
- *
- * Relevant documentation:
- * Cortex-M series processors -> Cortex-M3 -> Revision: xxx ->
- * Cortex-M3 Devices Generic User Guide -> The Cortex-M3 Processor ->
- * Exception Model -> Exception entry and return -> Exception entry
- * Cortex-M series processors -> Cortex-M3 -> Revision: xxx ->
- * Cortex-M3 Devices Generic User Guide -> Cortex-M3 Peripherals ->
- * System control block -> Configuration and Control Register (STKALIGN)
- *
- * This is just a helper function for use in the calculate_process_stack
- * function for a given architecture/rtos.
- */
-int64_t rtos_Cortex_M_stack_align(struct target *target,
- const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
- int64_t stack_ptr, size_t xpsr_offset)
-{
- const uint32_t ALIGN_NEEDED = (1 << 9);
- uint32_t xpsr;
- int64_t new_stack_ptr;
-
- new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
- stacking->stack_registers_size;
- xpsr = (target->endianness == TARGET_LITTLE_ENDIAN) ?
- le_to_h_u32(&stack_data[xpsr_offset]) :
- be_to_h_u32(&stack_data[xpsr_offset]);
- if ((xpsr & ALIGN_NEEDED) != 0) {
- LOG_DEBUG("XPSR(0x%08" PRIx32 ") indicated stack alignment was necessary\r\n",
- xpsr);
- new_stack_ptr -= (stacking->stack_growth_direction * 4);
- }
- return new_stack_ptr;
-}
-
-static int64_t rtos_standard_Cortex_M3_stack_align(struct target *target,
- const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
- int64_t stack_ptr)
-{
- const int XPSR_OFFSET = 0x3c;
- return rtos_Cortex_M_stack_align(target, stack_data, stacking,
- stack_ptr, XPSR_OFFSET);
-}
-
-const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking = {
- 0x40, /* stack_registers_size */
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- rtos_standard_Cortex_M3_stack_align, /* stack_alignment */
- rtos_standard_Cortex_M3_stack_offsets /* register_offsets */
-};
-
-const struct rtos_register_stacking rtos_standard_Cortex_M4F_stacking = {
- 0x44, /* stack_registers_size 4 more for LR*/
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- rtos_standard_Cortex_M3_stack_align, /* stack_alignment */
- rtos_standard_Cortex_M4F_stack_offsets /* register_offsets */
-};
-
-const struct rtos_register_stacking rtos_standard_Cortex_M4F_FPU_stacking = {
- 0xcc, /* stack_registers_size 4 more for LR + 48 more for FPU S0-S15 register*/
- -1, /* stack_growth_direction */
- ARMV7M_NUM_CORE_REGS, /* num_output_registers */
- rtos_standard_Cortex_M3_stack_align, /* stack_alignment */
- rtos_standard_Cortex_M4F_FPU_stack_offsets /* register_offsets */
-};
-
-const struct rtos_register_stacking rtos_standard_Cortex_R4_stacking = {
- 0x48, /* stack_registers_size */
- -1, /* stack_growth_direction */
- 26, /* num_output_registers */
- rtos_generic_stack_align8, /* stack_alignment */
- rtos_standard_Cortex_R4_stack_offsets /* register_offsets */
-};
-
-const struct rtos_register_stacking rtos_standard_NDS32_N1068_stacking = {
- 0x90, /* stack_registers_size */
- -1, /* stack_growth_direction */
- 32, /* num_output_registers */
- rtos_generic_stack_align8, /* stack_alignment */
- rtos_standard_NDS32_N1068_stack_offsets /* register_offsets */
-};
diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h
deleted file mode 100644
index 6971efd..0000000
--- a/src/rtos/rtos_standard_stackings.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H
-#define OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rtos.h"
-
-extern const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking;
-extern const struct rtos_register_stacking rtos_standard_Cortex_M4F_stacking;
-extern const struct rtos_register_stacking rtos_standard_Cortex_M4F_FPU_stacking;
-extern const struct rtos_register_stacking rtos_standard_Cortex_R4_stacking;
-extern const struct rtos_register_stacking rtos_standard_NDS32_N1068_stacking;
-int64_t rtos_generic_stack_align8(struct target *target,
- const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
- int64_t stack_ptr);
-int64_t rtos_Cortex_M_stack_align(struct target *target,
- const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
- int64_t stack_ptr, size_t xpsr_offset);
-
-#endif /* OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H */
diff --git a/src/server/Makefile.am b/src/server/Makefile.am
deleted file mode 100644
index 04d3035..0000000
--- a/src/server/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-include $(top_srcdir)/common.mk
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libserver.la
-noinst_HEADERS = server.h telnet_server.h gdb_server.h
-libserver_la_SOURCES = server.c telnet_server.c gdb_server.c
-
-libserver_la_SOURCES += server_stubs.c
-
-libserver_la_CFLAGS =
-if IS_MINGW
-# FD_* macros are sloppy with their signs on MinGW32 platform
-libserver_la_CFLAGS += -Wno-sign-compare
-endif
-
-# tcl server addons
-noinst_HEADERS += tcl_server.h
-libserver_la_SOURCES += tcl_server.c
-
-EXTRA_DIST = \
- startup.tcl
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
deleted file mode 100644
index 2387496..0000000
--- a/src/server/gdb_server.c
+++ /dev/null
@@ -1,3197 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * Copyright (C) ST-Ericsson SA 2011 *
- * michel.jaouen@stericsson.com : smp minimum support *
- * *
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * Copyright (C) 2013 Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <target/breakpoints.h>
-#include <target/target_request.h>
-#include <target/register.h>
-#include "server.h"
-#include <flash/nor/core.h>
-#include "gdb_server.h"
-#include <target/image.h>
-#include <jtag/jtag.h>
-#include "rtos/rtos.h"
-#include "target/smp.h"
-
-/**
- * @file
- * GDB server implementation.
- *
- * This implements the GDB Remote Serial Protocol, over TCP connections,
- * giving GDB access to the JTAG or other hardware debugging facilities
- * found in most modern embedded processors.
- */
-
-struct target_desc_format {
- char *tdesc;
- uint32_t tdesc_length;
-};
-
-/* private connection data for GDB */
-struct gdb_connection {
- char buffer[GDB_BUFFER_SIZE];
- char *buf_p;
- int buf_cnt;
- int ctrl_c;
- enum target_state frontend_state;
- struct image *vflash_image;
- int closed;
- int busy;
- int noack_mode;
- /* set flag to true if you want the next stepi to return immediately.
- * allowing GDB to pick up a fresh set of register values from the target
- * without modifying the target state. */
- bool sync;
- /* We delay reporting memory write errors until next step/continue or memory
- * write. This improves performance of gdb load significantly as the GDB packet
- * can be replied immediately and a new GDB packet will be ready without delay
- * (ca. 10% or so...). */
- bool mem_write_error;
- /* with extended-remote it seems we need to better emulate attach/detach.
- * what this means is we reply with a W stop reply after a kill packet,
- * normally we reply with a S reply via gdb_last_signal_packet.
- * as a side note this behaviour only effects gdb > 6.8 */
- bool attached;
- /* temporarily used for target description support */
- struct target_desc_format target_desc;
-};
-
-#if 0
-#define _DEBUG_GDB_IO_
-#endif
-
-static struct gdb_connection *current_gdb_connection;
-
-static int gdb_breakpoint_override;
-static enum breakpoint_type gdb_breakpoint_override_type;
-
-static int gdb_error(struct connection *connection, int retval);
-static char *gdb_port;
-static char *gdb_port_next;
-
-static void gdb_log_callback(void *priv, const char *file, unsigned line,
- const char *function, const char *string);
-
-/* number of gdb connections, mainly to suppress gdb related debugging spam
- * in helper/log.c when no gdb connections are actually active */
-int gdb_actual_connections;
-
-/* set if we are sending a memory map to gdb
- * via qXfer:memory-map:read packet */
-/* enabled by default*/
-static int gdb_use_memory_map = 1;
-/* enabled by default*/
-static int gdb_flash_program = 1;
-
-/* if set, data aborts cause an error to be reported in memory read packets
- * see the code in gdb_read_memory_packet() for further explanations.
- * Disabled by default.
- */
-static int gdb_report_data_abort;
-
-/* set if we are sending target descriptions to gdb
- * via qXfer:features:read packet */
-/* enabled by default */
-static int gdb_use_target_description = 1;
-
-/* current processing free-run type, used by file-I/O */
-static char gdb_running_type;
-
-static int gdb_last_signal(struct target *target)
-{
- switch (target->debug_reason) {
- case DBG_REASON_DBGRQ:
- return 0x2; /* SIGINT */
- case DBG_REASON_BREAKPOINT:
- case DBG_REASON_WATCHPOINT:
- case DBG_REASON_WPTANDBKPT:
- return 0x05; /* SIGTRAP */
- case DBG_REASON_SINGLESTEP:
- return 0x05; /* SIGTRAP */
- case DBG_REASON_NOTHALTED:
- return 0x0; /* no signal... shouldn't happen */
- default:
- LOG_USER("undefined debug reason %d - target needs reset",
- target->debug_reason);
- return 0x0;
- }
-}
-
-static int check_pending(struct connection *connection,
- int timeout_s, int *got_data)
-{
- /* a non-blocking socket will block if there is 0 bytes available on the socket,
- * but return with as many bytes as are available immediately
- */
- struct timeval tv;
- fd_set read_fds;
- struct gdb_connection *gdb_con = connection->priv;
- int t;
- if (got_data == NULL)
- got_data = &t;
- *got_data = 0;
-
- if (gdb_con->buf_cnt > 0) {
- *got_data = 1;
- return ERROR_OK;
- }
-
- FD_ZERO(&read_fds);
- FD_SET(connection->fd, &read_fds);
-
- tv.tv_sec = timeout_s;
- tv.tv_usec = 0;
- if (socket_select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0) {
- /* This can typically be because a "monitor" command took too long
- * before printing any progress messages
- */
- if (timeout_s > 0)
- return ERROR_GDB_TIMEOUT;
- else
- return ERROR_OK;
- }
- *got_data = FD_ISSET(connection->fd, &read_fds) != 0;
- return ERROR_OK;
-}
-
-static int gdb_get_char_inner(struct connection *connection, int *next_char)
-{
- struct gdb_connection *gdb_con = connection->priv;
- int retval = ERROR_OK;
-
-#ifdef _DEBUG_GDB_IO_
- char *debug_buffer;
-#endif
- for (;; ) {
- if (connection->service->type != CONNECTION_TCP)
- gdb_con->buf_cnt = read(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
- else {
- retval = check_pending(connection, 1, NULL);
- if (retval != ERROR_OK)
- return retval;
- gdb_con->buf_cnt = read_socket(connection->fd,
- gdb_con->buffer,
- GDB_BUFFER_SIZE);
- }
-
- if (gdb_con->buf_cnt > 0)
- break;
- if (gdb_con->buf_cnt == 0) {
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
-#ifdef _WIN32
- errno = WSAGetLastError();
-
- switch (errno) {
- case WSAEWOULDBLOCK:
- usleep(1000);
- break;
- case WSAECONNABORTED:
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- case WSAECONNRESET:
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- default:
- LOG_ERROR("read: %d", errno);
- exit(-1);
- }
-#else
- switch (errno) {
- case EAGAIN:
- usleep(1000);
- break;
- case ECONNABORTED:
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- case ECONNRESET:
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- default:
- LOG_ERROR("read: %s", strerror(errno));
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-#endif
- }
-
-#ifdef _DEBUG_GDB_IO_
- debug_buffer = strndup(gdb_con->buffer, gdb_con->buf_cnt);
- LOG_DEBUG("received '%s'", debug_buffer);
- free(debug_buffer);
-#endif
-
- gdb_con->buf_p = gdb_con->buffer;
- gdb_con->buf_cnt--;
- *next_char = *(gdb_con->buf_p++);
- if (gdb_con->buf_cnt > 0)
- connection->input_pending = 1;
- else
- connection->input_pending = 0;
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
-#endif
-
- return retval;
-}
-
-/**
- * The cool thing about this fn is that it allows buf_p and buf_cnt to be
- * held in registers in the inner loop.
- *
- * For small caches and embedded systems this is important!
- */
-static inline int gdb_get_char_fast(struct connection *connection,
- int *next_char, char **buf_p, int *buf_cnt)
-{
- int retval = ERROR_OK;
-
- if ((*buf_cnt)-- > 0) {
- *next_char = **buf_p;
- (*buf_p)++;
- if (*buf_cnt > 0)
- connection->input_pending = 1;
- else
- connection->input_pending = 0;
-
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
-#endif
-
- return ERROR_OK;
- }
-
- struct gdb_connection *gdb_con = connection->priv;
- gdb_con->buf_p = *buf_p;
- gdb_con->buf_cnt = *buf_cnt;
- retval = gdb_get_char_inner(connection, next_char);
- *buf_p = gdb_con->buf_p;
- *buf_cnt = gdb_con->buf_cnt;
-
- return retval;
-}
-
-static int gdb_get_char(struct connection *connection, int *next_char)
-{
- struct gdb_connection *gdb_con = connection->priv;
- return gdb_get_char_fast(connection, next_char, &gdb_con->buf_p, &gdb_con->buf_cnt);
-}
-
-static int gdb_putback_char(struct connection *connection, int last_char)
-{
- struct gdb_connection *gdb_con = connection->priv;
-
- if (gdb_con->buf_p > gdb_con->buffer) {
- *(--gdb_con->buf_p) = last_char;
- gdb_con->buf_cnt++;
- } else
- LOG_ERROR("BUG: couldn't put character back");
-
- return ERROR_OK;
-}
-
-/* The only way we can detect that the socket is closed is the first time
- * we write to it, we will fail. Subsequent write operations will
- * succeed. Shudder! */
-static int gdb_write(struct connection *connection, void *data, int len)
-{
- struct gdb_connection *gdb_con = connection->priv;
- if (gdb_con->closed)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- if (connection_write(connection, data, len) == len)
- return ERROR_OK;
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
-}
-
-static int gdb_put_packet_inner(struct connection *connection,
- char *buffer, int len)
-{
- int i;
- unsigned char my_checksum = 0;
-#ifdef _DEBUG_GDB_IO_
- char *debug_buffer;
-#endif
- int reply;
- int retval;
- struct gdb_connection *gdb_con = connection->priv;
-
- for (i = 0; i < len; i++)
- my_checksum += buffer[i];
-
-#ifdef _DEBUG_GDB_IO_
- /*
- * At this point we should have nothing in the input queue from GDB,
- * however sometimes '-' is sent even though we've already received
- * an ACK (+) for everything we've sent off.
- */
- int gotdata;
- for (;; ) {
- retval = check_pending(connection, 0, &gotdata);
- if (retval != ERROR_OK)
- return retval;
- if (!gotdata)
- break;
- retval = gdb_get_char(connection, &reply);
- if (retval != ERROR_OK)
- return retval;
- if (reply == '$') {
- /* fix a problem with some IAR tools */
- gdb_putback_char(connection, reply);
- LOG_DEBUG("Unexpected start of new packet");
- break;
- }
-
- LOG_WARNING("Discard unexpected char %c", reply);
- }
-#endif
-
- while (1) {
-#ifdef _DEBUG_GDB_IO_
- debug_buffer = strndup(buffer, len);
- LOG_DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum);
- free(debug_buffer);
-#endif
-
- char local_buffer[1024];
- local_buffer[0] = '$';
- if ((size_t)len + 4 <= sizeof(local_buffer)) {
- /* performance gain on smaller packets by only a single call to gdb_write() */
- memcpy(local_buffer + 1, buffer, len++);
- len += snprintf(local_buffer + len, sizeof(local_buffer) - len, "#%02x", my_checksum);
- retval = gdb_write(connection, local_buffer, len);
- if (retval != ERROR_OK)
- return retval;
- } else {
- /* larger packets are transmitted directly from caller supplied buffer
- * by several calls to gdb_write() to avoid dynamic allocation */
- snprintf(local_buffer + 1, sizeof(local_buffer) - 1, "#%02x", my_checksum);
- retval = gdb_write(connection, local_buffer, 1);
- if (retval != ERROR_OK)
- return retval;
- retval = gdb_write(connection, buffer, len);
- if (retval != ERROR_OK)
- return retval;
- retval = gdb_write(connection, local_buffer + 1, 3);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (gdb_con->noack_mode)
- break;
-
- retval = gdb_get_char(connection, &reply);
- if (retval != ERROR_OK)
- return retval;
-
- if (reply == '+')
- break;
- else if (reply == '-') {
- /* Stop sending output packets for now */
- log_remove_callback(gdb_log_callback, connection);
- LOG_WARNING("negative reply, retrying");
- } else if (reply == 0x3) {
- gdb_con->ctrl_c = 1;
- retval = gdb_get_char(connection, &reply);
- if (retval != ERROR_OK)
- return retval;
- if (reply == '+')
- break;
- else if (reply == '-') {
- /* Stop sending output packets for now */
- log_remove_callback(gdb_log_callback, connection);
- LOG_WARNING("negative reply, retrying");
- } else if (reply == '$') {
- LOG_ERROR("GDB missing ack(1) - assumed good");
- gdb_putback_char(connection, reply);
- return ERROR_OK;
- } else {
- LOG_ERROR("unknown character(1) 0x%2.2x in reply, dropping connection", reply);
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- }
- } else if (reply == '$') {
- LOG_ERROR("GDB missing ack(2) - assumed good");
- gdb_putback_char(connection, reply);
- return ERROR_OK;
- } else {
- LOG_ERROR("unknown character(2) 0x%2.2x in reply, dropping connection",
- reply);
- gdb_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
- }
- }
- if (gdb_con->closed)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- return ERROR_OK;
-}
-
-int gdb_put_packet(struct connection *connection, char *buffer, int len)
-{
- struct gdb_connection *gdb_con = connection->priv;
- gdb_con->busy = 1;
- int retval = gdb_put_packet_inner(connection, buffer, len);
- gdb_con->busy = 0;
-
- /* we sent some data, reset timer for keep alive messages */
- kept_alive();
-
- return retval;
-}
-
-static inline int fetch_packet(struct connection *connection,
- int *checksum_ok, int noack, int *len, char *buffer)
-{
- unsigned char my_checksum = 0;
- char checksum[3];
- int character;
- int retval = ERROR_OK;
-
- struct gdb_connection *gdb_con = connection->priv;
- my_checksum = 0;
- int count = 0;
- count = 0;
-
- /* move this over into local variables to use registers and give the
- * more freedom to optimize */
- char *buf_p = gdb_con->buf_p;
- int buf_cnt = gdb_con->buf_cnt;
-
- for (;; ) {
- /* The common case is that we have an entire packet with no escape chars.
- * We need to leave at least 2 bytes in the buffer to have
- * gdb_get_char() update various bits and bobs correctly.
- */
- if ((buf_cnt > 2) && ((buf_cnt + count) < *len)) {
- /* The compiler will struggle a bit with constant propagation and
- * aliasing, so we help it by showing that these values do not
- * change inside the loop
- */
- int i;
- char *buf = buf_p;
- int run = buf_cnt - 2;
- i = 0;
- int done = 0;
- while (i < run) {
- character = *buf++;
- i++;
- if (character == '#') {
- /* Danger! character can be '#' when esc is
- * used so we need an explicit boolean for done here. */
- done = 1;
- break;
- }
-
- if (character == '}') {
- /* data transmitted in binary mode (X packet)
- * uses 0x7d as escape character */
- my_checksum += character & 0xff;
- character = *buf++;
- i++;
- my_checksum += character & 0xff;
- buffer[count++] = (character ^ 0x20) & 0xff;
- } else {
- my_checksum += character & 0xff;
- buffer[count++] = character & 0xff;
- }
- }
- buf_p += i;
- buf_cnt -= i;
- if (done)
- break;
- }
- if (count > *len) {
- LOG_ERROR("packet buffer too small");
- retval = ERROR_GDB_BUFFER_TOO_SMALL;
- break;
- }
-
- retval = gdb_get_char_fast(connection, &character, &buf_p, &buf_cnt);
- if (retval != ERROR_OK)
- break;
-
- if (character == '#')
- break;
-
- if (character == '}') {
- /* data transmitted in binary mode (X packet)
- * uses 0x7d as escape character */
- my_checksum += character & 0xff;
-
- retval = gdb_get_char_fast(connection, &character, &buf_p, &buf_cnt);
- if (retval != ERROR_OK)
- break;
-
- my_checksum += character & 0xff;
- buffer[count++] = (character ^ 0x20) & 0xff;
- } else {
- my_checksum += character & 0xff;
- buffer[count++] = character & 0xff;
- }
- }
-
- gdb_con->buf_p = buf_p;
- gdb_con->buf_cnt = buf_cnt;
-
- if (retval != ERROR_OK)
- return retval;
-
- *len = count;
-
- retval = gdb_get_char(connection, &character);
- if (retval != ERROR_OK)
- return retval;
- checksum[0] = character;
- retval = gdb_get_char(connection, &character);
- if (retval != ERROR_OK)
- return retval;
- checksum[1] = character;
- checksum[2] = 0;
-
- if (!noack)
- *checksum_ok = (my_checksum == strtoul(checksum, NULL, 16));
-
- return ERROR_OK;
-}
-
-static int gdb_get_packet_inner(struct connection *connection,
- char *buffer, int *len)
-{
- int character;
- int retval;
- struct gdb_connection *gdb_con = connection->priv;
-
- while (1) {
- do {
- retval = gdb_get_char(connection, &character);
- if (retval != ERROR_OK)
- return retval;
-
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("character: '%c'", character);
-#endif
-
- switch (character) {
- case '$':
- break;
- case '+':
- /* According to the GDB documentation
- * (https://sourceware.org/gdb/onlinedocs/gdb/Packet-Acknowledgment.html):
- * "gdb sends a final `+` acknowledgment of the stub's `OK`
- * response, which can be safely ignored by the stub."
- * However OpenOCD server already is in noack mode at this
- * point and instead of ignoring this it was emitting a
- * warning. This code makes server ignore the first ACK
- * that will be received after going into noack mode,
- * warning only about subsequent ACK's. */
- if (gdb_con->noack_mode > 1) {
- LOG_WARNING("acknowledgment received, but no packet pending");
- } else if (gdb_con->noack_mode) {
- LOG_DEBUG("Received first acknowledgment after entering noack mode. Ignoring it.");
- gdb_con->noack_mode = 2;
- }
- break;
- case '-':
- LOG_WARNING("negative acknowledgment, but no packet pending");
- break;
- case 0x3:
- gdb_con->ctrl_c = 1;
- *len = 0;
- return ERROR_OK;
- default:
- LOG_WARNING("ignoring character 0x%x", character);
- break;
- }
- } while (character != '$');
-
- int checksum_ok = 0;
- /* explicit code expansion here to get faster inlined code in -O3 by not
- * calculating checksum */
- if (gdb_con->noack_mode) {
- retval = fetch_packet(connection, &checksum_ok, 1, len, buffer);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = fetch_packet(connection, &checksum_ok, 0, len, buffer);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (gdb_con->noack_mode) {
- /* checksum is not checked in noack mode */
- break;
- }
- if (checksum_ok) {
- retval = gdb_write(connection, "+", 1);
- if (retval != ERROR_OK)
- return retval;
- break;
- }
- }
- if (gdb_con->closed)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- return ERROR_OK;
-}
-
-static int gdb_get_packet(struct connection *connection, char *buffer, int *len)
-{
- struct gdb_connection *gdb_con = connection->priv;
- gdb_con->busy = 1;
- int retval = gdb_get_packet_inner(connection, buffer, len);
- gdb_con->busy = 0;
- return retval;
-}
-
-static int gdb_output_con(struct connection *connection, const char *line)
-{
- char *hex_buffer;
- int bin_size;
-
- bin_size = strlen(line);
-
- hex_buffer = malloc(bin_size * 2 + 2);
- if (hex_buffer == NULL)
- return ERROR_GDB_BUFFER_TOO_SMALL;
-
- hex_buffer[0] = 'O';
- int pkt_len = hexify(hex_buffer + 1, line, bin_size, bin_size * 2 + 1);
- int retval = gdb_put_packet(connection, hex_buffer, pkt_len + 1);
-
- free(hex_buffer);
- return retval;
-}
-
-static int gdb_output(struct command_context *context, const char *line)
-{
- /* this will be dumped to the log and also sent as an O packet if possible */
- LOG_USER_N("%s", line);
- return ERROR_OK;
-}
-
-static void gdb_signal_reply(struct target *target, struct connection *connection)
-{
- struct gdb_connection *gdb_connection = connection->priv;
- char sig_reply[45];
- char stop_reason[20];
- char current_thread[25];
- int sig_reply_len;
- int signal_var;
-
- rtos_update_threads(target);
-
- if (target->debug_reason == DBG_REASON_EXIT) {
- sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "W00");
- } else {
- if (gdb_connection->ctrl_c) {
- signal_var = 0x2;
- gdb_connection->ctrl_c = 0;
- } else
- signal_var = gdb_last_signal(target);
-
- stop_reason[0] = '\0';
- if (target->debug_reason == DBG_REASON_WATCHPOINT) {
- enum watchpoint_rw hit_wp_type;
- uint32_t hit_wp_address;
-
- if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) {
-
- switch (hit_wp_type) {
- case WPT_WRITE:
- snprintf(stop_reason, sizeof(stop_reason),
- "watch:%08" PRIx32 ";", hit_wp_address);
- break;
- case WPT_READ:
- snprintf(stop_reason, sizeof(stop_reason),
- "rwatch:%08" PRIx32 ";", hit_wp_address);
- break;
- case WPT_ACCESS:
- snprintf(stop_reason, sizeof(stop_reason),
- "awatch:%08" PRIx32 ";", hit_wp_address);
- break;
- default:
- break;
- }
- }
- }
-
- current_thread[0] = '\0';
- if (target->rtos != NULL) {
- snprintf(current_thread, sizeof(current_thread), "thread:%016" PRIx64 ";", target->rtos->current_thread);
- target->rtos->current_threadid = target->rtos->current_thread;
- }
-
- sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s%s",
- signal_var, stop_reason, current_thread);
- }
-
- gdb_put_packet(connection, sig_reply, sig_reply_len);
- gdb_connection->frontend_state = TARGET_HALTED;
-}
-
-static void gdb_fileio_reply(struct target *target, struct connection *connection)
-{
- struct gdb_connection *gdb_connection = connection->priv;
- char fileio_command[256];
- int command_len;
- bool program_exited = false;
-
- if (strcmp(target->fileio_info->identifier, "open") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2,
- target->fileio_info->param_3,
- target->fileio_info->param_4);
- else if (strcmp(target->fileio_info->identifier, "close") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1);
- else if (strcmp(target->fileio_info->identifier, "read") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2,
- target->fileio_info->param_3);
- else if (strcmp(target->fileio_info->identifier, "write") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2,
- target->fileio_info->param_3);
- else if (strcmp(target->fileio_info->identifier, "lseek") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2,
- target->fileio_info->param_3);
- else if (strcmp(target->fileio_info->identifier, "rename") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 "/%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2,
- target->fileio_info->param_3,
- target->fileio_info->param_4);
- else if (strcmp(target->fileio_info->identifier, "unlink") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2);
- else if (strcmp(target->fileio_info->identifier, "stat") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2,
- target->fileio_info->param_3);
- else if (strcmp(target->fileio_info->identifier, "fstat") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2);
- else if (strcmp(target->fileio_info->identifier, "gettimeofday") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2);
- else if (strcmp(target->fileio_info->identifier, "isatty") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1);
- else if (strcmp(target->fileio_info->identifier, "system") == 0)
- sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier,
- target->fileio_info->param_1,
- target->fileio_info->param_2);
- else if (strcmp(target->fileio_info->identifier, "exit") == 0) {
- /* If target hits exit syscall, report to GDB the program is terminated.
- * In addition, let target run its own exit syscall handler. */
- program_exited = true;
- sprintf(fileio_command, "W%02" PRIx32, target->fileio_info->param_1);
- } else {
- LOG_DEBUG("Unknown syscall: %s", target->fileio_info->identifier);
-
- /* encounter unknown syscall, continue */
- gdb_connection->frontend_state = TARGET_RUNNING;
- target_resume(target, 1, 0x0, 0, 0);
- return;
- }
-
- command_len = strlen(fileio_command);
- gdb_put_packet(connection, fileio_command, command_len);
-
- if (program_exited) {
- /* Use target_resume() to let target run its own exit syscall handler. */
- gdb_connection->frontend_state = TARGET_RUNNING;
- target_resume(target, 1, 0x0, 0, 0);
- } else {
- gdb_connection->frontend_state = TARGET_HALTED;
- rtos_update_threads(target);
- }
-}
-
-static void gdb_frontend_halted(struct target *target, struct connection *connection)
-{
- struct gdb_connection *gdb_connection = connection->priv;
-
- /* In the GDB protocol when we are stepping or continuing execution,
- * we have a lingering reply. Upon receiving a halted event
- * when we have that lingering packet, we reply to the original
- * step or continue packet.
- *
- * Executing monitor commands can bring the target in and
- * out of the running state so we'll see lots of TARGET_EVENT_XXX
- * that are to be ignored.
- */
- if (gdb_connection->frontend_state == TARGET_RUNNING) {
- /* stop forwarding log packets! */
- log_remove_callback(gdb_log_callback, connection);
-
- /* check fileio first */
- if (target_get_gdb_fileio_info(target, target->fileio_info) == ERROR_OK)
- gdb_fileio_reply(target, connection);
- else
- gdb_signal_reply(target, connection);
- }
-}
-
-static int gdb_target_callback_event_handler(struct target *target,
- enum target_event event, void *priv)
-{
- int retval;
- struct connection *connection = priv;
- struct gdb_service *gdb_service = connection->service->priv;
-
- if (gdb_service->target != target)
- return ERROR_OK;
-
- switch (event) {
- case TARGET_EVENT_GDB_HALT:
- gdb_frontend_halted(target, connection);
- break;
- case TARGET_EVENT_HALTED:
- target_call_event_callbacks(target, TARGET_EVENT_GDB_END);
- break;
- case TARGET_EVENT_GDB_FLASH_ERASE_START:
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- break;
- default:
- break;
- }
-
- return ERROR_OK;
-}
-
-static int gdb_new_connection(struct connection *connection)
-{
- struct gdb_connection *gdb_connection = malloc(sizeof(struct gdb_connection));
- struct gdb_service *gdb_service = connection->service->priv;
- int retval;
- int initial_ack;
-
- connection->priv = gdb_connection;
-
- /* initialize gdb connection information */
- gdb_connection->buf_p = gdb_connection->buffer;
- gdb_connection->buf_cnt = 0;
- gdb_connection->ctrl_c = 0;
- gdb_connection->frontend_state = TARGET_HALTED;
- gdb_connection->vflash_image = NULL;
- gdb_connection->closed = 0;
- gdb_connection->busy = 0;
- gdb_connection->noack_mode = 0;
- gdb_connection->sync = false;
- gdb_connection->mem_write_error = false;
- gdb_connection->attached = true;
- gdb_connection->target_desc.tdesc = NULL;
- gdb_connection->target_desc.tdesc_length = 0;
-
- /* send ACK to GDB for debug request */
- gdb_write(connection, "+", 1);
-
- /* output goes through gdb connection */
- command_set_output_handler(connection->cmd_ctx, gdb_output, connection);
-
- /* we must remove all breakpoints registered to the target as a previous
- * GDB session could leave dangling breakpoints if e.g. communication
- * timed out.
- */
- breakpoint_clear_target(gdb_service->target);
- watchpoint_clear_target(gdb_service->target);
-
- /* clean previous rtos session if supported*/
- if ((gdb_service->target->rtos) && (gdb_service->target->rtos->type->clean))
- gdb_service->target->rtos->type->clean(gdb_service->target);
-
- /* remove the initial ACK from the incoming buffer */
- retval = gdb_get_char(connection, &initial_ack);
- if (retval != ERROR_OK)
- return retval;
-
- /* FIX!!!??? would we actually ever receive a + here???
- * Not observed.
- */
- if (initial_ack != '+')
- gdb_putback_char(connection, initial_ack);
- target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_ATTACH);
-
- if (gdb_use_memory_map) {
- /* Connect must fail if the memory map can't be set up correctly.
- *
- * This will cause an auto_probe to be invoked, which is either
- * a no-op or it will fail when the target isn't ready(e.g. not halted).
- */
- int i;
- for (i = 0; i < flash_get_bank_count(); i++) {
- struct flash_bank *p;
- p = get_flash_bank_by_num_noprobe(i);
- if (p->target != gdb_service->target)
- continue;
- retval = get_flash_bank_by_num(i, &p);
- if (retval != ERROR_OK) {
- LOG_ERROR("Connect failed. Consider setting up a gdb-attach event for the target " \
- "to prepare target for GDB connect, or use 'gdb_memory_map disable'.");
- return retval;
- }
- }
- }
-
- gdb_actual_connections++;
- LOG_DEBUG("New GDB Connection: %d, Target %s, state: %s",
- gdb_actual_connections,
- target_name(gdb_service->target),
- target_state_name(gdb_service->target));
-
- /* DANGER! If we fail subsequently, we must remove this handler,
- * otherwise we occasionally see crashes as the timer can invoke the
- * callback fn.
- *
- * register callback to be informed about target events */
- target_register_event_callback(gdb_target_callback_event_handler, connection);
-
- return ERROR_OK;
-}
-
-static int gdb_connection_closed(struct connection *connection)
-{
- struct gdb_service *gdb_service = connection->service->priv;
- struct gdb_connection *gdb_connection = connection->priv;
-
- /* we're done forwarding messages. Tear down callback before
- * cleaning up connection.
- */
- log_remove_callback(gdb_log_callback, connection);
-
- gdb_actual_connections--;
- LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
- target_name(gdb_service->target),
- target_state_name(gdb_service->target),
- gdb_actual_connections);
-
- /* see if an image built with vFlash commands is left */
- if (gdb_connection->vflash_image) {
- image_close(gdb_connection->vflash_image);
- free(gdb_connection->vflash_image);
- gdb_connection->vflash_image = NULL;
- }
-
- /* if this connection registered a debug-message receiver delete it */
- delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target);
-
- if (connection->priv) {
- free(connection->priv);
- connection->priv = NULL;
- } else
- LOG_ERROR("BUG: connection->priv == NULL");
-
- target_unregister_event_callback(gdb_target_callback_event_handler, connection);
-
- target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_END);
-
- target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
-
- return ERROR_OK;
-}
-
-static void gdb_send_error(struct connection *connection, uint8_t the_error)
-{
- char err[4];
- snprintf(err, 4, "E%2.2X", the_error);
- gdb_put_packet(connection, err, 3);
-}
-
-static int gdb_last_signal_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- struct gdb_connection *gdb_con = connection->priv;
- char sig_reply[4];
- int signal_var;
-
- if (!gdb_con->attached) {
- /* if we are here we have received a kill packet
- * reply W stop reply otherwise gdb gets very unhappy */
- gdb_put_packet(connection, "W00", 3);
- return ERROR_OK;
- }
-
- signal_var = gdb_last_signal(target);
-
- snprintf(sig_reply, 4, "S%2.2x", signal_var);
- gdb_put_packet(connection, sig_reply, 3);
-
- return ERROR_OK;
-}
-
-static inline int gdb_reg_pos(struct target *target, int pos, int len)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- return pos;
- else
- return len - 1 - pos;
-}
-
-/* Convert register to string of bytes. NB! The # of bits in the
- * register might be non-divisible by 8(a byte), in which
- * case an entire byte is shown.
- *
- * NB! the format on the wire is the target endianness
- *
- * The format of reg->value is little endian
- *
- */
-static void gdb_str_to_target(struct target *target,
- char *tstr, struct reg *reg)
-{
- int i;
-
- uint8_t *buf;
- int buf_len;
- buf = reg->value;
- buf_len = DIV_ROUND_UP(reg->size, 8);
-
- for (i = 0; i < buf_len; i++) {
- int j = gdb_reg_pos(target, i, buf_len);
- tstr += sprintf(tstr, "%02x", buf[j]);
- }
-}
-
-/* copy over in register buffer */
-static void gdb_target_to_reg(struct target *target,
- char const *tstr, int str_len, uint8_t *bin)
-{
- if (str_len % 2) {
- LOG_ERROR("BUG: gdb value with uneven number of characters encountered");
- exit(-1);
- }
-
- int i;
- for (i = 0; i < str_len; i += 2) {
- unsigned t;
- if (sscanf(tstr + i, "%02x", &t) != 1) {
- LOG_ERROR("BUG: unable to convert register value");
- exit(-1);
- }
-
- int j = gdb_reg_pos(target, i/2, str_len/2);
- bin[j] = t;
- }
-}
-
-static int gdb_get_registers_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- struct reg **reg_list;
- int reg_list_size;
- int retval;
- int reg_packet_size = 0;
- char *reg_packet;
- char *reg_packet_p;
- int i;
-
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("-");
-#endif
-
- if ((target->rtos != NULL) && (ERROR_OK == rtos_get_gdb_reg_list(connection)))
- return ERROR_OK;
-
- retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
- REG_CLASS_GENERAL);
- if (retval != ERROR_OK)
- return gdb_error(connection, retval);
-
- for (i = 0; i < reg_list_size; i++)
- reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2;
-
- assert(reg_packet_size > 0);
-
- reg_packet = malloc(reg_packet_size + 1); /* plus one for string termination null */
- if (reg_packet == NULL)
- return ERROR_FAIL;
-
- reg_packet_p = reg_packet;
-
- for (i = 0; i < reg_list_size; i++) {
- if (!reg_list[i]->valid) {
- retval = reg_list[i]->type->get(reg_list[i]);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name);
- free(reg_packet);
- free(reg_list);
- return gdb_error(connection, retval);
- }
- }
- gdb_str_to_target(target, reg_packet_p, reg_list[i]);
- reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2;
- }
-
-#ifdef _DEBUG_GDB_IO_
- {
- char *reg_packet_p_debug;
- reg_packet_p_debug = strndup(reg_packet, reg_packet_size);
- LOG_DEBUG("reg_packet: %s", reg_packet_p_debug);
- free(reg_packet_p_debug);
- }
-#endif
-
- gdb_put_packet(connection, reg_packet, reg_packet_size);
- free(reg_packet);
-
- free(reg_list);
-
- return ERROR_OK;
-}
-
-static int gdb_set_registers_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- int i;
- struct reg **reg_list;
- int reg_list_size;
- int retval;
- char const *packet_p;
-
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("-");
-#endif
-
- /* skip command character */
- packet++;
- packet_size--;
-
- if (packet_size % 2) {
- LOG_WARNING("GDB set_registers packet with uneven characters received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
- REG_CLASS_GENERAL);
- if (retval != ERROR_OK)
- return gdb_error(connection, retval);
-
- packet_p = packet;
- for (i = 0; i < reg_list_size; i++) {
- uint8_t *bin_buf;
- int chars = (DIV_ROUND_UP(reg_list[i]->size, 8) * 2);
-
- if (packet_p + chars > packet + packet_size)
- LOG_ERROR("BUG: register packet is too small for registers");
-
- bin_buf = malloc(DIV_ROUND_UP(reg_list[i]->size, 8));
- gdb_target_to_reg(target, packet_p, chars, bin_buf);
-
- retval = reg_list[i]->type->set(reg_list[i], bin_buf);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Couldn't set register %s.", reg_list[i]->name);
- free(reg_list);
- free(bin_buf);
- return gdb_error(connection, retval);
- }
-
- /* advance packet pointer */
- packet_p += chars;
-
- free(bin_buf);
- }
-
- /* free struct reg *reg_list[] array allocated by get_gdb_reg_list */
- free(reg_list);
-
- gdb_put_packet(connection, "OK", 2);
-
- return ERROR_OK;
-}
-
-static int gdb_get_register_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- char *reg_packet;
- int reg_num = strtoul(packet + 1, NULL, 16);
- struct reg **reg_list;
- int reg_list_size;
- int retval;
-
-#ifdef _DEBUG_GDB_IO_
- LOG_DEBUG("-");
-#endif
-
- retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
- REG_CLASS_ALL);
- if (retval != ERROR_OK)
- return gdb_error(connection, retval);
-
- if (reg_list_size <= reg_num) {
- LOG_ERROR("gdb requested a non-existing register");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- if (!reg_list[reg_num]->valid) {
- retval = reg_list[reg_num]->type->get(reg_list[reg_num]);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name);
- free (reg_list);
- return gdb_error(connection, retval);
- }
- }
-
- reg_packet = malloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1); /* plus one for string termination null */
-
- gdb_str_to_target(target, reg_packet, reg_list[reg_num]);
-
- gdb_put_packet(connection, reg_packet, DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2);
-
- free(reg_list);
- free(reg_packet);
-
- return ERROR_OK;
-}
-
-static int gdb_set_register_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- char *separator;
- uint8_t *bin_buf;
- int reg_num = strtoul(packet + 1, &separator, 16);
- struct reg **reg_list;
- int reg_list_size;
- int retval;
-
- LOG_DEBUG("-");
-
- retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size,
- REG_CLASS_ALL);
- if (retval != ERROR_OK)
- return gdb_error(connection, retval);
-
- if (reg_list_size <= reg_num) {
- LOG_ERROR("gdb requested a non-existing register");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- if (*separator != '=') {
- LOG_ERROR("GDB 'set register packet', but no '=' following the register number");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- /* convert from GDB-string (target-endian) to hex-string (big-endian) */
- bin_buf = malloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8));
- int chars = (DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2);
-
- if ((unsigned int)chars != strlen(separator + 1)) {
- LOG_ERROR("gdb sent a packet with wrong register size");
- free(bin_buf);
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- gdb_target_to_reg(target, separator + 1, chars, bin_buf);
-
- retval = reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf);
- if (retval != ERROR_OK){
- LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name);
- free(bin_buf);
- free(reg_list);
- return gdb_error(connection, retval);
- }
-
- gdb_put_packet(connection, "OK", 2);
-
- free(bin_buf);
- free(reg_list);
-
- return ERROR_OK;
-}
-
-/* No attempt is made to translate the "retval" to
- * GDB speak. This has to be done at the calling
- * site as no mapping really exists.
- */
-static int gdb_error(struct connection *connection, int retval)
-{
- LOG_DEBUG("Reporting %i to GDB as generic error", retval);
- gdb_send_error(connection, EFAULT);
- return ERROR_OK;
-}
-
-/* We don't have to worry about the default 2 second timeout for GDB packets,
- * because GDB breaks up large memory reads into smaller reads.
- *
- * 8191 bytes by the looks of it. Why 8191 bytes instead of 8192?????
- */
-static int gdb_read_memory_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- char *separator;
- uint32_t addr = 0;
- uint32_t len = 0;
-
- uint8_t *buffer;
- char *hex_buffer;
-
- int retval = ERROR_OK;
-
- /* skip command character */
- packet++;
-
- addr = strtoul(packet, &separator, 16);
-
- if (*separator != ',') {
- LOG_ERROR("incomplete read memory packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- len = strtoul(separator + 1, NULL, 16);
-
- if (!len) {
- LOG_WARNING("invalid read memory packet received (len == 0)");
- gdb_put_packet(connection, NULL, 0);
- return ERROR_OK;
- }
-
- buffer = malloc(len);
-
- LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
-
- retval = target_read_buffer(target, addr, len, buffer);
-
- if ((retval != ERROR_OK) && !gdb_report_data_abort) {
- /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
- * At some point this might be fixed in GDB, in which case this code can be removed.
- *
- * OpenOCD developers are acutely aware of this problem, but there is nothing
- * gained by involving the user in this problem that hopefully will get resolved
- * eventually
- *
- * http://sourceware.org/cgi-bin/gnatsweb.pl? \
- * cmd = view%20audit-trail&database = gdb&pr = 2395
- *
- * For now, the default is to fix up things to make current GDB versions work.
- * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command.
- */
- memset(buffer, 0, len);
- retval = ERROR_OK;
- }
-
- if (retval == ERROR_OK) {
- hex_buffer = malloc(len * 2 + 1);
-
- int pkt_len = hexify(hex_buffer, (char *)buffer, len, len * 2 + 1);
-
- gdb_put_packet(connection, hex_buffer, pkt_len);
-
- free(hex_buffer);
- } else
- retval = gdb_error(connection, retval);
-
- free(buffer);
-
- return retval;
-}
-
-static int gdb_write_memory_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- char *separator;
- uint32_t addr = 0;
- uint32_t len = 0;
-
- uint8_t *buffer;
- int retval;
-
- /* skip command character */
- packet++;
-
- addr = strtoul(packet, &separator, 16);
-
- if (*separator != ',') {
- LOG_ERROR("incomplete write memory packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- len = strtoul(separator + 1, &separator, 16);
-
- if (*(separator++) != ':') {
- LOG_ERROR("incomplete write memory packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- buffer = malloc(len);
-
- LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
-
- if (unhexify((char *)buffer, separator, len) != (int)len)
- LOG_ERROR("unable to decode memory packet");
-
- retval = target_write_buffer(target, addr, len, buffer);
-
- if (retval == ERROR_OK)
- gdb_put_packet(connection, "OK", 2);
- else
- retval = gdb_error(connection, retval);
-
- free(buffer);
-
- return retval;
-}
-
-static int gdb_write_memory_binary_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- char *separator;
- uint32_t addr = 0;
- uint32_t len = 0;
-
- int retval = ERROR_OK;
-
- /* skip command character */
- packet++;
-
- addr = strtoul(packet, &separator, 16);
-
- if (*separator != ',') {
- LOG_ERROR("incomplete write memory binary packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- len = strtoul(separator + 1, &separator, 16);
-
- if (*(separator++) != ':') {
- LOG_ERROR("incomplete write memory binary packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- struct gdb_connection *gdb_connection = connection->priv;
-
- if (gdb_connection->mem_write_error) {
- retval = ERROR_FAIL;
- /* now that we have reported the memory write error, we can clear the condition */
- gdb_connection->mem_write_error = false;
- }
-
- /* By replying the packet *immediately* GDB will send us a new packet
- * while we write the last one to the target.
- */
- if (retval == ERROR_OK)
- gdb_put_packet(connection, "OK", 2);
- else {
- retval = gdb_error(connection, retval);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (len) {
- LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
-
- retval = target_write_buffer(target, addr, len, (uint8_t *)separator);
- if (retval != ERROR_OK)
- gdb_connection->mem_write_error = true;
- }
-
- return ERROR_OK;
-}
-
-static int gdb_step_continue_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- int current = 0;
- uint32_t address = 0x0;
- int retval = ERROR_OK;
-
- LOG_DEBUG("-");
-
- if (packet_size > 1)
- address = strtoul(packet + 1, NULL, 16);
- else
- current = 1;
-
- gdb_running_type = packet[0];
- if (packet[0] == 'c') {
- LOG_DEBUG("continue");
- /* resume at current address, don't handle breakpoints, not debugging */
- retval = target_resume(target, current, address, 0, 0);
- } else if (packet[0] == 's') {
- LOG_DEBUG("step");
- /* step at current or address, don't handle breakpoints */
- retval = target_step(target, current, address, 0);
- }
- return retval;
-}
-
-static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- int type;
- enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
- enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */;
- uint32_t address;
- uint32_t size;
- char *separator;
- int retval;
-
- LOG_DEBUG("-");
-
- type = strtoul(packet + 1, &separator, 16);
-
- if (type == 0) /* memory breakpoint */
- bp_type = BKPT_SOFT;
- else if (type == 1) /* hardware breakpoint */
- bp_type = BKPT_HARD;
- else if (type == 2) /* write watchpoint */
- wp_type = WPT_WRITE;
- else if (type == 3) /* read watchpoint */
- wp_type = WPT_READ;
- else if (type == 4) /* access watchpoint */
- wp_type = WPT_ACCESS;
- else {
- LOG_ERROR("invalid gdb watch/breakpoint type(%d), dropping connection", type);
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- if (gdb_breakpoint_override && ((bp_type == BKPT_SOFT) || (bp_type == BKPT_HARD)))
- bp_type = gdb_breakpoint_override_type;
-
- if (*separator != ',') {
- LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- address = strtoul(separator + 1, &separator, 16);
-
- if (*separator != ',') {
- LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- size = strtoul(separator + 1, &separator, 16);
-
- switch (type) {
- case 0:
- case 1:
- if (packet[0] == 'Z') {
- retval = breakpoint_add(target, address, size, bp_type);
- if (retval != ERROR_OK) {
- retval = gdb_error(connection, retval);
- if (retval != ERROR_OK)
- return retval;
- } else
- gdb_put_packet(connection, "OK", 2);
- } else {
- breakpoint_remove(target, address);
- gdb_put_packet(connection, "OK", 2);
- }
- break;
- case 2:
- case 3:
- case 4:
- {
- if (packet[0] == 'Z') {
- retval = watchpoint_add(target, address, size, wp_type, 0, 0xffffffffu);
- if (retval != ERROR_OK) {
- retval = gdb_error(connection, retval);
- if (retval != ERROR_OK)
- return retval;
- } else
- gdb_put_packet(connection, "OK", 2);
- } else {
- watchpoint_remove(target, address);
- gdb_put_packet(connection, "OK", 2);
- }
- break;
- }
- default:
- break;
- }
-
- return ERROR_OK;
-}
-
-/* print out a string and allocate more space as needed,
- * mainly used for XML at this point
- */
-static void xml_printf(int *retval, char **xml, int *pos, int *size,
- const char *fmt, ...)
-{
- if (*retval != ERROR_OK)
- return;
- int first = 1;
-
- for (;; ) {
- if ((*xml == NULL) || (!first)) {
- /* start by 0 to exercise all the code paths.
- * Need minimum 2 bytes to fit 1 char and 0 terminator. */
-
- *size = *size * 2 + 2;
- char *t = *xml;
- *xml = realloc(*xml, *size);
- if (*xml == NULL) {
- if (t)
- free(t);
- *retval = ERROR_SERVER_REMOTE_CLOSED;
- return;
- }
- }
-
- va_list ap;
- int ret;
- va_start(ap, fmt);
- ret = vsnprintf(*xml + *pos, *size - *pos, fmt, ap);
- va_end(ap);
- if ((ret > 0) && ((ret + 1) < *size - *pos)) {
- *pos += ret;
- return;
- }
- /* there was just enough or not enough space, allocate more. */
- first = 0;
- }
-}
-
-static int decode_xfer_read(char const *buf, char **annex, int *ofs, unsigned int *len)
-{
- /* Locate the annex. */
- const char *annex_end = strchr(buf, ':');
- if (annex_end == NULL)
- return ERROR_FAIL;
-
- /* After the read marker and annex, qXfer looks like a
- * traditional 'm' packet. */
- char *separator;
- *ofs = strtoul(annex_end + 1, &separator, 16);
-
- if (*separator != ',')
- return ERROR_FAIL;
-
- *len = strtoul(separator + 1, NULL, 16);
-
- /* Extract the annex if needed */
- if (annex != NULL) {
- *annex = strndup(buf, annex_end - buf);
- if (*annex == NULL)
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int compare_bank(const void *a, const void *b)
-{
- struct flash_bank *b1, *b2;
- b1 = *((struct flash_bank **)a);
- b2 = *((struct flash_bank **)b);
-
- if (b1->base == b2->base)
- return 0;
- else if (b1->base > b2->base)
- return 1;
- else
- return -1;
-}
-
-static int gdb_memory_map(struct connection *connection,
- char const *packet, int packet_size)
-{
- /* We get away with only specifying flash here. Regions that are not
- * specified are treated as if we provided no memory map(if not we
- * could detect the holes and mark them as RAM).
- * Normally we only execute this code once, but no big deal if we
- * have to regenerate it a couple of times.
- */
-
- struct target *target = get_target_from_connection(connection);
- struct flash_bank *p;
- char *xml = NULL;
- int size = 0;
- int pos = 0;
- int retval = ERROR_OK;
- struct flash_bank **banks;
- int offset;
- int length;
- char *separator;
- uint32_t ram_start = 0;
- int i;
- int target_flash_banks = 0;
-
- /* skip command character */
- packet += 23;
-
- offset = strtoul(packet, &separator, 16);
- length = strtoul(separator + 1, &separator, 16);
-
- xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
-
- /* Sort banks in ascending order. We need to report non-flash
- * memory as ram (or rather read/write) by default for GDB, since
- * it has no concept of non-cacheable read/write memory (i/o etc).
- *
- * FIXME Most non-flash addresses are *NOT* RAM! Don't lie.
- * Current versions of GDB assume unlisted addresses are RAM...
- */
- banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
-
- for (i = 0; i < flash_get_bank_count(); i++) {
- p = get_flash_bank_by_num_noprobe(i);
- if (p->target != target)
- continue;
- retval = get_flash_bank_by_num(i, &p);
- if (retval != ERROR_OK) {
- free(banks);
- gdb_error(connection, retval);
- return retval;
- }
- banks[target_flash_banks++] = p;
- }
-
- qsort(banks, target_flash_banks, sizeof(struct flash_bank *),
- compare_bank);
-
- for (i = 0; i < target_flash_banks; i++) {
- int j;
- unsigned sector_size = 0;
- uint32_t start;
-
- p = banks[i];
- start = p->base;
-
- if (ram_start < p->base)
- xml_printf(&retval, &xml, &pos, &size,
- "<memory type=\"ram\" start=\"0x%x\" "
- "length=\"0x%x\"/>\n",
- ram_start, p->base - ram_start);
-
- /* Report adjacent groups of same-size sectors. So for
- * example top boot CFI flash will list an initial region
- * with several large sectors (maybe 128KB) and several
- * smaller ones at the end (maybe 32KB). STR7 will have
- * regions with 8KB, 32KB, and 64KB sectors; etc.
- */
- for (j = 0; j < p->num_sectors; j++) {
- unsigned group_len;
-
- /* Maybe start a new group of sectors. */
- if (sector_size == 0) {
- start = p->base + p->sectors[j].offset;
- xml_printf(&retval, &xml, &pos, &size,
- "<memory type=\"flash\" "
- "start=\"0x%x\" ",
- start);
- sector_size = p->sectors[j].size;
- }
-
- /* Does this finish a group of sectors?
- * If not, continue an already-started group.
- */
- if (j == p->num_sectors - 1)
- group_len = (p->base + p->size) - start;
- else if (p->sectors[j + 1].size != sector_size)
- group_len = p->base + p->sectors[j + 1].offset
- - start;
- else
- continue;
-
- xml_printf(&retval, &xml, &pos, &size,
- "length=\"0x%x\">\n"
- "<property name=\"blocksize\">"
- "0x%x</property>\n"
- "</memory>\n",
- group_len,
- sector_size);
- sector_size = 0;
- }
-
- ram_start = p->base + p->size;
- }
-
- if (ram_start != 0)
- xml_printf(&retval, &xml, &pos, &size,
- "<memory type=\"ram\" start=\"0x%x\" "
- "length=\"0x%x\"/>\n",
- ram_start, 0-ram_start);
- /* ELSE a flash chip could be at the very end of the 32 bit address
- * space, in which case ram_start will be precisely 0
- */
-
- free(banks);
- banks = NULL;
-
- xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
-
- if (retval != ERROR_OK) {
- gdb_error(connection, retval);
- return retval;
- }
-
- if (offset + length > pos)
- length = pos - offset;
-
- char *t = malloc(length + 1);
- t[0] = 'l';
- memcpy(t + 1, xml + offset, length);
- gdb_put_packet(connection, t, length + 1);
-
- free(t);
- free(xml);
- return ERROR_OK;
-}
-
-static const char *gdb_get_reg_type_name(enum reg_type type)
-{
- switch (type) {
- case REG_TYPE_INT:
- return "int";
- case REG_TYPE_INT8:
- return "int8";
- case REG_TYPE_INT16:
- return "int16";
- case REG_TYPE_INT32:
- return "int32";
- case REG_TYPE_INT64:
- return "int64";
- case REG_TYPE_INT128:
- return "int128";
- case REG_TYPE_UINT8:
- return "uint8";
- case REG_TYPE_UINT16:
- return "uint16";
- case REG_TYPE_UINT32:
- return "uint32";
- case REG_TYPE_UINT64:
- return "uint64";
- case REG_TYPE_UINT128:
- return "uint128";
- case REG_TYPE_CODE_PTR:
- return "code_ptr";
- case REG_TYPE_DATA_PTR:
- return "data_ptr";
- case REG_TYPE_FLOAT:
- return "float";
- case REG_TYPE_IEEE_SINGLE:
- return "ieee_single";
- case REG_TYPE_IEEE_DOUBLE:
- return "ieee_double";
- case REG_TYPE_ARCH_DEFINED:
- return "int"; /* return arbitrary string to avoid compile warning. */
- }
-
- return "int"; /* "int" as default value */
-}
-
-static int gdb_generate_reg_type_description(struct target *target,
- char **tdesc, int *pos, int *size, struct reg_data_type *type)
-{
- int retval = ERROR_OK;
-
- if (type->type_class == REG_TYPE_CLASS_VECTOR) {
- /* <vector id="id" type="type" count="count"/> */
- xml_printf(&retval, tdesc, pos, size,
- "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>\n",
- type->id, type->reg_type_vector->type->id,
- type->reg_type_vector->count);
-
- } else if (type->type_class == REG_TYPE_CLASS_UNION) {
- /* <union id="id">
- * <field name="name" type="type"/> ...
- * </union> */
- xml_printf(&retval, tdesc, pos, size,
- "<union id=\"%s\">\n",
- type->id);
-
- struct reg_data_type_union_field *field;
- field = type->reg_type_union->fields;
- while (field != NULL) {
- xml_printf(&retval, tdesc, pos, size,
- "<field name=\"%s\" type=\"%s\"/>\n",
- field->name, field->type->id);
-
- field = field->next;
- }
-
- xml_printf(&retval, tdesc, pos, size,
- "</union>\n");
-
- } else if (type->type_class == REG_TYPE_CLASS_STRUCT) {
- struct reg_data_type_struct_field *field;
- field = type->reg_type_struct->fields;
-
- if (field->use_bitfields) {
- /* <struct id="id" size="size">
- * <field name="name" start="start" end="end"/> ...
- * </struct> */
- xml_printf(&retval, tdesc, pos, size,
- "<struct id=\"%s\" size=\"%d\">\n",
- type->id, type->reg_type_struct->size);
- while (field != NULL) {
- xml_printf(&retval, tdesc, pos, size,
- "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n",
- field->name, field->bitfield->start,
- field->bitfield->end);
-
- field = field->next;
- }
- } else {
- /* <struct id="id">
- * <field name="name" type="type"/> ...
- * </struct> */
- xml_printf(&retval, tdesc, pos, size,
- "<struct id=\"%s\">\n",
- type->id);
- while (field != NULL) {
- xml_printf(&retval, tdesc, pos, size,
- "<field name=\"%s\" type=\"%s\"/>\n",
- field->name, field->type->id);
-
- field = field->next;
- }
- }
-
- xml_printf(&retval, tdesc, pos, size,
- "</struct>\n");
-
- } else if (type->type_class == REG_TYPE_CLASS_FLAGS) {
- /* <flags id="id" size="size">
- * <field name="name" start="start" end="end"/> ...
- * </flags> */
- xml_printf(&retval, tdesc, pos, size,
- "<flags id=\"%s\" size=\"%d\">\n",
- type->id, type->reg_type_flags->size);
-
- struct reg_data_type_flags_field *field;
- field = type->reg_type_flags->fields;
- while (field != NULL) {
- xml_printf(&retval, tdesc, pos, size,
- "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n",
- field->name, field->bitfield->start, field->bitfield->end);
-
- field = field->next;
- }
-
- xml_printf(&retval, tdesc, pos, size,
- "</flags>\n");
-
- }
-
- return ERROR_OK;
-}
-
-/* Get a list of available target registers features. feature_list must
- * be freed by caller.
- */
-static int get_reg_features_list(struct target *target, char const **feature_list[], int *feature_list_size,
- struct reg **reg_list, int reg_list_size)
-{
- int tbl_sz = 0;
-
- /* Start with only one element */
- *feature_list = calloc(1, sizeof(char *));
-
- for (int i = 0; i < reg_list_size; i++) {
- if (reg_list[i]->exist == false)
- continue;
-
- if (reg_list[i]->feature != NULL
- && reg_list[i]->feature->name != NULL
- && (strcmp(reg_list[i]->feature->name, ""))) {
- /* We found a feature, check if the feature is already in the
- * table. If not, allocate a new entry for the table and
- * put the new feature in it.
- */
- for (int j = 0; j < (tbl_sz + 1); j++) {
- if (!((*feature_list)[j])) {
- (*feature_list)[tbl_sz++] = reg_list[i]->feature->name;
- *feature_list = realloc(*feature_list, sizeof(char *) * (tbl_sz + 1));
- (*feature_list)[tbl_sz] = NULL;
- break;
- } else {
- if (!strcmp((*feature_list)[j], reg_list[i]->feature->name))
- break;
- }
- }
- }
- }
-
- if (feature_list_size)
- *feature_list_size = tbl_sz;
-
- return ERROR_OK;
-}
-
-static int gdb_generate_target_description(struct target *target, char **tdesc_out)
-{
- int retval = ERROR_OK;
- struct reg **reg_list = NULL;
- int reg_list_size;
- char const **features = NULL;
- int feature_list_size = 0;
- char *tdesc = NULL;
- int pos = 0;
- int size = 0;
-
- retval = target_get_gdb_reg_list(target, &reg_list,
- &reg_list_size, REG_CLASS_ALL);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("get register list failed");
- retval = ERROR_FAIL;
- goto error;
- }
-
- if (reg_list_size <= 0) {
- LOG_ERROR("get register list failed");
- retval = ERROR_FAIL;
- goto error;
- }
-
- /* Get a list of available target registers features */
- retval = get_reg_features_list(target, &features, &feature_list_size, reg_list, reg_list_size);
- if (retval != ERROR_OK) {
- LOG_ERROR("Can't get the registers feature list");
- retval = ERROR_FAIL;
- goto error;
- }
-
- /* If we found some features associated with registers, create sections */
- int current_feature = 0;
-
- xml_printf(&retval, &tdesc, &pos, &size,
- "<?xml version=\"1.0\"?>\n"
- "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n"
- "<target version=\"1.0\">\n");
-
- /* generate target description according to register list */
- if (features != NULL) {
- while (features[current_feature]) {
-
- xml_printf(&retval, &tdesc, &pos, &size,
- "<feature name=\"%s\">\n",
- features[current_feature]);
-
- int i;
- for (i = 0; i < reg_list_size; i++) {
-
- if (reg_list[i]->exist == false)
- continue;
-
- if (strcmp(reg_list[i]->feature->name, features[current_feature]))
- continue;
-
- const char *type_str;
- if (reg_list[i]->reg_data_type != NULL) {
- if (reg_list[i]->reg_data_type->type == REG_TYPE_ARCH_DEFINED) {
- /* generate <type... first, if there are architecture-defined types. */
- gdb_generate_reg_type_description(target, &tdesc, &pos, &size,
- reg_list[i]->reg_data_type);
-
- type_str = reg_list[i]->reg_data_type->id;
- } else {
- /* predefined type */
- type_str = gdb_get_reg_type_name(
- reg_list[i]->reg_data_type->type);
- }
- } else {
- /* Default type is "int" */
- type_str = "int";
- }
-
- xml_printf(&retval, &tdesc, &pos, &size,
- "<reg name=\"%s\"", reg_list[i]->name);
- xml_printf(&retval, &tdesc, &pos, &size,
- " bitsize=\"%d\"", reg_list[i]->size);
- xml_printf(&retval, &tdesc, &pos, &size,
- " regnum=\"%d\"", reg_list[i]->number);
- if (reg_list[i]->caller_save)
- xml_printf(&retval, &tdesc, &pos, &size,
- " save-restore=\"yes\"");
- else
- xml_printf(&retval, &tdesc, &pos, &size,
- " save-restore=\"no\"");
-
- xml_printf(&retval, &tdesc, &pos, &size,
- " type=\"%s\"", type_str);
-
- if (reg_list[i]->group != NULL)
- xml_printf(&retval, &tdesc, &pos, &size,
- " group=\"%s\"", reg_list[i]->group);
-
- xml_printf(&retval, &tdesc, &pos, &size,
- "/>\n");
- }
-
- xml_printf(&retval, &tdesc, &pos, &size,
- "</feature>\n");
-
- current_feature++;
- }
- }
-
- xml_printf(&retval, &tdesc, &pos, &size,
- "</target>\n");
-
-error:
- free(features);
- free(reg_list);
-
- if (retval == ERROR_OK)
- *tdesc_out = tdesc;
- else
- free(tdesc);
-
- return retval;
-}
-
-static int gdb_get_target_description_chunk(struct target *target, struct target_desc_format *target_desc,
- char **chunk, int32_t offset, uint32_t length)
-{
- if (target_desc == NULL) {
- LOG_ERROR("Unable to Generate Target Description");
- return ERROR_FAIL;
- }
-
- char *tdesc = target_desc->tdesc;
- uint32_t tdesc_length = target_desc->tdesc_length;
-
- if (tdesc == NULL) {
- int retval = gdb_generate_target_description(target, &tdesc);
- if (retval != ERROR_OK) {
- LOG_ERROR("Unable to Generate Target Description");
- return ERROR_FAIL;
- }
-
- tdesc_length = strlen(tdesc);
- }
-
- char transfer_type;
-
- if (length < (tdesc_length - offset))
- transfer_type = 'm';
- else
- transfer_type = 'l';
-
- *chunk = malloc(length + 2);
- if (*chunk == NULL) {
- LOG_ERROR("Unable to allocate memory");
- return ERROR_FAIL;
- }
-
- (*chunk)[0] = transfer_type;
- if (transfer_type == 'm') {
- strncpy((*chunk) + 1, tdesc + offset, length);
- (*chunk)[1 + length] = '\0';
- } else {
- strncpy((*chunk) + 1, tdesc + offset, tdesc_length - offset);
- (*chunk)[1 + (tdesc_length - offset)] = '\0';
-
- /* After gdb-server sends out last chunk, invalidate tdesc. */
- free(tdesc);
- tdesc = NULL;
- tdesc_length = 0;
- }
-
- target_desc->tdesc = tdesc;
- target_desc->tdesc_length = tdesc_length;
-
- return ERROR_OK;
-}
-
-static int gdb_target_description_supported(struct target *target, int *supported)
-{
- int retval = ERROR_OK;
- struct reg **reg_list = NULL;
- int reg_list_size = 0;
- char const **features = NULL;
- int feature_list_size = 0;
-
- retval = target_get_gdb_reg_list(target, &reg_list,
- &reg_list_size, REG_CLASS_ALL);
- if (retval != ERROR_OK) {
- LOG_ERROR("get register list failed");
- goto error;
- }
-
- if (reg_list_size <= 0) {
- LOG_ERROR("get register list failed");
- retval = ERROR_FAIL;
- goto error;
- }
-
- /* Get a list of available target registers features */
- retval = get_reg_features_list(target, &features, &feature_list_size, reg_list, reg_list_size);
- if (retval != ERROR_OK) {
- LOG_ERROR("Can't get the registers feature list");
- goto error;
- }
-
- if (supported) {
- if (feature_list_size)
- *supported = 1;
- else
- *supported = 0;
- }
-
-error:
- free(features);
-
- free(reg_list);
-
- return retval;
-}
-
-static int gdb_query_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct command_context *cmd_ctx = connection->cmd_ctx;
- struct gdb_connection *gdb_connection = connection->priv;
- struct target *target = get_target_from_connection(connection);
-
- if (strncmp(packet, "qRcmd,", 6) == 0) {
- if (packet_size > 6) {
- char *cmd;
- cmd = malloc((packet_size - 6) / 2 + 1);
- int len = unhexify(cmd, packet + 6, (packet_size - 6) / 2);
- cmd[len] = 0;
-
- /* We want to print all debug output to GDB connection */
- log_add_callback(gdb_log_callback, connection);
- target_call_timer_callbacks_now();
- /* some commands need to know the GDB connection, make note of current
- * GDB connection. */
- current_gdb_connection = gdb_connection;
- command_run_line(cmd_ctx, cmd);
- current_gdb_connection = NULL;
- target_call_timer_callbacks_now();
- log_remove_callback(gdb_log_callback, connection);
- free(cmd);
- }
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- } else if (strncmp(packet, "qCRC:", 5) == 0) {
- if (packet_size > 5) {
- int retval;
- char gdb_reply[10];
- char *separator;
- uint32_t checksum;
- uint32_t addr = 0;
- uint32_t len = 0;
-
- /* skip command character */
- packet += 5;
-
- addr = strtoul(packet, &separator, 16);
-
- if (*separator != ',') {
- LOG_ERROR("incomplete read memory packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- len = strtoul(separator + 1, NULL, 16);
-
- retval = target_checksum_memory(target, addr, len, &checksum);
-
- if (retval == ERROR_OK) {
- snprintf(gdb_reply, 10, "C%8.8" PRIx32 "", checksum);
- gdb_put_packet(connection, gdb_reply, 9);
- } else {
- retval = gdb_error(connection, retval);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
- }
- } else if (strncmp(packet, "qSupported", 10) == 0) {
- /* we currently support packet size and qXfer:memory-map:read (if enabled)
- * qXfer:features:read is supported for some targets */
- int retval = ERROR_OK;
- char *buffer = NULL;
- int pos = 0;
- int size = 0;
- int gdb_target_desc_supported = 0;
-
- /* we need to test that the target supports target descriptions */
- retval = gdb_target_description_supported(target, &gdb_target_desc_supported);
- if (retval != ERROR_OK) {
- LOG_INFO("Failed detecting Target Description Support, disabling");
- gdb_target_desc_supported = 0;
- }
-
- /* support may be disabled globally */
- if (gdb_use_target_description == 0) {
- if (gdb_target_desc_supported)
- LOG_WARNING("Target Descriptions Supported, but disabled");
- gdb_target_desc_supported = 0;
- }
-
- xml_printf(&retval,
- &buffer,
- &pos,
- &size,
- "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+",
- (GDB_BUFFER_SIZE - 1),
- ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-',
- (gdb_target_desc_supported == 1) ? '+' : '-');
-
- if (retval != ERROR_OK) {
- gdb_send_error(connection, 01);
- return ERROR_OK;
- }
-
- gdb_put_packet(connection, buffer, strlen(buffer));
- free(buffer);
-
- return ERROR_OK;
- } else if ((strncmp(packet, "qXfer:memory-map:read::", 23) == 0)
- && (flash_get_bank_count() > 0))
- return gdb_memory_map(connection, packet, packet_size);
- else if (strncmp(packet, "qXfer:features:read:", 20) == 0) {
- char *xml = NULL;
- int retval = ERROR_OK;
-
- int offset;
- unsigned int length;
-
- /* skip command character */
- packet += 20;
-
- if (decode_xfer_read(packet, NULL, &offset, &length) < 0) {
- gdb_send_error(connection, 01);
- return ERROR_OK;
- }
-
- /* Target should prepare correct target description for annex.
- * The first character of returned xml is 'm' or 'l'. 'm' for
- * there are *more* chunks to transfer. 'l' for it is the *last*
- * chunk of target description.
- */
- retval = gdb_get_target_description_chunk(target, &gdb_connection->target_desc,
- &xml, offset, length);
- if (retval != ERROR_OK) {
- gdb_error(connection, retval);
- return retval;
- }
-
- gdb_put_packet(connection, xml, strlen(xml));
-
- free(xml);
- return ERROR_OK;
- } else if (strncmp(packet, "QStartNoAckMode", 15) == 0) {
- gdb_connection->noack_mode = 1;
- gdb_put_packet(connection, "OK", 2);
- return ERROR_OK;
- }
-
- gdb_put_packet(connection, "", 0);
- return ERROR_OK;
-}
-
-static int gdb_v_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct gdb_connection *gdb_connection = connection->priv;
- struct gdb_service *gdb_service = connection->service->priv;
- int result;
-
- /* if flash programming disabled - send a empty reply */
-
- if (gdb_flash_program == 0) {
- gdb_put_packet(connection, "", 0);
- return ERROR_OK;
- }
-
- if (strncmp(packet, "vFlashErase:", 12) == 0) {
- unsigned long addr;
- unsigned long length;
-
- char const *parse = packet + 12;
- if (*parse == '\0') {
- LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- addr = strtoul(parse, (char **)&parse, 16);
-
- if (*(parse++) != ',' || *parse == '\0') {
- LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- length = strtoul(parse, (char **)&parse, 16);
-
- if (*parse != '\0') {
- LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- /* assume all sectors need erasing - stops any problems
- * when flash_write is called multiple times */
- flash_set_dirty();
-
- /* perform any target specific operations before the erase */
- target_call_event_callbacks(gdb_service->target,
- TARGET_EVENT_GDB_FLASH_ERASE_START);
-
- /* vFlashErase:addr,length messages require region start and
- * end to be "block" aligned ... if padding is ever needed,
- * GDB will have become dangerously confused.
- */
- result = flash_erase_address_range(gdb_service->target,
- false, addr, length);
-
- /* perform any target specific operations after the erase */
- target_call_event_callbacks(gdb_service->target,
- TARGET_EVENT_GDB_FLASH_ERASE_END);
-
- /* perform erase */
- if (result != ERROR_OK) {
- /* GDB doesn't evaluate the actual error number returned,
- * treat a failed erase as an I/O error
- */
- gdb_send_error(connection, EIO);
- LOG_ERROR("flash_erase returned %i", result);
- } else
- gdb_put_packet(connection, "OK", 2);
-
- return ERROR_OK;
- }
-
- if (strncmp(packet, "vFlashWrite:", 12) == 0) {
- int retval;
- unsigned long addr;
- unsigned long length;
- char const *parse = packet + 12;
-
- if (*parse == '\0') {
- LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
- addr = strtoul(parse, (char **)&parse, 16);
- if (*(parse++) != ':') {
- LOG_ERROR("incomplete vFlashErase packet received, dropping connection");
- return ERROR_SERVER_REMOTE_CLOSED;
- }
- length = packet_size - (parse - packet);
-
- /* create a new image if there isn't already one */
- if (gdb_connection->vflash_image == NULL) {
- gdb_connection->vflash_image = malloc(sizeof(struct image));
- image_open(gdb_connection->vflash_image, "", "build");
- }
-
- /* create new section with content from packet buffer */
- retval = image_add_section(gdb_connection->vflash_image,
- addr, length, 0x0, (uint8_t const *)parse);
- if (retval != ERROR_OK)
- return retval;
-
- gdb_put_packet(connection, "OK", 2);
-
- return ERROR_OK;
- }
-
- if (strncmp(packet, "vFlashDone", 10) == 0) {
- uint32_t written;
-
- /* process the flashing buffer. No need to erase as GDB
- * always issues a vFlashErase first. */
- target_call_event_callbacks(gdb_service->target,
- TARGET_EVENT_GDB_FLASH_WRITE_START);
- result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, 0);
- target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_WRITE_END);
- if (result != ERROR_OK) {
- if (result == ERROR_FLASH_DST_OUT_OF_BANK)
- gdb_put_packet(connection, "E.memtype", 9);
- else
- gdb_send_error(connection, EIO);
- } else {
- LOG_DEBUG("wrote %u bytes from vFlash image to flash", (unsigned)written);
- gdb_put_packet(connection, "OK", 2);
- }
-
- image_close(gdb_connection->vflash_image);
- free(gdb_connection->vflash_image);
- gdb_connection->vflash_image = NULL;
-
- return ERROR_OK;
- }
-
- gdb_put_packet(connection, "", 0);
- return ERROR_OK;
-}
-
-static int gdb_detach(struct connection *connection)
-{
- struct gdb_service *gdb_service = connection->service->priv;
-
- target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
-
- return gdb_put_packet(connection, "OK", 2);
-}
-
-/* The format of 'F' response packet is
- * Fretcode,errno,Ctrl-C flag;call-specific attachment
- */
-static int gdb_fileio_response_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- char *separator;
- char *parsing_point;
- int fileio_retcode = strtoul(packet + 1, &separator, 16);
- int fileio_errno = 0;
- bool fileio_ctrl_c = false;
- int retval;
-
- LOG_DEBUG("-");
-
- if (*separator == ',') {
- parsing_point = separator + 1;
- fileio_errno = strtoul(parsing_point, &separator, 16);
- if (*separator == ',') {
- if (*(separator + 1) == 'C') {
- /* TODO: process ctrl-c */
- fileio_ctrl_c = true;
- }
- }
- }
-
- LOG_DEBUG("File-I/O response, retcode: 0x%x, errno: 0x%x, ctrl-c: %s",
- fileio_retcode, fileio_errno, fileio_ctrl_c ? "true" : "false");
-
- retval = target_gdb_fileio_end(target, fileio_retcode, fileio_errno, fileio_ctrl_c);
- if (retval != ERROR_OK)
- return ERROR_FAIL;
-
- /* After File-I/O ends, keep continue or step */
- if (gdb_running_type == 'c')
- retval = target_resume(target, 1, 0x0, 0, 0);
- else if (gdb_running_type == 's')
- retval = target_step(target, 1, 0x0, 0);
- else
- retval = ERROR_FAIL;
-
- if (retval != ERROR_OK)
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static void gdb_log_callback(void *priv, const char *file, unsigned line,
- const char *function, const char *string)
-{
- struct connection *connection = priv;
- struct gdb_connection *gdb_con = connection->priv;
-
- if (gdb_con->busy) {
- /* do not reply this using the O packet */
- return;
- }
-
- gdb_output_con(connection, string);
-}
-
-static void gdb_sig_halted(struct connection *connection)
-{
- char sig_reply[4];
- snprintf(sig_reply, 4, "T%2.2x", 2);
- gdb_put_packet(connection, sig_reply, 3);
-}
-
-static int gdb_input_inner(struct connection *connection)
-{
- /* Do not allocate this on the stack */
- static char gdb_packet_buffer[GDB_BUFFER_SIZE];
-
- struct gdb_service *gdb_service = connection->service->priv;
- struct target *target = gdb_service->target;
- char const *packet = gdb_packet_buffer;
- int packet_size;
- int retval;
- struct gdb_connection *gdb_con = connection->priv;
- static int extended_protocol;
-
- /* drain input buffer. If one of the packets fail, then an error
- * packet is replied, if applicable.
- *
- * This loop will terminate and the error code is returned.
- *
- * The calling fn will check if this error is something that
- * can be recovered from, or if the connection must be closed.
- *
- * If the error is recoverable, this fn is called again to
- * drain the rest of the buffer.
- */
- do {
- packet_size = GDB_BUFFER_SIZE-1;
- retval = gdb_get_packet(connection, gdb_packet_buffer, &packet_size);
- if (retval != ERROR_OK)
- return retval;
-
- /* terminate with zero */
- gdb_packet_buffer[packet_size] = '\0';
-
- if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
- if (packet[0] == 'X') {
- /* binary packets spew junk into the debug log stream */
- char buf[50];
- int x;
- for (x = 0; (x < 49) && (packet[x] != ':'); x++)
- buf[x] = packet[x];
- buf[x] = 0;
- LOG_DEBUG("received packet: '%s:<binary-data>'", buf);
- } else
- LOG_DEBUG("received packet: '%s'", packet);
- }
-
- if (packet_size > 0) {
- retval = ERROR_OK;
- switch (packet[0]) {
- case 'T': /* Is thread alive? */
- gdb_thread_packet(connection, packet, packet_size);
- break;
- case 'H': /* Set current thread ( 'c' for step and continue,
- * 'g' for all other operations ) */
- gdb_thread_packet(connection, packet, packet_size);
- break;
- case 'q':
- case 'Q':
- retval = gdb_thread_packet(connection, packet, packet_size);
- if (retval == GDB_THREAD_PACKET_NOT_CONSUMED)
- retval = gdb_query_packet(connection, packet, packet_size);
- break;
- case 'g':
- retval = gdb_get_registers_packet(connection, packet, packet_size);
- break;
- case 'G':
- retval = gdb_set_registers_packet(connection, packet, packet_size);
- break;
- case 'p':
- retval = gdb_get_register_packet(connection, packet, packet_size);
- break;
- case 'P':
- retval = gdb_set_register_packet(connection, packet, packet_size);
- break;
- case 'm':
- retval = gdb_read_memory_packet(connection, packet, packet_size);
- break;
- case 'M':
- retval = gdb_write_memory_packet(connection, packet, packet_size);
- break;
- case 'z':
- case 'Z':
- retval = gdb_breakpoint_watchpoint_packet(connection, packet, packet_size);
- break;
- case '?':
- gdb_last_signal_packet(connection, packet, packet_size);
- break;
- case 'c':
- case 's':
- {
- gdb_thread_packet(connection, packet, packet_size);
- log_add_callback(gdb_log_callback, connection);
-
- if (gdb_con->mem_write_error) {
- LOG_ERROR("Memory write failure!");
-
- /* now that we have reported the memory write error,
- * we can clear the condition */
- gdb_con->mem_write_error = false;
- }
-
- bool nostep = false;
- bool already_running = false;
- if (target->state == TARGET_RUNNING) {
- LOG_WARNING("WARNING! The target is already running. "
- "All changes GDB did to registers will be discarded! "
- "Waiting for target to halt.");
- already_running = true;
- } else if (target->state != TARGET_HALTED) {
- LOG_WARNING("The target is not in the halted nor running stated, " \
- "stepi/continue ignored.");
- nostep = true;
- } else if ((packet[0] == 's') && gdb_con->sync) {
- /* Hmm..... when you issue a continue in GDB, then a "stepi" is
- * sent by GDB first to OpenOCD, thus defeating the check to
- * make only the single stepping have the sync feature...
- */
- nostep = true;
- LOG_WARNING("stepi ignored. GDB will now fetch the register state " \
- "from the target.");
- }
- gdb_con->sync = false;
-
- if (!already_running && nostep) {
- /* Either the target isn't in the halted state, then we can't
- * step/continue. This might be early setup, etc.
- *
- * Or we want to allow GDB to pick up a fresh set of
- * register values without modifying the target state.
- *
- */
- gdb_sig_halted(connection);
-
- /* stop forwarding log packets! */
- log_remove_callback(gdb_log_callback, connection);
- } else {
- /* We're running/stepping, in which case we can
- * forward log output until the target is halted
- */
- gdb_con->frontend_state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
-
- if (!already_running) {
- /* Here we don't want packet processing to stop even if this fails,
- * so we use a local variable instead of retval. */
- retval = gdb_step_continue_packet(connection, packet, packet_size);
- if (retval != ERROR_OK) {
- /* we'll never receive a halted
- * condition... issue a false one..
- */
- gdb_frontend_halted(target, connection);
- }
- }
- }
- }
- break;
- case 'v':
- retval = gdb_v_packet(connection, packet, packet_size);
- break;
- case 'D':
- retval = gdb_detach(connection);
- extended_protocol = 0;
- break;
- case 'X':
- retval = gdb_write_memory_binary_packet(connection, packet, packet_size);
- if (retval != ERROR_OK)
- return retval;
- break;
- case 'k':
- if (extended_protocol != 0) {
- gdb_con->attached = false;
- break;
- }
- gdb_put_packet(connection, "OK", 2);
- return ERROR_SERVER_REMOTE_CLOSED;
- case '!':
- /* handle extended remote protocol */
- extended_protocol = 1;
- gdb_put_packet(connection, "OK", 2);
- break;
- case 'R':
- /* handle extended restart packet */
- breakpoint_clear_target(gdb_service->target);
- watchpoint_clear_target(gdb_service->target);
- command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %s",
- target_name(target));
- /* set connection as attached after reset */
- gdb_con->attached = true;
- /* info rtos parts */
- gdb_thread_packet(connection, packet, packet_size);
- break;
-
- case 'j':
- /* packet supported only by smp target i.e cortex_a.c*/
- /* handle smp packet replying coreid played to gbd */
- gdb_read_smp_packet(connection, packet, packet_size);
- break;
-
- case 'J':
- /* packet supported only by smp target i.e cortex_a.c */
- /* handle smp packet setting coreid to be played at next
- * resume to gdb */
- gdb_write_smp_packet(connection, packet, packet_size);
- break;
-
- case 'F':
- /* File-I/O extension */
- /* After gdb uses host-side syscall to complete target file
- * I/O, gdb sends host-side syscall return value to target
- * by 'F' packet.
- * The format of 'F' response packet is
- * Fretcode,errno,Ctrl-C flag;call-specific attachment
- */
- gdb_con->frontend_state = TARGET_RUNNING;
- log_add_callback(gdb_log_callback, connection);
- gdb_fileio_response_packet(connection, packet, packet_size);
- break;
-
- default:
- /* ignore unknown packets */
- LOG_DEBUG("ignoring 0x%2.2x packet", packet[0]);
- gdb_put_packet(connection, NULL, 0);
- break;
- }
-
- /* if a packet handler returned an error, exit input loop */
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (gdb_con->ctrl_c) {
- if (target->state == TARGET_RUNNING) {
- retval = target_halt(target);
- if (retval != ERROR_OK)
- target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
- gdb_con->ctrl_c = 0;
- } else {
- LOG_INFO("The target is not running when halt was requested, stopping GDB.");
- target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
- }
- }
-
- } while (gdb_con->buf_cnt > 0);
-
- return ERROR_OK;
-}
-
-static int gdb_input(struct connection *connection)
-{
- int retval = gdb_input_inner(connection);
- struct gdb_connection *gdb_con = connection->priv;
- if (retval == ERROR_SERVER_REMOTE_CLOSED)
- return retval;
-
- /* logging does not propagate the error, yet can set the gdb_con->closed flag */
- if (gdb_con->closed)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- /* we'll recover from any other errors(e.g. temporary timeouts, etc.) */
- return ERROR_OK;
-}
-
-static int gdb_target_start(struct target *target, const char *port)
-{
- struct gdb_service *gdb_service;
- int ret;
- gdb_service = malloc(sizeof(struct gdb_service));
-
- if (NULL == gdb_service)
- return -ENOMEM;
-
- gdb_service->target = target;
- gdb_service->core[0] = -1;
- gdb_service->core[1] = -1;
- target->gdb_service = gdb_service;
-
- ret = add_service("gdb",
- port, 1, &gdb_new_connection, &gdb_input,
- &gdb_connection_closed, gdb_service);
- /* initialialize all targets gdb service with the same pointer */
- {
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if (curr != target)
- curr->gdb_service = gdb_service;
- head = head->next;
- }
- }
- return ret;
-}
-
-static int gdb_target_add_one(struct target *target)
-{
- /* one gdb instance per smp list */
- if ((target->smp) && (target->gdb_service))
- return ERROR_OK;
- int retval = gdb_target_start(target, gdb_port_next);
- if (retval == ERROR_OK) {
- long portnumber;
- /* If we can parse the port number
- * then we increment the port number for the next target.
- */
- char *end;
- portnumber = strtol(gdb_port_next, &end, 0);
- if (!*end) {
- if (parse_long(gdb_port_next, &portnumber) == ERROR_OK) {
- free(gdb_port_next);
- gdb_port_next = alloc_printf("%d", portnumber+1);
- }
- }
- }
- return retval;
-}
-
-int gdb_target_add_all(struct target *target)
-{
- if (strcmp(gdb_port, "disabled") == 0) {
- LOG_INFO("gdb server disabled");
- return ERROR_OK;
- }
-
- if (NULL == target) {
- LOG_WARNING("gdb services need one or more targets defined");
- return ERROR_OK;
- }
-
- while (NULL != target) {
- int retval = gdb_target_add_one(target);
- if (ERROR_OK != retval)
- return retval;
-
- target = target->next;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_gdb_sync_command)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (current_gdb_connection == NULL) {
- command_print(CMD_CTX,
- "gdb_sync command can only be run from within gdb using \"monitor gdb_sync\"");
- return ERROR_FAIL;
- }
-
- current_gdb_connection->sync = true;
-
- return ERROR_OK;
-}
-
-/* daemon configuration command gdb_port */
-COMMAND_HANDLER(handle_gdb_port_command)
-{
- int retval = CALL_COMMAND_HANDLER(server_pipe_command, &gdb_port);
- if (ERROR_OK == retval) {
- free(gdb_port_next);
- gdb_port_next = strdup(gdb_port);
- }
- return retval;
-}
-
-COMMAND_HANDLER(handle_gdb_memory_map_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_use_memory_map);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_gdb_flash_program_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_flash_program);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_gdb_report_data_abort_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_report_data_abort);
- return ERROR_OK;
-}
-
-/* gdb_breakpoint_override */
-COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
-{
- if (CMD_ARGC == 0) {
- /* nothing */
- } else if (CMD_ARGC == 1) {
- gdb_breakpoint_override = 1;
- if (strcmp(CMD_ARGV[0], "hard") == 0)
- gdb_breakpoint_override_type = BKPT_HARD;
- else if (strcmp(CMD_ARGV[0], "soft") == 0)
- gdb_breakpoint_override_type = BKPT_SOFT;
- else if (strcmp(CMD_ARGV[0], "disable") == 0)
- gdb_breakpoint_override = 0;
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (gdb_breakpoint_override)
- LOG_USER("force %s breakpoints",
- (gdb_breakpoint_override_type == BKPT_HARD) ? "hard" : "soft");
- else
- LOG_USER("breakpoint type is not overridden");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_gdb_target_description_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_use_target_description);
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_gdb_save_tdesc_command)
-{
- char *tdesc;
- uint32_t tdesc_length;
- struct target *target = get_current_target(CMD_CTX);
-
- int retval = gdb_generate_target_description(target, &tdesc);
- if (retval != ERROR_OK) {
- LOG_ERROR("Unable to Generate Target Description");
- return ERROR_FAIL;
- }
-
- tdesc_length = strlen(tdesc);
-
- struct fileio *fileio;
- size_t size_written;
-
- char *tdesc_filename = alloc_printf("%s.xml", target_type_name(target));
- if (tdesc_filename == NULL) {
- retval = ERROR_FAIL;
- goto out;
- }
-
- retval = fileio_open(&fileio, tdesc_filename, FILEIO_WRITE, FILEIO_TEXT);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Can't open %s for writing", tdesc_filename);
- goto out;
- }
-
- retval = fileio_write(fileio, tdesc_length, tdesc, &size_written);
-
- fileio_close(fileio);
-
- if (retval != ERROR_OK)
- LOG_ERROR("Error while writing the tdesc file");
-
-out:
- free(tdesc_filename);
- free(tdesc);
-
- return retval;
-}
-
-static const struct command_registration gdb_command_handlers[] = {
- {
- .name = "gdb_sync",
- .handler = handle_gdb_sync_command,
- .mode = COMMAND_ANY,
- .help = "next stepi will return immediately allowing "
- "GDB to fetch register state without affecting "
- "target state",
- .usage = ""
- },
- {
- .name = "gdb_port",
- .handler = handle_gdb_port_command,
- .mode = COMMAND_ANY,
- .help = "Normally gdb listens to a TCP/IP port. Each subsequent GDB "
- "server listens for the next port number after the "
- "base port number specified. "
- "No arguments reports GDB port. \"pipe\" means listen to stdin "
- "output to stdout, an integer is base port number, \"disable\" disables "
- "port. Any other string is are interpreted as named pipe to listen to. "
- "Output pipe is the same name as input pipe, but with 'o' appended.",
- .usage = "[port_num]",
- },
- {
- .name = "gdb_memory_map",
- .handler = handle_gdb_memory_map_command,
- .mode = COMMAND_CONFIG,
- .help = "enable or disable memory map",
- .usage = "('enable'|'disable')"
- },
- {
- .name = "gdb_flash_program",
- .handler = handle_gdb_flash_program_command,
- .mode = COMMAND_CONFIG,
- .help = "enable or disable flash program",
- .usage = "('enable'|'disable')"
- },
- {
- .name = "gdb_report_data_abort",
- .handler = handle_gdb_report_data_abort_command,
- .mode = COMMAND_CONFIG,
- .help = "enable or disable reporting data aborts",
- .usage = "('enable'|'disable')"
- },
- {
- .name = "gdb_breakpoint_override",
- .handler = handle_gdb_breakpoint_override_command,
- .mode = COMMAND_ANY,
- .help = "Display or specify type of breakpoint "
- "to be used by gdb 'break' commands.",
- .usage = "('hard'|'soft'|'disable')"
- },
- {
- .name = "gdb_target_description",
- .handler = handle_gdb_target_description_command,
- .mode = COMMAND_CONFIG,
- .help = "enable or disable target description",
- .usage = "('enable'|'disable')"
- },
- {
- .name = "gdb_save_tdesc",
- .handler = handle_gdb_save_tdesc_command,
- .mode = COMMAND_EXEC,
- .help = "Save the target description file",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int gdb_register_commands(struct command_context *cmd_ctx)
-{
- gdb_port = strdup("3333");
- gdb_port_next = strdup("3333");
- return register_commands(cmd_ctx, NULL, gdb_command_handlers);
-}
diff --git a/src/server/gdb_server.h b/src/server/gdb_server.h
deleted file mode 100644
index 2b4ac4e..0000000
--- a/src/server/gdb_server.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2009 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_SERVER_GDB_SERVER_H
-#define OPENOCD_SERVER_GDB_SERVER_H
-
-struct image;
-struct reg;
-#include <target/target.h>
-
-#define GDB_BUFFER_SIZE 16384
-
-int gdb_target_add_all(struct target *target);
-int gdb_register_commands(struct command_context *command_context);
-
-int gdb_put_packet(struct connection *connection, char *buffer, int len);
-
-static inline struct target *get_target_from_connection(struct connection *connection)
-{
- struct gdb_service *gdb_service = connection->service->priv;
- return gdb_service->target;
-}
-
-#define ERROR_GDB_BUFFER_TOO_SMALL (-800)
-#define ERROR_GDB_TIMEOUT (-801)
-
-#endif /* OPENOCD_SERVER_GDB_SERVER_H */
diff --git a/src/server/server.c b/src/server/server.c
deleted file mode 100644
index f6889a0..0000000
--- a/src/server/server.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "server.h"
-#include <target/target.h>
-#include <target/target_request.h>
-#include <target/openrisc/jsp_server.h>
-#include "openocd.h"
-#include "tcl_server.h"
-#include "telnet_server.h"
-
-#include <signal.h>
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#ifndef _WIN32
-#include <netinet/tcp.h>
-#endif
-
-static struct service *services;
-
-/* shutdown_openocd == 1: exit the main event loop, and quit the
- * debugger; 2: quit with non-zero return code */
-static int shutdown_openocd;
-
-/* store received signal to exit application by killing ourselves */
-static int last_signal;
-
-/* set the polling period to 100ms */
-static int polling_period = 100;
-
-/* address by name on which to listen for incoming TCP/IP connections */
-static char *bindto_name;
-
-static int add_connection(struct service *service, struct command_context *cmd_ctx)
-{
- socklen_t address_size;
- struct connection *c, **p;
- int retval;
- int flag = 1;
-
- c = malloc(sizeof(struct connection));
- c->fd = -1;
- c->fd_out = -1;
- memset(&c->sin, 0, sizeof(c->sin));
- c->cmd_ctx = copy_command_context(cmd_ctx);
- c->service = service;
- c->input_pending = 0;
- c->priv = NULL;
- c->next = NULL;
-
- if (service->type == CONNECTION_TCP) {
- address_size = sizeof(c->sin);
-
- c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
- c->fd_out = c->fd;
-
- /* This increases performance dramatically for e.g. GDB load which
- * does not have a sliding window protocol.
- *
- * Ignore errors from this fn as it probably just means less performance
- */
- setsockopt(c->fd, /* socket affected */
- IPPROTO_TCP, /* set option at TCP level */
- TCP_NODELAY, /* name of option */
- (char *)&flag, /* the cast is historical cruft */
- sizeof(int)); /* length of option value */
-
- LOG_INFO("accepting '%s' connection on tcp/%s", service->name, service->port);
- retval = service->new_connection(c);
- if (retval != ERROR_OK) {
- close_socket(c->fd);
- LOG_ERROR("attempted '%s' connection rejected", service->name);
- command_done(c->cmd_ctx);
- free(c);
- return retval;
- }
- } else if (service->type == CONNECTION_STDINOUT) {
- c->fd = service->fd;
- c->fd_out = fileno(stdout);
-
-#ifdef _WIN32
- /* we are using stdin/out so ignore ctrl-c under windoze */
- SetConsoleCtrlHandler(NULL, TRUE);
-#endif
-
- /* do not check for new connections again on stdin */
- service->fd = -1;
-
- LOG_INFO("accepting '%s' connection from pipe", service->name);
- retval = service->new_connection(c);
- if (retval != ERROR_OK) {
- LOG_ERROR("attempted '%s' connection rejected", service->name);
- command_done(c->cmd_ctx);
- free(c);
- return retval;
- }
- } else if (service->type == CONNECTION_PIPE) {
- c->fd = service->fd;
- /* do not check for new connections again on stdin */
- service->fd = -1;
-
- char *out_file = alloc_printf("%so", service->port);
- c->fd_out = open(out_file, O_WRONLY);
- free(out_file);
- if (c->fd_out == -1) {
- LOG_ERROR("could not open %s", service->port);
- exit(1);
- }
-
- LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
- retval = service->new_connection(c);
- if (retval != ERROR_OK) {
- LOG_ERROR("attempted '%s' connection rejected", service->name);
- command_done(c->cmd_ctx);
- free(c);
- return retval;
- }
- }
-
- /* add to the end of linked list */
- for (p = &service->connections; *p; p = &(*p)->next)
- ;
- *p = c;
-
- if (service->max_connections != CONNECTION_LIMIT_UNLIMITED)
- service->max_connections--;
-
- return ERROR_OK;
-}
-
-static int remove_connection(struct service *service, struct connection *connection)
-{
- struct connection **p = &service->connections;
- struct connection *c;
-
- /* find connection */
- while ((c = *p)) {
- if (c->fd == connection->fd) {
- service->connection_closed(c);
- if (service->type == CONNECTION_TCP)
- close_socket(c->fd);
- else if (service->type == CONNECTION_PIPE) {
- /* The service will listen to the pipe again */
- c->service->fd = c->fd;
- }
-
- command_done(c->cmd_ctx);
-
- /* delete connection */
- *p = c->next;
- free(c);
-
- if (service->max_connections != CONNECTION_LIMIT_UNLIMITED)
- service->max_connections++;
-
- break;
- }
-
- /* redirect p to next list pointer */
- p = &(*p)->next;
- }
-
- return ERROR_OK;
-}
-
-/* FIX! make service return error instead of invoking exit() */
-int add_service(char *name,
- const char *port,
- int max_connections,
- new_connection_handler_t new_connection_handler,
- input_handler_t input_handler,
- connection_closed_handler_t connection_closed_handler,
- void *priv)
-{
- struct service *c, **p;
- struct hostent *hp;
- int so_reuseaddr_option = 1;
-
- c = malloc(sizeof(struct service));
-
- c->name = strdup(name);
- c->port = strdup(port);
- c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */
- c->fd = -1;
- c->connections = NULL;
- c->new_connection = new_connection_handler;
- c->input = input_handler;
- c->connection_closed = connection_closed_handler;
- c->priv = priv;
- c->next = NULL;
- long portnumber;
- if (strcmp(c->port, "pipe") == 0)
- c->type = CONNECTION_STDINOUT;
- else {
- char *end;
- portnumber = strtol(c->port, &end, 0);
- if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) {
- c->portnumber = portnumber;
- c->type = CONNECTION_TCP;
- } else
- c->type = CONNECTION_PIPE;
- }
-
- if (c->type == CONNECTION_TCP) {
- c->max_connections = max_connections;
-
- c->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (c->fd == -1) {
- LOG_ERROR("error creating socket: %s", strerror(errno));
- exit(-1);
- }
-
- setsockopt(c->fd,
- SOL_SOCKET,
- SO_REUSEADDR,
- (void *)&so_reuseaddr_option,
- sizeof(int));
-
- socket_nonblock(c->fd);
-
- memset(&c->sin, 0, sizeof(c->sin));
- c->sin.sin_family = AF_INET;
-
- if (bindto_name == NULL)
- c->sin.sin_addr.s_addr = INADDR_ANY;
- else {
- hp = gethostbyname(bindto_name);
- if (hp == NULL) {
- LOG_ERROR("couldn't resolve bindto address: %s", bindto_name);
- exit(-1);
- }
- memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length);
- }
- c->sin.sin_port = htons(c->portnumber);
-
- if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) {
- LOG_ERROR("couldn't bind %s to socket: %s", name, strerror(errno));
- exit(-1);
- }
-
-#ifndef _WIN32
- int segsize = 65536;
- setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int));
-#endif
- int window_size = 128 * 1024;
-
- /* These setsockopt()s must happen before the listen() */
-
- setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF,
- (char *)&window_size, sizeof(window_size));
- setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF,
- (char *)&window_size, sizeof(window_size));
-
- if (listen(c->fd, 1) == -1) {
- LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
- exit(-1);
- }
- } else if (c->type == CONNECTION_STDINOUT) {
- c->fd = fileno(stdin);
-
-#ifdef _WIN32
- /* for win32 set stdin/stdout to binary mode */
- if (_setmode(_fileno(stdout), _O_BINARY) < 0)
- LOG_WARNING("cannot change stdout mode to binary");
- if (_setmode(_fileno(stdin), _O_BINARY) < 0)
- LOG_WARNING("cannot change stdin mode to binary");
- if (_setmode(_fileno(stderr), _O_BINARY) < 0)
- LOG_WARNING("cannot change stderr mode to binary");
-#else
- socket_nonblock(c->fd);
-#endif
- } else if (c->type == CONNECTION_PIPE) {
-#ifdef _WIN32
- /* we currenty do not support named pipes under win32
- * so exit openocd for now */
- LOG_ERROR("Named pipes currently not supported under this os");
- exit(1);
-#else
- /* Pipe we're reading from */
- c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
- if (c->fd == -1) {
- LOG_ERROR("could not open %s", c->port);
- exit(1);
- }
-#endif
- }
-
- /* add to the end of linked list */
- for (p = &services; *p; p = &(*p)->next)
- ;
- *p = c;
-
- return ERROR_OK;
-}
-
-static int remove_services(void)
-{
- struct service *c = services;
-
- /* loop service */
- while (c) {
- struct service *next = c->next;
-
- if (c->name)
- free(c->name);
-
- if (c->type == CONNECTION_PIPE) {
- if (c->fd != -1)
- close(c->fd);
- }
- if (c->port)
- free(c->port);
-
- if (c->priv)
- free(c->priv);
-
- /* delete service */
- free(c);
-
- /* remember the last service for unlinking */
- c = next;
- }
-
- services = NULL;
-
- return ERROR_OK;
-}
-
-int server_loop(struct command_context *command_context)
-{
- struct service *service;
-
- bool poll_ok = true;
-
- /* used in select() */
- fd_set read_fds;
- int fd_max;
-
- /* used in accept() */
- int retval;
-
-#ifndef _WIN32
- if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
- LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
-#endif
-
- while (!shutdown_openocd) {
- /* monitor sockets for activity */
- fd_max = 0;
- FD_ZERO(&read_fds);
-
- /* add service and connection fds to read_fds */
- for (service = services; service; service = service->next) {
- if (service->fd != -1) {
- /* listen for new connections */
- FD_SET(service->fd, &read_fds);
-
- if (service->fd > fd_max)
- fd_max = service->fd;
- }
-
- if (service->connections) {
- struct connection *c;
-
- for (c = service->connections; c; c = c->next) {
- /* check for activity on the connection */
- FD_SET(c->fd, &read_fds);
- if (c->fd > fd_max)
- fd_max = c->fd;
- }
- }
- }
-
- struct timeval tv;
- tv.tv_sec = 0;
- if (poll_ok) {
- /* we're just polling this iteration, this is faster on embedded
- * hosts */
- tv.tv_usec = 0;
- retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
- } else {
- /* Every 100ms, can be changed with "poll_period" command */
- tv.tv_usec = polling_period * 1000;
- /* Only while we're sleeping we'll let others run */
- openocd_sleep_prelude();
- kept_alive();
- retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
- openocd_sleep_postlude();
- }
-
- if (retval == -1) {
-#ifdef _WIN32
-
- errno = WSAGetLastError();
-
- if (errno == WSAEINTR)
- FD_ZERO(&read_fds);
- else {
- LOG_ERROR("error during select: %s", strerror(errno));
- exit(-1);
- }
-#else
-
- if (errno == EINTR)
- FD_ZERO(&read_fds);
- else {
- LOG_ERROR("error during select: %s", strerror(errno));
- exit(-1);
- }
-#endif
- }
-
- if (retval == 0) {
- /* We only execute these callbacks when there was nothing to do or we timed
- *out */
- target_call_timer_callbacks();
- process_jim_events(command_context);
-
- FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */
-
- /* We timed out/there was nothing to do, timeout rather than poll next time
- **/
- poll_ok = false;
- } else {
- /* There was something to do, next time we'll just poll */
- poll_ok = true;
- }
-
- /* This is a simple back-off algorithm where we immediately
- * re-poll if we did something this time around.
- *
- * This greatly improves performance of DCC.
- */
- poll_ok = poll_ok || target_got_message();
-
- for (service = services; service; service = service->next) {
- /* handle new connections on listeners */
- if ((service->fd != -1)
- && (FD_ISSET(service->fd, &read_fds))) {
- if (service->max_connections != 0)
- add_connection(service, command_context);
- else {
- if (service->type == CONNECTION_TCP) {
- struct sockaddr_in sin;
- socklen_t address_size = sizeof(sin);
- int tmp_fd;
- tmp_fd = accept(service->fd,
- (struct sockaddr *)&service->sin,
- &address_size);
- close_socket(tmp_fd);
- }
- LOG_INFO(
- "rejected '%s' connection, no more connections allowed",
- service->name);
- }
- }
-
- /* handle activity on connections */
- if (service->connections) {
- struct connection *c;
-
- for (c = service->connections; c; ) {
- if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending) {
- retval = service->input(c);
- if (retval != ERROR_OK) {
- struct connection *next = c->next;
- if (service->type == CONNECTION_PIPE ||
- service->type == CONNECTION_STDINOUT) {
- /* if connection uses a pipe then
- * shutdown openocd on error */
- shutdown_openocd = 1;
- }
- remove_connection(service, c);
- LOG_INFO("dropped '%s' connection",
- service->name);
- c = next;
- continue;
- }
- }
- c = c->next;
- }
- }
- }
-
-#ifdef _WIN32
- MSG msg;
- while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
- if (msg.message == WM_QUIT)
- shutdown_openocd = 1;
- }
-#endif
- }
-
- return shutdown_openocd != 2 ? ERROR_OK : ERROR_FAIL;
-}
-
-#ifdef _WIN32
-BOOL WINAPI ControlHandler(DWORD dwCtrlType)
-{
- shutdown_openocd = 1;
- return TRUE;
-}
-#endif
-
-void sig_handler(int sig)
-{
- /* store only first signal that hits us */
- if (!last_signal)
- last_signal = sig;
- shutdown_openocd = 1;
-}
-
-int server_preinit(void)
-{
- /* this currently only calls WSAStartup on native win32 systems
- * before any socket operations are performed.
- * This is an issue if you call init in your config script */
-
-#ifdef _WIN32
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(2, 2);
-
- if (WSAStartup(wVersionRequested, &wsaData) != 0) {
- LOG_ERROR("Failed to Open Winsock");
- exit(-1);
- }
-
- /* register ctrl-c handler */
- SetConsoleCtrlHandler(ControlHandler, TRUE);
-
- signal(SIGBREAK, sig_handler);
-#endif
- signal(SIGINT, sig_handler);
- signal(SIGTERM, sig_handler);
- signal(SIGABRT, sig_handler);
-
- return ERROR_OK;
-}
-
-int server_init(struct command_context *cmd_ctx)
-{
- int ret = tcl_init();
- if (ERROR_OK != ret)
- return ret;
-
- return telnet_init("Open On-Chip Debugger");
-}
-
-int server_quit(void)
-{
- remove_services();
- target_quit();
-
-#ifdef _WIN32
- WSACleanup();
- SetConsoleCtrlHandler(ControlHandler, FALSE);
-
- return ERROR_OK;
-#endif
-
- /* return signal number so we can kill ourselves */
- return last_signal;
-}
-
-void exit_on_signal(int sig)
-{
-#ifndef _WIN32
- /* bring back default system handler and kill yourself */
- signal(sig, SIG_DFL);
- kill(getpid(), sig);
-#endif
-}
-
-int connection_write(struct connection *connection, const void *data, int len)
-{
- if (len == 0) {
- /* successful no-op. Sockets and pipes behave differently here... */
- return 0;
- }
- if (connection->service->type == CONNECTION_TCP)
- return write_socket(connection->fd_out, data, len);
- else
- return write(connection->fd_out, data, len);
-}
-
-int connection_read(struct connection *connection, void *data, int len)
-{
- if (connection->service->type == CONNECTION_TCP)
- return read_socket(connection->fd, data, len);
- else
- return read(connection->fd, data, len);
-}
-
-/* tell the server we want to shut down */
-COMMAND_HANDLER(handle_shutdown_command)
-{
- LOG_USER("shutdown command invoked");
-
- shutdown_openocd = 1;
-
- if (CMD_ARGC == 1) {
- if (!strcmp(CMD_ARGV[0], "error")) {
- shutdown_openocd = 2;
- return ERROR_FAIL;
- }
- }
-
- return ERROR_COMMAND_CLOSE_CONNECTION;
-}
-
-COMMAND_HANDLER(handle_poll_period_command)
-{
- if (CMD_ARGC == 0)
- LOG_WARNING("You need to set a period value");
- else
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], polling_period);
-
- LOG_INFO("set servers polling period to %ums", polling_period);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_bindto_command)
-{
- switch (CMD_ARGC) {
- case 0:
- command_print(CMD_CTX, "bindto name: %s", bindto_name);
- break;
- case 1:
- free(bindto_name);
- bindto_name = strdup(CMD_ARGV[0]);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return ERROR_OK;
-}
-
-static const struct command_registration server_command_handlers[] = {
- {
- .name = "shutdown",
- .handler = &handle_shutdown_command,
- .mode = COMMAND_ANY,
- .usage = "",
- .help = "shut the server down",
- },
- {
- .name = "poll_period",
- .handler = &handle_poll_period_command,
- .mode = COMMAND_ANY,
- .usage = "",
- .help = "set the servers polling period",
- },
- {
- .name = "bindto",
- .handler = &handle_bindto_command,
- .mode = COMMAND_ANY,
- .usage = "[name]",
- .help = "Specify address by name on which to listen for "
- "incoming TCP/IP connections",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int server_register_commands(struct command_context *cmd_ctx)
-{
- int retval = telnet_register_commands(cmd_ctx);
- if (ERROR_OK != retval)
- return retval;
-
- retval = tcl_register_commands(cmd_ctx);
- if (ERROR_OK != retval)
- return retval;
-
- retval = jsp_register_commands(cmd_ctx);
- if (ERROR_OK != retval)
- return retval;
-
- return register_commands(cmd_ctx, NULL, server_command_handlers);
-}
-
-COMMAND_HELPER(server_port_command, unsigned short *out)
-{
- switch (CMD_ARGC) {
- case 0:
- command_print(CMD_CTX, "%d", *out);
- break;
- case 1:
- {
- uint16_t port;
- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
- *out = port;
- break;
- }
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return ERROR_OK;
-}
-
-COMMAND_HELPER(server_pipe_command, char **out)
-{
- switch (CMD_ARGC) {
- case 0:
- command_print(CMD_CTX, "%s", *out);
- break;
- case 1:
- {
- if (CMD_CTX->mode == COMMAND_EXEC) {
- LOG_WARNING("unable to change server port after init");
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- free(*out);
- *out = strdup(CMD_ARGV[0]);
- break;
- }
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return ERROR_OK;
-}
diff --git a/src/server/server.h b/src/server/server.h
deleted file mode 100644
index 68ad16d..0000000
--- a/src/server/server.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_SERVER_SERVER_H
-#define OPENOCD_SERVER_SERVER_H
-
-#include <helper/log.h>
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-enum connection_type {
- CONNECTION_TCP,
- CONNECTION_PIPE,
- CONNECTION_STDINOUT
-};
-
-#define CONNECTION_LIMIT_UNLIMITED (-1)
-
-struct connection {
- int fd;
- int fd_out; /* When using pipes we're writing to a different fd */
- struct sockaddr_in sin;
- struct command_context *cmd_ctx;
- struct service *service;
- int input_pending;
- void *priv;
- struct connection *next;
-};
-
-typedef int (*new_connection_handler_t)(struct connection *connection);
-typedef int (*input_handler_t)(struct connection *connection);
-typedef int (*connection_closed_handler_t)(struct connection *connection);
-
-struct service {
- char *name;
- enum connection_type type;
- char *port;
- unsigned short portnumber;
- int fd;
- struct sockaddr_in sin;
- int max_connections;
- struct connection *connections;
- new_connection_handler_t new_connection;
- input_handler_t input;
- connection_closed_handler_t connection_closed;
- void *priv;
- struct service *next;
-};
-
-int add_service(char *name, const char *port,
- int max_connections, new_connection_handler_t new_connection_handler,
- input_handler_t in_handler, connection_closed_handler_t close_handler,
- void *priv);
-
-int server_preinit(void);
-int server_init(struct command_context *cmd_ctx);
-int server_quit(void);
-void exit_on_signal(int);
-
-int server_loop(struct command_context *command_context);
-
-int server_register_commands(struct command_context *context);
-
-int connection_write(struct connection *connection, const void *data, int len);
-int connection_read(struct connection *connection, void *data, int len);
-
-/**
- * Used by server_loop(), defined in server_stubs.c
- */
-void openocd_sleep_prelude(void);
-/**
- * Used by server_loop(), defined in server_stubs.c
- */
-void openocd_sleep_postlude(void);
-
-/**
- * Defines an extended command handler function declaration to enable
- * access to (and manipulation of) the server port number.
- * Call server_port like a normal COMMAND_HANDLER with an extra @a out parameter
- * to receive the specified port number.
- */
-COMMAND_HELPER(server_pipe_command, char **out);
-
-COMMAND_HELPER(server_port_command, unsigned short *out);
-
-#define ERROR_SERVER_REMOTE_CLOSED (-400)
-#define ERROR_CONNECTION_REJECTED (-401)
-
-#endif /* OPENOCD_SERVER_SERVER_H */
diff --git a/src/server/server_stubs.c b/src/server/server_stubs.c
deleted file mode 100644
index a4c0172..0000000
--- a/src/server/server_stubs.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "server.h"
-
-void openocd_sleep_prelude(void)
-{
- /* no-op */
-}
-void openocd_sleep_postlude(void)
-{
- /* no-op */
-}
diff --git a/src/server/startup.tcl b/src/server/startup.tcl
deleted file mode 100644
index 64ace40..0000000
--- a/src/server/startup.tcl
+++ /dev/null
@@ -1,10 +0,0 @@
-# Defines basic Tcl procs for OpenOCD server modules
-
-# Handle GDB 'R' packet. Can be overridden by configuration script,
-# but it's not something one would expect target scripts to do
-# normally
-proc ocd_gdb_restart {target_id} {
- # Fix!!! we're resetting all targets here! Really we should reset only
- # one target
- reset halt
-}
diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c
deleted file mode 100644
index 15a8736..0000000
--- a/src/server/tcl_server.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "tcl_server.h"
-#include <target/target.h>
-#include <helper/binarybuffer.h>
-
-#define TCL_SERVER_VERSION "TCL Server 0.1"
-#define TCL_LINE_INITIAL (4*1024)
-#define TCL_LINE_MAX (4*1024*1024)
-
-struct tcl_connection {
- int tc_linedrop;
- int tc_lineoffset;
- int tc_line_size;
- char *tc_line;
- int tc_outerror;/* flag an output error */
- enum target_state tc_laststate;
- bool tc_notify;
- bool tc_trace;
-};
-
-static char *tcl_port;
-
-/* handlers */
-static int tcl_new_connection(struct connection *connection);
-static int tcl_input(struct connection *connection);
-static int tcl_output(struct connection *connection, const void *buf, ssize_t len);
-static int tcl_closed(struct connection *connection);
-
-static int tcl_target_callback_event_handler(struct target *target,
- enum target_event event, void *priv)
-{
- struct connection *connection = priv;
- struct tcl_connection *tclc;
- char buf[256];
-
- tclc = connection->priv;
-
- if (tclc->tc_notify) {
- snprintf(buf, sizeof(buf), "type target_event event %s\r\n\x1a", target_event_name(event));
- tcl_output(connection, buf, strlen(buf));
- }
-
- if (tclc->tc_laststate != target->state) {
- tclc->tc_laststate = target->state;
- if (tclc->tc_notify) {
- snprintf(buf, sizeof(buf), "type target_state state %s\r\n\x1a", target_state_name(target));
- tcl_output(connection, buf, strlen(buf));
- }
- }
-
- return ERROR_OK;
-}
-
-static int tcl_target_callback_reset_handler(struct target *target,
- enum target_reset_mode reset_mode, void *priv)
-{
- struct connection *connection = priv;
- struct tcl_connection *tclc;
- char buf[256];
-
- tclc = connection->priv;
-
- if (tclc->tc_notify) {
- snprintf(buf, sizeof(buf), "type target_reset mode %s\r\n\x1a", target_reset_mode_name(reset_mode));
- tcl_output(connection, buf, strlen(buf));
- }
-
- return ERROR_OK;
-}
-
-static int tcl_target_callback_trace_handler(struct target *target,
- size_t len, uint8_t *data, void *priv)
-{
- struct connection *connection = priv;
- struct tcl_connection *tclc;
- char *header = "type target_trace data ";
- char *trailer = "\r\n\x1a";
- size_t hex_len = len * 2 + 1;
- size_t max_len = hex_len + strlen(header) + strlen(trailer);
- char *buf, *hex;
-
- tclc = connection->priv;
-
- if (tclc->tc_trace) {
- hex = malloc(hex_len);
- buf = malloc(max_len);
- hexify(hex, (const char *)data, len, hex_len);
- snprintf(buf, max_len, "%s%s%s", header, hex, trailer);
- tcl_output(connection, buf, strlen(buf));
- free(hex);
- free(buf);
- }
-
- return ERROR_OK;
-}
-
-/* write data out to a socket.
- *
- * this is a blocking write, so the return value must equal the length, if
- * that is not the case then flag the connection with an output error.
- */
-int tcl_output(struct connection *connection, const void *data, ssize_t len)
-{
- ssize_t wlen;
- struct tcl_connection *tclc;
-
- tclc = connection->priv;
- if (tclc->tc_outerror)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- wlen = connection_write(connection, data, len);
-
- if (wlen == len)
- return ERROR_OK;
-
- LOG_ERROR("error during write: %d != %d", (int)wlen, (int)len);
- tclc->tc_outerror = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
-}
-
-/* connections */
-static int tcl_new_connection(struct connection *connection)
-{
- struct tcl_connection *tclc;
-
- tclc = calloc(1, sizeof(struct tcl_connection));
- if (tclc == NULL)
- return ERROR_CONNECTION_REJECTED;
-
- tclc->tc_line_size = TCL_LINE_INITIAL;
- tclc->tc_line = malloc(tclc->tc_line_size);
- if (tclc->tc_line == NULL) {
- free(tclc);
- return ERROR_CONNECTION_REJECTED;
- }
-
- connection->priv = tclc;
-
- struct target *target = get_target_by_num(connection->cmd_ctx->current_target);
- if (target != NULL)
- tclc->tc_laststate = target->state;
-
- /* store the connection object on cmd_ctx so we can access it from command handlers */
- connection->cmd_ctx->output_handler_priv = connection;
-
- target_register_event_callback(tcl_target_callback_event_handler, connection);
- target_register_reset_callback(tcl_target_callback_reset_handler, connection);
- target_register_trace_callback(tcl_target_callback_trace_handler, connection);
-
- return ERROR_OK;
-}
-
-static int tcl_input(struct connection *connection)
-{
- Jim_Interp *interp = (Jim_Interp *)connection->cmd_ctx->interp;
- int retval;
- int i;
- ssize_t rlen;
- const char *result;
- int reslen;
- struct tcl_connection *tclc;
- unsigned char in[256];
- char *tc_line_new;
- int tc_line_size_new;
-
- rlen = connection_read(connection, &in, sizeof(in));
- if (rlen <= 0) {
- if (rlen < 0)
- LOG_ERROR("error during read: %s", strerror(errno));
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- tclc = connection->priv;
- if (tclc == NULL)
- return ERROR_CONNECTION_REJECTED;
-
- /* push as much data into the line as possible */
- for (i = 0; i < rlen; i++) {
- /* buffer the data */
- tclc->tc_line[tclc->tc_lineoffset] = in[i];
- if (tclc->tc_lineoffset < tclc->tc_line_size) {
- tclc->tc_lineoffset++;
- } else if (tclc->tc_line_size >= TCL_LINE_MAX) {
- /* maximum line size reached, drop line */
- tclc->tc_linedrop = 1;
- } else {
- /* grow line buffer: exponential below 1 MB, linear above */
- if (tclc->tc_line_size <= 1*1024*1024)
- tc_line_size_new = tclc->tc_line_size * 2;
- else
- tc_line_size_new = tclc->tc_line_size + 1*1024*1024;
-
- if (tc_line_size_new > TCL_LINE_MAX)
- tc_line_size_new = TCL_LINE_MAX;
-
- tc_line_new = realloc(tclc->tc_line, tc_line_size_new);
- if (tc_line_new == NULL) {
- tclc->tc_linedrop = 1;
- } else {
- tclc->tc_line = tc_line_new;
- tclc->tc_line_size = tc_line_size_new;
- tclc->tc_lineoffset++;
- }
-
- }
-
- /* ctrl-z is end of command. When testing from telnet, just
- * press ctrl-z a couple of times first to put telnet into the
- * mode where it will send 0x1a in response to pressing ctrl-z
- */
- if (in[i] != '\x1a')
- continue;
-
- /* process the line */
- if (tclc->tc_linedrop) {
-#define ESTR "line too long\n"
- retval = tcl_output(connection, ESTR, sizeof(ESTR));
- if (retval != ERROR_OK)
- return retval;
-#undef ESTR
- } else {
- tclc->tc_line[tclc->tc_lineoffset-1] = '\0';
- command_run_line(connection->cmd_ctx, tclc->tc_line);
- result = Jim_GetString(Jim_GetResult(interp), &reslen);
- retval = tcl_output(connection, result, reslen);
- if (retval != ERROR_OK)
- return retval;
- /* Always output ctrl-d as end of line to allow multiline results */
- tcl_output(connection, "\x1a", 1);
- }
-
- tclc->tc_lineoffset = 0;
- tclc->tc_linedrop = 0;
- }
-
- return ERROR_OK;
-}
-
-static int tcl_closed(struct connection *connection)
-{
- struct tcl_connection *tclc;
- tclc = connection->priv;
-
- /* cleanup connection context */
- if (tclc) {
- free(tclc->tc_line);
- free(tclc);
- connection->priv = NULL;
- }
-
- target_unregister_event_callback(tcl_target_callback_event_handler, connection);
- target_unregister_reset_callback(tcl_target_callback_reset_handler, connection);
- target_unregister_trace_callback(tcl_target_callback_trace_handler, connection);
-
- return ERROR_OK;
-}
-
-int tcl_init(void)
-{
- if (strcmp(tcl_port, "disabled") == 0) {
- LOG_INFO("tcl server disabled");
- return ERROR_OK;
- }
-
- return add_service("tcl", tcl_port, CONNECTION_LIMIT_UNLIMITED,
- &tcl_new_connection, &tcl_input,
- &tcl_closed, NULL);
-}
-
-COMMAND_HANDLER(handle_tcl_port_command)
-{
- return CALL_COMMAND_HANDLER(server_pipe_command, &tcl_port);
-}
-
-COMMAND_HANDLER(handle_tcl_notifications_command)
-{
- struct connection *connection = NULL;
- struct tcl_connection *tclc = NULL;
-
- if (CMD_CTX->output_handler_priv != NULL)
- connection = CMD_CTX->output_handler_priv;
-
- if (connection != NULL && !strcmp(connection->service->name, "tcl")) {
- tclc = connection->priv;
- return CALL_COMMAND_HANDLER(handle_command_parse_bool, &tclc->tc_notify, "Target Notification output ");
- } else {
- LOG_ERROR("%s: can only be called from the tcl server", CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-}
-
-COMMAND_HANDLER(handle_tcl_trace_command)
-{
- struct connection *connection = NULL;
- struct tcl_connection *tclc = NULL;
-
- if (CMD_CTX->output_handler_priv != NULL)
- connection = CMD_CTX->output_handler_priv;
-
- if (connection != NULL && !strcmp(connection->service->name, "tcl")) {
- tclc = connection->priv;
- return CALL_COMMAND_HANDLER(handle_command_parse_bool, &tclc->tc_trace, "Target trace output ");
- } else {
- LOG_ERROR("%s: can only be called from the tcl server", CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-}
-
-static const struct command_registration tcl_command_handlers[] = {
- {
- .name = "tcl_port",
- .handler = handle_tcl_port_command,
- .mode = COMMAND_ANY,
- .help = "Specify port on which to listen "
- "for incoming Tcl syntax. "
- "Read help on 'gdb_port'.",
- .usage = "[port_num]",
- },
- {
- .name = "tcl_notifications",
- .handler = handle_tcl_notifications_command,
- .mode = COMMAND_EXEC,
- .help = "Target Notification output",
- .usage = "[on|off]",
- },
- {
- .name = "tcl_trace",
- .handler = handle_tcl_trace_command,
- .mode = COMMAND_EXEC,
- .help = "Target trace output",
- .usage = "[on|off]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int tcl_register_commands(struct command_context *cmd_ctx)
-{
- tcl_port = strdup("6666");
- return register_commands(cmd_ctx, NULL, tcl_command_handlers);
-}
diff --git a/src/server/tcl_server.h b/src/server/tcl_server.h
deleted file mode 100644
index 422c794..0000000
--- a/src/server/tcl_server.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_SERVER_TCL_SERVER_H
-#define OPENOCD_SERVER_TCL_SERVER_H
-
-#include <server/server.h>
-
-int tcl_init(void);
-int tcl_register_commands(struct command_context *cmd_ctx);
-
-#endif /* OPENOCD_SERVER_TCL_SERVER_H */
diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c
deleted file mode 100644
index 0f5769a..0000000
--- a/src/server/telnet_server.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "telnet_server.h"
-#include <target/target_request.h>
-#include <helper/configuration.h>
-
-static char *telnet_port;
-
-static char *negotiate =
- "\xFF\xFB\x03" /* IAC WILL Suppress Go Ahead */
- "\xFF\xFB\x01" /* IAC WILL Echo */
- "\xFF\xFD\x03" /* IAC DO Suppress Go Ahead */
- "\xFF\xFE\x01"; /* IAC DON'T Echo */
-
-#define CTRL(c) (c - '@')
-#define TELNET_HISTORY ".openocd_history"
-
-/* The only way we can detect that the socket is closed is the first time
- * we write to it, we will fail. Subsequent write operations will
- * succeed. Shudder!
- */
-static int telnet_write(struct connection *connection, const void *data,
- int len)
-{
- struct telnet_connection *t_con = connection->priv;
- if (t_con->closed)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- if (connection_write(connection, data, len) == len)
- return ERROR_OK;
- t_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
-}
-
-static int telnet_prompt(struct connection *connection)
-{
- struct telnet_connection *t_con = connection->priv;
-
- return telnet_write(connection, t_con->prompt, strlen(t_con->prompt));
-}
-
-static int telnet_outputline(struct connection *connection, const char *line)
-{
- int len;
-
- /* process lines in buffer */
- while (*line) {
- char *line_end = strchr(line, '\n');
-
- if (line_end)
- len = line_end-line;
- else
- len = strlen(line);
-
- telnet_write(connection, line, len);
- if (line_end) {
- telnet_write(connection, "\r\n", 2);
- line += len + 1;
- } else
- line += len;
- }
-
- return ERROR_OK;
-}
-
-static int telnet_output(struct command_context *cmd_ctx, const char *line)
-{
- struct connection *connection = cmd_ctx->output_handler_priv;
-
- return telnet_outputline(connection, line);
-}
-
-static void telnet_log_callback(void *priv, const char *file, unsigned line,
- const char *function, const char *string)
-{
- struct connection *connection = priv;
- struct telnet_connection *t_con = connection->priv;
- int i;
-
- /* if there is no prompt, simply output the message */
- if (t_con->line_cursor < 0) {
- telnet_outputline(connection, string);
- return;
- }
-
- /* clear the command line */
- for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
- telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
- for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
- telnet_write(connection, " ", i > 16 ? 16 : i);
- for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
- telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
-
- /* output the message */
- telnet_outputline(connection, string);
-
- /* put the command line to its previous state */
- telnet_prompt(connection);
- telnet_write(connection, t_con->line, t_con->line_size);
- for (i = t_con->line_size; i > t_con->line_cursor; i--)
- telnet_write(connection, "\b", 1);
-}
-
-static void telnet_load_history(struct telnet_connection *t_con)
-{
- FILE *histfp;
- char buffer[TELNET_BUFFER_SIZE];
- int i = 0;
-
- char *history = get_home_dir(TELNET_HISTORY);
-
- if (history == NULL) {
- LOG_INFO("unable to get user home directory, telnet history will be disabled");
- return;
- }
-
- histfp = fopen(history, "rb");
-
- if (histfp) {
-
- while (fgets(buffer, sizeof(buffer), histfp) != NULL) {
-
- char *p = strchr(buffer, '\n');
- if (p)
- *p = '\0';
- if (buffer[0] && i < TELNET_LINE_HISTORY_SIZE)
- t_con->history[i++] = strdup(buffer);
- }
-
- t_con->next_history = i;
- t_con->next_history %= TELNET_LINE_HISTORY_SIZE;
- /* try to set to last entry - 1, that way we skip over any exit/shutdown cmds */
- t_con->current_history = t_con->next_history > 0 ? i - 1 : 0;
- fclose(histfp);
- }
-
- free(history);
-}
-
-static void telnet_save_history(struct telnet_connection *t_con)
-{
- FILE *histfp;
- int i;
- int num;
-
- char *history = get_home_dir(TELNET_HISTORY);
-
- if (history == NULL) {
- LOG_INFO("unable to get user home directory, telnet history will be disabled");
- return;
- }
-
- histfp = fopen(history, "wb");
-
- if (histfp) {
-
- num = TELNET_LINE_HISTORY_SIZE;
- i = t_con->current_history + 1;
- i %= TELNET_LINE_HISTORY_SIZE;
-
- while (t_con->history[i] == NULL && num > 0) {
- i++;
- i %= TELNET_LINE_HISTORY_SIZE;
- num--;
- }
-
- if (num > 0) {
- for (; num > 0; num--) {
- fprintf(histfp, "%s\n", t_con->history[i]);
- i++;
- i %= TELNET_LINE_HISTORY_SIZE;
- }
- }
- fclose(histfp);
- }
-
- free(history);
-}
-
-static int telnet_new_connection(struct connection *connection)
-{
- struct telnet_connection *telnet_connection;
- struct telnet_service *telnet_service = connection->service->priv;
- int i;
-
- telnet_connection = malloc(sizeof(struct telnet_connection));
-
- if (!telnet_connection) {
- LOG_ERROR("Failed to allocate telnet connection.");
- return ERROR_FAIL;
- }
-
- connection->priv = telnet_connection;
-
- /* initialize telnet connection information */
- telnet_connection->closed = 0;
- telnet_connection->line_size = 0;
- telnet_connection->line_cursor = 0;
- telnet_connection->option_size = 0;
- telnet_connection->prompt = strdup("> ");
- telnet_connection->state = TELNET_STATE_DATA;
-
- /* output goes through telnet connection */
- command_set_output_handler(connection->cmd_ctx, telnet_output, connection);
-
- /* negotiate telnet options */
- telnet_write(connection, negotiate, strlen(negotiate));
-
- /* print connection banner */
- if (telnet_service->banner) {
- telnet_write(connection, telnet_service->banner, strlen(telnet_service->banner));
- telnet_write(connection, "\r\n", 2);
- }
-
- /* the prompt is always placed at the line beginning */
- telnet_write(connection, "\r", 1);
- telnet_prompt(connection);
-
- /* initialize history */
- for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)
- telnet_connection->history[i] = NULL;
- telnet_connection->next_history = 0;
- telnet_connection->current_history = 0;
- telnet_load_history(telnet_connection);
-
- log_add_callback(telnet_log_callback, connection);
-
- return ERROR_OK;
-}
-
-static void telnet_clear_line(struct connection *connection,
- struct telnet_connection *t_con)
-{
- /* move to end of line */
- if (t_con->line_cursor < t_con->line_size)
- telnet_write(connection,
- t_con->line + t_con->line_cursor,
- t_con->line_size - t_con->line_cursor);
-
- /* backspace, overwrite with space, backspace */
- while (t_con->line_size > 0) {
- telnet_write(connection, "\b \b", 3);
- t_con->line_size--;
- }
- t_con->line_cursor = 0;
-}
-
-static void telnet_history_go(struct connection *connection, int idx)
-{
- struct telnet_connection *t_con = connection->priv;
-
- if (t_con->history[idx]) {
- telnet_clear_line(connection, t_con);
- t_con->line_size = strlen(t_con->history[idx]);
- t_con->line_cursor = t_con->line_size;
- memcpy(t_con->line, t_con->history[idx], t_con->line_size);
- telnet_write(connection, t_con->line, t_con->line_size);
- t_con->current_history = idx;
- }
- t_con->state = TELNET_STATE_DATA;
-}
-
-static void telnet_history_up(struct connection *connection)
-{
- struct telnet_connection *t_con = connection->priv;
-
- int last_history = (t_con->current_history > 0) ?
- t_con->current_history - 1 :
- TELNET_LINE_HISTORY_SIZE-1;
- telnet_history_go(connection, last_history);
-}
-
-static void telnet_history_down(struct connection *connection)
-{
- struct telnet_connection *t_con = connection->priv;
-
- int next_history = (t_con->current_history + 1) % TELNET_LINE_HISTORY_SIZE;
- telnet_history_go(connection, next_history);
-}
-
-static int telnet_input(struct connection *connection)
-{
- int bytes_read;
- unsigned char buffer[TELNET_BUFFER_SIZE];
- unsigned char *buf_p;
- struct telnet_connection *t_con = connection->priv;
- struct command_context *command_context = connection->cmd_ctx;
-
- bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE);
-
- if (bytes_read == 0)
- return ERROR_SERVER_REMOTE_CLOSED;
- else if (bytes_read == -1) {
- LOG_ERROR("error during read: %s", strerror(errno));
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- buf_p = buffer;
- while (bytes_read) {
- switch (t_con->state) {
- case TELNET_STATE_DATA:
- if (*buf_p == 0xff)
- t_con->state = TELNET_STATE_IAC;
- else {
- if (isprint(*buf_p)) { /* printable character */
- /* watch buffer size leaving one spare character for
- * string null termination */
- if (t_con->line_size == TELNET_LINE_MAX_SIZE-1) {
- /* output audible bell if buffer is full
- * "\a" does not work, at least on windows */
- telnet_write(connection, "\x07", 1);
- } else if (t_con->line_cursor == t_con->line_size) {
- telnet_write(connection, buf_p, 1);
- t_con->line[t_con->line_size++] = *buf_p;
- t_con->line_cursor++;
- } else {
- int i;
- memmove(t_con->line + t_con->line_cursor + 1,
- t_con->line + t_con->line_cursor,
- t_con->line_size - t_con->line_cursor);
- t_con->line[t_con->line_cursor] = *buf_p;
- t_con->line_size++;
- telnet_write(connection,
- t_con->line + t_con->line_cursor,
- t_con->line_size - t_con->line_cursor);
- t_con->line_cursor++;
- for (i = t_con->line_cursor; i < t_con->line_size; i++)
- telnet_write(connection, "\b", 1);
- }
- } else { /* non-printable */
- if (*buf_p == 0x1b) { /* escape */
- t_con->state = TELNET_STATE_ESCAPE;
- t_con->last_escape = '\x00';
- } else if ((*buf_p == 0xd) || (*buf_p == 0xa)) { /* CR/LF */
- int retval;
-
- /* skip over combinations with CR/LF and NUL characters */
- if ((bytes_read > 1) && ((*(buf_p + 1) == 0xa) ||
- (*(buf_p + 1) == 0xd))) {
- buf_p++;
- bytes_read--;
- }
- if ((bytes_read > 1) && (*(buf_p + 1) == 0)) {
- buf_p++;
- bytes_read--;
- }
- t_con->line[t_con->line_size] = 0;
-
- telnet_write(connection, "\r\n\x00", 3);
-
- if (strcmp(t_con->line, "history") == 0) {
- int i;
- for (i = 1; i < TELNET_LINE_HISTORY_SIZE; i++) {
- /* the t_con->next_history line contains empty string
- * (unless NULL), thus it is not printed */
- char *history_line = t_con->history[(t_con->
- next_history + i) %
- TELNET_LINE_HISTORY_SIZE];
- if (history_line) {
- telnet_write(connection, history_line,
- strlen(history_line));
- telnet_write(connection, "\r\n\x00", 3);
- }
- }
- t_con->line_size = 0;
- t_con->line_cursor = 0;
- continue;
- }
-
- /* save only non-blank not repeating lines in the history */
- char *prev_line = t_con->history[(t_con->current_history > 0) ?
- t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1];
- if (*t_con->line && (prev_line == NULL ||
- strcmp(t_con->line, prev_line))) {
- /* if the history slot is already taken, free it */
- if (t_con->history[t_con->next_history])
- free(t_con->history[t_con->next_history]);
-
- /* add line to history */
- t_con->history[t_con->next_history] = strdup(t_con->line);
-
- /* wrap history at TELNET_LINE_HISTORY_SIZE */
- t_con->next_history = (t_con->next_history + 1) %
- TELNET_LINE_HISTORY_SIZE;
-
- /* current history line starts at the new entry */
- t_con->current_history =
- t_con->next_history;
-
- if (t_con->history[t_con->current_history])
- free(t_con->history[t_con->current_history]);
- t_con->history[t_con->current_history] = strdup("");
- }
-
- t_con->line_size = 0;
-
- /* to suppress prompt in log callback during command execution */
- t_con->line_cursor = -1;
-
- if (strcmp(t_con->line, "shutdown") == 0)
- telnet_save_history(t_con);
-
- retval = command_run_line(command_context, t_con->line);
-
- t_con->line_cursor = 0;
-
- if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- /* the prompt is always * placed at the line beginning */
- telnet_write(connection, "\r", 1);
-
- retval = telnet_prompt(connection);
- if (retval == ERROR_SERVER_REMOTE_CLOSED)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- } else if ((*buf_p == 0x7f) || (*buf_p == 0x8)) { /* delete character */
- if (t_con->line_cursor > 0) {
- if (t_con->line_cursor != t_con->line_size) {
- int i;
- telnet_write(connection, "\b", 1);
- t_con->line_cursor--;
- t_con->line_size--;
- memmove(t_con->line + t_con->line_cursor,
- t_con->line + t_con->line_cursor + 1,
- t_con->line_size -
- t_con->line_cursor);
-
- telnet_write(connection,
- t_con->line + t_con->line_cursor,
- t_con->line_size -
- t_con->line_cursor);
- telnet_write(connection, " \b", 2);
- for (i = t_con->line_cursor; i < t_con->line_size; i++)
- telnet_write(connection, "\b", 1);
- } else {
- t_con->line_size--;
- t_con->line_cursor--;
- /* back space: move the 'printer' head one char
- * back, overwrite with space, move back again */
- telnet_write(connection, "\b \b", 3);
- }
- }
- } else if (*buf_p == 0x15) /* clear line */
- telnet_clear_line(connection, t_con);
- else if (*buf_p == CTRL('B')) { /* cursor left */
- if (t_con->line_cursor > 0) {
- telnet_write(connection, "\b", 1);
- t_con->line_cursor--;
- }
- t_con->state = TELNET_STATE_DATA;
- } else if (*buf_p == CTRL('F')) { /* cursor right */
- if (t_con->line_cursor < t_con->line_size)
- telnet_write(connection, t_con->line + t_con->line_cursor++, 1);
- t_con->state = TELNET_STATE_DATA;
- } else if (*buf_p == CTRL('P')) /* cursor up */
- telnet_history_up(connection);
- else if (*buf_p == CTRL('N')) /* cursor down */
- telnet_history_down(connection);
- else
- LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p);
- }
- }
- break;
- case TELNET_STATE_IAC:
- switch (*buf_p) {
- case 0xfe:
- t_con->state = TELNET_STATE_DONT;
- break;
- case 0xfd:
- t_con->state = TELNET_STATE_DO;
- break;
- case 0xfc:
- t_con->state = TELNET_STATE_WONT;
- break;
- case 0xfb:
- t_con->state = TELNET_STATE_WILL;
- break;
- }
- break;
- case TELNET_STATE_SB:
- break;
- case TELNET_STATE_SE:
- break;
- case TELNET_STATE_WILL:
- case TELNET_STATE_WONT:
- case TELNET_STATE_DO:
- case TELNET_STATE_DONT:
- t_con->state = TELNET_STATE_DATA;
- break;
- case TELNET_STATE_ESCAPE:
- if (t_con->last_escape == '[') {
- if (*buf_p == 'D') { /* cursor left */
- if (t_con->line_cursor > 0) {
- telnet_write(connection, "\b", 1);
- t_con->line_cursor--;
- }
- t_con->state = TELNET_STATE_DATA;
- } else if (*buf_p == 'C') { /* cursor right */
- if (t_con->line_cursor < t_con->line_size)
- telnet_write(connection,
- t_con->line + t_con->line_cursor++, 1);
- t_con->state = TELNET_STATE_DATA;
- } else if (*buf_p == 'A') { /* cursor up */
- telnet_history_up(connection);
- } else if (*buf_p == 'B') { /* cursor down */
- telnet_history_down(connection);
- } else if (*buf_p == '3')
- t_con->last_escape = *buf_p;
- else
- t_con->state = TELNET_STATE_DATA;
- } else if (t_con->last_escape == '3') {
- /* Remove character */
- if (*buf_p == '~') {
- if (t_con->line_cursor < t_con->line_size) {
- int i;
- t_con->line_size--;
- /* remove char from line buffer */
- memmove(t_con->line + t_con->line_cursor,
- t_con->line + t_con->line_cursor + 1,
- t_con->line_size - t_con->line_cursor);
-
- /* print remainder of buffer */
- telnet_write(connection, t_con->line + t_con->line_cursor,
- t_con->line_size - t_con->line_cursor);
- /* overwrite last char with whitespace */
- telnet_write(connection, " \b", 2);
-
- /* move back to cursor position*/
- for (i = t_con->line_cursor; i < t_con->line_size; i++)
- telnet_write(connection, "\b", 1);
- }
-
- t_con->state = TELNET_STATE_DATA;
- } else
- t_con->state = TELNET_STATE_DATA;
- } else if (t_con->last_escape == '\x00') {
- if (*buf_p == '[')
- t_con->last_escape = *buf_p;
- else
- t_con->state = TELNET_STATE_DATA;
- } else {
- LOG_ERROR("BUG: unexpected value in t_con->last_escape");
- t_con->state = TELNET_STATE_DATA;
- }
-
- break;
- default:
- LOG_ERROR("unknown telnet state");
- exit(-1);
- }
-
- bytes_read--;
- buf_p++;
- }
-
- return ERROR_OK;
-}
-
-static int telnet_connection_closed(struct connection *connection)
-{
- struct telnet_connection *t_con = connection->priv;
- int i;
-
- log_remove_callback(telnet_log_callback, connection);
-
- if (t_con->prompt) {
- free(t_con->prompt);
- t_con->prompt = NULL;
- }
-
- /* save telnet history */
- telnet_save_history(t_con);
-
- for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++) {
- if (t_con->history[i]) {
- free(t_con->history[i]);
- t_con->history[i] = NULL;
- }
- }
-
- /* if this connection registered a debug-message receiver delete it */
- delete_debug_msg_receiver(connection->cmd_ctx, NULL);
-
- if (connection->priv) {
- free(connection->priv);
- connection->priv = NULL;
- } else
- LOG_ERROR("BUG: connection->priv == NULL");
-
- return ERROR_OK;
-}
-
-int telnet_init(char *banner)
-{
- if (strcmp(telnet_port, "disabled") == 0) {
- LOG_INFO("telnet server disabled");
- return ERROR_OK;
- }
-
- struct telnet_service *telnet_service;
-
- telnet_service = malloc(sizeof(struct telnet_service));
-
- if (!telnet_service) {
- LOG_ERROR("Failed to allocate telnet service.");
- return ERROR_FAIL;
- }
-
- telnet_service->banner = banner;
-
- return add_service("telnet",
- telnet_port,
- CONNECTION_LIMIT_UNLIMITED,
- telnet_new_connection,
- telnet_input,
- telnet_connection_closed,
- telnet_service);
-}
-
-/* daemon configuration command telnet_port */
-COMMAND_HANDLER(handle_telnet_port_command)
-{
- return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port);
-}
-
-COMMAND_HANDLER(handle_exit_command)
-{
- return ERROR_COMMAND_CLOSE_CONNECTION;
-}
-
-static const struct command_registration telnet_command_handlers[] = {
- {
- .name = "exit",
- .handler = handle_exit_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "exit telnet session",
- },
- {
- .name = "telnet_port",
- .handler = handle_telnet_port_command,
- .mode = COMMAND_ANY,
- .help = "Specify port on which to listen "
- "for incoming telnet connections. "
- "Read help on 'gdb_port'.",
- .usage = "[port_num]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int telnet_register_commands(struct command_context *cmd_ctx)
-{
- telnet_port = strdup("4444");
- return register_commands(cmd_ctx, NULL, telnet_command_handlers);
-}
diff --git a/src/server/telnet_server.h b/src/server/telnet_server.h
deleted file mode 100644
index 04ba965..0000000
--- a/src/server/telnet_server.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_SERVER_TELNET_SERVER_H
-#define OPENOCD_SERVER_TELNET_SERVER_H
-
-#include <server/server.h>
-
-#define TELNET_BUFFER_SIZE (1024)
-
-#define TELNET_OPTION_MAX_SIZE (128)
-#define TELNET_LINE_HISTORY_SIZE (128)
-#define TELNET_LINE_MAX_SIZE (256)
-
-enum telnet_states {
- TELNET_STATE_DATA,
- TELNET_STATE_IAC,
- TELNET_STATE_SB,
- TELNET_STATE_SE,
- TELNET_STATE_WILL,
- TELNET_STATE_WONT,
- TELNET_STATE_DO,
- TELNET_STATE_DONT,
- TELNET_STATE_ESCAPE,
-};
-
-struct telnet_connection {
- char *prompt;
- enum telnet_states state;
- char line[TELNET_LINE_MAX_SIZE];
- int line_size;
- int line_cursor;
- char option[TELNET_OPTION_MAX_SIZE];
- int option_size;
- char last_escape;
- char *history[TELNET_LINE_HISTORY_SIZE];
- int next_history;
- int current_history;
- int closed;
-};
-
-struct telnet_service {
- char *banner;
-};
-
-int telnet_init(char *banner);
-int telnet_register_commands(struct command_context *command_context);
-
-#endif /* OPENOCD_SERVER_TELNET_SERVER_H */
diff --git a/src/svf/Makefile.am b/src/svf/Makefile.am
deleted file mode 100644
index 3a14d20..0000000
--- a/src/svf/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-include $(top_srcdir)/common.mk
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libsvf.la
-noinst_HEADERS = svf.h
-libsvf_la_SOURCES = svf.c
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/svf/svf.c b/src/svf/svf.c
deleted file mode 100644
index e7e815c..0000000
--- a/src/svf/svf.c
+++ /dev/null
@@ -1,1578 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Simon Qian *
- * SimonQian@SimonQian.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* The specification for SVF is available here:
- * http://www.asset-intertech.com/support/svf.pdf
- * Below, this document is refered to as the "SVF spec".
- *
- * The specification for XSVF is available here:
- * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf
- * Below, this document is refered to as the "XSVF spec".
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/jtag.h>
-#include "svf.h"
-#include <helper/time_support.h>
-
-/* SVF command */
-enum svf_command {
- ENDDR,
- ENDIR,
- FREQUENCY,
- HDR,
- HIR,
- PIO,
- PIOMAP,
- RUNTEST,
- SDR,
- SIR,
- STATE,
- TDR,
- TIR,
- TRST,
-};
-
-static const char *svf_command_name[14] = {
- "ENDDR",
- "ENDIR",
- "FREQUENCY",
- "HDR",
- "HIR",
- "PIO",
- "PIOMAP",
- "RUNTEST",
- "SDR",
- "SIR",
- "STATE",
- "TDR",
- "TIR",
- "TRST"
-};
-
-enum trst_mode {
- TRST_ON,
- TRST_OFF,
- TRST_Z,
- TRST_ABSENT
-};
-
-static const char *svf_trst_mode_name[4] = {
- "ON",
- "OFF",
- "Z",
- "ABSENT"
-};
-
-struct svf_statemove {
- tap_state_t from;
- tap_state_t to;
- uint32_t num_of_moves;
- tap_state_t paths[8];
-};
-
-/*
- * These paths are from the SVF specification for the STATE command, to be
- * used when the STATE command only includes the final state. The first
- * element of the path is the "from" (current) state, and the last one is
- * the "to" (target) state.
- *
- * All specified paths are the shortest ones in the JTAG spec, and are thus
- * not (!!) exact matches for the paths used elsewhere in OpenOCD. Note
- * that PAUSE-to-PAUSE transitions all go through UPDATE and then CAPTURE,
- * which has specific effects on the various registers; they are not NOPs.
- *
- * Paths to RESET are disabled here. As elsewhere in OpenOCD, and in XSVF
- * and many SVF implementations, we don't want to risk missing that state.
- * To get to RESET, always we ignore the current state.
- */
-static const struct svf_statemove svf_statemoves[] = {
- /* from to num_of_moves, paths[8] */
-/* {TAP_RESET, TAP_RESET, 1, {TAP_RESET}}, */
- {TAP_RESET, TAP_IDLE, 2, {TAP_RESET, TAP_IDLE} },
- {TAP_RESET, TAP_DRPAUSE, 6, {TAP_RESET, TAP_IDLE, TAP_DRSELECT,
- TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE} },
- {TAP_RESET, TAP_IRPAUSE, 7, {TAP_RESET, TAP_IDLE, TAP_DRSELECT,
- TAP_IRSELECT, TAP_IRCAPTURE,
- TAP_IREXIT1, TAP_IRPAUSE} },
-
-/* {TAP_IDLE, TAP_RESET, 4, {TAP_IDLE,
- * TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
- {TAP_IDLE, TAP_IDLE, 1, {TAP_IDLE} },
- {TAP_IDLE, TAP_DRPAUSE, 5, {TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE,
- TAP_DREXIT1, TAP_DRPAUSE} },
- {TAP_IDLE, TAP_IRPAUSE, 6, {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT,
- TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE} },
-
-/* {TAP_DRPAUSE, TAP_RESET, 6, {TAP_DRPAUSE,
- * TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
- {TAP_DRPAUSE, TAP_IDLE, 4, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE,
- TAP_IDLE} },
- {TAP_DRPAUSE, TAP_DRPAUSE, 7, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE,
- TAP_DRSELECT, TAP_DRCAPTURE,
- TAP_DREXIT1, TAP_DRPAUSE} },
- {TAP_DRPAUSE, TAP_IRPAUSE, 8, {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE,
- TAP_DRSELECT, TAP_IRSELECT,
- TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE} },
-
-/* {TAP_IRPAUSE, TAP_RESET, 6, {TAP_IRPAUSE,
- * TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}}, */
- {TAP_IRPAUSE, TAP_IDLE, 4, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE,
- TAP_IDLE} },
- {TAP_IRPAUSE, TAP_DRPAUSE, 7, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE,
- TAP_DRSELECT, TAP_DRCAPTURE,
- TAP_DREXIT1, TAP_DRPAUSE} },
- {TAP_IRPAUSE, TAP_IRPAUSE, 8, {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE,
- TAP_DRSELECT, TAP_IRSELECT,
- TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE} }
-};
-
-#define XXR_TDI (1 << 0)
-#define XXR_TDO (1 << 1)
-#define XXR_MASK (1 << 2)
-#define XXR_SMASK (1 << 3)
-struct svf_xxr_para {
- int len;
- int data_mask;
- uint8_t *tdi;
- uint8_t *tdo;
- uint8_t *mask;
- uint8_t *smask;
-};
-
-struct svf_para {
- float frequency;
- tap_state_t ir_end_state;
- tap_state_t dr_end_state;
- tap_state_t runtest_run_state;
- tap_state_t runtest_end_state;
- enum trst_mode trst_mode;
-
- struct svf_xxr_para hir_para;
- struct svf_xxr_para hdr_para;
- struct svf_xxr_para tir_para;
- struct svf_xxr_para tdr_para;
- struct svf_xxr_para sir_para;
- struct svf_xxr_para sdr_para;
-};
-
-static struct svf_para svf_para;
-static const struct svf_para svf_para_init = {
-/* frequency, ir_end_state, dr_end_state, runtest_run_state, runtest_end_state, trst_mode */
- 0, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TRST_Z,
-/* hir_para */
-/* {len, data_mask, tdi, tdo, mask, smask}, */
- {0, 0, NULL, NULL, NULL, NULL},
-/* hdr_para */
-/* {len, data_mask, tdi, tdo, mask, smask}, */
- {0, 0, NULL, NULL, NULL, NULL},
-/* tir_para */
-/* {len, data_mask, tdi, tdo, mask, smask}, */
- {0, 0, NULL, NULL, NULL, NULL},
-/* tdr_para */
-/* {len, data_mask, tdi, tdo, mask, smask}, */
- {0, 0, NULL, NULL, NULL, NULL},
-/* sir_para */
-/* {len, data_mask, tdi, tdo, mask, smask}, */
- {0, 0, NULL, NULL, NULL, NULL},
-/* sdr_para */
-/* {len, data_mask, tdi, tdo, mask, smask}, */
- {0, 0, NULL, NULL, NULL, NULL},
-};
-
-struct svf_check_tdo_para {
- int line_num; /* used to record line number of the check operation */
- /* so more information could be printed */
- int enabled; /* check is enabled or not */
- int buffer_offset; /* buffer_offset to buffers */
- int bit_len; /* bit length to check */
-};
-
-#define SVF_CHECK_TDO_PARA_SIZE 1024
-static struct svf_check_tdo_para *svf_check_tdo_para;
-static int svf_check_tdo_para_index;
-
-static int svf_read_command_from_file(FILE *fd);
-static int svf_check_tdo(void);
-static int svf_add_check_para(uint8_t enabled, int buffer_offset, int bit_len);
-static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str);
-static int svf_execute_tap(void);
-
-static FILE *svf_fd;
-static char *svf_read_line;
-static size_t svf_read_line_size;
-static char *svf_command_buffer;
-static size_t svf_command_buffer_size;
-static int svf_line_number;
-static int svf_getline(char **lineptr, size_t *n, FILE *stream);
-
-#define SVF_MAX_BUFFER_SIZE_TO_COMMIT (1024 * 1024)
-static uint8_t *svf_tdi_buffer, *svf_tdo_buffer, *svf_mask_buffer;
-static int svf_buffer_index, svf_buffer_size ;
-static int svf_quiet;
-static int svf_nil;
-static int svf_ignore_error;
-
-/* Targetting particular tap */
-static int svf_tap_is_specified;
-static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi);
-
-/* Progress Indicator */
-static int svf_progress_enabled;
-static long svf_total_lines;
-static int svf_percentage;
-static int svf_last_printed_percentage = -1;
-
-/*
- * macro is used to print the svf hex buffer at desired debug level
- * DEBUG, INFO, ERROR, USER
- */
-#define SVF_BUF_LOG(_lvl, _buf, _nbits, _desc) \
- svf_hexbuf_print(LOG_LVL_##_lvl , __FILE__, __LINE__, __func__, _buf, _nbits, _desc)
-
-static void svf_hexbuf_print(int dbg_lvl, const char *file, unsigned line,
- const char *function, const uint8_t *buf,
- int bit_len, const char *desc)
-{
- int j, len = 0;
- int byte_len = DIV_ROUND_UP(bit_len, 8);
- int msbits = bit_len % 8;
-
- /* allocate 2 bytes per hex digit */
- char *prbuf = malloc((byte_len * 2) + 2 + 1);
- if (!prbuf)
- return;
-
- /* print correct number of bytes, mask excess bits where applicable */
- uint8_t msb = buf[byte_len - 1] & (msbits ? (1 << msbits) - 1 : 0xff);
- len = sprintf(prbuf, msbits <= 4 ? "0x%01"PRIx8 : "0x%02"PRIx8, msb);
- for (j = byte_len - 2; j >= 0; j--)
- len += sprintf(prbuf + len, "%02"PRIx8, buf[j]);
-
- log_printf_lf(dbg_lvl, file, line, function, "%8s = %s", desc ? desc : " ", prbuf);
-
- free(prbuf);
-}
-
-static int svf_realloc_buffers(size_t len)
-{
- void *ptr;
-
- if (svf_execute_tap() != ERROR_OK)
- return ERROR_FAIL;
-
- ptr = realloc(svf_tdi_buffer, len);
- if (!ptr)
- return ERROR_FAIL;
- svf_tdi_buffer = ptr;
-
- ptr = realloc(svf_tdo_buffer, len);
- if (!ptr)
- return ERROR_FAIL;
- svf_tdo_buffer = ptr;
-
- ptr = realloc(svf_mask_buffer, len);
- if (!ptr)
- return ERROR_FAIL;
- svf_mask_buffer = ptr;
-
- svf_buffer_size = len;
-
- return ERROR_OK;
-}
-
-static void svf_free_xxd_para(struct svf_xxr_para *para)
-{
- if (NULL != para) {
- if (para->tdi != NULL) {
- free(para->tdi);
- para->tdi = NULL;
- }
- if (para->tdo != NULL) {
- free(para->tdo);
- para->tdo = NULL;
- }
- if (para->mask != NULL) {
- free(para->mask);
- para->mask = NULL;
- }
- if (para->smask != NULL) {
- free(para->smask);
- para->smask = NULL;
- }
- }
-}
-
-int svf_add_statemove(tap_state_t state_to)
-{
- tap_state_t state_from = cmd_queue_cur_state;
- unsigned index_var;
-
- /* when resetting, be paranoid and ignore current state */
- if (state_to == TAP_RESET) {
- if (svf_nil)
- return ERROR_OK;
-
- jtag_add_tlr();
- return ERROR_OK;
- }
-
- for (index_var = 0; index_var < ARRAY_SIZE(svf_statemoves); index_var++) {
- if ((svf_statemoves[index_var].from == state_from)
- && (svf_statemoves[index_var].to == state_to)) {
- if (svf_nil)
- continue;
- /* recorded path includes current state ... avoid
- *extra TCKs! */
- if (svf_statemoves[index_var].num_of_moves > 1)
- jtag_add_pathmove(svf_statemoves[index_var].num_of_moves - 1,
- svf_statemoves[index_var].paths + 1);
- else
- jtag_add_pathmove(svf_statemoves[index_var].num_of_moves,
- svf_statemoves[index_var].paths);
- return ERROR_OK;
- }
- }
- LOG_ERROR("SVF: can not move to %s", tap_state_name(state_to));
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(handle_svf_command)
-{
-#define SVF_MIN_NUM_OF_OPTIONS 1
-#define SVF_MAX_NUM_OF_OPTIONS 5
- int command_num = 0;
- int ret = ERROR_OK;
- int64_t time_measure_ms;
- int time_measure_s, time_measure_m;
-
- /* use NULL to indicate a "plain" svf file which accounts for
- * any additional devices in the scan chain, otherwise the device
- * that should be affected
- */
- struct jtag_tap *tap = NULL;
-
- if ((CMD_ARGC < SVF_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > SVF_MAX_NUM_OF_OPTIONS))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* parse command line */
- svf_quiet = 0;
- svf_nil = 0;
- svf_progress_enabled = 0;
- svf_ignore_error = 0;
- for (unsigned int i = 0; i < CMD_ARGC; i++) {
- if (strcmp(CMD_ARGV[i], "-tap") == 0) {
- tap = jtag_tap_by_string(CMD_ARGV[i+1]);
- if (!tap) {
- command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[i+1]);
- return ERROR_FAIL;
- }
- i++;
- } else if ((strcmp(CMD_ARGV[i],
- "quiet") == 0) || (strcmp(CMD_ARGV[i], "-quiet") == 0))
- svf_quiet = 1;
- else if ((strcmp(CMD_ARGV[i], "nil") == 0) || (strcmp(CMD_ARGV[i], "-nil") == 0))
- svf_nil = 1;
- else if ((strcmp(CMD_ARGV[i],
- "progress") == 0) || (strcmp(CMD_ARGV[i], "-progress") == 0))
- svf_progress_enabled = 1;
- else if ((strcmp(CMD_ARGV[i],
- "ignore_error") == 0) || (strcmp(CMD_ARGV[i], "-ignore_error") == 0))
- svf_ignore_error = 1;
- else {
- svf_fd = fopen(CMD_ARGV[i], "r");
- if (svf_fd == NULL) {
- int err = errno;
- command_print(CMD_CTX, "open(\"%s\"): %s", CMD_ARGV[i], strerror(err));
- /* no need to free anything now */
- return ERROR_COMMAND_SYNTAX_ERROR;
- } else
- LOG_USER("svf processing file: \"%s\"", CMD_ARGV[i]);
- }
- }
-
- if (svf_fd == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* get time */
- time_measure_ms = timeval_ms();
-
- /* init */
- svf_line_number = 0;
- svf_command_buffer_size = 0;
-
- svf_check_tdo_para_index = 0;
- svf_check_tdo_para = malloc(sizeof(struct svf_check_tdo_para) * SVF_CHECK_TDO_PARA_SIZE);
- if (NULL == svf_check_tdo_para) {
- LOG_ERROR("not enough memory");
- ret = ERROR_FAIL;
- goto free_all;
- }
-
- svf_buffer_index = 0;
- /* double the buffer size */
- /* in case current command cannot be committed, and next command is a bit scan command */
- /* here is 32K bits for this big scan command, it should be enough */
- /* buffer will be reallocated if buffer size is not enough */
- if (svf_realloc_buffers(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT) != ERROR_OK) {
- ret = ERROR_FAIL;
- goto free_all;
- }
-
- memcpy(&svf_para, &svf_para_init, sizeof(svf_para));
-
- if (!svf_nil) {
- /* TAP_RESET */
- jtag_add_tlr();
- }
-
- if (tap) {
- /* Tap is specified, set header/trailer paddings */
- int header_ir_len = 0, header_dr_len = 0, trailer_ir_len = 0, trailer_dr_len = 0;
- struct jtag_tap *check_tap;
-
- svf_tap_is_specified = 1;
-
- for (check_tap = jtag_all_taps(); check_tap; check_tap = check_tap->next_tap) {
- if (check_tap->abs_chain_position < tap->abs_chain_position) {
- /* Header */
- header_ir_len += check_tap->ir_length;
- header_dr_len++;
- } else if (check_tap->abs_chain_position > tap->abs_chain_position) {
- /* Trailer */
- trailer_ir_len += check_tap->ir_length;
- trailer_dr_len++;
- }
- }
-
- /* HDR %d TDI (0) */
- if (ERROR_OK != svf_set_padding(&svf_para.hdr_para, header_dr_len, 0)) {
- LOG_ERROR("failed to set data header");
- return ERROR_FAIL;
- }
-
- /* HIR %d TDI (0xFF) */
- if (ERROR_OK != svf_set_padding(&svf_para.hir_para, header_ir_len, 0xFF)) {
- LOG_ERROR("failed to set instruction header");
- return ERROR_FAIL;
- }
-
- /* TDR %d TDI (0) */
- if (ERROR_OK != svf_set_padding(&svf_para.tdr_para, trailer_dr_len, 0)) {
- LOG_ERROR("failed to set data trailer");
- return ERROR_FAIL;
- }
-
- /* TIR %d TDI (0xFF) */
- if (ERROR_OK != svf_set_padding(&svf_para.tir_para, trailer_ir_len, 0xFF)) {
- LOG_ERROR("failed to set instruction trailer");
- return ERROR_FAIL;
- }
- }
-
- if (svf_progress_enabled) {
- /* Count total lines in file. */
- while (!feof(svf_fd)) {
- svf_getline(&svf_command_buffer, &svf_command_buffer_size, svf_fd);
- svf_total_lines++;
- }
- rewind(svf_fd);
- }
- while (ERROR_OK == svf_read_command_from_file(svf_fd)) {
- /* Log Output */
- if (svf_quiet) {
- if (svf_progress_enabled) {
- svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5;
- if (svf_last_printed_percentage != svf_percentage) {
- LOG_USER_N("\r%d%% ", svf_percentage);
- svf_last_printed_percentage = svf_percentage;
- }
- }
- } else {
- if (svf_progress_enabled) {
- svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5;
- LOG_USER_N("%3d%% %s", svf_percentage, svf_read_line);
- } else
- LOG_USER_N("%s", svf_read_line);
- }
- /* Run Command */
- if (ERROR_OK != svf_run_command(CMD_CTX, svf_command_buffer)) {
- LOG_ERROR("fail to run command at line %d", svf_line_number);
- ret = ERROR_FAIL;
- break;
- }
- command_num++;
- }
-
- if ((!svf_nil) && (ERROR_OK != jtag_execute_queue()))
- ret = ERROR_FAIL;
- else if (ERROR_OK != svf_check_tdo())
- ret = ERROR_FAIL;
-
- /* print time */
- time_measure_ms = timeval_ms() - time_measure_ms;
- time_measure_s = time_measure_ms / 1000;
- time_measure_ms %= 1000;
- time_measure_m = time_measure_s / 60;
- time_measure_s %= 60;
- if (time_measure_ms < 1000)
- command_print(CMD_CTX,
- "\r\nTime used: %dm%ds%" PRId64 "ms ",
- time_measure_m,
- time_measure_s,
- time_measure_ms);
-
-free_all:
-
- fclose(svf_fd);
- svf_fd = 0;
-
- /* free buffers */
- if (svf_command_buffer) {
- free(svf_command_buffer);
- svf_command_buffer = NULL;
- svf_command_buffer_size = 0;
- }
- if (svf_check_tdo_para) {
- free(svf_check_tdo_para);
- svf_check_tdo_para = NULL;
- svf_check_tdo_para_index = 0;
- }
- if (svf_tdi_buffer) {
- free(svf_tdi_buffer);
- svf_tdi_buffer = NULL;
- }
- if (svf_tdo_buffer) {
- free(svf_tdo_buffer);
- svf_tdo_buffer = NULL;
- }
- if (svf_mask_buffer) {
- free(svf_mask_buffer);
- svf_mask_buffer = NULL;
- }
- svf_buffer_index = 0;
- svf_buffer_size = 0;
-
- svf_free_xxd_para(&svf_para.hdr_para);
- svf_free_xxd_para(&svf_para.hir_para);
- svf_free_xxd_para(&svf_para.tdr_para);
- svf_free_xxd_para(&svf_para.tir_para);
- svf_free_xxd_para(&svf_para.sdr_para);
- svf_free_xxd_para(&svf_para.sir_para);
-
- if (ERROR_OK == ret)
- command_print(CMD_CTX,
- "svf file programmed %s for %d commands with %d errors",
- (svf_ignore_error > 1) ? "unsuccessfully" : "successfully",
- command_num,
- (svf_ignore_error > 1) ? (svf_ignore_error - 1) : 0);
- else
- command_print(CMD_CTX, "svf file programmed failed");
-
- svf_ignore_error = 0;
- return ret;
-}
-
-static int svf_getline(char **lineptr, size_t *n, FILE *stream)
-{
-#define MIN_CHUNK 16 /* Buffer is increased by this size each time as required */
- size_t i = 0;
-
- if (*lineptr == NULL) {
- *n = MIN_CHUNK;
- *lineptr = malloc(*n);
- if (!*lineptr)
- return -1;
- }
-
- (*lineptr)[0] = fgetc(stream);
- while ((*lineptr)[i] != '\n') {
- (*lineptr)[++i] = fgetc(stream);
- if (feof(stream)) {
- (*lineptr)[0] = 0;
- return -1;
- }
- if ((i + 2) > *n) {
- *n += MIN_CHUNK;
- *lineptr = realloc(*lineptr, *n);
- }
- }
-
- (*lineptr)[++i] = 0;
-
- return sizeof(*lineptr);
-}
-
-#define SVFP_CMD_INC_CNT 1024
-static int svf_read_command_from_file(FILE *fd)
-{
- unsigned char ch;
- int i = 0;
- size_t cmd_pos = 0;
- int cmd_ok = 0, slash = 0;
-
- if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
- return ERROR_FAIL;
- svf_line_number++;
- ch = svf_read_line[0];
- while (!cmd_ok && (ch != 0)) {
- switch (ch) {
- case '!':
- slash = 0;
- if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
- return ERROR_FAIL;
- svf_line_number++;
- i = -1;
- break;
- case '/':
- if (++slash == 2) {
- slash = 0;
- if (svf_getline(&svf_read_line, &svf_read_line_size,
- svf_fd) <= 0)
- return ERROR_FAIL;
- svf_line_number++;
- i = -1;
- }
- break;
- case ';':
- slash = 0;
- cmd_ok = 1;
- break;
- case '\n':
- svf_line_number++;
- if (svf_getline(&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
- return ERROR_FAIL;
- i = -1;
- case '\r':
- slash = 0;
- /* Don't save '\r' and '\n' if no data is parsed */
- if (!cmd_pos)
- break;
- default:
- /* The parsing code currently expects a space
- * before parentheses -- "TDI (123)". Also a
- * space afterwards -- "TDI (123) TDO(456)".
- * But such spaces are optional... instead of
- * parser updates, cope with that by adding the
- * spaces as needed.
- *
- * Ensure there are 3 bytes available, for:
- * - current character
- * - added space.
- * - terminating NUL ('\0')
- */
- if (cmd_pos + 3 > svf_command_buffer_size) {
- svf_command_buffer = realloc(svf_command_buffer, cmd_pos + 3);
- svf_command_buffer_size = cmd_pos + 3;
- if (svf_command_buffer == NULL) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
- }
-
- /* insert a space before '(' */
- if ('(' == ch)
- svf_command_buffer[cmd_pos++] = ' ';
-
- svf_command_buffer[cmd_pos++] = (char)toupper(ch);
-
- /* insert a space after ')' */
- if (')' == ch)
- svf_command_buffer[cmd_pos++] = ' ';
- break;
- }
- ch = svf_read_line[++i];
- }
-
- if (cmd_ok) {
- svf_command_buffer[cmd_pos] = '\0';
- return ERROR_OK;
- } else
- return ERROR_FAIL;
-}
-
-static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
-{
- int pos = 0, num = 0, space_found = 1, in_bracket = 0;
-
- while (pos < len) {
- switch (str[pos]) {
- case '!':
- case '/':
- LOG_ERROR("fail to parse svf command");
- return ERROR_FAIL;
- case '(':
- in_bracket = 1;
- goto parse_char;
- case ')':
- in_bracket = 0;
- goto parse_char;
- default:
-parse_char:
- if (!in_bracket && isspace((int) str[pos])) {
- space_found = 1;
- str[pos] = '\0';
- } else if (space_found) {
- argus[num++] = &str[pos];
- space_found = 0;
- }
- break;
- }
- pos++;
- }
-
- *num_of_argu = num;
-
- return ERROR_OK;
-}
-
-bool svf_tap_state_is_stable(tap_state_t state)
-{
- return (TAP_RESET == state) || (TAP_IDLE == state)
- || (TAP_DRPAUSE == state) || (TAP_IRPAUSE == state);
-}
-
-static int svf_find_string_in_array(char *str, char **strs, int num_of_element)
-{
- int i;
-
- for (i = 0; i < num_of_element; i++) {
- if (!strcmp(str, strs[i]))
- return i;
- }
- return 0xFF;
-}
-
-static int svf_adjust_array_length(uint8_t **arr, int orig_bit_len, int new_bit_len)
-{
- int new_byte_len = (new_bit_len + 7) >> 3;
-
- if ((NULL == *arr) || (((orig_bit_len + 7) >> 3) < ((new_bit_len + 7) >> 3))) {
- if (*arr != NULL) {
- free(*arr);
- *arr = NULL;
- }
- *arr = malloc(new_byte_len);
- if (NULL == *arr) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
- memset(*arr, 0, new_byte_len);
- }
- return ERROR_OK;
-}
-
-static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi)
-{
- int error = ERROR_OK;
- error |= svf_adjust_array_length(&para->tdi, para->len, len);
- memset(para->tdi, tdi, (len + 7) >> 3);
- error |= svf_adjust_array_length(&para->tdo, para->len, len);
- error |= svf_adjust_array_length(&para->mask, para->len, len);
- para->len = len;
- para->data_mask = XXR_TDI;
-
- return error;
-}
-
-static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_len, int bit_len)
-{
- int i, str_len = strlen(str), str_hbyte_len = (bit_len + 3) >> 2;
- uint8_t ch = 0;
-
- if (ERROR_OK != svf_adjust_array_length(bin, orig_bit_len, bit_len)) {
- LOG_ERROR("fail to adjust length of array");
- return ERROR_FAIL;
- }
-
- /* fill from LSB (end of str) to MSB (beginning of str) */
- for (i = 0; i < str_hbyte_len; i++) {
- ch = 0;
- while (str_len > 0) {
- ch = str[--str_len];
-
- /* Skip whitespace. The SVF specification (rev E) is
- * deficient in terms of basic lexical issues like
- * where whitespace is allowed. Long bitstrings may
- * require line ends for correctness, since there is
- * a hard limit on line length.
- */
- if (!isspace(ch)) {
- if ((ch >= '0') && (ch <= '9')) {
- ch = ch - '0';
- break;
- } else if ((ch >= 'A') && (ch <= 'F')) {
- ch = ch - 'A' + 10;
- break;
- } else {
- LOG_ERROR("invalid hex string");
- return ERROR_FAIL;
- }
- }
-
- ch = 0;
- }
-
- /* write bin */
- if (i % 2) {
- /* MSB */
- (*bin)[i / 2] |= ch << 4;
- } else {
- /* LSB */
- (*bin)[i / 2] = 0;
- (*bin)[i / 2] |= ch;
- }
- }
-
- /* consume optional leading '0' MSBs or whitespace */
- while (str_len > 0 && ((str[str_len - 1] == '0')
- || isspace((int) str[str_len - 1])))
- str_len--;
-
- /* check validity: we must have consumed everything */
- if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0) {
- LOG_ERROR("value execeeds length");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int svf_check_tdo(void)
-{
- int i, len, index_var;
-
- for (i = 0; i < svf_check_tdo_para_index; i++) {
- index_var = svf_check_tdo_para[i].buffer_offset;
- len = svf_check_tdo_para[i].bit_len;
- if ((svf_check_tdo_para[i].enabled)
- && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var],
- &svf_mask_buffer[index_var], len)) {
- LOG_ERROR("tdo check error at line %d",
- svf_check_tdo_para[i].line_num);
- SVF_BUF_LOG(ERROR, &svf_tdi_buffer[index_var], len, "READ");
- SVF_BUF_LOG(ERROR, &svf_tdo_buffer[index_var], len, "WANT");
- SVF_BUF_LOG(ERROR, &svf_mask_buffer[index_var], len, "MASK");
-
- if (svf_ignore_error == 0)
- return ERROR_FAIL;
- else
- svf_ignore_error++;
- }
- }
- svf_check_tdo_para_index = 0;
-
- return ERROR_OK;
-}
-
-static int svf_add_check_para(uint8_t enabled, int buffer_offset, int bit_len)
-{
- if (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE) {
- LOG_ERROR("toooooo many operation undone");
- return ERROR_FAIL;
- }
-
- svf_check_tdo_para[svf_check_tdo_para_index].line_num = svf_line_number;
- svf_check_tdo_para[svf_check_tdo_para_index].bit_len = bit_len;
- svf_check_tdo_para[svf_check_tdo_para_index].enabled = enabled;
- svf_check_tdo_para[svf_check_tdo_para_index].buffer_offset = buffer_offset;
- svf_check_tdo_para_index++;
-
- return ERROR_OK;
-}
-
-static int svf_execute_tap(void)
-{
- if ((!svf_nil) && (ERROR_OK != jtag_execute_queue()))
- return ERROR_FAIL;
- else if (ERROR_OK != svf_check_tdo())
- return ERROR_FAIL;
-
- svf_buffer_index = 0;
-
- return ERROR_OK;
-}
-
-static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
-{
- char *argus[256], command;
- int num_of_argu = 0, i;
-
- /* tmp variable */
- int i_tmp;
-
- /* for RUNTEST */
- int run_count;
- float min_time;
- /* for XXR */
- struct svf_xxr_para *xxr_para_tmp;
- uint8_t **pbuffer_tmp;
- struct scan_field field;
- /* for STATE */
- tap_state_t *path = NULL, state;
- /* flag padding commands skipped due to -tap command */
- int padding_command_skipped = 0;
-
- if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu))
- return ERROR_FAIL;
-
- /* NOTE: we're a bit loose here, because we ignore case in
- * TAP state names (instead of insisting on uppercase).
- */
-
- command = svf_find_string_in_array(argus[0],
- (char **)svf_command_name, ARRAY_SIZE(svf_command_name));
- switch (command) {
- case ENDDR:
- case ENDIR:
- if (num_of_argu != 2) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
- return ERROR_FAIL;
- }
-
- i_tmp = tap_state_by_name(argus[1]);
-
- if (svf_tap_state_is_stable(i_tmp)) {
- if (command == ENDIR) {
- svf_para.ir_end_state = i_tmp;
- LOG_DEBUG("\tIR end_state = %s",
- tap_state_name(i_tmp));
- } else {
- svf_para.dr_end_state = i_tmp;
- LOG_DEBUG("\tDR end_state = %s",
- tap_state_name(i_tmp));
- }
- } else {
- LOG_ERROR("%s: %s is not a stable state",
- argus[0], argus[1]);
- return ERROR_FAIL;
- }
- break;
- case FREQUENCY:
- if ((num_of_argu != 1) && (num_of_argu != 3)) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
- return ERROR_FAIL;
- }
- if (1 == num_of_argu) {
- /* TODO: set jtag speed to full speed */
- svf_para.frequency = 0;
- } else {
- if (strcmp(argus[2], "HZ")) {
- LOG_ERROR("HZ not found in FREQUENCY command");
- return ERROR_FAIL;
- }
- if (ERROR_OK != svf_execute_tap())
- return ERROR_FAIL;
- svf_para.frequency = atof(argus[1]);
- /* TODO: set jtag speed to */
- if (svf_para.frequency > 0) {
- command_run_linef(cmd_ctx,
- "adapter_khz %d",
- (int)svf_para.frequency / 1000);
- LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
- }
- }
- break;
- case HDR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.hdr_para;
- goto XXR_common;
- case HIR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.hir_para;
- goto XXR_common;
- case TDR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.tdr_para;
- goto XXR_common;
- case TIR:
- if (svf_tap_is_specified) {
- padding_command_skipped = 1;
- break;
- }
- xxr_para_tmp = &svf_para.tir_para;
- goto XXR_common;
- case SDR:
- xxr_para_tmp = &svf_para.sdr_para;
- goto XXR_common;
- case SIR:
- xxr_para_tmp = &svf_para.sir_para;
- goto XXR_common;
-XXR_common:
- /* XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] */
- if ((num_of_argu > 10) || (num_of_argu % 2)) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
- return ERROR_FAIL;
- }
- i_tmp = xxr_para_tmp->len;
- xxr_para_tmp->len = atoi(argus[1]);
- /* If we are to enlarge the buffers, all parts of xxr_para_tmp
- * need to be freed */
- if (i_tmp < xxr_para_tmp->len) {
- free(xxr_para_tmp->tdi);
- xxr_para_tmp->tdi = NULL;
- free(xxr_para_tmp->tdo);
- xxr_para_tmp->tdo = NULL;
- free(xxr_para_tmp->mask);
- xxr_para_tmp->mask = NULL;
- free(xxr_para_tmp->smask);
- xxr_para_tmp->smask = NULL;
- }
-
- LOG_DEBUG("\tlength = %d", xxr_para_tmp->len);
- xxr_para_tmp->data_mask = 0;
- for (i = 2; i < num_of_argu; i += 2) {
- if ((strlen(argus[i + 1]) < 3) || (argus[i + 1][0] != '(') ||
- (argus[i + 1][strlen(argus[i + 1]) - 1] != ')')) {
- LOG_ERROR("data section error");
- return ERROR_FAIL;
- }
- argus[i + 1][strlen(argus[i + 1]) - 1] = '\0';
- /* TDI, TDO, MASK, SMASK */
- if (!strcmp(argus[i], "TDI")) {
- /* TDI */
- pbuffer_tmp = &xxr_para_tmp->tdi;
- xxr_para_tmp->data_mask |= XXR_TDI;
- } else if (!strcmp(argus[i], "TDO")) {
- /* TDO */
- pbuffer_tmp = &xxr_para_tmp->tdo;
- xxr_para_tmp->data_mask |= XXR_TDO;
- } else if (!strcmp(argus[i], "MASK")) {
- /* MASK */
- pbuffer_tmp = &xxr_para_tmp->mask;
- xxr_para_tmp->data_mask |= XXR_MASK;
- } else if (!strcmp(argus[i], "SMASK")) {
- /* SMASK */
- pbuffer_tmp = &xxr_para_tmp->smask;
- xxr_para_tmp->data_mask |= XXR_SMASK;
- } else {
- LOG_ERROR("unknow parameter: %s", argus[i]);
- return ERROR_FAIL;
- }
- if (ERROR_OK !=
- svf_copy_hexstring_to_binary(&argus[i + 1][1], pbuffer_tmp, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to parse hex value");
- return ERROR_FAIL;
- }
- SVF_BUF_LOG(DEBUG, *pbuffer_tmp, xxr_para_tmp->len, argus[i]);
- }
- /* If a command changes the length of the last scan of the same type and the
- * MASK parameter is absent, */
- /* the mask pattern used is all cares */
- if (!(xxr_para_tmp->data_mask & XXR_MASK) && (i_tmp != xxr_para_tmp->len)) {
- /* MASK not defined and length changed */
- if (ERROR_OK !=
- svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to adjust length of array");
- return ERROR_FAIL;
- }
- buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len);
- }
- /* If TDO is absent, no comparison is needed, set the mask to 0 */
- if (!(xxr_para_tmp->data_mask & XXR_TDO)) {
- if (NULL == xxr_para_tmp->tdo) {
- if (ERROR_OK !=
- svf_adjust_array_length(&xxr_para_tmp->tdo, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to adjust length of array");
- return ERROR_FAIL;
- }
- }
- if (NULL == xxr_para_tmp->mask) {
- if (ERROR_OK !=
- svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp,
- xxr_para_tmp->len)) {
- LOG_ERROR("fail to adjust length of array");
- return ERROR_FAIL;
- }
- }
- memset(xxr_para_tmp->mask, 0, (xxr_para_tmp->len + 7) >> 3);
- }
- /* do scan if necessary */
- if (SDR == command) {
- /* check buffer size first, reallocate if necessary */
- i = svf_para.hdr_para.len + svf_para.sdr_para.len +
- svf_para.tdr_para.len;
- if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) {
- /* reallocate buffer */
- if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
- }
-
- /* assemble dr data */
- i = 0;
- buf_set_buf(svf_para.hdr_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.hdr_para.len);
- i += svf_para.hdr_para.len;
- buf_set_buf(svf_para.sdr_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.sdr_para.len);
- i += svf_para.sdr_para.len;
- buf_set_buf(svf_para.tdr_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.tdr_para.len);
- i += svf_para.tdr_para.len;
-
- /* add check data */
- if (svf_para.sdr_para.data_mask & XXR_TDO) {
- /* assemble dr mask data */
- i = 0;
- buf_set_buf(svf_para.hdr_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.hdr_para.len);
- i += svf_para.hdr_para.len;
- buf_set_buf(svf_para.sdr_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.sdr_para.len);
- i += svf_para.sdr_para.len;
- buf_set_buf(svf_para.tdr_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.tdr_para.len);
-
- /* assemble dr check data */
- i = 0;
- buf_set_buf(svf_para.hdr_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.hdr_para.len);
- i += svf_para.hdr_para.len;
- buf_set_buf(svf_para.sdr_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.sdr_para.len);
- i += svf_para.sdr_para.len;
- buf_set_buf(svf_para.tdr_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.tdr_para.len);
- i += svf_para.tdr_para.len;
-
- svf_add_check_para(1, svf_buffer_index, i);
- } else
- svf_add_check_para(0, svf_buffer_index, i);
- field.num_bits = i;
- field.out_value = &svf_tdi_buffer[svf_buffer_index];
- field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL;
- if (!svf_nil) {
- /* NOTE: doesn't use SVF-specified state paths */
- jtag_add_plain_dr_scan(field.num_bits,
- field.out_value,
- field.in_value,
- svf_para.dr_end_state);
- }
-
- svf_buffer_index += (i + 7) >> 3;
- } else if (SIR == command) {
- /* check buffer size first, reallocate if necessary */
- i = svf_para.hir_para.len + svf_para.sir_para.len +
- svf_para.tir_para.len;
- if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) {
- if (svf_realloc_buffers(svf_buffer_index + ((i + 7) >> 3)) != ERROR_OK) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
- }
-
- /* assemble ir data */
- i = 0;
- buf_set_buf(svf_para.hir_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.hir_para.len);
- i += svf_para.hir_para.len;
- buf_set_buf(svf_para.sir_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.sir_para.len);
- i += svf_para.sir_para.len;
- buf_set_buf(svf_para.tir_para.tdi,
- 0,
- &svf_tdi_buffer[svf_buffer_index],
- i,
- svf_para.tir_para.len);
- i += svf_para.tir_para.len;
-
- /* add check data */
- if (svf_para.sir_para.data_mask & XXR_TDO) {
- /* assemble dr mask data */
- i = 0;
- buf_set_buf(svf_para.hir_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.hir_para.len);
- i += svf_para.hir_para.len;
- buf_set_buf(svf_para.sir_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.sir_para.len);
- i += svf_para.sir_para.len;
- buf_set_buf(svf_para.tir_para.mask,
- 0,
- &svf_mask_buffer[svf_buffer_index],
- i,
- svf_para.tir_para.len);
-
- /* assemble dr check data */
- i = 0;
- buf_set_buf(svf_para.hir_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.hir_para.len);
- i += svf_para.hir_para.len;
- buf_set_buf(svf_para.sir_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.sir_para.len);
- i += svf_para.sir_para.len;
- buf_set_buf(svf_para.tir_para.tdo,
- 0,
- &svf_tdo_buffer[svf_buffer_index],
- i,
- svf_para.tir_para.len);
- i += svf_para.tir_para.len;
-
- svf_add_check_para(1, svf_buffer_index, i);
- } else
- svf_add_check_para(0, svf_buffer_index, i);
- field.num_bits = i;
- field.out_value = &svf_tdi_buffer[svf_buffer_index];
- field.in_value = (xxr_para_tmp->data_mask & XXR_TDO) ? &svf_tdi_buffer[svf_buffer_index] : NULL;
- if (!svf_nil) {
- /* NOTE: doesn't use SVF-specified state paths */
- jtag_add_plain_ir_scan(field.num_bits,
- field.out_value,
- field.in_value,
- svf_para.ir_end_state);
- }
-
- svf_buffer_index += (i + 7) >> 3;
- }
- break;
- case PIO:
- case PIOMAP:
- LOG_ERROR("PIO and PIOMAP are not supported");
- return ERROR_FAIL;
- break;
- case RUNTEST:
- /* RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time
- * SEC]] [ENDSTATE end_state] */
- /* RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE
- * end_state] */
- if ((num_of_argu < 3) && (num_of_argu > 11)) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
- return ERROR_FAIL;
- }
- /* init */
- run_count = 0;
- min_time = 0;
- i = 1;
-
- /* run_state */
- i_tmp = tap_state_by_name(argus[i]);
- if (i_tmp != TAP_INVALID) {
- if (svf_tap_state_is_stable(i_tmp)) {
- svf_para.runtest_run_state = i_tmp;
-
- /* When a run_state is specified, the new
- * run_state becomes the default end_state.
- */
- svf_para.runtest_end_state = i_tmp;
- LOG_DEBUG("\trun_state = %s", tap_state_name(i_tmp));
- i++;
- } else {
- LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp));
- return ERROR_FAIL;
- }
- }
-
- /* run_count run_clk */
- if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC")) {
- if (!strcmp(argus[i + 1], "TCK")) {
- /* clock source is TCK */
- run_count = atoi(argus[i]);
- LOG_DEBUG("\trun_count@TCK = %d", run_count);
- } else {
- LOG_ERROR("%s not supported for clock", argus[i + 1]);
- return ERROR_FAIL;
- }
- i += 2;
- }
- /* min_time SEC */
- if (((i + 2) <= num_of_argu) && !strcmp(argus[i + 1], "SEC")) {
- min_time = atof(argus[i]);
- LOG_DEBUG("\tmin_time = %fs", min_time);
- i += 2;
- }
- /* MAXIMUM max_time SEC */
- if (((i + 3) <= num_of_argu) &&
- !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC")) {
- float max_time = 0;
- max_time = atof(argus[i + 1]);
- LOG_DEBUG("\tmax_time = %fs", max_time);
- i += 3;
- }
- /* ENDSTATE end_state */
- if (((i + 2) <= num_of_argu) && !strcmp(argus[i], "ENDSTATE")) {
- i_tmp = tap_state_by_name(argus[i + 1]);
-
- if (svf_tap_state_is_stable(i_tmp)) {
- svf_para.runtest_end_state = i_tmp;
- LOG_DEBUG("\tend_state = %s", tap_state_name(i_tmp));
- } else {
- LOG_ERROR("%s: %s is not a stable state", argus[0], tap_state_name(i_tmp));
- return ERROR_FAIL;
- }
- i += 2;
- }
-
- /* all parameter should be parsed */
- if (i == num_of_argu) {
-#if 1
- /* FIXME handle statemove failures */
- uint32_t min_usec = 1000000 * min_time;
-
- /* enter into run_state if necessary */
- if (cmd_queue_cur_state != svf_para.runtest_run_state)
- svf_add_statemove(svf_para.runtest_run_state);
-
- /* add clocks and/or min wait */
- if (run_count > 0) {
- if (!svf_nil)
- jtag_add_clocks(run_count);
- }
-
- if (min_usec > 0) {
- if (!svf_nil)
- jtag_add_sleep(min_usec);
- }
-
- /* move to end_state if necessary */
- if (svf_para.runtest_end_state != svf_para.runtest_run_state)
- svf_add_statemove(svf_para.runtest_end_state);
-
-#else
- if (svf_para.runtest_run_state != TAP_IDLE) {
- LOG_ERROR("cannot runtest in %s state",
- tap_state_name(svf_para.runtest_run_state));
- return ERROR_FAIL;
- }
-
- if (!svf_nil)
- jtag_add_runtest(run_count, svf_para.runtest_end_state);
-#endif
- } else {
- LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed",
- i,
- num_of_argu);
- return ERROR_FAIL;
- }
- break;
- case STATE:
- /* STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state */
- if (num_of_argu < 2) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
- return ERROR_FAIL;
- }
- if (num_of_argu > 2) {
- /* STATE pathstate1 ... stable_state */
- path = malloc((num_of_argu - 1) * sizeof(tap_state_t));
- if (NULL == path) {
- LOG_ERROR("not enough memory");
- return ERROR_FAIL;
- }
- num_of_argu--; /* num of path */
- i_tmp = 1; /* path is from parameter 1 */
- for (i = 0; i < num_of_argu; i++, i_tmp++) {
- path[i] = tap_state_by_name(argus[i_tmp]);
- if (path[i] == TAP_INVALID) {
- LOG_ERROR("%s: %s is not a valid state", argus[0], argus[i_tmp]);
- free(path);
- return ERROR_FAIL;
- }
- /* OpenOCD refuses paths containing TAP_RESET */
- if (TAP_RESET == path[i]) {
- /* FIXME last state MUST be stable! */
- if (i > 0) {
- if (!svf_nil)
- jtag_add_pathmove(i, path);
- }
- if (!svf_nil)
- jtag_add_tlr();
- num_of_argu -= i + 1;
- i = -1;
- }
- }
- if (num_of_argu > 0) {
- /* execute last path if necessary */
- if (svf_tap_state_is_stable(path[num_of_argu - 1])) {
- /* last state MUST be stable state */
- if (!svf_nil)
- jtag_add_pathmove(num_of_argu, path);
- LOG_DEBUG("\tmove to %s by path_move",
- tap_state_name(path[num_of_argu - 1]));
- } else {
- LOG_ERROR("%s: %s is not a stable state",
- argus[0],
- tap_state_name(path[num_of_argu - 1]));
- free(path);
- return ERROR_FAIL;
- }
- }
-
- free(path);
- path = NULL;
- } else {
- /* STATE stable_state */
- state = tap_state_by_name(argus[1]);
- if (svf_tap_state_is_stable(state)) {
- LOG_DEBUG("\tmove to %s by svf_add_statemove",
- tap_state_name(state));
- /* FIXME handle statemove failures */
- svf_add_statemove(state);
- } else {
- LOG_ERROR("%s: %s is not a stable state",
- argus[0], tap_state_name(state));
- return ERROR_FAIL;
- }
- }
- break;
- case TRST:
- /* TRST trst_mode */
- if (num_of_argu != 2) {
- LOG_ERROR("invalid parameter of %s", argus[0]);
- return ERROR_FAIL;
- }
- if (svf_para.trst_mode != TRST_ABSENT) {
- if (ERROR_OK != svf_execute_tap())
- return ERROR_FAIL;
- i_tmp = svf_find_string_in_array(argus[1],
- (char **)svf_trst_mode_name,
- ARRAY_SIZE(svf_trst_mode_name));
- switch (i_tmp) {
- case TRST_ON:
- if (!svf_nil)
- jtag_add_reset(1, 0);
- break;
- case TRST_Z:
- case TRST_OFF:
- if (!svf_nil)
- jtag_add_reset(0, 0);
- break;
- case TRST_ABSENT:
- break;
- default:
- LOG_ERROR("unknown TRST mode: %s", argus[1]);
- return ERROR_FAIL;
- }
- svf_para.trst_mode = i_tmp;
- LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name[svf_para.trst_mode]);
- } else {
- LOG_ERROR("can not accpet TRST command if trst_mode is ABSENT");
- return ERROR_FAIL;
- }
- break;
- default:
- LOG_ERROR("invalid svf command: %s", argus[0]);
- return ERROR_FAIL;
- break;
- }
-
- if (!svf_quiet) {
- if (padding_command_skipped)
- LOG_USER("(Above Padding command skipped, as per -tap argument)");
- }
-
- if (debug_level >= LOG_LVL_DEBUG) {
- /* for convenient debugging, execute tap if possible */
- if ((svf_buffer_index > 0) && \
- (((command != STATE) && (command != RUNTEST)) || \
- ((command == STATE) && (num_of_argu == 2)))) {
- if (ERROR_OK != svf_execute_tap())
- return ERROR_FAIL;
-
- /* output debug info */
- if ((SIR == command) || (SDR == command)) {
- SVF_BUF_LOG(DEBUG, svf_tdi_buffer, svf_check_tdo_para[0].bit_len, "TDO read");
- }
- }
- } else {
- /* for fast executing, execute tap if necessary */
- /* half of the buffer is for the next command */
- if (((svf_buffer_index >= SVF_MAX_BUFFER_SIZE_TO_COMMIT) ||
- (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE / 2)) && \
- (((command != STATE) && (command != RUNTEST)) || \
- ((command == STATE) && (num_of_argu == 2))))
- return svf_execute_tap();
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration svf_command_handlers[] = {
- {
- .name = "svf",
- .handler = handle_svf_command,
- .mode = COMMAND_EXEC,
- .help = "Runs a SVF file.",
- .usage = "svf [-tap device.tap] <file> [quiet] [nil] [progress] [ignore_error]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int svf_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, svf_command_handlers);
-}
diff --git a/src/svf/svf.h b/src/svf/svf.h
deleted file mode 100644
index 4101a3f..0000000
--- a/src/svf/svf.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Simon Qian *
- * SimonQian@SimonQian.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_SVF_SVF_H
-#define OPENOCD_SVF_SVF_H
-
-#include <jtag/jtag.h>
-
-int svf_register_commands(struct command_context *cmd_ctx);
-
-/**
- * svf_add_statemove() moves from the current state to @a goal_state.
- *
- * @param goal_state The final TAP state.
- * @return ERROR_OK on success, or an error code on failure.
- *
- * The current and goal states must satisfy svf_tap_state_is_stable().
- * State transition paths used by this routine are those given in the
- * SVF specification for single-argument STATE commands (and also used
- * for various other state transitions).
- */
-int svf_add_statemove(tap_state_t goal_state);
-
-/**
- * svf_tap_state_is_stable() returns true for stable non-SHIFT states
- *
- * @param state The TAP state in question
- * @return true iff the state is stable and not a SHIFT state.
- */
-bool svf_tap_state_is_stable(tap_state_t state);
-
-#endif /* OPENOCD_SVF_SVF_H */
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
deleted file mode 100644
index 44299fc..0000000
--- a/src/target/Makefile.am
+++ /dev/null
@@ -1,219 +0,0 @@
-include $(top_srcdir)/common.mk
-
-if OOCD_TRACE
-OOCD_TRACE_FILES = oocd_trace.c
-else
-OOCD_TRACE_FILES =
-endif
-
-SUBDIRS = openrisc
-libtarget_la_LIBADD = $(top_builddir)/src/target/openrisc/libopenrisc.la
-
-BIN2C = $(top_srcdir)/src/helper/bin2char.sh
-
-DEBUG_HANDLER = $(srcdir)/xscale/debug_handler.bin
-EXTRA_DIST = \
- startup.tcl \
- $(wildcard $(srcdir)/xscale/*)
-
-DEBUG_HEADER = xscale_debug.inc
-BUILT_SOURCES = $(DEBUG_HEADER)
-CLEANFILES = $(DEBUG_HEADER)
-
-$(DEBUG_HEADER): $(DEBUG_HANDLER) $(BIN2C)
- $(BIN2C) < $< > $@ || { rm -f $@; false; }
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libtarget.la
-libtarget_la_SOURCES = \
- $(TARGET_CORE_SRC) \
- $(ARM_DEBUG_SRC) \
- $(ARMV4_5_SRC) \
- $(ARMV6_SRC) \
- $(ARMV7_SRC) \
- $(ARM_MISC_SRC) \
- $(AVR32_SRC) \
- $(MIPS32_SRC) \
- $(NDS32_SRC) \
- $(INTEL_IA32_SRC) \
- $(RISCV_SRC) \
- avrt.c \
- dsp563xx.c \
- dsp563xx_once.c \
- dsp5680xx.c \
- hla_target.c
-
-TARGET_CORE_SRC = \
- algorithm.c \
- register.c \
- image.c \
- breakpoints.c \
- target.c \
- target_request.c \
- testee.c \
- smp.c
-
-ARMV4_5_SRC = \
- armv4_5.c \
- armv4_5_mmu.c \
- armv4_5_cache.c \
- $(ARM7_9_SRC)
-
-ARM7_9_SRC = \
- arm7_9_common.c \
- arm7tdmi.c \
- arm720t.c \
- arm9tdmi.c \
- arm920t.c \
- arm966e.c \
- arm946e.c \
- arm926ejs.c \
- feroceon.c
-
-ARM_MISC_SRC = \
- fa526.c \
- xscale.c
-
-ARMV6_SRC = \
- arm11.c \
- arm11_dbgtap.c
-
-ARMV7_SRC = \
- armv7m.c \
- armv7m_trace.c \
- cortex_m.c \
- armv7a.c \
- cortex_a.c \
- ls1_sap.c
-
-ARM_DEBUG_SRC = \
- arm_dpm.c \
- arm_jtag.c \
- arm_disassembler.c \
- arm_simulator.c \
- arm_semihosting.c \
- arm_adi_v5.c \
- armv7a_cache.c \
- armv7a_cache_l2x.c \
- adi_v5_jtag.c \
- adi_v5_swd.c \
- embeddedice.c \
- trace.c \
- etb.c \
- etm.c \
- $(OOCD_TRACE_FILES) \
- etm_dummy.c
-
-AVR32_SRC = \
- avr32_ap7k.c \
- avr32_jtag.c \
- avr32_mem.c \
- avr32_regs.c
-
-MIPS32_SRC = \
- mips32.c \
- mips_m4k.c \
- mips32_pracc.c \
- mips32_dmaacc.c \
- mips_ejtag.c
-
-NDS32_SRC = \
- nds32.c \
- nds32_reg.c \
- nds32_cmd.c \
- nds32_disassembler.c \
- nds32_tlb.c \
- nds32_v2.c \
- nds32_v3_common.c \
- nds32_v3.c \
- nds32_v3m.c \
- nds32_aice.c
-
-INTEL_IA32_SRC = \
- quark_x10xx.c \
- quark_d20xx.c \
- lakemont.c \
- x86_32_common.c
-
-RISCV_SRC = \
- riscv/riscv-011.c \
- riscv/riscv-013.c \
- riscv/riscv.c
-
-noinst_HEADERS = \
- algorithm.h \
- arm.h \
- arm_dpm.h \
- arm_jtag.h \
- arm_adi_v5.h \
- armv7a_cache.h \
- armv7a_cache_l2x.h \
- arm_disassembler.h \
- arm_opcodes.h \
- arm_simulator.h \
- arm_semihosting.h \
- arm7_9_common.h \
- arm7tdmi.h \
- arm720t.h \
- arm9tdmi.h \
- arm920t.h \
- arm926ejs.h \
- arm966e.h \
- arm946e.h \
- arm11.h \
- arm11_dbgtap.h \
- armv4_5.h \
- armv4_5_mmu.h \
- armv4_5_cache.h \
- armv7a.h \
- armv7m.h \
- armv7m_trace.h \
- avrt.h \
- dsp563xx.h \
- dsp563xx_once.h \
- dsp5680xx.h \
- breakpoints.h \
- cortex_m.h \
- cortex_a.h \
- embeddedice.h \
- etb.h \
- etm.h \
- etm_dummy.h \
- image.h \
- mips32.h \
- mips_m4k.h \
- mips_ejtag.h \
- mips32_pracc.h \
- mips32_dmaacc.h \
- oocd_trace.h \
- register.h \
- target.h \
- target_type.h \
- trace.h \
- target_request.h \
- trace.h \
- xscale.h \
- smp.h \
- avr32_ap7k.h \
- avr32_jtag.h \
- avr32_mem.h \
- avr32_regs.h \
- nds32.h \
- nds32_cmd.h \
- nds32_disassembler.h \
- nds32_edm.h \
- nds32_insn.h \
- nds32_reg.h \
- nds32_tlb.h \
- nds32_v2.h \
- nds32_v3_common.h \
- nds32_v3.h \
- nds32_v3m.h \
- nds32_aice.h \
- lakemont.h \
- x86_32_common.h
-
-ocddatadir = $(pkglibdir)
-nobase_dist_ocddata_DATA =
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c
deleted file mode 100644
index 2717c9e..0000000
--- a/src/target/adi_v5_jtag.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Magnus Lundin
- * lundin@mlu.mine.nu
- *
- * Copyright (C) 2008 by Spencer Oliver
- * spen@spen-soft.co.uk
- *
- * Copyright (C) 2009 by Oyvind Harboe
- * oyvind.harboe@zylin.com
- *
- * Copyright (C) 2009-2010 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- ***************************************************************************/
-
-/**
- * @file
- * This file implements JTAG transport support for cores implementing
- the ARM Debug Interface version 5 (ADIv5).
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "arm_adi_v5.h"
-#include <helper/time_support.h>
-#include <helper/list.h>
-
-/*#define DEBUG_WAIT*/
-
-/* JTAG instructions/registers for JTAG-DP and SWJ-DP */
-#define JTAG_DP_ABORT 0x8
-#define JTAG_DP_DPACC 0xA
-#define JTAG_DP_APACC 0xB
-#define JTAG_DP_IDCODE 0xE
-
-/* three-bit ACK values for DPACC and APACC reads */
-#define JTAG_ACK_OK_FAULT 0x2
-#define JTAG_ACK_WAIT 0x1
-
-static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack);
-
-#ifdef DEBUG_WAIT
-static const char *dap_reg_name(int instr, int reg_addr)
-{
- char *reg_name = "UNK";
-
- if (instr == JTAG_DP_DPACC) {
- switch (reg_addr) {
- case DP_ABORT:
- reg_name = "ABORT";
- break;
- case DP_CTRL_STAT:
- reg_name = "CTRL/STAT";
- break;
- case DP_SELECT:
- reg_name = "SELECT";
- break;
- case DP_RDBUFF:
- reg_name = "RDBUFF";
- break;
- case DP_WCR:
- reg_name = "WCR";
- break;
- default:
- reg_name = "UNK";
- break;
- }
- }
-
- if (instr == JTAG_DP_APACC) {
- switch (reg_addr) {
- case MEM_AP_REG_CSW:
- reg_name = "CSW";
- break;
- case MEM_AP_REG_TAR:
- reg_name = "TAR";
- break;
- case MEM_AP_REG_DRW:
- reg_name = "DRW";
- break;
- case MEM_AP_REG_BD0:
- reg_name = "BD0";
- break;
- case MEM_AP_REG_BD1:
- reg_name = "BD1";
- break;
- case MEM_AP_REG_BD2:
- reg_name = "BD2";
- break;
- case MEM_AP_REG_BD3:
- reg_name = "BD3";
- break;
- case MEM_AP_REG_CFG:
- reg_name = "CFG";
- break;
- case MEM_AP_REG_BASE:
- reg_name = "BASE";
- break;
- case AP_REG_IDR:
- reg_name = "IDR";
- break;
- default:
- reg_name = "UNK";
- break;
- }
- }
-
- return reg_name;
-}
-#endif
-
-struct dap_cmd {
- struct list_head lh;
- uint8_t instr;
- uint8_t reg_addr;
- uint8_t RnW;
- uint8_t *invalue;
- uint8_t ack;
- uint32_t memaccess_tck;
- uint32_t dp_select;
-
- struct scan_field fields[2];
- uint8_t out_addr_buf;
- uint8_t invalue_buf[4];
- uint8_t outvalue_buf[4];
-};
-
-static void log_dap_cmd(const char *header, struct dap_cmd *el)
-{
-#ifdef DEBUG_WAIT
- LOG_DEBUG("%s: %2s %6s %5s 0x%08x 0x%08x %2s", header,
- el->instr == JTAG_DP_APACC ? "AP" : "DP",
- dap_reg_name(el->instr, el->reg_addr),
- el->RnW == DPAP_READ ? "READ" : "WRITE",
- buf_get_u32(el->outvalue_buf, 0, 32),
- buf_get_u32(el->invalue, 0, 32),
- el->ack == JTAG_ACK_OK_FAULT ? "OK" :
- (el->ack == JTAG_ACK_WAIT ? "WAIT" : "INVAL"));
-#endif
-}
-
-static struct dap_cmd *dap_cmd_new(uint8_t instr,
- uint8_t reg_addr, uint8_t RnW,
- uint8_t *outvalue, uint8_t *invalue,
- uint32_t memaccess_tck)
-{
- struct dap_cmd *cmd;
-
- cmd = (struct dap_cmd *)calloc(1, sizeof(struct dap_cmd));
- if (cmd != NULL) {
- INIT_LIST_HEAD(&cmd->lh);
- cmd->instr = instr;
- cmd->reg_addr = reg_addr;
- cmd->RnW = RnW;
- if (outvalue != NULL)
- memcpy(cmd->outvalue_buf, outvalue, 4);
- cmd->invalue = (invalue != NULL) ? invalue : cmd->invalue_buf;
- cmd->memaccess_tck = memaccess_tck;
- }
-
- return cmd;
-}
-
-static void flush_journal(struct list_head *lh)
-{
- struct dap_cmd *el, *tmp;
-
- list_for_each_entry_safe(el, tmp, lh, lh) {
- list_del(&el->lh);
- free(el);
- }
-}
-
-/***************************************************************************
- *
- * DPACC and APACC scanchain access through JTAG-DP (or SWJ-DP)
- *
-***************************************************************************/
-
-static int adi_jtag_dp_scan_cmd(struct adiv5_dap *dap, struct dap_cmd *cmd, uint8_t *ack)
-{
- struct jtag_tap *tap = dap->tap;
- int retval;
-
- retval = arm_jtag_set_instr(tap, cmd->instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- /* Scan out a read or write operation using some DP or AP register.
- * For APACC access with any sticky error flag set, this is discarded.
- */
- cmd->fields[0].num_bits = 3;
- buf_set_u32(&cmd->out_addr_buf, 0, 3, ((cmd->reg_addr >> 1) & 0x6) | (cmd->RnW & 0x1));
- cmd->fields[0].out_value = &cmd->out_addr_buf;
- cmd->fields[0].in_value = (ack != NULL) ? ack : &cmd->ack;
-
- /* NOTE: if we receive JTAG_ACK_WAIT, the previous operation did not
- * complete; data we write is discarded, data we read is unpredictable.
- * When overrun detect is active, STICKYORUN is set.
- */
-
- cmd->fields[1].num_bits = 32;
- cmd->fields[1].out_value = cmd->outvalue_buf;
- cmd->fields[1].in_value = cmd->invalue;
-
- jtag_add_dr_scan(tap, 2, cmd->fields, TAP_IDLE);
-
- /* Add specified number of tck clocks after starting memory bus
- * access, giving the hardware time to complete the access.
- * They provide more time for the (MEM) AP to complete the read ...
- * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec.
- */
- if (cmd->instr == JTAG_DP_APACC) {
- if (((cmd->reg_addr == MEM_AP_REG_DRW)
- || ((cmd->reg_addr & 0xF0) == MEM_AP_REG_BD0))
- && (cmd->memaccess_tck != 0))
- jtag_add_runtest(cmd->memaccess_tck, TAP_IDLE);
- }
-
- return ERROR_OK;
-}
-
-static int adi_jtag_dp_scan_cmd_sync(struct adiv5_dap *dap, struct dap_cmd *cmd, uint8_t *ack)
-{
- int retval;
-
- retval = adi_jtag_dp_scan_cmd(dap, cmd, ack);
- if (retval != ERROR_OK)
- return retval;
-
- return jtag_execute_queue();
-}
-
-/**
- * Scan DPACC or APACC using target ordered uint8_t buffers. No endianness
- * conversions are performed. See section 4.4.3 of the ADIv5 spec, which
- * discusses operations which access these registers.
- *
- * Note that only one scan is performed. If RnW is set, a separate scan
- * will be needed to collect the data which was read; the "invalue" collects
- * the posted result of a preceding operation, not the current one.
- *
- * @param dap the DAP
- * @param instr JTAG_DP_APACC (AP access) or JTAG_DP_DPACC (DP access)
- * @param reg_addr two significant bits; A[3:2]; for APACC access, the
- * SELECT register has more addressing bits.
- * @param RnW false iff outvalue will be written to the DP or AP
- * @param outvalue points to a 32-bit (little-endian) integer
- * @param invalue NULL, or points to a 32-bit (little-endian) integer
- * @param ack points to where the three bit JTAG_ACK_* code will be stored
- * @param memaccess_tck number of idle cycles to add after AP access
- */
-
-static int adi_jtag_dp_scan(struct adiv5_dap *dap,
- uint8_t instr, uint8_t reg_addr, uint8_t RnW,
- uint8_t *outvalue, uint8_t *invalue,
- uint32_t memaccess_tck, uint8_t *ack)
-{
- struct dap_cmd *cmd;
- int retval;
-
- cmd = dap_cmd_new(instr, reg_addr, RnW, outvalue, invalue, memaccess_tck);
- if (cmd != NULL)
- cmd->dp_select = dap->select;
- else
- return ERROR_JTAG_DEVICE_ERROR;
-
- retval = adi_jtag_dp_scan_cmd(dap, cmd, ack);
- if (retval == ERROR_OK)
- list_add_tail(&cmd->lh, &dap->cmd_journal);
-
- return retval;
-}
-
-/**
- * Scan DPACC or APACC out and in from host ordered uint32_t buffers.
- * This is exactly like adi_jtag_dp_scan(), except that endianness
- * conversions are performed (so the types of invalue and outvalue
- * must be different).
- */
-static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap,
- uint8_t instr, uint8_t reg_addr, uint8_t RnW,
- uint32_t outvalue, uint32_t *invalue,
- uint32_t memaccess_tck, uint8_t *ack)
-{
- uint8_t out_value_buf[4];
- int retval;
-
- buf_set_u32(out_value_buf, 0, 32, outvalue);
-
- retval = adi_jtag_dp_scan(dap, instr, reg_addr, RnW,
- out_value_buf, (uint8_t *)invalue, memaccess_tck, ack);
- if (retval != ERROR_OK)
- return retval;
-
- if (invalue)
- jtag_add_callback(arm_le_to_h_u32,
- (jtag_callback_data_t) invalue);
-
- return retval;
-}
-
-static int adi_jtag_finish_read(struct adiv5_dap *dap)
-{
- int retval = ERROR_OK;
-
- if (dap->last_read != NULL) {
- retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC,
- DP_RDBUFF, DPAP_READ, 0, dap->last_read, 0, NULL);
- dap->last_read = NULL;
- }
-
- return retval;
-}
-
-static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *dap,
- uint8_t instr, uint8_t reg_addr, uint8_t RnW,
- uint32_t outvalue, uint32_t *invalue, uint32_t memaccess_tck)
-{
- int retval;
-
- /* Issue the read or write */
- retval = adi_jtag_dp_scan_u32(dap, instr, reg_addr,
- RnW, outvalue, NULL, memaccess_tck, NULL);
- if (retval != ERROR_OK)
- return retval;
-
- /* For reads, collect posted value; RDBUFF has no other effect.
- * Assumes read gets acked with OK/FAULT, and CTRL_STAT says "OK".
- */
- if ((RnW == DPAP_READ) && (invalue != NULL)) {
- retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC,
- DP_RDBUFF, DPAP_READ, 0, invalue, 0, NULL);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return jtag_execute_queue();
-}
-
-static int jtagdp_overrun_check(struct adiv5_dap *dap)
-{
- int retval;
- struct dap_cmd *el, *tmp, *prev = NULL;
- int found_wait = 0;
- int64_t time_now;
- LIST_HEAD(replay_list);
-
- /* make sure all queued transactions are complete */
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- goto done;
-
- /* skip all completed transactions up to the first WAIT */
- list_for_each_entry(el, &dap->cmd_journal, lh) {
- if (el->ack == JTAG_ACK_OK_FAULT) {
- log_dap_cmd("LOG", el);
- } else if (el->ack == JTAG_ACK_WAIT) {
- found_wait = 1;
- break;
- } else {
- LOG_ERROR("Invalid ACK (%1x) in DAP response", el->ack);
- log_dap_cmd("ERR", el);
- retval = ERROR_JTAG_DEVICE_ERROR;
- goto done;
- }
- }
-
- /*
- * If we found a stalled transaction and a previous transaction
- * exists, check if it's a READ access.
- */
- if (found_wait && el != list_first_entry(&dap->cmd_journal, struct dap_cmd, lh)) {
- prev = list_entry(el->lh.prev, struct dap_cmd, lh);
- if (prev->RnW == DPAP_READ) {
- log_dap_cmd("PND", prev);
- /* search for the next OK transaction, it contains
- * the result of the previous READ */
- tmp = el;
- list_for_each_entry_from(tmp, &dap->cmd_journal, lh) {
- if (tmp->ack == JTAG_ACK_OK_FAULT) {
- /* recover the read value */
- log_dap_cmd("FND", tmp);
- if (el->invalue != el->invalue_buf) {
- uint32_t invalue = le_to_h_u32(tmp->invalue);
- memcpy(el->invalue, &invalue, sizeof(uint32_t));
- }
- prev = NULL;
- break;
- }
- }
-
- if (prev != NULL) {
- log_dap_cmd("LST", el);
-
- /*
- * At this point we're sure that no previous
- * transaction completed and the DAP/AP is still
- * in busy state. We know that the next "OK" scan
- * will return the READ result we need to recover.
- * To complete the READ, we just keep polling RDBUFF
- * until the WAIT condition clears
- */
- tmp = dap_cmd_new(JTAG_DP_DPACC,
- DP_RDBUFF, DPAP_READ, NULL, NULL, 0);
- if (tmp == NULL) {
- retval = ERROR_JTAG_DEVICE_ERROR;
- goto done;
- }
- /* synchronously retry the command until it succeeds */
- time_now = timeval_ms();
- do {
- retval = adi_jtag_dp_scan_cmd_sync(dap, tmp, NULL);
- if (retval != ERROR_OK)
- break;
- if (tmp->ack == JTAG_ACK_OK_FAULT) {
- log_dap_cmd("FND", tmp);
- if (el->invalue != el->invalue_buf) {
- uint32_t invalue = le_to_h_u32(tmp->invalue);
- memcpy(el->invalue, &invalue, sizeof(uint32_t));
- }
- break;
- }
- if (tmp->ack != JTAG_ACK_WAIT) {
- LOG_ERROR("Invalid ACK (%1x) in DAP response", tmp->ack);
- log_dap_cmd("ERR", tmp);
- retval = ERROR_JTAG_DEVICE_ERROR;
- break;
- }
-
- } while (timeval_ms() - time_now < 1000);
-
- if (retval == ERROR_OK) {
- /* timeout happened */
- if (tmp->ack != JTAG_ACK_OK_FAULT) {
- LOG_ERROR("Timeout during WAIT recovery");
- dap->select = DP_SELECT_INVALID;
- jtag_ap_q_abort(dap, NULL);
- /* clear the sticky overrun condition */
- adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
- DP_CTRL_STAT, DPAP_WRITE,
- dap->dp_ctrl_stat | SSTICKYORUN, NULL, 0);
- retval = ERROR_JTAG_DEVICE_ERROR;
- }
- }
-
- /* we're done with this command, release it */
- free(tmp);
-
- if (retval != ERROR_OK)
- goto done;
-
- }
- /* make el->invalue point to the default invalue
- * so that we can safely retry it without clobbering
- * the result we just recovered */
- el->invalue = el->invalue_buf;
- }
- }
-
- /* move all remaining transactions over to the replay list */
- list_for_each_entry_safe_from(el, tmp, &dap->cmd_journal, lh) {
- log_dap_cmd("REP", el);
- list_move_tail(&el->lh, &replay_list);
- }
-
- /* we're done with the journal, flush it */
- flush_journal(&dap->cmd_journal);
-
- /* check for overrun condition in the last batch of transactions */
- if (found_wait) {
- LOG_INFO("DAP transaction stalled (WAIT) - slowing down");
- /* clear the sticky overrun condition */
- retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
- DP_CTRL_STAT, DPAP_WRITE,
- dap->dp_ctrl_stat | SSTICKYORUN, NULL, 0);
- if (retval != ERROR_OK)
- goto done;
-
- /* restore SELECT register first */
- if (!list_empty(&replay_list)) {
- el = list_first_entry(&replay_list, struct dap_cmd, lh);
- tmp = dap_cmd_new(JTAG_DP_DPACC,
- DP_SELECT, DPAP_WRITE, (uint8_t *)&el->dp_select, NULL, 0);
- if (tmp == NULL) {
- retval = ERROR_JTAG_DEVICE_ERROR;
- goto done;
- }
- list_add(&tmp->lh, &replay_list);
-
- dap->select = DP_SELECT_INVALID;
- }
-
- list_for_each_entry_safe(el, tmp, &replay_list, lh) {
- time_now = timeval_ms();
- do {
- retval = adi_jtag_dp_scan_cmd_sync(dap, el, NULL);
- if (retval != ERROR_OK)
- break;
- log_dap_cmd("REC", el);
- if (el->ack == JTAG_ACK_OK_FAULT) {
- if (el->invalue != el->invalue_buf) {
- uint32_t invalue = le_to_h_u32(el->invalue);
- memcpy(el->invalue, &invalue, sizeof(uint32_t));
- }
- break;
- }
- if (el->ack != JTAG_ACK_WAIT) {
- LOG_ERROR("Invalid ACK (%1x) in DAP response", el->ack);
- log_dap_cmd("ERR", el);
- retval = ERROR_JTAG_DEVICE_ERROR;
- break;
- }
- } while (timeval_ms() - time_now < 1000);
-
- if (retval == ERROR_OK) {
- if (el->ack != JTAG_ACK_OK_FAULT) {
- LOG_ERROR("Timeout during WAIT recovery");
- dap->select = DP_SELECT_INVALID;
- jtag_ap_q_abort(dap, NULL);
- /* clear the sticky overrun condition */
- adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
- DP_CTRL_STAT, DPAP_WRITE,
- dap->dp_ctrl_stat | SSTICKYORUN, NULL, 0);
- retval = ERROR_JTAG_DEVICE_ERROR;
- break;
- }
- } else
- break;
- }
- }
-
- done:
- flush_journal(&replay_list);
- flush_journal(&dap->cmd_journal);
- return retval;
-}
-
-static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
-{
- int retval;
- uint32_t ctrlstat;
-
- /* too expensive to call keep_alive() here */
-
- /* Post CTRL/STAT read; discard any previous posted read value
- * but collect its ACK status.
- */
- retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
- DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0);
- if (retval != ERROR_OK)
- goto done;
-
- /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */
-
- /* Check for STICKYERR */
- if (ctrlstat & SSTICKYERR) {
- LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
- /* Check power to debug regions */
- if ((ctrlstat & (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) !=
- (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) {
- LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened");
- retval = ERROR_JTAG_DEVICE_ERROR;
- goto done;
- }
-
- if (ctrlstat & SSTICKYERR)
- LOG_ERROR("JTAG-DP STICKY ERROR");
- if (ctrlstat & SSTICKYORUN)
- LOG_DEBUG("JTAG-DP STICKY OVERRUN");
-
- /* Clear Sticky Error Bits */
- retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC,
- DP_CTRL_STAT, DPAP_WRITE,
- dap->dp_ctrl_stat | SSTICKYERR, NULL, 0);
- if (retval != ERROR_OK)
- goto done;
-
- if (ctrlstat & SSTICKYERR) {
- retval = ERROR_JTAG_DEVICE_ERROR;
- goto done;
- }
- }
-
- done:
- flush_journal(&dap->cmd_journal);
- return retval;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg,
- uint32_t *data)
-{
- int retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC, reg,
- DPAP_READ, 0, dap->last_read, 0, NULL);
- dap->last_read = data;
- return retval;
-}
-
-static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg,
- uint32_t data)
-{
- int retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC,
- reg, DPAP_WRITE, data, dap->last_read, 0, NULL);
- dap->last_read = NULL;
- return retval;
-}
-
-/** Select the AP register bank matching bits 7:4 of reg. */
-static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg)
-{
- struct adiv5_dap *dap = ap->dap;
- uint32_t sel = ((uint32_t)ap->ap_num << 24) | (reg & 0x000000F0);
-
- if (sel == dap->select)
- return ERROR_OK;
-
- dap->select = sel;
-
- return jtag_dp_q_write(dap, DP_SELECT, sel);
-}
-
-static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg,
- uint32_t *data)
-{
- int retval = jtag_ap_q_bankselect(ap, reg);
- if (retval != ERROR_OK)
- return retval;
-
- retval = adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg,
- DPAP_READ, 0, ap->dap->last_read, ap->memaccess_tck, NULL);
- ap->dap->last_read = data;
-
- return retval;
-}
-
-static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned reg,
- uint32_t data)
-{
- int retval = jtag_ap_q_bankselect(ap, reg);
- if (retval != ERROR_OK)
- return retval;
-
- retval = adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg,
- DPAP_WRITE, data, ap->dap->last_read, ap->memaccess_tck, NULL);
- ap->dap->last_read = NULL;
- return retval;
-}
-
-static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack)
-{
- /* for JTAG, this is the only valid ABORT register operation */
- int retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_ABORT,
- 0, DPAP_WRITE, 1, NULL, 0, NULL);
- if (retval != ERROR_OK)
- return retval;
-
- return jtag_execute_queue();
-}
-
-static int jtag_dp_run(struct adiv5_dap *dap)
-{
- int retval;
- int retval2 = ERROR_OK;
-
- retval = adi_jtag_finish_read(dap);
- if (retval != ERROR_OK)
- goto done;
- retval2 = jtagdp_overrun_check(dap);
- retval = jtagdp_transaction_endcheck(dap);
-
- done:
- return (retval2 != ERROR_OK) ? retval2 : retval;
-}
-
-static int jtag_dp_sync(struct adiv5_dap *dap)
-{
- return jtagdp_overrun_check(dap);
-}
-
-/* FIXME don't export ... just initialize as
- * part of DAP setup
-*/
-const struct dap_ops jtag_dp_ops = {
- .queue_dp_read = jtag_dp_q_read,
- .queue_dp_write = jtag_dp_q_write,
- .queue_ap_read = jtag_ap_q_read,
- .queue_ap_write = jtag_ap_q_write,
- .queue_ap_abort = jtag_ap_q_abort,
- .run = jtag_dp_run,
- .sync = jtag_dp_sync,
-};
-
-
-static const uint8_t swd2jtag_bitseq[] = {
- /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
- * putting both JTAG and SWD logic into reset state.
- */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Switching equence disables SWD and enables JTAG
- * NOTE: bits in the DP's IDCODE can expose the need for
- * the old/deprecated sequence (0xae 0xde).
- */
- 0x3c, 0xe7,
- /* At least 50 TCK/SWCLK cycles with TMS/SWDIO high,
- * putting both JTAG and SWD logic into reset state.
- * NOTE: some docs say "at least 5".
- */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
-
-/** Put the debug link into JTAG mode, if the target supports it.
- * The link's initial mode may be either SWD or JTAG.
- *
- * @param target Enters JTAG mode (if possible).
- *
- * Note that targets implemented with SW-DP do not support JTAG, and
- * that some targets which could otherwise support it may have been
- * configured to disable JTAG signaling
- *
- * @return ERROR_OK or else a fault code.
- */
-int dap_to_jtag(struct target *target)
-{
- int retval;
-
- LOG_DEBUG("Enter JTAG mode");
-
- /* REVISIT it's nasty to need to make calls to a "jtag"
- * subsystem if the link isn't in JTAG mode...
- */
-
- retval = jtag_add_tms_seq(8 * sizeof(swd2jtag_bitseq),
- swd2jtag_bitseq, TAP_RESET);
- if (retval == ERROR_OK)
- retval = jtag_execute_queue();
-
- /* REVISIT set up the DAP's ops vector for JTAG mode. */
-
- return retval;
-}
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
deleted file mode 100644
index 41ddbd7..0000000
--- a/src/target/adi_v5_swd.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/***************************************************************************
- *
- * Copyright (C) 2010 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- ***************************************************************************/
-
-/**
- * @file
- * Utilities to support ARM "Serial Wire Debug" (SWD), a low pin-count debug
- * link protocol used in cases where JTAG is not wanted. This is coupled to
- * recent versions of ARM's "CoreSight" debug framework. This specific code
- * is a transport level interface, with "target/arm_adi_v5.[hc]" code
- * understanding operation semantics, shared with the JTAG transport.
- *
- * Single-DAP support only.
- *
- * for details, see "ARM IHI 0031A"
- * ARM Debug Interface v5 Architecture Specification
- * especially section 5.3 for SWD protocol
- *
- * On many chips (most current Cortex-M3 parts) SWD is a run-time alternative
- * to JTAG. Boards may support one or both. There are also SWD-only chips,
- * (using SW-DP not SWJ-DP).
- *
- * Even boards that also support JTAG can benefit from SWD support, because
- * usually there's no way to access the SWO trace view mechanism in JTAG mode.
- * That is, trace access may require SWD support.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "arm_adi_v5.h"
-#include <helper/time_support.h>
-
-#include <transport/transport.h>
-#include <jtag/interface.h>
-
-#include <jtag/swd.h>
-
-/* YUK! - but this is currently a global.... */
-extern struct jtag_interface *jtag_interface;
-static bool do_sync;
-
-static void swd_finish_read(struct adiv5_dap *dap)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- if (dap->last_read != NULL) {
- swd->read_reg(swd_cmd(true, false, DP_RDBUFF), dap->last_read, 0);
- dap->last_read = NULL;
- }
-}
-
-static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg,
- uint32_t data);
-static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
- uint32_t *data);
-
-static void swd_clear_sticky_errors(struct adiv5_dap *dap)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
- swd->write_reg(swd_cmd(false, false, DP_ABORT),
- STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
-}
-
-static int swd_run_inner(struct adiv5_dap *dap)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- int retval;
-
- retval = swd->run();
-
- if (retval != ERROR_OK) {
- /* fault response */
- dap->do_reconnect = true;
- }
-
- return retval;
-}
-
-static int swd_connect(struct adiv5_dap *dap)
-{
- uint32_t dpidr;
- int status;
-
- /* FIXME validate transport config ... is the
- * configured DAP present (check IDCODE)?
- * Is *only* one DAP configured?
- *
- * MUST READ DPIDR
- */
-
- /* Check if we should reset srst already when connecting, but not if reconnecting. */
- if (!dap->do_reconnect) {
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
- if (jtag_reset_config & RESET_SRST_NO_GATING)
- swd_add_reset(1);
- else
- LOG_WARNING("\'srst_nogate\' reset_config option is required");
- }
- }
-
- /* Note, debugport_init() does setup too */
- jtag_interface->swd->switch_seq(JTAG_TO_SWD);
-
- /* Clear link state, including the SELECT cache. */
- dap->do_reconnect = false;
- dap->select = DP_SELECT_INVALID;
-
- swd_queue_dp_read(dap, DP_DPIDR, &dpidr);
-
- /* force clear all sticky faults */
- swd_clear_sticky_errors(dap);
-
- status = swd_run_inner(dap);
-
- if (status == ERROR_OK) {
- LOG_INFO("SWD DPIDR %#8.8" PRIx32, dpidr);
- dap->do_reconnect = false;
- } else
- dap->do_reconnect = true;
-
- return status;
-}
-
-static inline int check_sync(struct adiv5_dap *dap)
-{
- return do_sync ? swd_run_inner(dap) : ERROR_OK;
-}
-
-static int swd_check_reconnect(struct adiv5_dap *dap)
-{
- if (dap->do_reconnect)
- return swd_connect(dap);
-
- return ERROR_OK;
-}
-
-static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
- swd->write_reg(swd_cmd(false, false, DP_ABORT),
- DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
- return check_sync(dap);
-}
-
-/** Select the DP register bank matching bits 7:4 of reg. */
-static void swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg)
-{
- /* Only register address 4 is banked. */
- if ((reg & 0xf) != 4)
- return;
-
- uint32_t select_dp_bank = (reg & 0x000000F0) >> 4;
- uint32_t sel = select_dp_bank
- | (dap->select & (DP_SELECT_APSEL | DP_SELECT_APBANK));
-
- if (sel == dap->select)
- return;
-
- dap->select = sel;
-
- swd_queue_dp_write(dap, DP_SELECT, sel);
-}
-
-static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
- uint32_t *data)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
- int retval = swd_check_reconnect(dap);
- if (retval != ERROR_OK)
- return retval;
-
- swd_queue_dp_bankselect(dap, reg);
- swd->read_reg(swd_cmd(true, false, reg), data, 0);
-
- return check_sync(dap);
-}
-
-static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg,
- uint32_t data)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
- int retval = swd_check_reconnect(dap);
- if (retval != ERROR_OK)
- return retval;
-
- swd_finish_read(dap);
- swd_queue_dp_bankselect(dap, reg);
- swd->write_reg(swd_cmd(false, false, reg), data, 0);
-
- return check_sync(dap);
-}
-
-/** Select the AP register bank matching bits 7:4 of reg. */
-static void swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
-{
- struct adiv5_dap *dap = ap->dap;
- uint32_t sel = ((uint32_t)ap->ap_num << 24)
- | (reg & 0x000000F0)
- | (dap->select & DP_SELECT_DPBANK);
-
- if (sel == dap->select)
- return;
-
- dap->select = sel;
-
- swd_queue_dp_write(dap, DP_SELECT, sel);
-}
-
-static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
- uint32_t *data)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
- struct adiv5_dap *dap = ap->dap;
-
- int retval = swd_check_reconnect(dap);
- if (retval != ERROR_OK)
- return retval;
-
- swd_queue_ap_bankselect(ap, reg);
- swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck);
- dap->last_read = data;
-
- return check_sync(dap);
-}
-
-static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg,
- uint32_t data)
-{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
- struct adiv5_dap *dap = ap->dap;
-
- int retval = swd_check_reconnect(dap);
- if (retval != ERROR_OK)
- return retval;
-
- swd_finish_read(dap);
- swd_queue_ap_bankselect(ap, reg);
- swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck);
-
- return check_sync(dap);
-}
-
-/** Executes all queued DAP operations. */
-static int swd_run(struct adiv5_dap *dap)
-{
- swd_finish_read(dap);
- return swd_run_inner(dap);
-}
-
-const struct dap_ops swd_dap_ops = {
- .queue_dp_read = swd_queue_dp_read,
- .queue_dp_write = swd_queue_dp_write,
- .queue_ap_read = swd_queue_ap_read,
- .queue_ap_write = swd_queue_ap_write,
- .queue_ap_abort = swd_queue_ap_abort,
- .run = swd_run,
-};
-
-/*
- * This represents the bits which must be sent out on TMS/SWDIO to
- * switch a DAP implemented using an SWJ-DP module into SWD mode.
- * These bits are stored (and transmitted) LSB-first.
- *
- * See the DAP-Lite specification, section 2.2.5 for information
- * about making the debug link select SWD or JTAG. (Similar info
- * is in a few other ARM documents.)
- */
-static const uint8_t jtag2swd_bitseq[] = {
- /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
- * putting both JTAG and SWD logic into reset state.
- */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- /* Switching sequence enables SWD and disables JTAG
- * NOTE: bits in the DP's IDCODE may expose the need for
- * an old/obsolete/deprecated sequence (0xb6 0xed).
- */
- 0x9e, 0xe7,
- /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
- * putting both JTAG and SWD logic into reset state.
- */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
-
-/**
- * Put the debug link into SWD mode, if the target supports it.
- * The link's initial mode may be either JTAG (for example,
- * with SWJ-DP after reset) or SWD.
- *
- * @param target Enters SWD mode (if possible).
- *
- * Note that targets using the JTAG-DP do not support SWD, and that
- * some targets which could otherwise support it may have have been
- * configured to disable SWD signaling
- *
- * @return ERROR_OK or else a fault code.
- */
-int dap_to_swd(struct target *target)
-{
- struct arm *arm = target_to_arm(target);
- int retval;
-
- if (!arm->dap) {
- LOG_ERROR("SWD mode is not available");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("Enter SWD mode");
-
- /* REVISIT it's ugly to need to make calls to a "jtag"
- * subsystem if the link may not be in JTAG mode...
- */
-
- retval = jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq),
- jtag2swd_bitseq, TAP_INVALID);
- if (retval == ERROR_OK)
- retval = jtag_execute_queue();
-
- /* set up the DAP's ops vector for SWD mode. */
- arm->dap->ops = &swd_dap_ops;
-
- return retval;
-}
-
-static const struct command_registration swd_commands[] = {
- {
- /*
- * Set up SWD and JTAG targets identically, unless/until
- * infrastructure improves ... meanwhile, ignore all
- * JTAG-specific stuff like IR length for SWD.
- *
- * REVISIT can we verify "just one SWD DAP" here/early?
- */
- .name = "newdap",
- .jim_handler = jim_jtag_newtap,
- .mode = COMMAND_CONFIG,
- .help = "declare a new SWD DAP"
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration swd_handlers[] = {
- {
- .name = "swd",
- .mode = COMMAND_ANY,
- .help = "SWD command group",
- .chain = swd_commands,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int swd_select(struct command_context *ctx)
-{
- int retval;
-
- retval = register_commands(ctx, NULL, swd_handlers);
-
- if (retval != ERROR_OK)
- return retval;
-
- const struct swd_driver *swd = jtag_interface->swd;
-
- /* be sure driver is in SWD mode; start
- * with hardware default TRN (1), it can be changed later
- */
- if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
- LOG_DEBUG("no SWD driver?");
- return ERROR_FAIL;
- }
-
- retval = swd->init();
- if (retval != ERROR_OK) {
- LOG_DEBUG("can't init SWD driver");
- return retval;
- }
-
- /* force DAP into SWD mode (not JTAG) */
- /*retval = dap_to_swd(target);*/
-
- if (ctx->current_target) {
- /* force DAP into SWD mode (not JTAG) */
- struct target *target = get_current_target(ctx);
- retval = dap_to_swd(target);
- }
-
- return retval;
-}
-
-static int swd_init(struct command_context *ctx)
-{
- struct target *target = get_current_target(ctx);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
- /* Force the DAP's ops vector for SWD mode.
- * messy - is there a better way? */
- arm->dap->ops = &swd_dap_ops;
- /* First connect after init is not reconnecting. */
- dap->do_reconnect = false;
-
- return swd_connect(dap);
-}
-
-static struct transport swd_transport = {
- .name = "swd",
- .select = swd_select,
- .init = swd_init,
-};
-
-static void swd_constructor(void) __attribute__((constructor));
-static void swd_constructor(void)
-{
- transport_register(&swd_transport);
-}
-
-/** Returns true if the current debug session
- * is using SWD as its transport.
- */
-bool transport_is_swd(void)
-{
- return get_current_transport() == &swd_transport;
-}
diff --git a/src/target/algorithm.c b/src/target/algorithm.c
deleted file mode 100644
index 9fc9386..0000000
--- a/src/target/algorithm.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "algorithm.h"
-#include <helper/binarybuffer.h>
-
-void init_mem_param(struct mem_param *param, uint32_t address, uint32_t size, enum param_direction direction)
-{
- param->address = address;
- param->size = size;
- param->value = malloc(size);
- param->direction = direction;
-}
-
-void destroy_mem_param(struct mem_param *param)
-{
- free(param->value);
- param->value = NULL;
-}
-
-void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction direction)
-{
- param->reg_name = reg_name;
- param->size = size;
- param->value = malloc(DIV_ROUND_UP(size, 8));
- param->direction = direction;
-}
-
-void destroy_reg_param(struct reg_param *param)
-{
- free(param->value);
- param->value = NULL;
-}
diff --git a/src/target/algorithm.h b/src/target/algorithm.h
deleted file mode 100644
index d216a82..0000000
--- a/src/target/algorithm.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ALGORITHM_H
-#define OPENOCD_TARGET_ALGORITHM_H
-
-enum param_direction {
- PARAM_IN,
- PARAM_OUT,
- PARAM_IN_OUT
-};
-
-struct mem_param {
- uint32_t address;
- uint32_t size;
- uint8_t *value;
- enum param_direction direction;
-};
-
-struct reg_param {
- const char *reg_name;
- uint32_t size;
- uint8_t *value;
- enum param_direction direction;
-};
-
-void init_mem_param(struct mem_param *param,
- uint32_t address, uint32_t size, enum param_direction dir);
-void destroy_mem_param(struct mem_param *param);
-
-void init_reg_param(struct reg_param *param,
- char *reg_name, uint32_t size, enum param_direction dir);
-void destroy_reg_param(struct reg_param *param);
-
-#endif /* OPENOCD_TARGET_ALGORITHM_H */
diff --git a/src/target/arm.h b/src/target/arm.h
deleted file mode 100644
index 163db23..0000000
--- a/src/target/arm.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2005 by Dominic Rath
- * Dominic.Rath@gmx.de
- *
- * Copyright (C) 2008 by Spencer Oliver
- * spen@spen-soft.co.uk
- *
- * Copyright (C) 2009 by Øyvind Harboe
- * oyvind.harboe@zylin.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef OPENOCD_TARGET_ARM_H
-#define OPENOCD_TARGET_ARM_H
-
-#include <helper/command.h>
-#include "target.h"
-
-
-/**
- * @file
- * Holds the interface to ARM cores.
- *
- * At this writing, only "classic ARM" cores built on the ARMv4 register
- * and mode model are supported. The Thumb2-only microcontroller profile
- * support has not yet been integrated, affecting Cortex-M parts.
- */
-
-/**
- * Represent state of an ARM core.
- *
- * Most numbers match the five low bits of the *PSR registers on
- * "classic ARM" processors, which build on the ARMv4 processor
- * modes and register set.
- *
- * ARM_MODE_ANY is a magic value, often used as a wildcard.
- *
- * Only the microcontroller cores (ARMv6-M, ARMv7-M) support ARM_MODE_THREAD,
- * ARM_MODE_USER_THREAD, and ARM_MODE_HANDLER. Those are the only modes
- * they support.
- */
-enum arm_mode {
- ARM_MODE_USR = 16,
- ARM_MODE_FIQ = 17,
- ARM_MODE_IRQ = 18,
- ARM_MODE_SVC = 19,
- ARM_MODE_MON = 22,
- ARM_MODE_ABT = 23,
- ARM_MODE_UND = 27,
- ARM_MODE_1176_MON = 28,
- ARM_MODE_SYS = 31,
-
- ARM_MODE_THREAD = 0,
- ARM_MODE_USER_THREAD = 1,
- ARM_MODE_HANDLER = 2,
-
- ARM_MODE_ANY = -1
-};
-
-const char *arm_mode_name(unsigned psr_mode);
-bool is_arm_mode(unsigned psr_mode);
-
-/** The PSR "T" and "J" bits define the mode of "classic ARM" cores. */
-enum arm_state {
- ARM_STATE_ARM,
- ARM_STATE_THUMB,
- ARM_STATE_JAZELLE,
- ARM_STATE_THUMB_EE,
-};
-
-#define ARM_COMMON_MAGIC 0x0A450A45
-
-/**
- * Represents a generic ARM core, with standard application registers.
- *
- * There are sixteen application registers (including PC, SP, LR) and a PSR.
- * Cortex-M series cores do not support as many core states or shadowed
- * registers as traditional ARM cores, and only support Thumb2 instructions.
- */
-struct arm {
- int common_magic;
- struct reg_cache *core_cache;
-
- /** Handle to the PC; valid in all core modes. */
- struct reg *pc;
-
- /** Handle to the CPSR/xPSR; valid in all core modes. */
- struct reg *cpsr;
-
- /** Handle to the SPSR; valid only in core modes with an SPSR. */
- struct reg *spsr;
-
- /** Support for arm_reg_current() */
- const int *map;
-
- /**
- * Indicates what registers are in the ARM state core register set.
- * ARM_MODE_ANY indicates the standard set of 37 registers,
- * seen on for example ARM7TDMI cores. ARM_MODE_MON indicates three
- * more registers are shadowed, for "Secure Monitor" mode.
- * ARM_MODE_THREAD indicates a microcontroller profile core,
- * which only shadows SP.
- */
- enum arm_mode core_type;
-
- /** Record the current core mode: SVC, USR, or some other mode. */
- enum arm_mode core_mode;
-
- /** Record the current core state: ARM, Thumb, or otherwise. */
- enum arm_state core_state;
-
- /** Flag reporting unavailability of the BKPT instruction. */
- bool is_armv4;
-
- /** Flag reporting armv6m based core. */
- bool is_armv6m;
-
- /** Flag reporting whether semihosting is active. */
- bool is_semihosting;
-
- /** Value to be returned by semihosting SYS_ERRNO request. */
- int semihosting_errno;
-
- int (*setup_semihosting)(struct target *target, int enable);
-
- /** Backpointer to the target. */
- struct target *target;
-
- /** Handle for the debug module, if one is present. */
- struct arm_dpm *dpm;
-
- /** Handle for the Embedded Trace Module, if one is present. */
- struct etm_context *etm;
-
- /* FIXME all these methods should take "struct arm *" not target */
-
- /** Retrieve all core registers, for display. */
- int (*full_context)(struct target *target);
-
- /** Retrieve a single core register. */
- int (*read_core_reg)(struct target *target, struct reg *reg,
- int num, enum arm_mode mode);
- int (*write_core_reg)(struct target *target, struct reg *reg,
- int num, enum arm_mode mode, uint8_t *value);
-
- /** Read coprocessor register. */
- int (*mrc)(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t *value);
-
- /** Write coprocessor register. */
- int (*mcr)(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t value);
-
- void *arch_info;
-
- /** For targets conforming to ARM Debug Interface v5,
- * this handle references the Debug Access Port (DAP)
- * used to make requests to the target.
- */
- struct adiv5_dap *dap;
-};
-
-/** Convert target handle to generic ARM target state handle. */
-static inline struct arm *target_to_arm(struct target *target)
-{
- assert(target != NULL);
- return target->arch_info;
-}
-
-static inline bool is_arm(struct arm *arm)
-{
- assert(arm != NULL);
- return arm->common_magic == ARM_COMMON_MAGIC;
-}
-
-struct arm_algorithm {
- int common_magic;
-
- enum arm_mode core_mode;
- enum arm_state core_state;
-};
-
-struct arm_reg {
- int num;
- enum arm_mode mode;
- struct target *target;
- struct arm *arm;
- uint8_t value[4];
-};
-
-struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm);
-
-extern const struct command_registration arm_command_handlers[];
-
-int arm_arch_state(struct target *target);
-int arm_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class);
-
-int arm_init_arch_info(struct target *target, struct arm *arm);
-
-/* REVISIT rename this once it's usable by ARMv7-M */
-int armv4_5_run_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info);
-int armv4_5_run_algorithm_inner(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info,
- int (*run_it)(struct target *target, uint32_t exit_point,
- int timeout_ms, void *arch_info));
-
-int arm_checksum_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *checksum);
-int arm_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank);
-
-void arm_set_cpsr(struct arm *arm, uint32_t cpsr);
-struct reg *arm_reg_current(struct arm *arm, unsigned regnum);
-
-extern struct reg arm_gdb_dummy_fp_reg;
-extern struct reg arm_gdb_dummy_fps_reg;
-
-#endif /* OPENOCD_TARGET_ARM_H */
diff --git a/src/target/arm11.c b/src/target/arm11.c
deleted file mode 100644
index cbe4d45..0000000
--- a/src/target/arm11.c
+++ /dev/null
@@ -1,1382 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 digenius technology GmbH. *
- * Michael Bruck *
- * *
- * Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 Georg Acher <acher@in.tum.de> *
- * *
- * Copyright (C) 2009 David Brownell *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "etm.h"
-#include "breakpoints.h"
-#include "arm11_dbgtap.h"
-#include "arm_simulator.h"
-#include <helper/time_support.h>
-#include "target_type.h"
-#include "algorithm.h"
-#include "register.h"
-#include "arm_opcodes.h"
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-
-static int arm11_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints);
-
-
-/** Check and if necessary take control of the system
- *
- * \param arm11 Target state variable.
- */
-static int arm11_check_init(struct arm11_common *arm11)
-{
- CHECK_RETVAL(arm11_read_DSCR(arm11));
-
- if (!(arm11->dscr & DSCR_HALT_DBG_MODE)) {
- LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
- LOG_DEBUG("Bringing target into debug mode");
-
- arm11->dscr |= DSCR_HALT_DBG_MODE;
- CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
-
- /* add further reset initialization here */
-
- arm11->simulate_reset_on_next_halt = true;
-
- if (arm11->dscr & DSCR_CORE_HALTED) {
- /** \todo TODO: this needs further scrutiny because
- * arm11_debug_entry() never gets called. (WHY NOT?)
- * As a result we don't read the actual register states from
- * the target.
- */
-
- arm11->arm.target->state = TARGET_HALTED;
- arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
- } else {
- arm11->arm.target->state = TARGET_RUNNING;
- arm11->arm.target->debug_reason = DBG_REASON_NOTHALTED;
- }
-
- CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));
- }
-
- return ERROR_OK;
-}
-
-/**
- * Save processor state. This is called after a HALT instruction
- * succeeds, and on other occasions the processor enters debug mode
- * (breakpoint, watchpoint, etc). Caller has updated arm11->dscr.
- */
-static int arm11_debug_entry(struct arm11_common *arm11)
-{
- int retval;
-
- arm11->arm.target->state = TARGET_HALTED;
- arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
-
- /* REVISIT entire cache should already be invalid !!! */
- register_cache_invalidate(arm11->arm.core_cache);
-
- /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */
-
- /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
- arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL);
- if (arm11->is_wdtr_saved) {
- arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
-
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain5_fields[3];
-
- arm11_setup_field(arm11, 32, NULL,
- &arm11->saved_wdtr, chain5_fields + 0);
- arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 1);
- arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
- chain5_fields), chain5_fields, TAP_DRPAUSE);
-
- }
-
- /* DSCR: set the Execute ARM instruction enable bit.
- *
- * ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode",
- * but not to issue ITRs(?). The ARMv7 arch spec says it's required
- * for executing instructions via ITR.
- */
- CHECK_RETVAL(arm11_write_DSCR(arm11, DSCR_ITR_EN | arm11->dscr));
-
-
- /* From the spec:
- Before executing any instruction in debug state you have to drain the write buffer.
- This ensures that no imprecise Data Aborts can return at a later point:*/
-
- /** \todo TODO: Test drain write buffer. */
-
-#if 0
- while (1) {
- /* MRC p14,0,R0,c5,c10,0 */
- /* arm11_run_instr_no_data1(arm11, / *0xee150e1a* /0xe320f000); */
-
- /* mcr 15, 0, r0, cr7, cr10, {4} */
- arm11_run_instr_no_data1(arm11, 0xee070f9a);
-
- uint32_t dscr = arm11_read_DSCR(arm11);
-
- LOG_DEBUG("DRAIN, DSCR %08x", dscr);
-
- if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT) {
- arm11_run_instr_no_data1(arm11, 0xe320f000);
-
- dscr = arm11_read_DSCR(arm11);
-
- LOG_DEBUG("DRAIN, DSCR %08x (DONE)", dscr);
-
- break;
- }
- }
-#endif
-
- /* Save registers.
- *
- * NOTE: ARM1136 TRM suggests saving just R0 here now, then
- * CPSR and PC after the rDTR stuff. We do it all at once.
- */
- retval = arm_dpm_read_current_registers(&arm11->dpm);
- if (retval != ERROR_OK)
- LOG_ERROR("DPM REG READ -- fail");
-
- retval = arm11_run_instr_data_prepare(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- /* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */
- arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL);
- if (arm11->is_rdtr_saved) {
- /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
- retval = arm11_run_instr_data_from_core_via_r0(arm11,
- 0xEE100E15, &arm11->saved_rdtr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* REVISIT Now that we've saved core state, there's may also
- * be MMU and cache state to care about ...
- */
-
- if (arm11->simulate_reset_on_next_halt) {
- arm11->simulate_reset_on_next_halt = false;
-
- LOG_DEBUG("Reset c1 Control Register");
-
- /* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */
-
- /* MCR p15,0,R0,c1,c0,0 */
- retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0);
- if (retval != ERROR_OK)
- return retval;
-
- }
-
- if (arm11->arm.target->debug_reason == DBG_REASON_WATCHPOINT) {
- uint32_t wfar;
-
- /* MRC p15, 0, <Rd>, c6, c0, 1 ; Read WFAR */
- retval = arm11_run_instr_data_from_core_via_r0(arm11,
- ARMV4_5_MRC(15, 0, 0, 6, 0, 1),
- &wfar);
- if (retval != ERROR_OK)
- return retval;
- arm_dpm_report_wfar(arm11->arm.dpm, wfar);
- }
-
-
- retval = arm11_run_instr_data_finish(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-/**
- * Restore processor state. This is called in preparation for
- * the RESTART function.
- */
-static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
-{
- int retval;
-
- /* See e.g. ARM1136 TRM, "14.8.5 Leaving Debug state" */
-
- /* NOTE: the ARM1136 TRM suggests restoring all registers
- * except R0/PC/CPSR right now. Instead, we do them all
- * at once, just a bit later on.
- */
-
- /* REVISIT once we start caring about MMU and cache state,
- * address it here ...
- */
-
- /* spec says clear wDTR and rDTR; we assume they are clear as
- otherwise our programming would be sloppy */
- {
- CHECK_RETVAL(arm11_read_DSCR(arm11));
-
- if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL)) {
- /*
- The wDTR/rDTR two registers that are used to send/receive data to/from
- the core in tandem with corresponding instruction codes that are
- written into the core. The RDTR FULL/WDTR FULL flag indicates that the
- registers hold data that was written by one side (CPU or JTAG) and not
- read out by the other side.
- */
- LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08x)",
- (unsigned) arm11->dscr);
- return ERROR_FAIL;
- }
- }
-
- /* maybe restore original wDTR */
- if (arm11->is_wdtr_saved) {
- retval = arm11_run_instr_data_prepare(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- /* MCR p14,0,R0,c0,c5,0 */
- retval = arm11_run_instr_data_to_core_via_r0(arm11,
- 0xee000e15, arm11->saved_wdtr);
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm11_run_instr_data_finish(arm11);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* restore CPSR, PC, and R0 ... after flushing any modified
- * registers.
- */
- CHECK_RETVAL(arm_dpm_write_dirty_registers(&arm11->dpm, bpwp));
-
- CHECK_RETVAL(arm11_bpwp_flush(arm11));
-
- register_cache_invalidate(arm11->arm.core_cache);
-
- /* restore DSCR */
- CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
-
- /* maybe restore rDTR */
- if (arm11->is_rdtr_saved) {
- arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
-
- arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain5_fields[3];
-
- uint8_t Ready = 0; /* ignored */
- uint8_t Valid = 0; /* ignored */
-
- arm11_setup_field(arm11, 32, &arm11->saved_rdtr,
- NULL, chain5_fields + 0);
- arm11_setup_field(arm11, 1, &Ready, NULL, chain5_fields + 1);
- arm11_setup_field(arm11, 1, &Valid, NULL, chain5_fields + 2);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
- chain5_fields), chain5_fields, TAP_DRPAUSE);
- }
-
- /* now processor is ready to RESTART */
-
- return ERROR_OK;
-}
-
-/* poll current target status */
-static int arm11_poll(struct target *target)
-{
- int retval;
- struct arm11_common *arm11 = target_to_arm11(target);
-
- CHECK_RETVAL(arm11_check_init(arm11));
-
- if (arm11->dscr & DSCR_CORE_HALTED) {
- if (target->state != TARGET_HALTED) {
- enum target_state old_state = target->state;
-
- LOG_DEBUG("enter TARGET_HALTED");
- retval = arm11_debug_entry(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- target_call_event_callbacks(target,
- (old_state == TARGET_DEBUG_RUNNING)
- ? TARGET_EVENT_DEBUG_HALTED
- : TARGET_EVENT_HALTED);
- }
- } else {
- if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) {
- LOG_DEBUG("enter TARGET_RUNNING");
- target->state = TARGET_RUNNING;
- target->debug_reason = DBG_REASON_NOTHALTED;
- }
- }
-
- return ERROR_OK;
-}
-/* architecture specific status reply */
-static int arm11_arch_state(struct target *target)
-{
- struct arm11_common *arm11 = target_to_arm11(target);
- int retval;
-
- retval = arm_arch_state(target);
-
- /* REVISIT also display ARM11-specific MMU and cache status ... */
-
- if (target->debug_reason == DBG_REASON_WATCHPOINT)
- LOG_USER("Watchpoint triggered at PC %#08x",
- (unsigned) arm11->dpm.wp_pc);
-
- return retval;
-}
-
-/* target execution control */
-static int arm11_halt(struct target *target)
-{
- struct arm11_common *arm11 = target_to_arm11(target);
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state == TARGET_UNKNOWN)
- arm11->simulate_reset_on_next_halt = true;
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- int i = 0;
-
- while (1) {
- CHECK_RETVAL(arm11_read_DSCR(arm11));
-
- if (arm11->dscr & DSCR_CORE_HALTED)
- break;
-
-
- int64_t then = 0;
- if (i == 1000)
- then = timeval_ms();
- if (i >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
- i++;
- }
-
- enum target_state old_state = target->state;
-
- CHECK_RETVAL(arm11_debug_entry(arm11));
-
- CHECK_RETVAL(
- target_call_event_callbacks(target,
- old_state ==
- TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED));
-
- return ERROR_OK;
-}
-
-static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address)
-{
- void *value = arm11->arm.pc->value;
-
- /* use the current program counter */
- if (current)
- address = buf_get_u32(value, 0, 32);
-
- /* Make sure that the gdb thumb fixup does not
- * kill the return address
- */
- switch (arm11->arm.core_state) {
- case ARM_STATE_ARM:
- address &= 0xFFFFFFFC;
- break;
- case ARM_STATE_THUMB:
- /* When the return address is loaded into PC
- * bit 0 must be 1 to stay in Thumb state
- */
- address |= 0x1;
- break;
-
- /* catch-all for JAZELLE and THUMB_EE */
- default:
- break;
- }
-
- buf_set_u32(value, 0, 32, address);
- arm11->arm.pc->dirty = 1;
- arm11->arm.pc->valid = 1;
-
- return address;
-}
-
-static int arm11_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- /* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */
- /* current, address, handle_breakpoints, debug_execution); */
-
- struct arm11_common *arm11 = target_to_arm11(target);
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- address = arm11_nextpc(arm11, current, address);
-
- LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : "");
-
- /* clear breakpoints/watchpoints and VCR*/
- CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));
-
- if (!debug_execution)
- target_free_all_working_areas(target);
-
- /* Should we skip over breakpoints matching the PC? */
- if (handle_breakpoints) {
- struct breakpoint *bp;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- if (bp->address == address) {
- LOG_DEBUG("must step over %08" PRIx32 "", bp->address);
- arm11_step(target, 1, 0, 0);
- break;
- }
- }
- }
-
- /* activate all breakpoints */
- if (true) {
- struct breakpoint *bp;
- unsigned brp_num = 0;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- struct arm11_sc7_action brp[2];
-
- brp[0].write = 1;
- brp[0].address = ARM11_SC7_BVR0 + brp_num;
- brp[0].value = bp->address;
- brp[1].write = 1;
- brp[1].address = ARM11_SC7_BCR0 + brp_num;
- brp[1].value = 0x1 |
- (3 <<
- 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21);
-
- CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)));
-
- LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num,
- bp->address);
-
- brp_num++;
- }
-
- if (arm11->vcr)
- CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr));
- }
-
- /* activate all watchpoints and breakpoints */
- CHECK_RETVAL(arm11_leave_debug_state(arm11, true));
-
- arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- int i = 0;
- while (1) {
- CHECK_RETVAL(arm11_read_DSCR(arm11));
-
- LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
-
- if (arm11->dscr & DSCR_CORE_RESTARTED)
- break;
-
-
- int64_t then = 0;
- if (i == 1000)
- then = timeval_ms();
- if (i >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
- i++;
- }
-
- target->debug_reason = DBG_REASON_NOTHALTED;
- if (!debug_execution)
- target->state = TARGET_RUNNING;
- else
- target->state = TARGET_DEBUG_RUNNING;
- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
-
- return ERROR_OK;
-}
-
-static int arm11_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- struct arm11_common *arm11 = target_to_arm11(target);
-
- address = arm11_nextpc(arm11, current, address);
-
- LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : "");
-
-
- /** \todo TODO: Thumb not supported here */
-
- uint32_t next_instruction;
-
- CHECK_RETVAL(arm11_read_memory_word(arm11, address, &next_instruction));
-
- /* skip over BKPT */
- if ((next_instruction & 0xFFF00070) == 0xe1200070) {
- address = arm11_nextpc(arm11, 0, address + 4);
- LOG_DEBUG("Skipping BKPT %08" PRIx32, address);
- }
- /* skip over Wait for interrupt / Standby
- * mcr 15, 0, r?, cr7, cr0, {4} */
- else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) {
- address = arm11_nextpc(arm11, 0, address + 4);
- LOG_DEBUG("Skipping WFI %08" PRIx32, address);
- }
- /* ignore B to self */
- else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe)
- LOG_DEBUG("Not stepping jump to self");
- else {
- /** \todo TODO: check if break-/watchpoints make any sense at all in combination
- * with this. */
-
- /** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively
- * the VCR might be something worth looking into. */
-
-
- /* Set up breakpoint for stepping */
-
- struct arm11_sc7_action brp[2];
-
- brp[0].write = 1;
- brp[0].address = ARM11_SC7_BVR0;
- brp[1].write = 1;
- brp[1].address = ARM11_SC7_BCR0;
-
- if (arm11->hardware_step) {
- /* Hardware single stepping ("instruction address
- * mismatch") is used if enabled. It's not quite
- * exactly "run one instruction"; "branch to here"
- * loops won't break, neither will some other cases,
- * but it's probably the best default.
- *
- * Hardware single stepping isn't supported on v6
- * debug modules. ARM1176 and v7 can support it...
- *
- * FIXME Thumb stepping likely needs to use 0x03
- * or 0xc0 byte masks, not 0x0f.
- */
- brp[0].value = address;
- brp[1].value = 0x1 | (3 << 1) | (0x0F << 5)
- | (0 << 14) | (0 << 16) | (0 << 20)
- | (2 << 21);
- } else {
- /* Sets a breakpoint on the next PC, as calculated
- * by instruction set simulation.
- *
- * REVISIT stepping Thumb on ARM1156 requires Thumb2
- * support from the simulator.
- */
- uint32_t next_pc;
- int retval;
-
- retval = arm_simulate_step(target, &next_pc);
- if (retval != ERROR_OK)
- return retval;
-
- brp[0].value = next_pc;
- brp[1].value = 0x1 | (3 << 1) | (0x0F << 5)
- | (0 << 14) | (0 << 16) | (0 << 20)
- | (0 << 21);
- }
-
- CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)));
-
- /* resume */
-
-
- if (arm11->step_irq_enable)
- /* this disable should be redundant ... */
- arm11->dscr &= ~DSCR_INT_DIS;
- else
- arm11->dscr |= DSCR_INT_DIS;
-
-
- CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints));
-
- arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- /* wait for halt */
- int i = 0;
-
- while (1) {
- const uint32_t mask = DSCR_CORE_RESTARTED
- | DSCR_CORE_HALTED;
-
- CHECK_RETVAL(arm11_read_DSCR(arm11));
- LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr);
-
- if ((arm11->dscr & mask) == mask)
- break;
-
- long long then = 0;
- if (i == 1000)
- then = timeval_ms();
- if (i >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING(
- "Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
- i++;
- }
-
- /* clear breakpoint */
- CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));
-
- /* save state */
- CHECK_RETVAL(arm11_debug_entry(arm11));
-
- /* restore default state */
- arm11->dscr &= ~DSCR_INT_DIS;
-
- }
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
-
- return ERROR_OK;
-}
-
-static int arm11_assert_reset(struct target *target)
-{
- struct arm11_common *arm11 = target_to_arm11(target);
-
- if (!(target_was_examined(target))) {
- if (jtag_get_reset_config() & RESET_HAS_SRST)
- jtag_add_reset(0, 1);
- else {
- LOG_WARNING("Reset is not asserted because the target is not examined.");
- LOG_WARNING("Use a reset button or power cycle the target.");
- return ERROR_TARGET_NOT_EXAMINED;
- }
- } else {
-
- /* optionally catch reset vector */
- if (target->reset_halt && !(arm11->vcr & 1))
- CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1));
-
- /* Issue some kind of warm reset. */
- if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
- target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
- else if (jtag_get_reset_config() & RESET_HAS_SRST) {
- /* REVISIT handle "pulls" cases, if there's
- * hardware that needs them to work.
- */
- jtag_add_reset(0, 1);
- } else {
- LOG_ERROR("%s: how to reset?", target_name(target));
- return ERROR_FAIL;
- }
- }
-
- /* registers are now invalid */
- register_cache_invalidate(arm11->arm.core_cache);
-
- target->state = TARGET_RESET;
-
- return ERROR_OK;
-}
-
-/*
- * - There is another bug in the arm11 core. (iMX31 specific again?)
- * When you generate an access to external logic (for example DDR
- * controller via AHB bus) and that block is not configured (perhaps
- * it is still held in reset), that transaction will never complete.
- * This will hang arm11 core but it will also hang JTAG controller.
- * Nothing short of srst assertion will bring it out of this.
- */
-
-static int arm11_deassert_reset(struct target *target)
-{
- struct arm11_common *arm11 = target_to_arm11(target);
- int retval;
-
- /* be certain SRST is off */
- jtag_add_reset(0, 0);
-
- /* WORKAROUND i.MX31 problems: SRST goofs the TAP, and resets
- * at least DSCR. OMAP24xx doesn't show that problem, though
- * SRST-only reset seems to be problematic for other reasons.
- * (Secure boot sequences being one likelihood!)
- */
- jtag_add_tlr();
-
- CHECK_RETVAL(arm11_poll(target));
-
- if (target->reset_halt) {
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("%s: ran after reset and before halt ...",
- target_name(target));
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- /* maybe restore vector catch config */
- if (target->reset_halt && !(arm11->vcr & 1))
- CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr));
-
- return ERROR_OK;
-}
-
-/* target memory access
- * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
- * count: number of items of <size>
- *
- * arm11_config_memrw_no_increment - in the future we may want to be able
- * to read/write a range of data to a "port". a "port" is an action on
- * read memory address for some peripheral.
- */
-static int arm11_read_memory_inner(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer,
- bool arm11_config_memrw_no_increment)
-{
- /** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment
- *problems */
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "",
- address,
- size,
- count);
-
- struct arm11_common *arm11 = target_to_arm11(target);
-
- retval = arm11_run_instr_data_prepare(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- /* MRC p14,0,r0,c0,c5,0 */
- retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
- if (retval != ERROR_OK)
- return retval;
-
- switch (size) {
- case 1:
- arm11->arm.core_cache->reg_list[1].dirty = true;
-
- for (size_t i = 0; i < count; i++) {
- /* ldrb r1, [r0], #1 */
- /* ldrb r1, [r0] */
- CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
- !arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000));
-
- uint32_t res;
- /* MCR p14,0,R1,c0,c5,0 */
- CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
-
- *buffer++ = res;
- }
-
- break;
-
- case 2:
- {
- arm11->arm.core_cache->reg_list[1].dirty = true;
-
- for (size_t i = 0; i < count; i++) {
- /* ldrh r1, [r0], #2 */
- CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
- !arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0));
-
- uint32_t res;
-
- /* MCR p14,0,R1,c0,c5,0 */
- CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
-
- uint16_t svalue = res;
- memcpy(buffer + i * sizeof(uint16_t), &svalue, sizeof(uint16_t));
- }
-
- break;
- }
-
- case 4:
- {
- uint32_t instr = !arm11_config_memrw_no_increment ? 0xecb05e01 : 0xed905e00;
- /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
- uint32_t *words = (uint32_t *)(void *)buffer;
-
- /* LDC p14,c5,[R0],#4 */
- /* LDC p14,c5,[R0] */
- CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, instr, words, count));
- break;
- }
- }
-
- return arm11_run_instr_data_finish(arm11);
-}
-
-static int arm11_read_memory(struct target *target,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- uint8_t *buffer)
-{
- return arm11_read_memory_inner(target, address, size, count, buffer, false);
-}
-
-/*
-* no_increment - in the future we may want to be able
-* to read/write a range of data to a "port". a "port" is an action on
-* read memory address for some peripheral.
-*/
-static int arm11_write_memory_inner(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, const uint8_t *buffer,
- bool no_increment)
-{
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "",
- address,
- size,
- count);
-
- struct arm11_common *arm11 = target_to_arm11(target);
-
- retval = arm11_run_instr_data_prepare(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- /* load r0 with buffer address
- * MRC p14,0,r0,c0,c5,0 */
- retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
- if (retval != ERROR_OK)
- return retval;
-
- /* burst writes are not used for single words as those may well be
- * reset init script writes.
- *
- * The other advantage is that as burst writes are default, we'll
- * now exercise both burst and non-burst code paths with the
- * default settings, increasing code coverage.
- */
- bool burst = arm11->memwrite_burst && (count > 1);
-
- switch (size) {
- case 1:
- {
- arm11->arm.core_cache->reg_list[1].dirty = true;
-
- for (size_t i = 0; i < count; i++) {
- /* load r1 from DCC with byte data */
- /* MRC p14,0,r1,c0,c5,0 */
- retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
- if (retval != ERROR_OK)
- return retval;
-
- /* write r1 to memory */
- /* strb r1, [r0], #1 */
- /* strb r1, [r0] */
- retval = arm11_run_instr_no_data1(arm11,
- !no_increment ? 0xe4c01001 : 0xe5c01000);
- if (retval != ERROR_OK)
- return retval;
- }
-
- break;
- }
-
- case 2:
- {
- arm11->arm.core_cache->reg_list[1].dirty = true;
-
- for (size_t i = 0; i < count; i++) {
- uint16_t value;
- memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
-
- /* load r1 from DCC with halfword data */
- /* MRC p14,0,r1,c0,c5,0 */
- retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
- if (retval != ERROR_OK)
- return retval;
-
- /* write r1 to memory */
- /* strh r1, [r0], #2 */
- /* strh r1, [r0] */
- retval = arm11_run_instr_no_data1(arm11,
- !no_increment ? 0xe0c010b2 : 0xe1c010b0);
- if (retval != ERROR_OK)
- return retval;
- }
-
- break;
- }
-
- case 4: {
- /* stream word data through DCC directly to memory */
- /* increment: STC p14,c5,[R0],#4 */
- /* no increment: STC p14,c5,[R0]*/
- uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00;
-
- /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
- uint32_t *words = (uint32_t *)(void *)buffer;
-
- /* "burst" here just means trusting each instruction executes
- * fully before we run the next one: per-word roundtrips, to
- * check the Ready flag, are not used.
- */
- if (!burst)
- retval = arm11_run_instr_data_to_core(arm11,
- instr, words, count);
- else
- retval = arm11_run_instr_data_to_core_noack(arm11,
- instr, words, count);
- if (retval != ERROR_OK)
- return retval;
-
- break;
- }
- }
-
- /* r0 verification */
- if (!no_increment) {
- uint32_t r0;
-
- /* MCR p14,0,R0,c0,c5,0 */
- retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1);
- if (retval != ERROR_OK)
- return retval;
-
- if (address + size * count != r0) {
- LOG_ERROR("Data transfer failed. Expected end "
- "address 0x%08x, got 0x%08x",
- (unsigned) (address + size * count),
- (unsigned) r0);
-
- if (burst)
- LOG_ERROR(
- "use 'arm11 memwrite burst disable' to disable fast burst mode");
-
-
- if (arm11->memwrite_error_fatal)
- return ERROR_FAIL;
- }
- }
-
- return arm11_run_instr_data_finish(arm11);
-}
-
-static int arm11_write_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- /* pointer increment matters only for multi-unit writes ...
- * not e.g. to a "reset the chip" controller.
- */
- return arm11_write_memory_inner(target, address, size,
- count, buffer, count == 1);
-}
-
-/* target break-/watchpoint control
-* rw: 0 = write, 1 = read, 2 = access
-*/
-static int arm11_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct arm11_common *arm11 = target_to_arm11(target);
-
-#if 0
- if (breakpoint->type == BKPT_SOFT) {
- LOG_INFO("sw breakpoint requested, but software breakpoints not enabled");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-#endif
-
- if (!arm11->free_brps) {
- LOG_DEBUG("no breakpoint unit available for hardware breakpoint");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->length != 4) {
- LOG_DEBUG("only breakpoints of four bytes length supported");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- arm11->free_brps--;
-
- return ERROR_OK;
-}
-
-static int arm11_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct arm11_common *arm11 = target_to_arm11(target);
-
- arm11->free_brps++;
-
- return ERROR_OK;
-}
-
-static int arm11_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm11_common *arm11;
-
- if (target->tap == NULL)
- return ERROR_FAIL;
-
- if (target->tap->ir_length != 5) {
- LOG_ERROR("'target arm11' expects IR LENGTH = 5");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- arm11 = calloc(1, sizeof *arm11);
- if (!arm11)
- return ERROR_FAIL;
-
- arm11->arm.core_type = ARM_MODE_ANY;
- arm_init_arch_info(target, &arm11->arm);
-
- arm11->jtag_info.tap = target->tap;
- arm11->jtag_info.scann_size = 5;
- arm11->jtag_info.scann_instr = ARM11_SCAN_N;
- arm11->jtag_info.cur_scan_chain = ~0; /* invalid/unknown */
- arm11->jtag_info.intest_instr = ARM11_INTEST;
-
- arm11->memwrite_burst = true;
- arm11->memwrite_error_fatal = true;
-
- return ERROR_OK;
-}
-
-static int arm11_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- /* Initialize anything we can set up without talking to the target */
- return ERROR_OK;
-}
-
-/* talk to the target and set things up */
-static int arm11_examine(struct target *target)
-{
- int retval;
- char *type;
- struct arm11_common *arm11 = target_to_arm11(target);
- uint32_t didr, device_id;
- uint8_t implementor;
-
- /* FIXME split into do-first-time and do-every-time logic ... */
-
- /* check IDCODE */
-
- arm11_add_IR(arm11, ARM11_IDCODE, ARM11_TAP_DEFAULT);
-
- struct scan_field idcode_field;
-
- arm11_setup_field(arm11, 32, NULL, &device_id, &idcode_field);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &idcode_field, TAP_DRPAUSE);
-
- /* check DIDR */
-
- arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT);
-
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain0_fields[2];
-
- arm11_setup_field(arm11, 32, NULL, &didr, chain0_fields + 0);
- arm11_setup_field(arm11, 8, NULL, &implementor, chain0_fields + 1);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
- chain0_fields), chain0_fields, TAP_IDLE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- /* assume the manufacturer id is ok; check the part # */
- switch ((device_id >> 12) & 0xFFFF) {
- case 0x7B36:
- type = "ARM1136";
- break;
- case 0x7B37:
- type = "ARM11 MPCore";
- break;
- case 0x7B56:
- type = "ARM1156";
- break;
- case 0x7B76:
- arm11->arm.core_type = ARM_MODE_MON;
- /* NOTE: could default arm11->hardware_step to true */
- type = "ARM1176";
- break;
- default:
- LOG_ERROR("unexpected ARM11 ID code");
- return ERROR_FAIL;
- }
- LOG_INFO("found %s", type);
-
- /* unlikely this could ever fail, but ... */
- switch ((didr >> 16) & 0x0F) {
- case ARM11_DEBUG_V6:
- case ARM11_DEBUG_V61: /* supports security extensions */
- break;
- default:
- LOG_ERROR("Only ARM v6 and v6.1 debug supported.");
- return ERROR_FAIL;
- }
-
- arm11->brp = ((didr >> 24) & 0x0F) + 1;
-
- /** \todo TODO: reserve one brp slot if we allow breakpoints during step */
- arm11->free_brps = arm11->brp;
-
- LOG_DEBUG("IDCODE %08" PRIx32 " IMPLEMENTOR %02x DIDR %08" PRIx32,
- device_id, implementor, didr);
-
- /* Build register cache "late", after target_init(), since we
- * want to know if this core supports Secure Monitor mode.
- */
- if (!target_was_examined(target))
- CHECK_RETVAL(arm11_dpm_init(arm11, didr));
-
- /* as a side-effect this reads DSCR and thus
- * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag
- * as suggested by the spec.
- */
-
- retval = arm11_check_init(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- /* ETM on ARM11 still uses original scanchain 6 access mode */
- if (arm11->arm.etm && !target_was_examined(target)) {
- *register_get_last_cache_p(&target->reg_cache) =
- etm_build_reg_cache(target, &arm11->jtag_info,
- arm11->arm.etm);
- CHECK_RETVAL(etm_setup(target));
- }
-
- target_set_examined(target);
-
- return ERROR_OK;
-}
-
-#define ARM11_BOOL_WRAPPER(name, print_name) \
- COMMAND_HANDLER(arm11_handle_bool_ ## name) \
- { \
- struct target *target = get_current_target(CMD_CTX); \
- struct arm11_common *arm11 = target_to_arm11(target); \
- \
- return CALL_COMMAND_HANDLER(handle_command_parse_bool, \
- &arm11->name, print_name); \
- }
-
-ARM11_BOOL_WRAPPER(memwrite_burst, "memory write burst mode")
-ARM11_BOOL_WRAPPER(memwrite_error_fatal, "fatal error mode for memory writes")
-ARM11_BOOL_WRAPPER(step_irq_enable, "IRQs while stepping")
-ARM11_BOOL_WRAPPER(hardware_step, "hardware single step")
-
-/* REVISIT handle the VCR bits like other ARMs: use symbols for
- * input and output values.
- */
-
-COMMAND_HANDLER(arm11_handle_vcr)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm11_common *arm11 = target_to_arm11(target);
-
- switch (CMD_ARGC) {
- case 0:
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], arm11->vcr);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- LOG_INFO("VCR 0x%08" PRIx32 "", arm11->vcr);
- return ERROR_OK;
-}
-
-static const struct command_registration arm11_mw_command_handlers[] = {
- {
- .name = "burst",
- .handler = arm11_handle_bool_memwrite_burst,
- .mode = COMMAND_ANY,
- .help = "Display or modify flag controlling potentially "
- "risky fast burst mode (default: enabled)",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "error_fatal",
- .handler = arm11_handle_bool_memwrite_error_fatal,
- .mode = COMMAND_ANY,
- .help = "Display or modify flag controlling transfer "
- "termination on transfer errors"
- " (default: enabled)",
- .usage = "['enable'|'disable']",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration arm11_any_command_handlers[] = {
- {
- /* "hardware_step" is only here to check if the default
- * simulate + breakpoint implementation is broken.
- * TEMPORARY! NOT DOCUMENTED! */
- .name = "hardware_step",
- .handler = arm11_handle_bool_hardware_step,
- .mode = COMMAND_ANY,
- .help = "DEBUG ONLY - Hardware single stepping"
- " (default: disabled)",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "memwrite",
- .mode = COMMAND_ANY,
- .help = "memwrite command group",
- .usage = "",
- .chain = arm11_mw_command_handlers,
- },
- {
- .name = "step_irq_enable",
- .handler = arm11_handle_bool_step_irq_enable,
- .mode = COMMAND_ANY,
- .help = "Display or modify flag controlling interrupt "
- "enable while stepping (default: disabled)",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "vcr",
- .handler = arm11_handle_vcr,
- .mode = COMMAND_ANY,
- .help = "Display or modify Vector Catch Register",
- .usage = "[value]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration arm11_command_handlers[] = {
- {
- .chain = arm_command_handlers,
- },
- {
- .chain = etm_command_handlers,
- },
- {
- .name = "arm11",
- .mode = COMMAND_ANY,
- .help = "ARM11 command group",
- .usage = "",
- .chain = arm11_any_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for ARM11xx targets. */
-struct target_type arm11_target = {
- .name = "arm11",
-
- .poll = arm11_poll,
- .arch_state = arm11_arch_state,
-
- .halt = arm11_halt,
- .resume = arm11_resume,
- .step = arm11_step,
-
- .assert_reset = arm11_assert_reset,
- .deassert_reset = arm11_deassert_reset,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm11_read_memory,
- .write_memory = arm11_write_memory,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .add_breakpoint = arm11_add_breakpoint,
- .remove_breakpoint = arm11_remove_breakpoint,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .commands = arm11_command_handlers,
- .target_create = arm11_target_create,
- .init_target = arm11_init_target,
- .examine = arm11_examine,
-};
diff --git a/src/target/arm11.h b/src/target/arm11.h
deleted file mode 100644
index 77cc223..0000000
--- a/src/target/arm11.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 digenius technology GmbH. *
- * Michael Bruck *
- * *
- * Copyright (C) 2008 Georg Acher <acher@in.tum.de> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM11_H
-#define OPENOCD_TARGET_ARM11_H
-
-#include "arm.h"
-#include "arm_dpm.h"
-
-#define ARM11_TAP_DEFAULT TAP_INVALID
-
-#define CHECK_RETVAL(action) \
- do { \
- int __retval = (action); \
- if (__retval != ERROR_OK) { \
- LOG_DEBUG("error while calling \"%s\"", \
- # action); \
- return __retval; \
- } \
- } while (0)
-
-/* bits from ARMv7 DIDR */
-enum arm11_debug_version {
- ARM11_DEBUG_V6 = 0x01,
- ARM11_DEBUG_V61 = 0x02,
- ARM11_DEBUG_V7 = 0x03,
- ARM11_DEBUG_V7_CP14 = 0x04,
-};
-
-struct arm11_common {
- struct arm arm;
-
- /** Debug module state. */
- struct arm_dpm dpm;
- struct arm11_sc7_action *bpwp_actions;
- unsigned bpwp_n;
-
- size_t brp; /**< Number of Breakpoint Register Pairs from DIDR */
- size_t free_brps; /**< Number of breakpoints allocated */
-
- uint32_t dscr; /**< Last retrieved DSCR value. */
-
- uint32_t saved_rdtr;
- uint32_t saved_wdtr;
-
- bool is_rdtr_saved;
- bool is_wdtr_saved;
-
- bool simulate_reset_on_next_halt; /**< Perform cleanups of the ARM state on next halt **/
-
- /* Per-core configurable options.
- * NOTE that several of these boolean options should not exist
- * once the relevant code is known to work correctly.
- */
- bool memwrite_burst;
- bool memwrite_error_fatal;
- bool step_irq_enable;
- bool hardware_step;
-
- /** Configured Vector Catch Register settings. */
- uint32_t vcr;
-
- struct arm_jtag jtag_info;
-};
-
-static inline struct arm11_common *target_to_arm11(struct target *target)
-{
- return container_of(target->arch_info, struct arm11_common, arm);
-}
-
-/**
- * ARM11 DBGTAP instructions
- *
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html
- */
-enum arm11_instructions {
- ARM11_EXTEST = 0x00,
- ARM11_SCAN_N = 0x02,
- ARM11_RESTART = 0x04,
- ARM11_HALT = 0x08,
- ARM11_INTEST = 0x0C,
- ARM11_ITRSEL = 0x1D,
- ARM11_IDCODE = 0x1E,
- ARM11_BYPASS = 0x1F,
-};
-
-enum arm11_sc7 {
- ARM11_SC7_NULL = 0,
- ARM11_SC7_VCR = 7,
- ARM11_SC7_PC = 8,
- ARM11_SC7_BVR0 = 64,
- ARM11_SC7_BCR0 = 80,
- ARM11_SC7_WVR0 = 96,
- ARM11_SC7_WCR0 = 112,
-};
-
-#endif /* OPENOCD_TARGET_ARM11_H */
diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c
deleted file mode 100644
index 2232b3e..0000000
--- a/src/target/arm11_dbgtap.c
+++ /dev/null
@@ -1,1195 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 digenius technology GmbH. *
- * Michael Bruck *
- * *
- * Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm_jtag.h"
-#include "arm11_dbgtap.h"
-
-#include <helper/time_support.h>
-
-#if 0
-#define JTAG_DEBUG(expr ...) do { if (1) \
- LOG_DEBUG(expr); } while (0)
-#else
-#define JTAG_DEBUG(expr ...) do { if (0) \
- LOG_DEBUG(expr); } while (0)
-#endif
-
-/*
-This pathmove goes from Pause-IR to Shift-IR while avoiding RTI. The
-behavior of the FTDI driver IIRC was to go via RTI.
-
-Conversely there may be other places in this code where the ARM11 code relies
-on the driver to hit through RTI when coming from Update-?R.
-*/
-static const tap_state_t arm11_move_pi_to_si_via_ci[] = {
- TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IRSHIFT
-};
-
-/* REVISIT no error handling here! */
-static void arm11_add_ir_scan_vc(struct jtag_tap *tap, struct scan_field *fields,
- tap_state_t state)
-{
- if (cmd_queue_cur_state == TAP_IRPAUSE)
- jtag_add_pathmove(ARRAY_SIZE(arm11_move_pi_to_si_via_ci),
- arm11_move_pi_to_si_via_ci);
-
- jtag_add_ir_scan(tap, fields, state);
-}
-
-static const tap_state_t arm11_move_pd_to_sd_via_cd[] = {
- TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DRSHIFT
-};
-
-/* REVISIT no error handling here! */
-void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields,
- tap_state_t state)
-{
- if (cmd_queue_cur_state == TAP_DRPAUSE)
- jtag_add_pathmove(ARRAY_SIZE(arm11_move_pd_to_sd_via_cd),
- arm11_move_pd_to_sd_via_cd);
-
- jtag_add_dr_scan(tap, num_fields, fields, state);
-}
-
-
-/** Code de-clutter: Construct struct scan_field to write out a value
- *
- * \param arm11 Target state variable.
- * \param num_bits Length of the data field
- * \param out_data pointer to the data that will be sent out
- * <em > (data is read when it is added to the JTAG queue)</em>
- * \param in_data pointer to the memory that will receive data that was clocked in
- * <em > (data is written when the JTAG queue is executed)</em>
- * \param field target data structure that will be initialized
- */
-void arm11_setup_field(struct arm11_common *arm11, int num_bits,
- void *out_data, void *in_data, struct scan_field *field)
-{
- field->num_bits = num_bits;
- field->out_value = out_data;
- field->in_value = in_data;
-}
-
-static const char *arm11_ir_to_string(uint8_t ir)
-{
- const char *s = "unknown";
-
- switch (ir) {
- case ARM11_EXTEST:
- s = "EXTEST";
- break;
- case ARM11_SCAN_N:
- s = "SCAN_N";
- break;
- case ARM11_RESTART:
- s = "RESTART";
- break;
- case ARM11_HALT:
- s = "HALT";
- break;
- case ARM11_INTEST:
- s = "INTEST";
- break;
- case ARM11_ITRSEL:
- s = "ITRSEL";
- break;
- case ARM11_IDCODE:
- s = "IDCODE";
- break;
- case ARM11_BYPASS:
- s = "BYPASS";
- break;
- }
- return s;
-}
-
-/** Write JTAG instruction register
- *
- * \param arm11 Target state variable.
- * \param instr An ARM11 DBGTAP instruction. Use enum #arm11_instructions.
- * \param state Pass the final TAP state or ARM11_TAP_DEFAULT for the default value (Pause-IR).
- *
- * \remarks This adds to the JTAG command queue but does \em not execute it.
- */
-void arm11_add_IR(struct arm11_common *arm11, uint8_t instr, tap_state_t state)
-{
- struct jtag_tap *tap = arm11->arm.target->tap;
-
- if (buf_get_u32(tap->cur_instr, 0, 5) == instr) {
- JTAG_DEBUG("IR <= 0x%02x SKIPPED", instr);
- return;
- }
-
- JTAG_DEBUG("IR <= %s (0x%02x)", arm11_ir_to_string(instr), instr);
-
- struct scan_field field;
-
- arm11_setup_field(arm11, 5, &instr, NULL, &field);
-
- arm11_add_ir_scan_vc(arm11->arm.target->tap,
- &field,
- state == ARM11_TAP_DEFAULT ? TAP_IRPAUSE : state);
-}
-
-/** Verify data shifted out from Scan Chain Register (SCREG). */
-static void arm11_in_handler_SCAN_N(uint8_t *in_value)
-{
- /* Don't expect JTAG layer to modify bits we didn't ask it to read */
- uint8_t v = *in_value & 0x1F;
-
- if (v != 0x10) {
- LOG_ERROR("'arm11 target' JTAG error SCREG OUT 0x%02x", v);
- jtag_set_error(ERROR_FAIL);
- }
-}
-
-/** Select and write to Scan Chain Register (SCREG)
- *
- * This function sets the instruction register to SCAN_N and writes
- * the data register with the selected chain number.
- *
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/Cacbjhfg.html
- *
- * \param arm11 Target state variable.
- * \param chain Scan chain that will be selected.
- * \param state Pass the final TAP state or ARM11_TAP_DEFAULT for the default
- * value (Pause-DR).
- *
- * Changes the current scan chain if needed, transitions to the specified
- * TAP state, and leaves the IR undefined.
- *
- * The chain takes effect when Update-DR is passed (usually when subsequently
- * the INTEXT/EXTEST instructions are written).
- *
- * \warning (Obsolete) Using this twice in a row will \em fail. The first
- * call will end in Pause-DR. The second call, due to the IR
- * caching, will not go through Capture-DR when shifting in the
- * new scan chain number. As a result the verification in
- * arm11_in_handler_SCAN_N() must fail.
- *
- * \remarks This adds to the JTAG command queue but does \em not execute it.
- */
-
-int arm11_add_debug_SCAN_N(struct arm11_common *arm11,
- uint8_t chain, tap_state_t state)
-{
- /* Don't needlessly switch the scan chain.
- * NOTE: the ITRSEL instruction fakes SCREG changing;
- * but leaves its actual value unchanged.
- */
-#if 0
- /* FIX!!! the optimization below is broken because we do not */
- /* invalidate the cur_scan_chain upon a TRST/TMS. See arm_jtag.c */
- /* for example on how to invalidate cur_scan_chain. Tested patches gladly */
- /* accepted! */
- if (arm11->jtag_info.cur_scan_chain == chain) {
- JTAG_DEBUG("SCREG <= %d SKIPPED", chain);
- return jtag_add_statemove((state == ARM11_TAP_DEFAULT)
- ? TAP_DRPAUSE : state);
- }
-#endif
- JTAG_DEBUG("SCREG <= %d", chain);
-
- arm11_add_IR(arm11, ARM11_SCAN_N, ARM11_TAP_DEFAULT);
-
- struct scan_field field;
-
- uint8_t tmp[1];
- arm11_setup_field(arm11, 5, &chain, &tmp, &field);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap,
- 1,
- &field,
- state == ARM11_TAP_DEFAULT ? TAP_DRPAUSE : state);
-
- jtag_execute_queue_noclear();
-
- arm11_in_handler_SCAN_N(tmp);
-
- arm11->jtag_info.cur_scan_chain = chain;
-
- return jtag_execute_queue();
-}
-
-/**
- * Queue a DR scan of the ITR register. Caller must have selected
- * scan chain 4 (ITR), possibly using ITRSEL.
- *
- * \param arm11 Target state variable.
- * \param inst An ARM11 processor instruction/opcode.
- * \param flag Optional parameter to retrieve the Ready flag;
- * this address will be written when the JTAG chain is scanned.
- * \param state The TAP state to enter after the DR scan.
- *
- * Going through the TAP_DRUPDATE state writes ITR only if Ready was
- * previously set. Only the Ready flag is readable by the scan.
- *
- * An instruction loaded into ITR is executed when going through the
- * TAP_IDLE state only if Ready was previously set and the debug state
- * is properly set up. Depending on the instruction, you may also need
- * to ensure that the rDTR is ready before that Run-Test/Idle state.
- */
-static void arm11_add_debug_INST(struct arm11_common *arm11,
- uint32_t inst, uint8_t *flag, tap_state_t state)
-{
- JTAG_DEBUG("INST <= 0x%08x", (unsigned) inst);
-
- struct scan_field itr[2];
-
- arm11_setup_field(arm11, 32, &inst, NULL, itr + 0);
- arm11_setup_field(arm11, 1, NULL, flag, itr + 1);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(itr), itr, state);
-}
-
-/**
- * Read and save the Debug Status and Control Register (DSCR).
- *
- * \param arm11 Target state variable.
- * \return Error status; arm11->dscr is updated on success.
- *
- * \remarks This is a stand-alone function that executes the JTAG
- * command queue. It does not require the ARM11 debug TAP to be
- * in any particular state.
- */
-int arm11_read_DSCR(struct arm11_common *arm11)
-{
- int retval;
-
- retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT);
- if (retval != ERROR_OK)
- return retval;
-
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
-
- uint32_t dscr;
- struct scan_field chain1_field;
-
- arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &chain1_field, TAP_DRPAUSE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- if (arm11->dscr != dscr)
- JTAG_DEBUG("DSCR = %08x (OLD %08x)",
- (unsigned) dscr,
- (unsigned) arm11->dscr);
-
- arm11->dscr = dscr;
-
- return ERROR_OK;
-}
-
-/** Write the Debug Status and Control Register (DSCR)
- *
- * same as CP14 c1
- *
- * \param arm11 Target state variable.
- * \param dscr DSCR content
- *
- * \remarks This is a stand-alone function that executes the JTAG command queue.
- */
-int arm11_write_DSCR(struct arm11_common *arm11, uint32_t dscr)
-{
- int retval;
- retval = arm11_add_debug_SCAN_N(arm11, 0x01, ARM11_TAP_DEFAULT);
- if (retval != ERROR_OK)
- return retval;
-
- arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain1_field;
-
- arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field);
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &chain1_field, TAP_DRPAUSE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- JTAG_DEBUG("DSCR <= %08x (OLD %08x)",
- (unsigned) dscr,
- (unsigned) arm11->dscr);
-
- arm11->dscr = dscr;
-
- return ERROR_OK;
-}
-
-/** Prepare the stage for ITR/DTR operations
- * from the arm11_run_instr... group of functions.
- *
- * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()
- * around a block of arm11_run_instr_... calls.
- *
- * Select scan chain 5 to allow quick access to DTR. When scan
- * chain 4 is needed to put in a register the ITRSel instruction
- * shortcut is used instead of actually changing the Scan_N
- * register.
- *
- * \param arm11 Target state variable.
- *
- */
-int arm11_run_instr_data_prepare(struct arm11_common *arm11)
-{
- return arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
-}
-
-/** Cleanup after ITR/DTR operations
- * from the arm11_run_instr... group of functions
- *
- * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()
- * around a block of arm11_run_instr_... calls.
- *
- * Any IDLE can lead to an instruction execution when
- * scan chains 4 or 5 are selected and the IR holds
- * INTEST or EXTEST. So we must disable that before
- * any following activities lead to an IDLE.
- *
- * \param arm11 Target state variable.
- *
- */
-int arm11_run_instr_data_finish(struct arm11_common *arm11)
-{
- return arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT);
-}
-
-/**
- * Execute one or more instructions via ITR.
- * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
- * is set, the ITR Ready flag is set (as seen on the previous entry to
- * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode Pointer to sequence of ARM opcodes
- * \param count Number of opcodes to execute
- *
- */
-static
-int arm11_run_instr_no_data(struct arm11_common *arm11,
- uint32_t *opcode, size_t count)
-{
- arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
-
- while (count--) {
- arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_IDLE);
-
- int i = 0;
- while (1) {
- uint8_t flag;
-
- arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_IDLE : TAP_DRPAUSE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- if (flag)
- break;
-
- int64_t then = 0;
-
- if (i == 1000)
- then = timeval_ms();
- if (i >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING(
- "Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
-
- i++;
- }
- }
-
- return ERROR_OK;
-}
-
-/** Execute one instruction via ITR
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode ARM opcode
- *
- */
-int arm11_run_instr_no_data1(struct arm11_common *arm11, uint32_t opcode)
-{
- return arm11_run_instr_no_data(arm11, &opcode, 1);
-}
-
-
-/** Execute one instruction via ITR repeatedly while
- * passing data to the core via DTR on each execution.
- *
- * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
- * is set, the ITR Ready flag is set (as seen on the previous entry to
- * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
- *
- * The executed instruction \em must read data from DTR.
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode ARM opcode
- * \param data Pointer to the data words to be passed to the core
- * \param count Number of data words and instruction repetitions
- *
- */
-int arm11_run_instr_data_to_core(struct arm11_common *arm11,
- uint32_t opcode,
- uint32_t *data,
- size_t count)
-{
- arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
-
- arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE);
-
- arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain5_fields[3];
-
- uint32_t Data;
- uint8_t Ready;
- uint8_t nRetry;
-
- arm11_setup_field(arm11, 32, &Data, NULL, chain5_fields + 0);
- arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1);
- arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2);
-
- while (count--) {
- int i = 0;
- do {
- Data = *data;
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
- chain5_fields), chain5_fields, TAP_IDLE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- JTAG_DEBUG("DTR Ready %d nRetry %d", Ready, nRetry);
-
- int64_t then = 0;
-
- if (i == 1000)
- then = timeval_ms();
- if (i >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING(
- "Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
-
- i++;
- } while (!Ready);
-
- data++;
- }
-
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
-
- int i = 0;
- do {
- Data = 0;
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
- chain5_fields), chain5_fields, TAP_DRPAUSE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d",
- (unsigned) Data, Ready, nRetry);
-
- int64_t then = 0;
-
- if (i == 1000)
- then = timeval_ms();
- if (i >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
-
- i++;
- } while (!Ready);
-
- return ERROR_OK;
-}
-
-/** JTAG path for arm11_run_instr_data_to_core_noack
- *
- * The repeated TAP_IDLE's do not cause a repeated execution
- * if passed without leaving the state.
- *
- * Since this is more than 7 bits (adjustable via adding more
- * TAP_IDLE's) it produces an artificial delay in the lower
- * layer (FT2232) that is long enough to finish execution on
- * the core but still shorter than any manually inducible delays.
- *
- * To disable this code, try "memwrite burst false"
- *
- * FIX!!! should we use multiple TAP_IDLE here or not???
- *
- * https://lists.berlios.de/pipermail/openocd-development/2009-July/009698.html
- * https://lists.berlios.de/pipermail/openocd-development/2009-August/009865.html
- */
-static const tap_state_t arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] = {
- TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE,
- TAP_DRSHIFT
-};
-
-/* This inner loop can be implemented by the minidriver, oftentimes in hardware... The
- * minidriver can call the default implementation as a fallback or implement it
- * from scratch.
- */
-int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap *tap,
- uint32_t opcode,
- uint32_t *data,
- size_t count)
-{
- struct scan_field chain5_fields[3];
-
- chain5_fields[0].num_bits = 32;
- chain5_fields[0].out_value = NULL; /*&Data*/
- chain5_fields[0].in_value = NULL;
-
- chain5_fields[1].num_bits = 1;
- chain5_fields[1].out_value = NULL;
- chain5_fields[1].in_value = NULL; /*&Ready*/
-
- chain5_fields[2].num_bits = 1;
- chain5_fields[2].out_value = NULL;
- chain5_fields[2].in_value = NULL;
-
- uint8_t *Readies;
- unsigned readiesNum = count;
- unsigned bytes = sizeof(*Readies)*readiesNum;
-
- Readies = malloc(bytes);
- if (Readies == NULL) {
- LOG_ERROR("Out of memory allocating %u bytes", bytes);
- return ERROR_FAIL;
- }
-
- uint8_t *ReadyPos = Readies;
- while (count--) {
- chain5_fields[0].out_value = (uint8_t *)(data++);
- chain5_fields[1].in_value = ReadyPos++;
-
- if (count > 0) {
- jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields,
- TAP_DRPAUSE);
- jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
- arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay);
- } else
- jtag_add_dr_scan(tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_IDLE);
- }
-
- int retval = jtag_execute_queue();
- if (retval == ERROR_OK) {
- unsigned error_count = 0;
-
- for (size_t i = 0; i < readiesNum; i++) {
- if (Readies[i] != 1)
- error_count++;
- }
-
- if (error_count > 0) {
- LOG_ERROR("%u words out of %u not transferred",
- error_count, readiesNum);
- retval = ERROR_FAIL;
- }
- }
- free(Readies);
-
- return retval;
-}
-
-int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
- uint32_t opcode,
- uint32_t *data,
- size_t count);
-
-#ifndef HAVE_JTAG_MINIDRIVER_H
-int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap *tap,
- uint32_t opcode,
- uint32_t *data,
- size_t count)
-{
- return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, data, count);
-}
-#endif
-
-/** Execute one instruction via ITR repeatedly while
- * passing data to the core via DTR on each execution.
- *
- * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
- * is set, the ITR Ready flag is set (as seen on the previous entry to
- * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
- *
- * No Ready check during transmission.
- *
- * The executed instruction \em must read data from DTR.
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode ARM opcode
- * \param data Pointer to the data words to be passed to the core
- * \param count Number of data words and instruction repetitions
- *
- */
-int arm11_run_instr_data_to_core_noack(struct arm11_common *arm11,
- uint32_t opcode,
- uint32_t *data,
- size_t count)
-{
- arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
-
- arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE);
-
- arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
-
- int retval = arm11_run_instr_data_to_core_noack_inner(arm11->arm.target->tap,
- opcode,
- data,
- count);
-
- if (retval != ERROR_OK)
- return retval;
-
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain5_fields[3];
-
- arm11_setup_field(arm11,
- 32,
- NULL /*&Data*/,
- NULL,
- chain5_fields + 0);
- arm11_setup_field(arm11,
- 1,
- NULL,
- NULL /*&Ready*/,
- chain5_fields + 1);
- arm11_setup_field(arm11,
- 1,
- NULL,
- NULL,
- chain5_fields + 2);
-
- uint8_t ready_flag;
- chain5_fields[1].in_value = &ready_flag;
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
- chain5_fields), chain5_fields, TAP_DRPAUSE);
-
- retval = jtag_execute_queue();
- if (retval == ERROR_OK) {
- if (ready_flag != 1) {
- LOG_ERROR("last word not transferred");
- retval = ERROR_FAIL;
- }
- }
-
- return retval;
-}
-
-
-/** Execute an instruction via ITR while handing data into the core via DTR.
- *
- * The executed instruction \em must read data from DTR.
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode ARM opcode
- * \param data Data word to be passed to the core via DTR
- *
- */
-int arm11_run_instr_data_to_core1(struct arm11_common *arm11, uint32_t opcode, uint32_t data)
-{
- return arm11_run_instr_data_to_core(arm11, opcode, &data, 1);
-}
-
-
-/** Execute one instruction via ITR repeatedly while
- * reading data from the core via DTR on each execution.
- *
- * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
- * is set, the ITR Ready flag is set (as seen on the previous entry to
- * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
- *
- * The executed instruction \em must write data to DTR.
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode ARM opcode
- * \param data Pointer to an array that receives the data words from the core
- * \param count Number of data words and instruction repetitions
- *
- */
-int arm11_run_instr_data_from_core(struct arm11_common *arm11,
- uint32_t opcode,
- uint32_t *data,
- size_t count)
-{
- arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
-
- arm11_add_debug_INST(arm11, opcode, NULL, TAP_IDLE);
-
- arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain5_fields[3];
-
- uint32_t Data;
- uint8_t Ready;
- uint8_t nRetry;
-
- arm11_setup_field(arm11, 32, NULL, &Data, chain5_fields + 0);
- arm11_setup_field(arm11, 1, NULL, &Ready, chain5_fields + 1);
- arm11_setup_field(arm11, 1, NULL, &nRetry, chain5_fields + 2);
-
- while (count--) {
- int i = 0;
- do {
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(
- chain5_fields), chain5_fields,
- count ? TAP_IDLE : TAP_DRPAUSE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d",
- (unsigned) Data, Ready, nRetry);
-
- int64_t then = 0;
-
- if (i == 1000)
- then = timeval_ms();
- if (i >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING(
- "Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
-
- i++;
- } while (!Ready);
-
- *data++ = Data;
- }
-
- return ERROR_OK;
-}
-
-/** Execute one instruction via ITR
- * then load r0 into DTR and read DTR from core.
- *
- * The first executed instruction (\p opcode) should write data to r0.
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode ARM opcode to write r0 with the value of interest
- * \param data Pointer to a data word that receives the value from r0 after \p opcode was executed.
- *
- */
-int arm11_run_instr_data_from_core_via_r0(struct arm11_common *arm11,
- uint32_t opcode,
- uint32_t *data)
-{
- int retval;
- retval = arm11_run_instr_no_data1(arm11, opcode);
- if (retval != ERROR_OK)
- return retval;
-
- /* MCR p14,0,R0,c0,c5,0 (move r0 -> wDTR -> local var) */
- arm11_run_instr_data_from_core(arm11, 0xEE000E15, data, 1);
-
- return ERROR_OK;
-}
-
-/** Load data into core via DTR then move it to r0 then
- * execute one instruction via ITR
- *
- * The final executed instruction (\p opcode) should read data from r0.
- *
- * \pre arm11_run_instr_data_prepare() / arm11_run_instr_data_finish() block
- *
- * \param arm11 Target state variable.
- * \param opcode ARM opcode to read r0 act upon it
- * \param data Data word that will be written to r0 before \p opcode is executed
- *
- */
-int arm11_run_instr_data_to_core_via_r0(struct arm11_common *arm11, uint32_t opcode, uint32_t data)
-{
- int retval;
- /* MRC p14,0,r0,c0,c5,0 */
- retval = arm11_run_instr_data_to_core1(arm11, 0xEE100E15, data);
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm11_run_instr_no_data1(arm11, opcode);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-/** Apply reads and writes to scan chain 7
- *
- * \see struct arm11_sc7_action
- *
- * \param arm11 Target state variable.
- * \param actions A list of read and/or write instructions
- * \param count Number of instructions in the list.
- *
- */
-int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, size_t count)
-{
- int retval;
-
- retval = arm11_add_debug_SCAN_N(arm11, 0x07, ARM11_TAP_DEFAULT);
- if (retval != ERROR_OK)
- return retval;
-
- arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
-
- struct scan_field chain7_fields[3];
-
- uint8_t nRW;
- uint32_t DataOut;
- uint8_t AddressOut;
- uint8_t Ready;
- uint32_t DataIn;
- uint8_t AddressIn;
-
- arm11_setup_field(arm11, 1, &nRW, &Ready, chain7_fields + 0);
- arm11_setup_field(arm11, 32, &DataOut, &DataIn, chain7_fields + 1);
- arm11_setup_field(arm11, 7, &AddressOut, &AddressIn, chain7_fields + 2);
-
- for (size_t i = 0; i < count + 1; i++) {
- if (i < count) {
- nRW = actions[i].write ? 1 : 0;
- DataOut = actions[i].value;
- AddressOut = actions[i].address;
- } else {
- nRW = 1;
- DataOut = 0;
- AddressOut = 0;
- }
-
- /* Timeout here so we don't get stuck. */
- int i_n = 0;
- while (1) {
- JTAG_DEBUG("SC7 <= c%-3d Data %08x %s",
- (unsigned) AddressOut,
- (unsigned) DataOut,
- nRW ? "write" : "read");
-
- arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain7_fields),
- chain7_fields, TAP_DRPAUSE);
-
- CHECK_RETVAL(jtag_execute_queue());
-
- /* 'nRW' is 'Ready' on read out */
- if (Ready)
- break;
-
- int64_t then = 0;
-
- if (i_n == 1000)
- then = timeval_ms();
- if (i_n >= 1000) {
- if ((timeval_ms()-then) > 1000) {
- LOG_WARNING(
- "Timeout (1000ms) waiting for instructions to complete");
- return ERROR_FAIL;
- }
- }
-
- i_n++;
- }
-
- if (!nRW)
- JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn);
-
- if (i > 0) {
- if (actions[i - 1].address != AddressIn)
- LOG_WARNING("Scan chain 7 shifted out unexpected address");
-
- if (!actions[i - 1].write)
- actions[i - 1].value = DataIn;
- else {
- if (actions[i - 1].value != DataIn)
- LOG_WARNING("Scan chain 7 shifted out unexpected data");
- }
- }
- }
- return ERROR_OK;
-}
-
-/** Clear VCR and all breakpoints and watchpoints via scan chain 7
- *
- * \param arm11 Target state variable.
- *
- */
-int arm11_sc7_clear_vbw(struct arm11_common *arm11)
-{
- size_t clear_bw_size = arm11->brp + 1;
- struct arm11_sc7_action *clear_bw = malloc(sizeof(struct arm11_sc7_action) * clear_bw_size);
- struct arm11_sc7_action *pos = clear_bw;
-
- for (size_t i = 0; i < clear_bw_size; i++) {
- clear_bw[i].write = true;
- clear_bw[i].value = 0;
- }
-
- for (size_t i = 0; i < arm11->brp; i++)
- (pos++)->address = ARM11_SC7_BCR0 + i;
-
- (pos++)->address = ARM11_SC7_VCR;
-
- int retval;
- retval = arm11_sc7_run(arm11, clear_bw, clear_bw_size);
-
- free(clear_bw);
-
- return retval;
-}
-
-/** Write VCR register
- *
- * \param arm11 Target state variable.
- * \param value Value to be written
- */
-int arm11_sc7_set_vcr(struct arm11_common *arm11, uint32_t value)
-{
- struct arm11_sc7_action set_vcr;
-
- set_vcr.write = true;
- set_vcr.address = ARM11_SC7_VCR;
- set_vcr.value = value;
-
- return arm11_sc7_run(arm11, &set_vcr, 1);
-}
-
-/** Read word from address
- *
- * \param arm11 Target state variable.
- * \param address Memory address to be read
- * \param result Pointer where to store result
- *
- */
-int arm11_read_memory_word(struct arm11_common *arm11, uint32_t address, uint32_t *result)
-{
- int retval;
- retval = arm11_run_instr_data_prepare(arm11);
- if (retval != ERROR_OK)
- return retval;
-
- /* MRC p14,0,r0,c0,c5,0 (r0 = address) */
- CHECK_RETVAL(arm11_run_instr_data_to_core1(arm11, 0xee100e15, address));
-
- /* LDC p14,c5,[R0],#4 (DTR = [r0]) */
- CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xecb05e01, result, 1));
-
- return arm11_run_instr_data_finish(arm11);
-}
-
-/************************************************************************/
-
-/*
- * ARM11 provider for the OpenOCD implementation of the standard
- * architectural ARM v6/v7 "Debug Programmer's Model" (DPM).
- */
-
-static inline struct arm11_common *dpm_to_arm11(struct arm_dpm *dpm)
-{
- return container_of(dpm, struct arm11_common, dpm);
-}
-
-static int arm11_dpm_prepare(struct arm_dpm *dpm)
-{
- return arm11_run_instr_data_prepare(dpm_to_arm11(dpm));
-}
-
-static int arm11_dpm_finish(struct arm_dpm *dpm)
-{
- return arm11_run_instr_data_finish(dpm_to_arm11(dpm));
-}
-
-static int arm11_dpm_instr_write_data_dcc(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t data)
-{
- return arm11_run_instr_data_to_core(dpm_to_arm11(dpm),
- opcode, &data, 1);
-}
-
-static int arm11_dpm_instr_write_data_r0(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t data)
-{
- return arm11_run_instr_data_to_core_via_r0(dpm_to_arm11(dpm),
- opcode, data);
-}
-
-static int arm11_dpm_instr_read_data_dcc(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t *data)
-{
- return arm11_run_instr_data_from_core(dpm_to_arm11(dpm),
- opcode, data, 1);
-}
-
-static int arm11_dpm_instr_read_data_r0(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t *data)
-{
- return arm11_run_instr_data_from_core_via_r0(dpm_to_arm11(dpm),
- opcode, data);
-}
-
-/* Because arm11_sc7_run() takes a vector of actions, we batch breakpoint
- * and watchpoint operations instead of running them right away. Since we
- * pre-allocated our vector, we don't need to worry about space.
- */
-static int arm11_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
- uint32_t addr, uint32_t control)
-{
- struct arm11_common *arm11 = dpm_to_arm11(dpm);
- struct arm11_sc7_action *action;
-
- action = arm11->bpwp_actions + arm11->bpwp_n;
-
- /* Invariant: this bp/wp is disabled.
- * It also happens that the core is halted here, but for
- * DPM-based cores we don't actually care about that.
- */
-
- action[0].write = action[1].write = true;
-
- action[0].value = addr;
- action[1].value = control;
-
- switch (index_t) {
- case 0 ... 15:
- action[0].address = ARM11_SC7_BVR0 + index_t;
- action[1].address = ARM11_SC7_BCR0 + index_t;
- break;
- case 16 ... 32:
- index_t -= 16;
- action[0].address = ARM11_SC7_WVR0 + index_t;
- action[1].address = ARM11_SC7_WCR0 + index_t;
- break;
- default:
- return ERROR_FAIL;
- }
-
- arm11->bpwp_n += 2;
-
- return ERROR_OK;
-}
-
-static int arm11_bpwp_disable(struct arm_dpm *dpm, unsigned index_t)
-{
- struct arm11_common *arm11 = dpm_to_arm11(dpm);
- struct arm11_sc7_action *action;
-
- action = arm11->bpwp_actions + arm11->bpwp_n;
-
- action[0].write = true;
- action[0].value = 0;
-
- switch (index_t) {
- case 0 ... 15:
- action[0].address = ARM11_SC7_BCR0 + index_t;
- break;
- case 16 ... 32:
- index_t -= 16;
- action[0].address = ARM11_SC7_WCR0 + index_t;
- break;
- default:
- return ERROR_FAIL;
- }
-
- arm11->bpwp_n += 1;
-
- return ERROR_OK;
-}
-
-/** Flush any pending breakpoint and watchpoint updates. */
-int arm11_bpwp_flush(struct arm11_common *arm11)
-{
- int retval;
-
- if (!arm11->bpwp_n)
- return ERROR_OK;
-
- retval = arm11_sc7_run(arm11, arm11->bpwp_actions, arm11->bpwp_n);
- arm11->bpwp_n = 0;
-
- return retval;
-}
-
-/** Set up high-level debug module utilities */
-int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr)
-{
- struct arm_dpm *dpm = &arm11->dpm;
- int retval;
-
- dpm->arm = &arm11->arm;
-
- dpm->didr = didr;
-
- dpm->prepare = arm11_dpm_prepare;
- dpm->finish = arm11_dpm_finish;
-
- dpm->instr_write_data_dcc = arm11_dpm_instr_write_data_dcc;
- dpm->instr_write_data_r0 = arm11_dpm_instr_write_data_r0;
-
- dpm->instr_read_data_dcc = arm11_dpm_instr_read_data_dcc;
- dpm->instr_read_data_r0 = arm11_dpm_instr_read_data_r0;
-
- dpm->bpwp_enable = arm11_bpwp_enable;
- dpm->bpwp_disable = arm11_bpwp_disable;
-
- retval = arm_dpm_setup(dpm);
- if (retval != ERROR_OK)
- return retval;
-
- /* alloc enough to enable all breakpoints and watchpoints at once */
- arm11->bpwp_actions = calloc(2 * (dpm->nbp + dpm->nwp),
- sizeof *arm11->bpwp_actions);
- if (!arm11->bpwp_actions)
- return ERROR_FAIL;
-
- retval = arm_dpm_initialize(dpm);
- if (retval != ERROR_OK)
- return retval;
-
- return arm11_bpwp_flush(arm11);
-}
diff --git a/src/target/arm11_dbgtap.h b/src/target/arm11_dbgtap.h
deleted file mode 100644
index 541434e..0000000
--- a/src/target/arm11_dbgtap.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 digenius technology GmbH. *
- * Michael Bruck *
- * *
- * Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM11_DBGTAP_H
-#define OPENOCD_TARGET_ARM11_DBGTAP_H
-
-#include "arm11.h"
-
-/* ARM11 internals */
-
-void arm11_setup_field(struct arm11_common *arm11, int num_bits,
- void *in_data, void *out_data, struct scan_field *field);
-void arm11_add_IR(struct arm11_common *arm11,
- uint8_t instr, tap_state_t state);
-int arm11_add_debug_SCAN_N(struct arm11_common *arm11,
- uint8_t chain, tap_state_t state);
-int arm11_read_DSCR(struct arm11_common *arm11);
-int arm11_write_DSCR(struct arm11_common *arm11, uint32_t dscr);
-
-int arm11_run_instr_data_prepare(struct arm11_common *arm11);
-int arm11_run_instr_data_finish(struct arm11_common *arm11);
-int arm11_run_instr_no_data1(struct arm11_common *arm11, uint32_t opcode);
-int arm11_run_instr_data_to_core(struct arm11_common *arm11,
- uint32_t opcode, uint32_t *data, size_t count);
-int arm11_run_instr_data_to_core_noack(struct arm11_common *arm11,
- uint32_t opcode, uint32_t *data, size_t count);
-int arm11_run_instr_data_to_core1(struct arm11_common *arm11,
- uint32_t opcode, uint32_t data);
-int arm11_run_instr_data_from_core(struct arm11_common *arm11,
- uint32_t opcode, uint32_t *data, size_t count);
-int arm11_run_instr_data_from_core_via_r0(struct arm11_common *arm11,
- uint32_t opcode, uint32_t *data);
-int arm11_run_instr_data_to_core_via_r0(struct arm11_common *arm11,
- uint32_t opcode, uint32_t data);
-
-void arm11_add_dr_scan_vc(struct jtag_tap *tap, int num_fields, struct scan_field *fields,
- tap_state_t state);
-
-/**
- * Used with arm11_sc7_run to make a list of read/write commands for
- * scan chain 7
- */
-struct arm11_sc7_action {
- bool write; /**< Access mode: true for write, false for read. */
- uint8_t address;/**< Register address mode. Use enum #arm11_sc7 */
- /**
- * If write then set this to value to be written. In read mode
- * this receives the read value when the function returns.
- */
- uint32_t value;
-};
-
-int arm11_sc7_run(struct arm11_common *arm11,
- struct arm11_sc7_action *actions, size_t count);
-
-/* Mid-level helper functions */
-int arm11_sc7_clear_vbw(struct arm11_common *arm11);
-int arm11_sc7_set_vcr(struct arm11_common *arm11, uint32_t value);
-
-int arm11_read_memory_word(struct arm11_common *arm11,
- uint32_t address, uint32_t *result);
-
-int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr);
-int arm11_bpwp_flush(struct arm11_common *arm11);
-
-#endif /* OPENOCD_TARGET_ARM11_DBGTAP_H */
diff --git a/src/target/arm720t.c b/src/target/arm720t.c
deleted file mode 100644
index 3991e19..0000000
--- a/src/target/arm720t.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2009 by Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm720t.h"
-#include <helper/time_support.h>
-#include "target_type.h"
-#include "register.h"
-#include "arm_opcodes.h"
-
-
-/*
- * ARM720 is an ARM7TDMI-S with MMU and ETM7. For information, see
- * ARM DDI 0229C especially Chapter 9 about debug support.
- */
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-static int arm720t_scan_cp15(struct target *target,
- uint32_t out, uint32_t *in, int instruction, int clock_arg)
-{
- int retval;
- struct arm720t_common *arm720t = target_to_arm720(target);
- struct arm_jtag *jtag_info;
- struct scan_field fields[2];
- uint8_t out_buf[4];
- uint8_t instruction_buf = instruction;
-
- jtag_info = &arm720t->arm7_9_common.jtag_info;
-
- buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 1;
- fields[0].out_value = &instruction_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 32;
- fields[1].out_value = out_buf;
- fields[1].in_value = NULL;
-
- if (in) {
- fields[1].in_value = (uint8_t *)in;
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
- jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
- } else
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
-
- if (clock_arg)
- jtag_add_runtest(0, TAP_DRPAUSE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (in)
- LOG_DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
- else
- LOG_DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock_arg);
-#else
- LOG_DEBUG("out: %8.8" PRIx32 ", instruction: %i, clock: %i", out, instruction, clock_arg);
-#endif
-
- return ERROR_OK;
-}
-
-static int arm720t_read_cp15(struct target *target, uint32_t opcode, uint32_t *value)
-{
- /* fetch CP15 opcode */
- arm720t_scan_cp15(target, opcode, NULL, 1, 1);
- /* "DECODE" stage */
- arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
- /* "EXECUTE" stage (1) */
- arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
- arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
- /* "EXECUTE" stage (2) */
- arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
- /* "EXECUTE" stage (3), CDATA is read */
- arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);
-
- return ERROR_OK;
-}
-
-static int arm720t_write_cp15(struct target *target, uint32_t opcode, uint32_t value)
-{
- /* fetch CP15 opcode */
- arm720t_scan_cp15(target, opcode, NULL, 1, 1);
- /* "DECODE" stage */
- arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
- /* "EXECUTE" stage (1) */
- arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
- arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
- /* "EXECUTE" stage (2) */
- arm720t_scan_cp15(target, value, NULL, 0, 1);
- arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
-
- return ERROR_OK;
-}
-
-static int arm720t_get_ttb(struct target *target, uint32_t *result)
-{
- uint32_t ttb = 0x0;
-
- int retval;
-
- retval = arm720t_read_cp15(target, 0xee120f10, &ttb);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- ttb &= 0xffffc000;
-
- *result = ttb;
-
- return ERROR_OK;
-}
-
-static int arm720t_disable_mmu_caches(struct target *target,
- int mmu, int d_u_cache, int i_cache)
-{
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = arm720t_read_cp15(target, 0xee110f10, &cp15_control);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (mmu)
- cp15_control &= ~0x1U;
-
- if (d_u_cache || i_cache)
- cp15_control &= ~0x4U;
-
- retval = arm720t_write_cp15(target, 0xee010f10, cp15_control);
- return retval;
-}
-
-static int arm720t_enable_mmu_caches(struct target *target,
- int mmu, int d_u_cache, int i_cache)
-{
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = arm720t_read_cp15(target, 0xee110f10, &cp15_control);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (mmu)
- cp15_control |= 0x1U;
-
- if (d_u_cache || i_cache)
- cp15_control |= 0x4U;
-
- retval = arm720t_write_cp15(target, 0xee010f10, cp15_control);
- return retval;
-}
-
-static int arm720t_post_debug_entry(struct target *target)
-{
- struct arm720t_common *arm720t = target_to_arm720(target);
- int retval;
-
- /* examine cp15 control reg */
- retval = arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm720t->cp15_control_reg);
-
- arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
- arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
- arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
- /* save i/d fault status and address register */
- retval = arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
- if (retval != ERROR_OK)
- return retval;
- retval = arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- return retval;
-}
-
-static void arm720t_pre_restore_context(struct target *target)
-{
- struct arm720t_common *arm720t = target_to_arm720(target);
-
- /* restore i/d fault status and address register */
- arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);
- arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
-}
-
-static int arm720t_verify_pointer(struct command_context *cmd_ctx,
- struct arm720t_common *arm720t)
-{
- if (arm720t->common_magic != ARM720T_COMMON_MAGIC) {
- command_print(cmd_ctx, "target is not an ARM720");
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-static int arm720t_arch_state(struct target *target)
-{
- struct arm720t_common *arm720t = target_to_arm720(target);
-
- static const char *state[] = {
- "disabled", "enabled"
- };
-
- arm_arch_state(target);
- LOG_USER("MMU: %s, Cache: %s",
- state[arm720t->armv4_5_mmu.mmu_enabled],
- state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
-
- return ERROR_OK;
-}
-
-static int arm720_mmu(struct target *target, int *enabled)
-{
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("%s: target not halted", __func__);
- return ERROR_TARGET_INVALID;
- }
-
- *enabled = target_to_arm720(target)->armv4_5_mmu.mmu_enabled;
- return ERROR_OK;
-}
-
-static int arm720_virt2phys(struct target *target,
- uint32_t virtual, uint32_t *physical)
-{
- uint32_t cb;
- struct arm720t_common *arm720t = target_to_arm720(target);
-
- uint32_t ret;
- int retval = armv4_5_mmu_translate_va(target,
- &arm720t->armv4_5_mmu, virtual, &cb, &ret);
- if (retval != ERROR_OK)
- return retval;
- *physical = ret;
- return ERROR_OK;
-}
-
-static int arm720t_read_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
- int retval;
- struct arm720t_common *arm720t = target_to_arm720(target);
-
- /* disable cache, but leave MMU enabled */
- if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
- retval = arm720t_disable_mmu_caches(target, 0, 1, 0);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = arm7_9_read_memory(target, address, size, count, buffer);
-
- if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
- retval = arm720t_enable_mmu_caches(target, 0, 1, 0);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int arm720t_read_phys_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct arm720t_common *arm720t = target_to_arm720(target);
-
- return armv4_5_mmu_read_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
-}
-
-static int arm720t_write_phys_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct arm720t_common *arm720t = target_to_arm720(target);
-
- return armv4_5_mmu_write_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
-}
-
-static int arm720t_soft_reset_halt(struct target *target)
-{
- int retval = ERROR_OK;
- struct arm720t_common *arm720t = target_to_arm720(target);
- struct reg *dbg_stat = &arm720t->arm7_9_common
- .eice_cache->reg_list[EICE_DBG_STAT];
- struct arm *arm = &arm720t->arm7_9_common.arm;
-
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- int timeout;
- while (!(timeout = ((timeval_ms()-then) > 1000))) {
- if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) {
- embeddedice_read_reg(dbg_stat);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- } else
- break;
- if (debug_level >= 3)
- alive_sleep(100);
- else
- keep_alive();
- }
- if (timeout) {
- LOG_ERROR("Failed to halt CPU after 1 sec");
- return ERROR_TARGET_TIMEOUT;
- }
-
- target->state = TARGET_HALTED;
-
- /* SVC, ARM state, IRQ and FIQ disabled */
- uint32_t cpsr;
-
- cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
- cpsr &= ~0xff;
- cpsr |= 0xd3;
- arm_set_cpsr(arm, cpsr);
- arm->cpsr->dirty = 1;
-
- /* start fetching from 0x0 */
- buf_set_u32(arm->pc->value, 0, 32, 0x0);
- arm->pc->dirty = 1;
- arm->pc->valid = 1;
-
- retval = arm720t_disable_mmu_caches(target, 1, 1, 1);
- if (retval != ERROR_OK)
- return retval;
- arm720t->armv4_5_mmu.mmu_enabled = 0;
- arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
- arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
- retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int arm720t_init_target(struct command_context *cmd_ctx, struct target *target)
-{
- return arm7tdmi_init_target(cmd_ctx, target);
-}
-
-/* FIXME remove forward decls */
-static int arm720t_mrc(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t *value);
-static int arm720t_mcr(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t value);
-
-static int arm720t_init_arch_info(struct target *target,
- struct arm720t_common *arm720t, struct jtag_tap *tap)
-{
- struct arm7_9_common *arm7_9 = &arm720t->arm7_9_common;
-
- arm7_9->arm.mrc = arm720t_mrc;
- arm7_9->arm.mcr = arm720t_mcr;
-
- arm7tdmi_init_arch_info(target, arm7_9, tap);
-
- arm720t->common_magic = ARM720T_COMMON_MAGIC;
-
- arm7_9->post_debug_entry = arm720t_post_debug_entry;
- arm7_9->pre_restore_context = arm720t_pre_restore_context;
-
- arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;
- arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;
- arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;
- arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;
- arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
- arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
- arm720t->armv4_5_mmu.has_tiny_pages = 0;
- arm720t->armv4_5_mmu.mmu_enabled = 0;
-
- return ERROR_OK;
-}
-
-static int arm720t_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm720t_common *arm720t = calloc(1, sizeof(*arm720t));
-
- arm720t->arm7_9_common.arm.is_armv4 = true;
- return arm720t_init_arch_info(target, arm720t, target->tap);
-}
-
-COMMAND_HANDLER(arm720t_handle_cp15_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct arm720t_common *arm720t = target_to_arm720(target);
-
- retval = arm720t_verify_pointer(CMD_CTX, arm720t);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- /* one or more argument, access a single register (write if second argument is given */
- if (CMD_ARGC >= 1) {
- uint32_t opcode;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode);
-
- if (CMD_ARGC == 1) {
- uint32_t value;
- retval = arm720t_read_cp15(target, opcode, &value);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
- return ERROR_OK;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
- } else if (CMD_ARGC == 2) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
-
- retval = arm720t_write_cp15(target, opcode, value);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
- return ERROR_OK;
- }
- command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
- }
- }
-
- return ERROR_OK;
-}
-
-static int arm720t_mrc(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t *value)
-{
- if (cpnum != 15) {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
-
- /* read "to" r0 */
- return arm720t_read_cp15(target,
- ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
- value);
-
-}
-
-static int arm720t_mcr(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t value)
-{
- if (cpnum != 15) {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
-
- /* write "from" r0 */
- return arm720t_write_cp15(target,
- ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
- value);
-}
-
-static const struct command_registration arm720t_exec_command_handlers[] = {
- {
- .name = "cp15",
- .handler = arm720t_handle_cp15_command,
- .mode = COMMAND_EXEC,
- /* prefer using less error-prone "arm mcr" or "arm mrc" */
- .help = "display/modify cp15 register using ARM opcode"
- " (DEPRECATED)",
- .usage = "instruction [value]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration arm720t_command_handlers[] = {
- {
- .chain = arm7_9_command_handlers,
- },
- {
- .name = "arm720t",
- .mode = COMMAND_ANY,
- .help = "arm720t command group",
- .usage = "",
- .chain = arm720t_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for ARM720 targets. */
-struct target_type arm720t_target = {
- .name = "arm720t",
-
- .poll = arm7_9_poll,
- .arch_state = arm720t_arch_state,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm720t_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm720t_read_memory,
- .write_memory = arm7_9_write_memory_opt,
- .read_phys_memory = arm720t_read_phys_memory,
- .write_phys_memory = arm720t_write_phys_memory,
- .mmu = arm720_mmu,
- .virt2phys = arm720_virt2phys,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm720t_command_handlers,
- .target_create = arm720t_target_create,
- .init_target = arm720t_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
-};
diff --git a/src/target/arm720t.h b/src/target/arm720t.h
deleted file mode 100644
index 31dad9c..0000000
--- a/src/target/arm720t.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM720T_H
-#define OPENOCD_TARGET_ARM720T_H
-
-#include "arm7tdmi.h"
-#include "armv4_5_mmu.h"
-
-#define ARM720T_COMMON_MAGIC 0xa720a720
-
-struct arm720t_common {
- struct arm7_9_common arm7_9_common;
- uint32_t common_magic;
- struct armv4_5_mmu_common armv4_5_mmu;
- uint32_t cp15_control_reg;
- uint32_t fsr_reg;
- uint32_t far_reg;
-};
-
-static inline struct arm720t_common *target_to_arm720(struct target *target)
-{
- return container_of(target->arch_info, struct arm720t_common, arm7_9_common.arm);
-}
-
-#endif /* OPENOCD_TARGET_ARM720T_H */
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
deleted file mode 100644
index c1d5c79..0000000
--- a/src/target/arm7_9_common.c
+++ /dev/null
@@ -1,2903 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by Hongtao Zheng *
- * hontor@126.com *
- * *
- * Copyright (C) 2009 by David Brownell *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "embeddedice.h"
-#include "target_request.h"
-#include "etm.h"
-#include <helper/time_support.h>
-#include "arm_simulator.h"
-#include "arm_semihosting.h"
-#include "algorithm.h"
-#include "register.h"
-#include "armv4_5.h"
-
-/**
- * @file
- * Hold common code supporting the ARM7 and ARM9 core generations.
- *
- * While the ARM core implementations evolved substantially during these
- * two generations, they look quite similar from the JTAG perspective.
- * Both have similar debug facilities, based on the same two scan chains
- * providing access to the core and to an EmbeddedICE module. Both can
- * support similar ETM and ETB modules, for tracing. And both expose
- * what could be viewed as "ARM Classic", with multiple processor modes,
- * shadowed registers, and support for the Thumb instruction set.
- *
- * Processor differences include things like presence or absence of MMU
- * and cache, pipeline sizes, use of a modified Harvard Architecure
- * (with separate instruction and data busses from the CPU), support
- * for cpu clock gating during idle, and more.
- */
-
-static int arm7_9_debug_entry(struct target *target);
-
-/**
- * Clear watchpoints for an ARM7/9 target.
- *
- * @param arm7_9 Pointer to the common struct for an ARM7/9 target
- * @return JTAG error status after executing queue
- */
-static int arm7_9_clear_watchpoints(struct arm7_9_common *arm7_9)
-{
- LOG_DEBUG("-");
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
- arm7_9->sw_breakpoint_count = 0;
- arm7_9->sw_breakpoints_added = 0;
- arm7_9->wp0_used = 0;
- arm7_9->wp1_used = arm7_9->wp1_used_default;
- arm7_9->wp_available = arm7_9->wp_available_max;
-
- return jtag_execute_queue();
-}
-
-/**
- * Assign a watchpoint to one of the two available hardware comparators in an
- * ARM7 or ARM9 target.
- *
- * @param arm7_9 Pointer to the common struct for an ARM7/9 target
- * @param breakpoint Pointer to the breakpoint to be used as a watchpoint
- */
-static void arm7_9_assign_wp(struct arm7_9_common *arm7_9, struct breakpoint *breakpoint)
-{
- if (!arm7_9->wp0_used) {
- arm7_9->wp0_used = 1;
- breakpoint->set = 1;
- arm7_9->wp_available--;
- } else if (!arm7_9->wp1_used) {
- arm7_9->wp1_used = 1;
- breakpoint->set = 2;
- arm7_9->wp_available--;
- } else
- LOG_ERROR("BUG: no hardware comparator available");
- LOG_DEBUG("BPID: %" PRId32 " (0x%08" PRIx32 ") using hw wp: %d",
- breakpoint->unique_id,
- breakpoint->address,
- breakpoint->set);
-}
-
-/**
- * Setup an ARM7/9 target's embedded ICE registers for software breakpoints.
- *
- * @param arm7_9 Pointer to common struct for ARM7/9 targets
- * @return Error codes if there is a problem finding a watchpoint or the result
- * of executing the JTAG queue
- */
-static int arm7_9_set_software_breakpoints(struct arm7_9_common *arm7_9)
-{
- if (arm7_9->sw_breakpoints_added)
- return ERROR_OK;
- if (arm7_9->wp_available < 1) {
- LOG_WARNING("can't enable sw breakpoints with no watchpoint unit available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- arm7_9->wp_available--;
-
- /* pick a breakpoint unit */
- if (!arm7_9->wp0_used) {
- arm7_9->sw_breakpoints_added = 1;
- arm7_9->wp0_used = 3;
- } else if (!arm7_9->wp1_used) {
- arm7_9->sw_breakpoints_added = 2;
- arm7_9->wp1_used = 3;
- } else {
- LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
- return ERROR_FAIL;
- }
-
- if (arm7_9->sw_breakpoints_added == 1) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], arm7_9->arm_bkpt);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0x0);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffffu);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
- } else if (arm7_9->sw_breakpoints_added == 2) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], arm7_9->arm_bkpt);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0x0);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0xffffffffu);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
- } else {
- LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
- return ERROR_FAIL;
- }
- LOG_DEBUG("SW BP using hw wp: %d",
- arm7_9->sw_breakpoints_added);
-
- return jtag_execute_queue();
-}
-
-/**
- * Setup the common pieces for an ARM7/9 target after reset or on startup.
- *
- * @param target Pointer to an ARM7/9 target to setup
- * @return Result of clearing the watchpoints on the target
- */
-static int arm7_9_setup(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- return arm7_9_clear_watchpoints(arm7_9);
-}
-
-/**
- * Set either a hardware or software breakpoint on an ARM7/9 target. The
- * breakpoint is set up even if it is already set. Some actions, e.g. reset,
- * might have erased the values in Embedded ICE.
- *
- * @param target Pointer to the target device to set the breakpoints on
- * @param breakpoint Pointer to the breakpoint to be set
- * @return For hardware breakpoints, this is the result of executing the JTAG
- * queue. For software breakpoints, this will be the status of the
- * required memory reads and writes
- */
-static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- int retval = ERROR_OK;
-
- LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32 ", Type: %d",
- breakpoint->unique_id,
- breakpoint->address,
- breakpoint->type);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- /* either an ARM (4 byte) or Thumb (2 byte) breakpoint */
- uint32_t mask = (breakpoint->length == 4) ? 0x3u : 0x1u;
-
- /* reassign a hw breakpoint */
- if (breakpoint->set == 0)
- arm7_9_assign_wp(arm7_9, breakpoint);
-
- if (breakpoint->set == 1) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], breakpoint->address);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffffu);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
- } else if (breakpoint->set == 2) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], breakpoint->address);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffffu);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
- } else {
- LOG_ERROR("BUG: no hardware comparator available");
- return ERROR_OK;
- }
-
- retval = jtag_execute_queue();
- } else if (breakpoint->type == BKPT_SOFT) {
- /* did we already set this breakpoint? */
- if (breakpoint->set)
- return ERROR_OK;
-
- if (breakpoint->length == 4) {
- uint32_t verify = 0xffffffff;
- /* keep the original instruction in target endianness */
- retval = target_read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- /* write the breakpoint instruction in target
- * endianness (arm7_9->arm_bkpt is host endian) */
- retval = target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, breakpoint->address, &verify);
- if (retval != ERROR_OK)
- return retval;
- if (verify != arm7_9->arm_bkpt) {
- LOG_ERROR("Unable to set 32 bit software breakpoint at address %08" PRIx32
- " - check that memory is read/writable", breakpoint->address);
- return ERROR_OK;
- }
- } else {
- uint16_t verify = 0xffff;
- /* keep the original instruction in target endianness */
- retval = target_read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- /* write the breakpoint instruction in target
- * endianness (arm7_9->thumb_bkpt is host endian) */
- retval = target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u16(target, breakpoint->address, &verify);
- if (retval != ERROR_OK)
- return retval;
- if (verify != arm7_9->thumb_bkpt) {
- LOG_ERROR("Unable to set thumb software breakpoint at address %08" PRIx32
- " - check that memory is read/writable", breakpoint->address);
- return ERROR_OK;
- }
- }
-
- retval = arm7_9_set_software_breakpoints(arm7_9);
- if (retval != ERROR_OK)
- return retval;
-
- arm7_9->sw_breakpoint_count++;
-
- breakpoint->set = 1;
- }
-
- return retval;
-}
-
-/**
- * Unsets an existing breakpoint on an ARM7/9 target. If it is a hardware
- * breakpoint, the watchpoint used will be freed and the Embedded ICE registers
- * will be updated. Otherwise, the software breakpoint will be restored to its
- * original instruction if it hasn't already been modified.
- *
- * @param target Pointer to ARM7/9 target to unset the breakpoint from
- * @param breakpoint Pointer to breakpoint to be unset
- * @return For hardware breakpoints, this is the result of executing the JTAG
- * queue. For software breakpoints, this will be the status of the
- * required memory reads and writes
- */
-static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32,
- breakpoint->unique_id,
- breakpoint->address);
-
- if (!breakpoint->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- LOG_DEBUG("BPID: %" PRId32 " Releasing hw wp: %d",
- breakpoint->unique_id,
- breakpoint->set);
- if (breakpoint->set == 1) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
- arm7_9->wp0_used = 0;
- arm7_9->wp_available++;
- } else if (breakpoint->set == 2) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
- arm7_9->wp1_used = 0;
- arm7_9->wp_available++;
- }
- retval = jtag_execute_queue();
- breakpoint->set = 0;
- } else {
- /* restore original instruction (kept in target endianness) */
- if (breakpoint->length == 4) {
- uint32_t current_instr;
- /* check that user program as not modified breakpoint instruction */
- retval = target_read_memory(target,
- breakpoint->address, 4, 1, (uint8_t *)&current_instr);
- if (retval != ERROR_OK)
- return retval;
- current_instr = target_buffer_get_u32(target, (uint8_t *)&current_instr);
- if (current_instr == arm7_9->arm_bkpt) {
- retval = target_write_memory(target,
- breakpoint->address, 4, 1, breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- } else {
- uint16_t current_instr;
- /* check that user program as not modified breakpoint instruction */
- retval = target_read_memory(target,
- breakpoint->address, 2, 1, (uint8_t *)&current_instr);
- if (retval != ERROR_OK)
- return retval;
- current_instr = target_buffer_get_u16(target, (uint8_t *)&current_instr);
- if (current_instr == arm7_9->thumb_bkpt) {
- retval = target_write_memory(target,
- breakpoint->address, 2, 1, breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- if (--arm7_9->sw_breakpoint_count == 0) {
- /* We have removed the last sw breakpoint, clear the hw breakpoint we used
- *to implement it */
- if (arm7_9->sw_breakpoints_added == 1)
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[
- EICE_W0_CONTROL_VALUE], 0);
- else if (arm7_9->sw_breakpoints_added == 2)
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[
- EICE_W1_CONTROL_VALUE], 0);
- }
-
- breakpoint->set = 0;
- }
-
- return retval;
-}
-
-/**
- * Add a breakpoint to an ARM7/9 target. This makes sure that there are no
- * dangling breakpoints and that the desired breakpoint can be added.
- *
- * @param target Pointer to the target ARM7/9 device to add a breakpoint to
- * @param breakpoint Pointer to the breakpoint to be added
- * @return An error status if there is a problem adding the breakpoint or the
- * result of setting the breakpoint
- */
-int arm7_9_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (arm7_9->breakpoint_count == 0) {
- /* make sure we don't have any dangling breakpoints. This is vital upon
- * GDB connect/disconnect
- */
- arm7_9_clear_watchpoints(arm7_9);
- }
-
- if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1)) {
- LOG_INFO("no watchpoint unit available for hardware breakpoint");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if ((breakpoint->length != 2) && (breakpoint->length != 4)) {
- LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->type == BKPT_HARD)
- arm7_9_assign_wp(arm7_9, breakpoint);
-
- arm7_9->breakpoint_count++;
-
- return arm7_9_set_breakpoint(target, breakpoint);
-}
-
-/**
- * Removes a breakpoint from an ARM7/9 target. This will make sure there are no
- * dangling breakpoints and updates available watchpoints if it is a hardware
- * breakpoint.
- *
- * @param target Pointer to the target to have a breakpoint removed
- * @param breakpoint Pointer to the breakpoint to be removed
- * @return Error status if there was a problem unsetting the breakpoint or the
- * watchpoints could not be cleared
- */
-int arm7_9_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- retval = arm7_9_unset_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
-
- if (breakpoint->type == BKPT_HARD)
- arm7_9->wp_available++;
-
- arm7_9->breakpoint_count--;
- if (arm7_9->breakpoint_count == 0) {
- /* make sure we don't have any dangling breakpoints */
- retval = arm7_9_clear_watchpoints(arm7_9);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Sets a watchpoint for an ARM7/9 target in one of the watchpoint units. It is
- * considered a bug to call this function when there are no available watchpoint
- * units.
- *
- * @param target Pointer to an ARM7/9 target to set a watchpoint on
- * @param watchpoint Pointer to the watchpoint to be set
- * @return Error status if watchpoint set fails or the result of executing the
- * JTAG queue
- */
-static int arm7_9_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- int rw_mask = 1;
- uint32_t mask;
-
- mask = watchpoint->length - 1;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (watchpoint->rw == WPT_ACCESS)
- rw_mask = 0;
- else
- rw_mask = 1;
-
- if (!arm7_9->wp0_used) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE],
- watchpoint->address);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK],
- watchpoint->mask);
- if (watchpoint->mask != 0xffffffffu)
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE],
- watchpoint->value);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK],
- 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE],
- EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- watchpoint->set = 1;
- arm7_9->wp0_used = 2;
- } else if (!arm7_9->wp1_used) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE],
- watchpoint->address);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK],
- watchpoint->mask);
- if (watchpoint->mask != 0xffffffffu)
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE],
- watchpoint->value);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK],
- 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE],
- EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- watchpoint->set = 2;
- arm7_9->wp1_used = 2;
- } else {
- LOG_ERROR("BUG: no hardware comparator available");
- return ERROR_OK;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Unset an existing watchpoint and clear the used watchpoint unit.
- *
- * @param target Pointer to the target to have the watchpoint removed
- * @param watchpoint Pointer to the watchpoint to be removed
- * @return Error status while trying to unset the watchpoint or the result of
- * executing the JTAG queue
- */
-static int arm7_9_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!watchpoint->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- if (watchpoint->set == 1) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- arm7_9->wp0_used = 0;
- } else if (watchpoint->set == 2) {
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- arm7_9->wp1_used = 0;
- }
- watchpoint->set = 0;
-
- return ERROR_OK;
-}
-
-/**
- * Add a watchpoint to an ARM7/9 target. If there are no watchpoint units
- * available, an error response is returned.
- *
- * @param target Pointer to the ARM7/9 target to add a watchpoint to
- * @param watchpoint Pointer to the watchpoint to be added
- * @return Error status while trying to add the watchpoint
- */
-int arm7_9_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (arm7_9->wp_available < 1)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- arm7_9->wp_available--;
-
- return ERROR_OK;
-}
-
-/**
- * Remove a watchpoint from an ARM7/9 target. The watchpoint will be unset and
- * the used watchpoint unit will be reopened.
- *
- * @param target Pointer to the target to remove a watchpoint from
- * @param watchpoint Pointer to the watchpoint to be removed
- * @return Result of trying to unset the watchpoint
- */
-int arm7_9_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (watchpoint->set) {
- retval = arm7_9_unset_watchpoint(target, watchpoint);
- if (retval != ERROR_OK)
- return retval;
- }
-
- arm7_9->wp_available++;
-
- return ERROR_OK;
-}
-
-/**
- * Restarts the target by sending a RESTART instruction and moving the JTAG
- * state to IDLE. This includes a timeout waiting for DBGACK and SYSCOMP to be
- * asserted by the processor.
- *
- * @param target Pointer to target to issue commands to
- * @return Error status if there is a timeout or a problem while executing the
- * JTAG queue
- */
-int arm7_9_execute_sys_speed(struct target *target)
-{
- int retval;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
- /* set RESTART instruction */
- if (arm7_9->need_bypass_before_restart) {
- arm7_9->need_bypass_before_restart = 0;
- retval = arm_jtag_set_instr(jtag_info->tap, 0xf, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = arm_jtag_set_instr(jtag_info->tap, 0x4, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- bool timeout;
- while (!(timeout = ((timeval_ms()-then) > 1000))) {
- /* read debug status register */
- embeddedice_read_reg(dbg_stat);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- if ((buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
- && (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_SYSCOMP, 1)))
- break;
- if (debug_level >= 3)
- alive_sleep(100);
- else
- keep_alive();
- }
- if (timeout) {
- LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %" PRIx32 "",
- buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
- return ERROR_TARGET_TIMEOUT;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Restarts the target by sending a RESTART instruction and moving the JTAG
- * state to IDLE. This validates that DBGACK and SYSCOMP are set without
- * waiting until they are.
- *
- * @param target Pointer to the target to issue commands to
- * @return Always ERROR_OK
- */
-static int arm7_9_execute_fast_sys_speed(struct target *target)
-{
- static int set;
- static uint8_t check_value[4], check_mask[4];
-
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
- int retval;
-
- /* set RESTART instruction */
- if (arm7_9->need_bypass_before_restart) {
- arm7_9->need_bypass_before_restart = 0;
- retval = arm_jtag_set_instr(jtag_info->tap, 0xf, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = arm_jtag_set_instr(jtag_info->tap, 0x4, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- if (!set) {
- /* check for DBGACK and SYSCOMP set (others don't care) */
-
- /* NB! These are constants that must be available until after next jtag_execute() and
- * we evaluate the values upon first execution in lieu of setting up these constants
- * during early setup.
- * */
- buf_set_u32(check_value, 0, 32, 0x9);
- buf_set_u32(check_mask, 0, 32, 0x9);
- set = 1;
- }
-
- /* read debug status register */
- embeddedice_read_reg_w_check(dbg_stat, check_value, check_mask);
-
- return ERROR_OK;
-}
-
-/**
- * Get some data from the ARM7/9 target.
- *
- * @param target Pointer to the ARM7/9 target to read data from
- * @param size The number of 32bit words to be read
- * @param buffer Pointer to the buffer that will hold the data
- * @return The result of receiving data from the Embedded ICE unit
- */
-int arm7_9_target_request_data(struct target *target, uint32_t size, uint8_t *buffer)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- uint32_t *data;
- int retval = ERROR_OK;
- uint32_t i;
-
- data = malloc(size * (sizeof(uint32_t)));
-
- retval = embeddedice_receive(jtag_info, data, size);
-
- /* return the 32-bit ints in the 8-bit array */
- for (i = 0; i < size; i++)
- h_u32_to_le(buffer + (i * 4), data[i]);
-
- free(data);
-
- return retval;
-}
-
-/**
- * Handles requests to an ARM7/9 target. If debug messaging is enabled, the
- * target is running and the DCC control register has the W bit high, this will
- * execute the request on the target.
- *
- * @param priv Void pointer expected to be a struct target pointer
- * @return ERROR_OK unless there are issues with the JTAG queue or when reading
- * from the Embedded ICE unit
- */
-static int arm7_9_handle_target_request(void *priv)
-{
- int retval = ERROR_OK;
- struct target *target = priv;
- if (!target_was_examined(target))
- return ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct reg *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
-
- if (!target->dbg_msg_enabled)
- return ERROR_OK;
-
- if (target->state == TARGET_RUNNING) {
- /* read DCC control register */
- embeddedice_read_reg(dcc_control);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* check W bit */
- if (buf_get_u32(dcc_control->value, 1, 1) == 1) {
- uint32_t request;
-
- retval = embeddedice_receive(jtag_info, &request, 1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_request(target, request);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- return ERROR_OK;
-}
-
-/**
- * Polls an ARM7/9 target for its current status. If DBGACK is set, the target
- * is manipulated to the right halted state based on its current state. This is
- * what happens:
- *
- * <table>
- * <tr><th > State</th><th > Action</th></tr>
- * <tr><td > TARGET_RUNNING | TARGET_RESET</td>
- * <td > Enters debug mode. If TARGET_RESET, pc may be checked</td></tr>
- * <tr><td > TARGET_UNKNOWN</td><td > Warning is logged</td></tr>
- * <tr><td > TARGET_DEBUG_RUNNING</td><td > Enters debug mode</td></tr>
- * <tr><td > TARGET_HALTED</td><td > Nothing</td></tr>
- * </table>
- *
- * If the target does not end up in the halted state, a warning is produced. If
- * DBGACK is cleared, then the target is expected to either be running or
- * running in debug.
- *
- * @param target Pointer to the ARM7/9 target to poll
- * @return ERROR_OK or an error status if a command fails
- */
-int arm7_9_poll(struct target *target)
-{
- int retval;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
- /* read debug status register */
- embeddedice_read_reg(dbg_stat);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1)) {
- /* LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, *32));*/
- if (target->state == TARGET_UNKNOWN) {
- /* Starting OpenOCD with target in debug-halt */
- target->state = TARGET_RUNNING;
- LOG_DEBUG("DBGACK already set during server startup.");
- }
- if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) {
- target->state = TARGET_HALTED;
-
- retval = arm7_9_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (arm_semihosting(target, &retval) != 0)
- return retval;
-
- retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- if (retval != ERROR_OK)
- return retval;
- }
- if (target->state == TARGET_DEBUG_RUNNING) {
- target->state = TARGET_HALTED;
- retval = arm7_9_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
- if (retval != ERROR_OK)
- return retval;
- }
- if (target->state != TARGET_HALTED)
- LOG_WARNING(
- "DBGACK set, but the target did not end up in the halted state %d",
- target->state);
- } else {
- if (target->state != TARGET_DEBUG_RUNNING)
- target->state = TARGET_RUNNING;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Asserts the reset (SRST) on an ARM7/9 target. Some -S targets (ARM966E-S in
- * the STR912 isn't affected, ARM926EJ-S in the LPC3180 and AT91SAM9260 is
- * affected) completely stop the JTAG clock while the core is held in reset
- * (SRST). It isn't possible to program the halt condition once reset is
- * asserted, hence a hook that allows the target to set up its reset-halt
- * condition is setup prior to asserting reset.
- *
- * @param target Pointer to an ARM7/9 target to assert reset on
- * @return ERROR_FAIL if the JTAG device does not have SRST, otherwise ERROR_OK
- */
-int arm7_9_assert_reset(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- bool use_event = false;
-
- /* TODO: apply hw reset signal in not examined state */
- if (!(target_was_examined(target))) {
- LOG_WARNING("Reset is not asserted because the target is not examined.");
- LOG_WARNING("Use a reset button or power cycle the target.");
- return ERROR_TARGET_NOT_EXAMINED;
- }
-
- LOG_DEBUG("target->state: %s", target_state_name(target));
-
- if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
- use_event = true;
- else if (!(jtag_reset_config & RESET_HAS_SRST)) {
- LOG_ERROR("%s: how to reset?", target_name(target));
- return ERROR_FAIL;
- }
-
- /* At this point trst has been asserted/deasserted once. We would
- * like to program EmbeddedICE while SRST is asserted, instead of
- * depending on SRST to leave that module alone. However, many CPUs
- * gate the JTAG clock while SRST is asserted; or JTAG may need
- * clock stability guarantees (adaptive clocking might help).
- *
- * So we assume JTAG access during SRST is off the menu unless it's
- * been specifically enabled.
- */
- bool srst_asserted = false;
-
- if (!use_event && !(jtag_reset_config & RESET_SRST_PULLS_TRST)
- && (jtag_reset_config & RESET_SRST_NO_GATING)) {
- jtag_add_reset(0, 1);
- srst_asserted = true;
- }
-
- if (target->reset_halt) {
- /*
- * For targets that don't support communication while SRST is
- * asserted, we need to set up the reset vector catch first.
- *
- * When we use TRST+SRST and that's equivalent to a power-up
- * reset, these settings may well be reset anyway; so setting
- * them here won't matter.
- */
- if (arm7_9->has_vector_catch) {
- /* program vector catch register to catch reset */
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1);
-
- /* extra runtest added as issues were found with
- * certain ARM9 cores (maybe more) - AT91SAM9260
- * and STR9
- */
- jtag_add_runtest(1, TAP_IDLE);
- } else {
- /* program watchpoint unit to match on reset vector
- * address
- */
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
- }
- }
-
- if (use_event)
- target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
- else {
- /* If we use SRST ... we'd like to issue just SRST, but the
- * board or chip may be set up so we have to assert TRST as
- * well. On some chips that combination is equivalent to a
- * power-up reset, and generally clobbers EICE state.
- */
- if (jtag_reset_config & RESET_SRST_PULLS_TRST)
- jtag_add_reset(1, 1);
- else if (!srst_asserted)
- jtag_add_reset(0, 1);
- jtag_add_sleep(50000);
- }
-
- target->state = TARGET_RESET;
- register_cache_invalidate(arm7_9->arm.core_cache);
-
- /* REVISIT why isn't standard debug entry logic sufficient?? */
- if (target->reset_halt && (!(jtag_reset_config & RESET_SRST_PULLS_TRST) || use_event)) {
- /* debug entry was prepared above */
- target->debug_reason = DBG_REASON_DBGRQ;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Deassert the reset (SRST) signal on an ARM7/9 target. If SRST pulls TRST
- * and the target is being reset into a halt, a warning will be triggered
- * because it is not possible to reset into a halted mode in this case. The
- * target is halted using the target's functions.
- *
- * @param target Pointer to the target to have the reset deasserted
- * @return ERROR_OK or an error from polling or halting the target
- */
-int arm7_9_deassert_reset(struct target *target)
-{
- int retval = ERROR_OK;
- LOG_DEBUG("target->state: %s", target_state_name(target));
-
- /* deassert reset lines */
- jtag_add_reset(0, 0);
-
- /* In case polling is disabled, we need to examine the
- * target and poll here for this target to work correctly.
- *
- * Otherwise, e.g. halt will fail afterwards with bogus
- * error messages as halt will believe that reset is
- * still in effect.
- */
- retval = target_examine_one(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_poll(target);
- if (retval != ERROR_OK)
- return retval;
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
- if (target->reset_halt && (jtag_reset_config & RESET_SRST_PULLS_TRST) != 0) {
- LOG_WARNING(
- "srst pulls trst - can not reset into halted mode. Issuing halt after reset.");
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
- return retval;
-}
-
-/**
- * Clears the halt condition for an ARM7/9 target. If it isn't coming out of
- * reset and if DBGRQ is used, it is progammed to be deasserted. If the reset
- * vector catch was used, it is restored. Otherwise, the control value is
- * restored and the watchpoint unit is restored if it was in use.
- *
- * @param target Pointer to the ARM7/9 target to have halt cleared
- * @return Always ERROR_OK
- */
-static int arm7_9_clear_halt(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-
- /* we used DBGRQ only if we didn't come out of reset */
- if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq) {
- /* program EmbeddedICE Debug Control Register to deassert DBGRQ
- */
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
- embeddedice_store_reg(dbg_ctrl);
- } else {
- if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch) {
- /* if we came out of reset, and vector catch is supported, we used
- * vector catch to enter debug state
- * restore the register in that case
- */
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH]);
- } else {
- /* restore registers if watchpoint unit 0 was in use
- */
- if (arm7_9->wp0_used) {
- if (arm7_9->debug_entry_from_reset)
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[
- EICE_W0_ADDR_VALUE]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[
- EICE_W0_ADDR_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[
- EICE_W0_DATA_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[
- EICE_W0_CONTROL_MASK]);
- }
- /* control value always has to be restored, as it was either disabled,
- * or enabled with possibly different bits
- */
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
- }
- }
-
- return ERROR_OK;
-}
-
-/**
- * Issue a software reset and halt to an ARM7/9 target. The target is halted
- * and then there is a wait until the processor shows the halt. This wait can
- * timeout and results in an error being returned. The software reset involves
- * clearing the halt, updating the debug control register, changing to ARM mode,
- * reset of the program counter, and reset of all of the registers.
- *
- * @param target Pointer to the ARM7/9 target to be reset and halted by software
- * @return Error status if any of the commands fail, otherwise ERROR_OK
- */
-int arm7_9_soft_reset_halt(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
- int i;
- int retval;
-
- /* FIX!!! replace some of this code with tcl commands
- *
- * halt # the halt command is synchronous
- * armv4_5 core_state arm
- *
- */
-
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- long long then = timeval_ms();
- int timeout;
- while (!(timeout = ((timeval_ms()-then) > 1000))) {
- if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) != 0)
- break;
- embeddedice_read_reg(dbg_stat);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- if (debug_level >= 3)
- alive_sleep(100);
- else
- keep_alive();
- }
- if (timeout) {
- LOG_ERROR("Failed to halt CPU after 1 sec");
- return ERROR_TARGET_TIMEOUT;
- }
- target->state = TARGET_HALTED;
-
- /* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS
- * ensure that DBGRQ is cleared
- */
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1);
- embeddedice_store_reg(dbg_ctrl);
-
- retval = arm7_9_clear_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* if the target is in Thumb state, change to ARM state */
- if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1)) {
- uint32_t r0_thumb, pc_thumb;
- LOG_DEBUG("target entered debug from Thumb state, changing to ARM");
- /* Entered debug from Thumb mode */
- arm->core_state = ARM_STATE_THUMB;
- arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
- }
-
- /* REVISIT likewise for bit 5 -- switch Jazelle-to-ARM */
-
- /* all register content is now invalid */
- register_cache_invalidate(arm->core_cache);
-
- /* SVC, ARM state, IRQ and FIQ disabled */
- uint32_t cpsr;
-
- cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
- cpsr &= ~0xff;
- cpsr |= 0xd3;
- arm_set_cpsr(arm, cpsr);
- arm->cpsr->dirty = 1;
-
- /* start fetching from 0x0 */
- buf_set_u32(arm->pc->value, 0, 32, 0x0);
- arm->pc->dirty = 1;
- arm->pc->valid = 1;
-
- /* reset registers */
- for (i = 0; i <= 14; i++) {
- struct reg *r = arm_reg_current(arm, i);
-
- buf_set_u32(r->value, 0, 32, 0xffffffff);
- r->dirty = 1;
- r->valid = 1;
- }
-
- retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-/**
- * Halt an ARM7/9 target. This is accomplished by either asserting the DBGRQ
- * line or by programming a watchpoint to trigger on any address. It is
- * considered a bug to call this function while the target is in the
- * TARGET_RESET state.
- *
- * @param target Pointer to the ARM7/9 target to be halted
- * @return Always ERROR_OK
- */
-int arm7_9_halt(struct target *target)
-{
- if (target->state == TARGET_RESET) {
- LOG_ERROR(
- "BUG: arm7/9 does not support halt during reset. This is handled in arm7_9_assert_reset()");
- return ERROR_OK;
- }
-
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- if (target->state == TARGET_UNKNOWN)
- LOG_WARNING("target was in unknown state when halt was requested");
-
- if (arm7_9->use_dbgrq) {
- /* program EmbeddedICE Debug Control Register to assert DBGRQ
- */
- if (arm7_9->set_special_dbgrq)
- arm7_9->set_special_dbgrq(target);
- else {
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 1);
- embeddedice_store_reg(dbg_ctrl);
- }
- } else {
- /* program watchpoint unit to match on any address
- */
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE],
- EICE_W_CTRL_ENABLE);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK],
- ~EICE_W_CTRL_nOPC & 0xff);
- }
-
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-/**
- * Handle an ARM7/9 target's entry into debug mode. The halt is cleared on the
- * ARM. The JTAG queue is then executed and the reason for debug entry is
- * examined. Once done, the target is verified to be halted and the processor
- * is forced into ARM mode. The core registers are saved for the current core
- * mode and the program counter (register 15) is updated as needed. The core
- * registers and CPSR and SPSR are saved for restoration later.
- *
- * @param target Pointer to target that is entering debug mode
- * @return Error code if anything fails, otherwise ERROR_OK
- */
-static int arm7_9_debug_entry(struct target *target)
-{
- int i;
- uint32_t context[16];
- uint32_t *context_p[16];
- uint32_t r0_thumb, pc_thumb;
- uint32_t cpsr, cpsr_mask = 0;
- int retval;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-
-#ifdef _DEBUG_ARM7_9_
- LOG_DEBUG("-");
-#endif
-
- /* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS
- * ensure that DBGRQ is cleared
- */
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1);
- embeddedice_store_reg(dbg_ctrl);
-
- retval = arm7_9_clear_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm7_9->examine_debug_reason(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* if the target is in Thumb state, change to ARM state */
- if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1)) {
- LOG_DEBUG("target entered debug from Thumb state");
- /* Entered debug from Thumb mode */
- arm->core_state = ARM_STATE_THUMB;
- cpsr_mask = 1 << 5;
- arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
- LOG_DEBUG("r0_thumb: 0x%8.8" PRIx32
- ", pc_thumb: 0x%8.8" PRIx32, r0_thumb, pc_thumb);
- } else if (buf_get_u32(dbg_stat->value, 5, 1)) {
- /* \todo Get some vaguely correct handling of Jazelle, if
- * anyone ever uses it and full info becomes available.
- * See ARM9EJS TRM B.7.1 for how to switch J->ARM; and
- * B.7.3 for the reverse. That'd be the bare minimum...
- */
- LOG_DEBUG("target entered debug from Jazelle state");
- arm->core_state = ARM_STATE_JAZELLE;
- cpsr_mask = 1 << 24;
- LOG_ERROR("Jazelle debug entry -- BROKEN!");
- } else {
- LOG_DEBUG("target entered debug from ARM state");
- /* Entered debug from ARM mode */
- arm->core_state = ARM_STATE_ARM;
- }
-
- for (i = 0; i < 16; i++)
- context_p[i] = &context[i];
- /* save core registers (r0 - r15 of current core mode) */
- arm7_9->read_core_regs(target, 0xffff, context_p);
-
- arm7_9->read_xpsr(target, &cpsr, 0);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* Sync our CPSR copy with J or T bits EICE reported, but
- * which we then erased by putting the core into ARM mode.
- */
- arm_set_cpsr(arm, cpsr | cpsr_mask);
-
- if (!is_arm_mode(arm->core_mode)) {
- target->state = TARGET_UNKNOWN;
- LOG_ERROR("cpsr contains invalid mode value - communication failure");
- return ERROR_TARGET_FAILURE;
- }
-
- LOG_DEBUG("target entered debug state in %s mode",
- arm_mode_name(arm->core_mode));
-
- if (arm->core_state == ARM_STATE_THUMB) {
- LOG_DEBUG("thumb state, applying fixups");
- context[0] = r0_thumb;
- context[15] = pc_thumb;
- } else if (arm->core_state == ARM_STATE_ARM) {
- /* adjust value stored by STM */
- context[15] -= 3 * 4;
- }
-
- if ((target->debug_reason != DBG_REASON_DBGRQ) || (!arm7_9->use_dbgrq))
- context[15] -= 3 * ((arm->core_state == ARM_STATE_ARM) ? 4 : 2);
- else
- context[15] -= arm7_9->dbgreq_adjust_pc *
- ((arm->core_state == ARM_STATE_ARM) ? 4 : 2);
-
- for (i = 0; i <= 15; i++) {
- struct reg *r = arm_reg_current(arm, i);
-
- LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, context[i]);
-
- buf_set_u32(r->value, 0, 32, context[i]);
- /* r0 and r15 (pc) have to be restored later */
- r->dirty = (i == 0) || (i == 15);
- r->valid = 1;
- }
-
- LOG_DEBUG("entered debug state at PC 0x%" PRIx32 "", context[15]);
-
- /* exceptions other than USR & SYS have a saved program status register */
- if (arm->spsr) {
- uint32_t spsr;
- arm7_9->read_xpsr(target, &spsr, 1);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- buf_set_u32(arm->spsr->value, 0, 32, spsr);
- arm->spsr->dirty = 0;
- arm->spsr->valid = 1;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (arm7_9->post_debug_entry) {
- retval = arm7_9->post_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-/**
- * Validate the full context for an ARM7/9 target in all processor modes. If
- * there are any invalid registers for the target, they will all be read. This
- * includes the PSR.
- *
- * @param target Pointer to the ARM7/9 target to capture the full context from
- * @return Error if the target is not halted, has an invalid core mode, or if
- * the JTAG queue fails to execute
- */
-static int arm7_9_full_context(struct target *target)
-{
- int i;
- int retval;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- /* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND)
- * SYS shares registers with User, so we don't touch SYS
- */
- for (i = 0; i < 6; i++) {
- uint32_t mask = 0;
- uint32_t *reg_p[16];
- int j;
- int valid = 1;
-
- /* check if there are invalid registers in the current mode
- */
- for (j = 0; j <= 16; j++) {
- if (ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j).valid == 0)
- valid = 0;
- }
-
- if (!valid) {
- uint32_t tmp_cpsr;
-
- /* change processor mode (and mask T bit) */
- tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8)
- & 0xe0;
- tmp_cpsr |= armv4_5_number_to_mode(i);
- tmp_cpsr &= ~0x20;
- arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
-
- for (j = 0; j < 15; j++) {
- if (ARMV4_5_CORE_REG_MODE(arm->core_cache,
- armv4_5_number_to_mode(i), j).valid == 0) {
- reg_p[j] = (uint32_t *)ARMV4_5_CORE_REG_MODE(
- arm->core_cache,
- armv4_5_number_to_mode(i),
- j).value;
- mask |= 1 << j;
- ARMV4_5_CORE_REG_MODE(arm->core_cache,
- armv4_5_number_to_mode(i),
- j).valid = 1;
- ARMV4_5_CORE_REG_MODE(arm->core_cache,
- armv4_5_number_to_mode(i),
- j).dirty = 0;
- }
- }
-
- /* if only the PSR is invalid, mask is all zeroes */
- if (mask)
- arm7_9->read_core_regs(target, mask, reg_p);
-
- /* check if the PSR has to be read */
- if (ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
- 16).valid == 0) {
- arm7_9->read_xpsr(target,
- (uint32_t *)ARMV4_5_CORE_REG_MODE(arm->core_cache,
- armv4_5_number_to_mode(i), 16).value, 1);
- ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
- 16).valid = 1;
- ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i),
- 16).dirty = 0;
- }
- }
- }
-
- /* restore processor mode (mask T bit) */
- arm7_9->write_xpsr_im8(target,
- buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- return ERROR_OK;
-}
-
-/**
- * Restore the processor context on an ARM7/9 target. The full processor
- * context is analyzed to see if any of the registers are dirty on this end, but
- * have a valid new value. If this is the case, the processor is changed to the
- * appropriate mode and the new register values are written out to the
- * processor. If there happens to be a dirty register with an invalid value, an
- * error will be logged.
- *
- * @param target Pointer to the ARM7/9 target to have its context restored
- * @return Error status if the target is not halted or the core mode in the
- * armv4_5 struct is invalid.
- */
-static int arm7_9_restore_context(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct reg *reg;
- enum arm_mode current_mode = arm->core_mode;
- int i, j;
- int dirty;
- int mode_change;
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (arm7_9->pre_restore_context)
- arm7_9->pre_restore_context(target);
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- /* iterate through processor modes (User, FIQ, IRQ, SVC, ABT, UND)
- * SYS shares registers with User, so we don't touch SYS
- */
- for (i = 0; i < 6; i++) {
- LOG_DEBUG("examining %s mode",
- arm_mode_name(arm->core_mode));
- dirty = 0;
- mode_change = 0;
- /* check if there are dirty registers in the current mode
- */
- for (j = 0; j <= 16; j++) {
- reg = &ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(i), j);
- if (reg->dirty == 1) {
- if (reg->valid == 1) {
- dirty = 1;
- LOG_DEBUG("examining dirty reg: %s", reg->name);
- struct arm_reg *reg_arch_info;
- reg_arch_info = reg->arch_info;
- if ((reg_arch_info->mode != ARM_MODE_ANY)
- && (reg_arch_info->mode != current_mode)
- && !((reg_arch_info->mode == ARM_MODE_USR)
- && (arm->core_mode == ARM_MODE_SYS))
- && !((reg_arch_info->mode == ARM_MODE_SYS)
- && (arm->core_mode == ARM_MODE_USR))) {
- mode_change = 1;
- LOG_DEBUG("require mode change");
- }
- } else
- LOG_ERROR("BUG: dirty register '%s', but no valid data",
- reg->name);
- }
- }
-
- if (dirty) {
- uint32_t mask = 0x0;
- int num_regs = 0;
- uint32_t regs[16];
-
- if (mode_change) {
- uint32_t tmp_cpsr;
-
- /* change processor mode (mask T bit) */
- tmp_cpsr = buf_get_u32(arm->cpsr->value,
- 0, 8) & 0xe0;
- tmp_cpsr |= armv4_5_number_to_mode(i);
- tmp_cpsr &= ~0x20;
- arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
- current_mode = armv4_5_number_to_mode(i);
- }
-
- for (j = 0; j <= 14; j++) {
- reg = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
- armv4_5_number_to_mode(i),
- j);
-
- if (reg->dirty == 1) {
- regs[j] = buf_get_u32(reg->value, 0, 32);
- mask |= 1 << j;
- num_regs++;
- reg->dirty = 0;
- reg->valid = 1;
- LOG_DEBUG("writing register %i mode %s "
- "with value 0x%8.8" PRIx32, j,
- arm_mode_name(arm->core_mode),
- regs[j]);
- }
- }
-
- if (mask)
- arm7_9->write_core_regs(target, mask, regs);
-
- reg =
- &ARMV4_5_CORE_REG_MODE(arm->core_cache, armv4_5_number_to_mode(
- i), 16);
- struct arm_reg *reg_arch_info;
- reg_arch_info = reg->arch_info;
- if ((reg->dirty) && (reg_arch_info->mode != ARM_MODE_ANY)) {
- LOG_DEBUG("writing SPSR of mode %i with value 0x%8.8" PRIx32 "",
- i,
- buf_get_u32(reg->value, 0, 32));
- arm7_9->write_xpsr(target, buf_get_u32(reg->value, 0, 32), 1);
- }
- }
- }
-
- if (!arm->cpsr->dirty && (arm->core_mode != current_mode)) {
- /* restore processor mode (mask T bit) */
- uint32_t tmp_cpsr;
-
- tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xE0;
- tmp_cpsr |= armv4_5_number_to_mode(i);
- tmp_cpsr &= ~0x20;
- LOG_DEBUG("writing lower 8 bit of cpsr with value 0x%2.2x", (unsigned)(tmp_cpsr));
- arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
-
- } else if (arm->cpsr->dirty) {
- /* CPSR has been changed, full restore necessary (mask T bit) */
- LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32,
- buf_get_u32(arm->cpsr->value, 0, 32));
- arm7_9->write_xpsr(target,
- buf_get_u32(arm->cpsr->value, 0, 32)
- & ~0x20, 0);
- arm->cpsr->dirty = 0;
- arm->cpsr->valid = 1;
- }
-
- /* restore PC */
- LOG_DEBUG("writing PC with value 0x%8.8" PRIx32,
- buf_get_u32(arm->pc->value, 0, 32));
- arm7_9->write_pc(target, buf_get_u32(arm->pc->value, 0, 32));
- arm->pc->dirty = 0;
-
- return ERROR_OK;
-}
-
-/**
- * Restart the core of an ARM7/9 target. A RESTART command is sent to the
- * instruction register and the JTAG state is set to TAP_IDLE causing a core
- * restart.
- *
- * @param target Pointer to the ARM7/9 target to be restarted
- * @return Result of executing the JTAG queue
- */
-static int arm7_9_restart_core(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- int retval;
-
- /* set RESTART instruction */
- if (arm7_9->need_bypass_before_restart) {
- arm7_9->need_bypass_before_restart = 0;
-
- retval = arm_jtag_set_instr(jtag_info->tap, 0xf, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = arm_jtag_set_instr(jtag_info->tap, 0x4, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- jtag_add_runtest(1, TAP_IDLE);
- return jtag_execute_queue();
-}
-
-/**
- * Enable the watchpoints on an ARM7/9 target. The target's watchpoints are
- * iterated through and are set on the target if they aren't already set.
- *
- * @param target Pointer to the ARM7/9 target to enable watchpoints on
- */
-static void arm7_9_enable_watchpoints(struct target *target)
-{
- struct watchpoint *watchpoint = target->watchpoints;
-
- while (watchpoint) {
- if (watchpoint->set == 0)
- arm7_9_set_watchpoint(target, watchpoint);
- watchpoint = watchpoint->next;
- }
-}
-
-/**
- * Enable the breakpoints on an ARM7/9 target. The target's breakpoints are
- * iterated through and are set on the target.
- *
- * @param target Pointer to the ARM7/9 target to enable breakpoints on
- */
-static void arm7_9_enable_breakpoints(struct target *target)
-{
- struct breakpoint *breakpoint = target->breakpoints;
-
- /* set any pending breakpoints */
- while (breakpoint) {
- arm7_9_set_breakpoint(target, breakpoint);
- breakpoint = breakpoint->next;
- }
-}
-
-int arm7_9_resume(struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints,
- int debug_execution)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
- int err, retval = ERROR_OK;
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!debug_execution)
- target_free_all_working_areas(target);
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current)
- buf_set_u32(arm->pc->value, 0, 32, address);
-
- uint32_t current_pc;
- current_pc = buf_get_u32(arm->pc->value, 0, 32);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- struct breakpoint *breakpoint;
- breakpoint = breakpoint_find(target,
- buf_get_u32(arm->pc->value, 0, 32));
- if (breakpoint != NULL) {
- LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (id: %" PRId32,
- breakpoint->address,
- breakpoint->unique_id);
- retval = arm7_9_unset_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
-
- /* calculate PC of next instruction */
- uint32_t next_pc;
- retval = arm_simulate_step(target, &next_pc);
- if (retval != ERROR_OK) {
- uint32_t current_opcode;
- target_read_u32(target, current_pc, &current_opcode);
- LOG_ERROR(
- "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "",
- current_opcode);
- return retval;
- }
-
- LOG_DEBUG("enable single-step");
- arm7_9->enable_single_step(target, next_pc);
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- retval = arm7_9_restore_context(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (arm->core_state == ARM_STATE_ARM)
- arm7_9->branch_resume(target);
- else if (arm->core_state == ARM_STATE_THUMB)
- arm7_9->branch_resume_thumb(target);
- else {
- LOG_ERROR("unhandled core state");
- return ERROR_FAIL;
- }
-
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
- embeddedice_write_reg(dbg_ctrl,
- buf_get_u32(dbg_ctrl->value, 0, dbg_ctrl->size));
- err = arm7_9_execute_sys_speed(target);
-
- LOG_DEBUG("disable single-step");
- arm7_9->disable_single_step(target);
-
- if (err != ERROR_OK) {
- retval = arm7_9_set_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
- target->state = TARGET_UNKNOWN;
- return err;
- }
-
- retval = arm7_9_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("new PC after step: 0x%8.8" PRIx32,
- buf_get_u32(arm->pc->value, 0, 32));
-
- LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
- retval = arm7_9_set_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- /* enable any pending breakpoints and watchpoints */
- arm7_9_enable_breakpoints(target);
- arm7_9_enable_watchpoints(target);
-
- retval = arm7_9_restore_context(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (arm->core_state == ARM_STATE_ARM)
- arm7_9->branch_resume(target);
- else if (arm->core_state == ARM_STATE_THUMB)
- arm7_9->branch_resume_thumb(target);
- else {
- LOG_ERROR("unhandled core state");
- return ERROR_FAIL;
- }
-
- /* deassert DBGACK and INTDIS */
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
- /* INTDIS only when we really resume, not during debug execution */
- if (!debug_execution)
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 0);
- embeddedice_write_reg(dbg_ctrl, buf_get_u32(dbg_ctrl->value, 0, dbg_ctrl->size));
-
- retval = arm7_9_restart_core(target);
- if (retval != ERROR_OK)
- return retval;
-
- target->debug_reason = DBG_REASON_NOTHALTED;
-
- if (!debug_execution) {
- /* registers are now invalid */
- register_cache_invalidate(arm->core_cache);
- target->state = TARGET_RUNNING;
- retval = target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- if (retval != ERROR_OK)
- return retval;
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- if (retval != ERROR_OK)
- return retval;
- }
-
- LOG_DEBUG("target resumed");
-
- return ERROR_OK;
-}
-
-void arm7_9_enable_eice_step(struct target *target, uint32_t next_pc)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- uint32_t current_pc;
- current_pc = buf_get_u32(arm->pc->value, 0, 32);
-
- if (next_pc != current_pc) {
- /* setup an inverse breakpoint on the current PC
- * - comparator 1 matches the current address
- * - rangeout from comparator 1 is connected to comparator 0 rangein
- * - comparator 0 matches any address, as long as rangein is low */
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE],
- EICE_W_CTRL_ENABLE);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK],
- ~(EICE_W_CTRL_RANGE | EICE_W_CTRL_nOPC) & 0xff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE],
- current_pc);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK],
- ~EICE_W_CTRL_nOPC & 0xff);
- } else {
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], next_pc);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE],
- EICE_W_CTRL_ENABLE);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK],
- ~EICE_W_CTRL_nOPC & 0xff);
- }
-}
-
-void arm7_9_disable_eice_step(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE]);
-}
-
-int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct breakpoint *breakpoint = NULL;
- int err, retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current)
- buf_set_u32(arm->pc->value, 0, 32, address);
-
- uint32_t current_pc = buf_get_u32(arm->pc->value, 0, 32);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints)
- breakpoint = breakpoint_find(target, current_pc);
- if (breakpoint != NULL) {
- retval = arm7_9_unset_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
- }
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- /* calculate PC of next instruction */
- uint32_t next_pc;
- retval = arm_simulate_step(target, &next_pc);
- if (retval != ERROR_OK) {
- uint32_t current_opcode;
- target_read_u32(target, current_pc, &current_opcode);
- LOG_ERROR(
- "Couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "",
- current_opcode);
- return retval;
- }
-
- retval = arm7_9_restore_context(target);
- if (retval != ERROR_OK)
- return retval;
-
- arm7_9->enable_single_step(target, next_pc);
-
- if (arm->core_state == ARM_STATE_ARM)
- arm7_9->branch_resume(target);
- else if (arm->core_state == ARM_STATE_THUMB)
- arm7_9->branch_resume_thumb(target);
- else {
- LOG_ERROR("unhandled core state");
- return ERROR_FAIL;
- }
-
- retval = target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- if (retval != ERROR_OK)
- return retval;
-
- err = arm7_9_execute_sys_speed(target);
- arm7_9->disable_single_step(target);
-
- /* registers are now invalid */
- register_cache_invalidate(arm->core_cache);
-
- if (err != ERROR_OK)
- target->state = TARGET_UNKNOWN;
- else {
- retval = arm7_9_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("target stepped");
- }
-
- if (breakpoint) {
- retval = arm7_9_set_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return err;
-}
-
-static int arm7_9_read_core_reg(struct target *target, struct reg *r,
- int num, enum arm_mode mode)
-{
- uint32_t *reg_p[16];
- int retval;
- struct arm_reg *areg = r->arch_info;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
-
- if (!is_arm_mode(arm->core_mode))
- return ERROR_FAIL;
- if ((num < 0) || (num > 16))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode)
- && (areg->mode != ARM_MODE_ANY)) {
- uint32_t tmp_cpsr;
-
- /* change processor mode (mask T bit) */
- tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xE0;
- tmp_cpsr |= mode;
- tmp_cpsr &= ~0x20;
- arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
- }
-
- uint32_t value = 0;
- if ((num >= 0) && (num <= 15)) {
- /* read a normal core register */
- reg_p[num] = &value;
-
- arm7_9->read_core_regs(target, 1 << num, reg_p);
- } else {
- /* read a program status register
- * if the register mode is MODE_ANY, we read the cpsr, otherwise a spsr
- */
- arm7_9->read_xpsr(target, &value, areg->mode != ARM_MODE_ANY);
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- r->valid = 1;
- r->dirty = 0;
- buf_set_u32(r->value, 0, 32, value);
-
- if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode)
- && (areg->mode != ARM_MODE_ANY)) {
- /* restore processor mode (mask T bit) */
- arm7_9->write_xpsr_im8(target,
- buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0);
- }
-
- return ERROR_OK;
-}
-
-static int arm7_9_write_core_reg(struct target *target, struct reg *r,
- int num, enum arm_mode mode, uint8_t *value)
-{
- uint32_t reg[16];
- struct arm_reg *areg = r->arch_info;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
-
- if (!is_arm_mode(arm->core_mode))
- return ERROR_FAIL;
- if ((num < 0) || (num > 16))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode)
- && (areg->mode != ARM_MODE_ANY)) {
- uint32_t tmp_cpsr;
-
- /* change processor mode (mask T bit) */
- tmp_cpsr = buf_get_u32(arm->cpsr->value, 0, 8) & 0xE0;
- tmp_cpsr |= mode;
- tmp_cpsr &= ~0x20;
- arm7_9->write_xpsr_im8(target, tmp_cpsr & 0xff, 0, 0);
- }
-
- if ((num >= 0) && (num <= 15)) {
- /* write a normal core register */
- reg[num] = buf_get_u32(value, 0, 32);
-
- arm7_9->write_core_regs(target, 1 << num, reg);
- } else {
- /* write a program status register
- * if the register mode is MODE_ANY, we write the cpsr, otherwise a spsr
- */
- int spsr = (areg->mode != ARM_MODE_ANY);
-
- uint32_t t = buf_get_u32(value, 0, 32);
- /* if we're writing the CPSR, mask the T bit */
- if (!spsr)
- t &= ~0x20;
-
- arm7_9->write_xpsr(target, t, spsr);
- }
-
- r->valid = 1;
- r->dirty = 0;
-
- if ((mode != ARM_MODE_ANY) && (mode != arm->core_mode)
- && (areg->mode != ARM_MODE_ANY)) {
- /* restore processor mode (mask T bit) */
- arm7_9->write_xpsr_im8(target,
- buf_get_u32(arm->cpsr->value, 0, 8) & ~0x20, 0, 0);
- }
-
- return jtag_execute_queue();
-}
-
-int arm7_9_read_memory(struct target *target,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- uint8_t *buffer)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- uint32_t reg[16];
- uint32_t num_accesses = 0;
- int thisrun_accesses;
- int i;
- uint32_t cpsr;
- int retval;
- int last_reg = 0;
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
- address, size, count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- /* load the base register with the address of the first word */
- reg[0] = address;
- arm7_9->write_core_regs(target, 0x1, reg);
-
- int j = 0;
-
- switch (size) {
- case 4:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- if (last_reg <= thisrun_accesses)
- last_reg = thisrun_accesses;
-
- arm7_9->load_word_regs(target, reg_list);
-
- /* fast memory reads are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else
- retval = arm7_9_execute_sys_speed(target);
- if (retval != ERROR_OK)
- return retval;
-
- arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 4);
-
- /* advance buffer, count number of accesses */
- buffer += thisrun_accesses * 4;
- num_accesses += thisrun_accesses;
-
- if ((j++%1024) == 0)
- keep_alive();
- }
- break;
- case 2:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- arm7_9->load_hword_reg(target, i);
- /* fast memory reads are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else
- retval = arm7_9_execute_sys_speed(target);
- if (retval != ERROR_OK)
- return retval;
-
- }
-
- arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 2);
-
- /* advance buffer, count number of accesses */
- buffer += thisrun_accesses * 2;
- num_accesses += thisrun_accesses;
-
- if ((j++%1024) == 0)
- keep_alive();
- }
- break;
- case 1:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- arm7_9->load_byte_reg(target, i);
- /* fast memory reads are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else
- retval = arm7_9_execute_sys_speed(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- arm7_9->read_core_regs_target_buffer(target, reg_list, buffer, 1);
-
- /* advance buffer, count number of accesses */
- buffer += thisrun_accesses * 1;
- num_accesses += thisrun_accesses;
-
- if ((j++%1024) == 0)
- keep_alive();
- }
- break;
- }
-
- if (!is_arm_mode(arm->core_mode))
- return ERROR_FAIL;
-
- for (i = 0; i <= last_reg; i++) {
- struct reg *r = arm_reg_current(arm, i);
- r->dirty = r->valid;
- }
-
- arm7_9->read_xpsr(target, &cpsr, 0);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while reading cpsr");
- return ERROR_TARGET_DATA_ABORT;
- }
-
- if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) {
- LOG_WARNING(
- "memory read caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")",
- address,
- size,
- count);
-
- arm7_9->write_xpsr_im8(target,
- buf_get_u32(arm->cpsr->value, 0, 8)
- & ~0x20, 0, 0);
-
- return ERROR_TARGET_DATA_ABORT;
- }
-
- return ERROR_OK;
-}
-
-int arm7_9_write_memory(struct target *target,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- const uint8_t *buffer)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-
- uint32_t reg[16];
- uint32_t num_accesses = 0;
- int thisrun_accesses;
- int i;
- uint32_t cpsr;
- int retval;
- int last_reg = 0;
-
-#ifdef _DEBUG_ARM7_9_
- LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
-#endif
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- /* load the base register with the address of the first word */
- reg[0] = address;
- arm7_9->write_core_regs(target, 0x1, reg);
-
- /* Clear DBGACK, to make sure memory fetches work as expected */
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 0);
- embeddedice_store_reg(dbg_ctrl);
-
- switch (size) {
- case 4:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- reg[i] = target_buffer_get_u32(target, buffer);
- buffer += 4;
- }
-
- arm7_9->write_core_regs(target, reg_list, reg);
-
- arm7_9->store_word_regs(target, reg_list);
-
- /* fast memory writes are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else {
- retval = arm7_9_execute_sys_speed(target);
-
- /*
- * if memory writes are made when the clock is running slow
- * (i.e. 32 kHz) which is necessary in some scripts to reconfigure
- * processor operations after a "reset halt" or "reset init",
- * need to immediately stroke the keep alive or will end up with
- * gdb "keep alive not sent error message" problem.
- */
-
- keep_alive();
- }
-
- if (retval != ERROR_OK)
- return retval;
-
- num_accesses += thisrun_accesses;
- }
- break;
- case 2:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- reg[i] = target_buffer_get_u16(target, buffer) & 0xffff;
- buffer += 2;
- }
-
- arm7_9->write_core_regs(target, reg_list, reg);
-
- for (i = 1; i <= thisrun_accesses; i++) {
- arm7_9->store_hword_reg(target, i);
-
- /* fast memory writes are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else {
- retval = arm7_9_execute_sys_speed(target);
-
- /*
- * if memory writes are made when the clock is running slow
- * (i.e. 32 kHz) which is necessary in some scripts to reconfigure
- * processor operations after a "reset halt" or "reset init",
- * need to immediately stroke the keep alive or will end up with
- * gdb "keep alive not sent error message" problem.
- */
-
- keep_alive();
- }
-
- if (retval != ERROR_OK)
- return retval;
- }
-
- num_accesses += thisrun_accesses;
- }
- break;
- case 1:
- while (num_accesses < count) {
- uint32_t reg_list;
- thisrun_accesses =
- ((count - num_accesses) >= 14) ? 14 : (count - num_accesses);
- reg_list = (0xffff >> (15 - thisrun_accesses)) & 0xfffe;
-
- for (i = 1; i <= thisrun_accesses; i++) {
- if (i > last_reg)
- last_reg = i;
- reg[i] = *buffer++ & 0xff;
- }
-
- arm7_9->write_core_regs(target, reg_list, reg);
-
- for (i = 1; i <= thisrun_accesses; i++) {
- arm7_9->store_byte_reg(target, i);
- /* fast memory writes are only safe when the target is running
- * from a sufficiently high clock (32 kHz is usually too slow)
- */
- if (arm7_9->fast_memory_access)
- retval = arm7_9_execute_fast_sys_speed(target);
- else {
- retval = arm7_9_execute_sys_speed(target);
-
- /*
- * if memory writes are made when the clock is running slow
- * (i.e. 32 kHz) which is necessary in some scripts to reconfigure
- * processor operations after a "reset halt" or "reset init",
- * need to immediately stroke the keep alive or will end up with
- * gdb "keep alive not sent error message" problem.
- */
-
- keep_alive();
- }
-
- if (retval != ERROR_OK)
- return retval;
-
- }
-
- num_accesses += thisrun_accesses;
- }
- break;
- }
-
- /* Re-Set DBGACK */
- buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
- embeddedice_store_reg(dbg_ctrl);
-
- if (!is_arm_mode(arm->core_mode))
- return ERROR_FAIL;
-
- for (i = 0; i <= last_reg; i++) {
- struct reg *r = arm_reg_current(arm, i);
- r->dirty = r->valid;
- }
-
- arm7_9->read_xpsr(target, &cpsr, 0);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while reading cpsr");
- return ERROR_TARGET_DATA_ABORT;
- }
-
- if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) {
- LOG_WARNING(
- "memory write caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")",
- address,
- size,
- count);
-
- arm7_9->write_xpsr_im8(target,
- buf_get_u32(arm->cpsr->value, 0, 8)
- & ~0x20, 0, 0);
-
- return ERROR_TARGET_DATA_ABORT;
- }
-
- return ERROR_OK;
-}
-
-int arm7_9_write_memory_opt(struct target *target,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- const uint8_t *buffer)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- int retval;
-
- if (size == 4 && count > 32 && arm7_9->bulk_write_memory) {
- /* Attempt to do a bulk write */
- retval = arm7_9->bulk_write_memory(target, address, count, buffer);
-
- if (retval == ERROR_OK)
- return ERROR_OK;
- }
-
- return arm7_9->write_memory(target, address, size, count, buffer);
-}
-
-int arm7_9_write_memory_no_opt(struct target *target,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- const uint8_t *buffer)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- return arm7_9->write_memory(target, address, size, count, buffer);
-}
-
-static int dcc_count;
-static const uint8_t *dcc_buffer;
-
-static int arm7_9_dcc_completion(struct target *target,
- uint32_t exit_point,
- int timeout_ms,
- void *arch_info)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- retval = target_wait_state(target, TARGET_DEBUG_RUNNING, 500);
- if (retval != ERROR_OK)
- return retval;
-
- int little = target->endianness == TARGET_LITTLE_ENDIAN;
- int count = dcc_count;
- const uint8_t *buffer = dcc_buffer;
- if (count > 2) {
- /* Handle first & last using standard embeddedice_write_reg and the middle ones w/the
- * core function repeated. */
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA],
- fast_target_buffer_get_u32(buffer, little));
- buffer += 4;
-
- struct embeddedice_reg *ice_reg =
- arm7_9->eice_cache->reg_list[EICE_COMMS_DATA].arch_info;
- uint8_t reg_addr = ice_reg->addr & 0x1f;
- struct jtag_tap *tap;
- tap = ice_reg->jtag_info->tap;
-
- embeddedice_write_dcc(tap, reg_addr, buffer, little, count-2);
- buffer += (count-2)*4;
-
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA],
- fast_target_buffer_get_u32(buffer, little));
- } else {
- int i;
- for (i = 0; i < count; i++) {
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA],
- fast_target_buffer_get_u32(buffer, little));
- buffer += 4;
- }
- }
-
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- return target_wait_state(target, TARGET_HALTED, 500);
-}
-
-static const uint32_t dcc_code[] = {
- /* r0 == input, points to memory buffer
- * r1 == scratch
- */
-
- /* spin until DCC control (c0) reports data arrived */
- 0xee101e10, /* w: mrc p14, #0, r1, c0, c0 */
- 0xe3110001, /* tst r1, #1 */
- 0x0afffffc, /* bne w */
-
- /* read word from DCC (c1), write to memory */
- 0xee111e10, /* mrc p14, #0, r1, c1, c0 */
- 0xe4801004, /* str r1, [r0], #4 */
-
- /* repeat */
- 0xeafffff9 /* b w */
-};
-
-int arm7_9_bulk_write_memory(struct target *target,
- uint32_t address,
- uint32_t count,
- const uint8_t *buffer)
-{
- int retval;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (address % 4 != 0)
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- if (!arm7_9->dcc_downloads)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- /* regrab previously allocated working_area, or allocate a new one */
- if (!arm7_9->dcc_working_area) {
- uint8_t dcc_code_buf[6 * 4];
-
- /* make sure we have a working area */
- if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK) {
- LOG_INFO("no working area available, falling back to memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* copy target instructions to target endianness */
- target_buffer_set_u32_array(target, dcc_code_buf, ARRAY_SIZE(dcc_code), dcc_code);
-
- /* write DCC code to working area, using the non-optimized
- * memory write to avoid ending up here again */
- retval = arm7_9_write_memory_no_opt(target,
- arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf);
- if (retval != ERROR_OK)
- return retval;
- }
-
- struct arm_algorithm arm_algo;
- struct reg_param reg_params[1];
-
- 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_IN_OUT);
-
- buf_set_u32(reg_params[0].value, 0, 32, address);
-
- dcc_count = count;
- dcc_buffer = buffer;
- retval = armv4_5_run_algorithm_inner(target, 0, NULL, 1, reg_params,
- arm7_9->dcc_working_area->address,
- arm7_9->dcc_working_area->address + 6*4,
- 20*1000, &arm_algo, arm7_9_dcc_completion);
-
- if (retval == ERROR_OK) {
- uint32_t endaddress = buf_get_u32(reg_params[0].value, 0, 32);
- if (endaddress != (address + count*4)) {
- LOG_ERROR(
- "DCC write failed, expected end address 0x%08" PRIx32 " got 0x%0" PRIx32 "",
- (address + count*4),
- endaddress);
- retval = ERROR_FAIL;
- }
- }
-
- destroy_reg_param(&reg_params[0]);
-
- return retval;
-}
-
-/**
- * Perform per-target setup that requires JTAG access.
- */
-int arm7_9_examine(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- int retval;
-
- if (!target_was_examined(target)) {
- struct reg_cache *t, **cache_p;
-
- t = embeddedice_build_reg_cache(target, arm7_9);
- if (t == NULL)
- return ERROR_FAIL;
-
- cache_p = register_get_last_cache_p(&target->reg_cache);
- (*cache_p) = t;
- arm7_9->eice_cache = (*cache_p);
-
- if (arm7_9->arm.etm)
- (*cache_p)->next = etm_build_reg_cache(target,
- &arm7_9->jtag_info,
- arm7_9->arm.etm);
-
- target_set_examined(target);
- }
-
- retval = embeddedice_setup(target);
- if (retval == ERROR_OK)
- retval = arm7_9_setup(target);
- if (retval == ERROR_OK && arm7_9->arm.etm)
- retval = etm_setup(target);
- return retval;
-}
-
-
-int arm7_9_check_reset(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (get_target_reset_nag() && !arm7_9->dcc_downloads)
- LOG_WARNING(
- "NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'.");
-
- if (get_target_reset_nag() && (target->working_area_size == 0))
- LOG_WARNING("NOTE! Severe performance degradation without working memory enabled.");
-
- if (get_target_reset_nag() && !arm7_9->fast_memory_access)
- LOG_WARNING(
- "NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'.");
-
- return ERROR_OK;
-}
-
-int arm7_9_endianness_callback(jtag_callback_data_t pu8_in,
- jtag_callback_data_t i_size, jtag_callback_data_t i_be,
- jtag_callback_data_t i_flip)
-{
- uint8_t *in = (uint8_t *)pu8_in;
- int size = (int)i_size;
- int be = (int)i_be;
- int flip = (int)i_flip;
- uint32_t readback;
-
- switch (size) {
- case 4:
- readback = le_to_h_u32(in);
- if (flip)
- readback = flip_u32(readback, 32);
- if (be)
- h_u32_to_be(in, readback);
- else
- h_u32_to_le(in, readback);
- break;
- case 2:
- readback = le_to_h_u16(in);
- if (flip)
- readback = flip_u32(readback, 16);
- if (be)
- h_u16_to_be(in, readback & 0xffff);
- else
- h_u16_to_le(in, readback & 0xffff);
- break;
- case 1:
- readback = *in;
- if (flip)
- readback = flip_u32(readback, 8);
- *in = readback & 0xff;
- break;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_arm7_9_dbgrq_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (!is_arm7_9(arm7_9)) {
- command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target");
- return ERROR_TARGET_INVALID;
- }
-
- if (CMD_ARGC > 0)
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm7_9->use_dbgrq);
-
- command_print(CMD_CTX,
- "use of EmbeddedICE dbgrq instead of breakpoint for target halt %s",
- (arm7_9->use_dbgrq) ? "enabled" : "disabled");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_arm7_9_fast_memory_access_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (!is_arm7_9(arm7_9)) {
- command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target");
- return ERROR_TARGET_INVALID;
- }
-
- if (CMD_ARGC > 0)
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm7_9->fast_memory_access);
-
- command_print(CMD_CTX,
- "fast memory access is %s",
- (arm7_9->fast_memory_access) ? "enabled" : "disabled");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_arm7_9_dcc_downloads_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (!is_arm7_9(arm7_9)) {
- command_print(CMD_CTX, "current target isn't an ARM7/ARM9 target");
- return ERROR_TARGET_INVALID;
- }
-
- if (CMD_ARGC > 0)
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm7_9->dcc_downloads);
-
- command_print(CMD_CTX,
- "dcc downloads are %s",
- (arm7_9->dcc_downloads) ? "enabled" : "disabled");
-
- return ERROR_OK;
-}
-
-static int arm7_9_setup_semihosting(struct target *target, int enable)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (!is_arm7_9(arm7_9)) {
- LOG_USER("current target isn't an ARM7/ARM9 target");
- return ERROR_TARGET_INVALID;
- }
-
- if (arm7_9->has_vector_catch) {
- struct reg *vector_catch = &arm7_9->eice_cache
- ->reg_list[EICE_VEC_CATCH];
-
- if (!vector_catch->valid)
- embeddedice_read_reg(vector_catch);
- buf_set_u32(vector_catch->value, 2, 1, enable);
- embeddedice_store_reg(vector_catch);
- } else {
- /* TODO: allow optional high vectors and/or BKPT_HARD */
- if (enable)
- breakpoint_add(target, 8, 4, BKPT_SOFT);
- else
- breakpoint_remove(target, 8);
- }
-
- return ERROR_OK;
-}
-
-int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9)
-{
- int retval = ERROR_OK;
- struct arm *arm = &arm7_9->arm;
-
- arm7_9->common_magic = ARM7_9_COMMON_MAGIC;
-
- retval = arm_jtag_setup_connection(&arm7_9->jtag_info);
- if (retval != ERROR_OK)
- return retval;
-
- /* caller must have allocated via calloc(), so everything's zeroed */
-
- arm7_9->wp_available_max = 2;
-
- arm7_9->fast_memory_access = false;
- arm7_9->dcc_downloads = false;
-
- arm->arch_info = arm7_9;
- arm->core_type = ARM_MODE_ANY;
- arm->read_core_reg = arm7_9_read_core_reg;
- arm->write_core_reg = arm7_9_write_core_reg;
- arm->full_context = arm7_9_full_context;
- arm->setup_semihosting = arm7_9_setup_semihosting;
-
- retval = arm_init_arch_info(target, arm);
- if (retval != ERROR_OK)
- return retval;
-
- return target_register_timer_callback(arm7_9_handle_target_request,
- 1, 1, target);
-}
-
-static const struct command_registration arm7_9_any_command_handlers[] = {
- {
- "dbgrq",
- .handler = handle_arm7_9_dbgrq_command,
- .mode = COMMAND_ANY,
- .usage = "['enable'|'disable']",
- .help = "use EmbeddedICE dbgrq instead of breakpoint "
- "for target halt requests",
- },
- {
- "fast_memory_access",
- .handler = handle_arm7_9_fast_memory_access_command,
- .mode = COMMAND_ANY,
- .usage = "['enable'|'disable']",
- .help = "use fast memory accesses instead of slower "
- "but potentially safer accesses",
- },
- {
- "dcc_downloads",
- .handler = handle_arm7_9_dcc_downloads_command,
- .mode = COMMAND_ANY,
- .usage = "['enable'|'disable']",
- .help = "use DCC downloads for larger memory writes",
- },
- COMMAND_REGISTRATION_DONE
-};
-const struct command_registration arm7_9_command_handlers[] = {
- {
- .chain = arm_command_handlers,
- },
- {
- .chain = etm_command_handlers,
- },
- {
- .name = "arm7_9",
- .mode = COMMAND_ANY,
- .help = "arm7/9 specific commands",
- .usage = "",
- .chain = arm7_9_any_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h
deleted file mode 100644
index 044384b..0000000
--- a/src/target/arm7_9_common.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by Hongtao Zheng *
- * hontor@126.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM7_9_COMMON_H
-#define OPENOCD_TARGET_ARM7_9_COMMON_H
-
-#include "arm.h"
-#include "arm_jtag.h"
-
-#define ARM7_9_COMMON_MAGIC 0x0a790a79 /**< */
-
-/**
- * Structure for items that are common between both ARM7 and ARM9 targets.
- */
-struct arm7_9_common {
- struct arm arm;
- uint32_t common_magic;
-
- struct arm_jtag jtag_info; /**< JTAG information for target */
- struct reg_cache *eice_cache; /**< Embedded ICE register cache */
-
- uint32_t arm_bkpt; /**< ARM breakpoint instruction */
- uint16_t thumb_bkpt; /**< Thumb breakpoint instruction */
-
- int sw_breakpoints_added; /**< Specifies which watchpoint software breakpoints are setup on */
- int sw_breakpoint_count; /**< keep track of number of software breakpoints we have set */
- int breakpoint_count; /**< Current number of set breakpoints */
- int wp_available; /**< Current number of available watchpoint units */
- int wp_available_max; /**< Maximum number of available watchpoint units */
- int wp0_used; /**< Specifies if and how watchpoint unit 0 is used */
- int wp1_used; /**< Specifies if and how watchpoint unit 1 is used */
- int wp1_used_default; /**< Specifies if and how watchpoint unit 1 is used by default */
- int dbgreq_adjust_pc; /**< Amount of PC adjustment caused by a DBGREQ */
- bool use_dbgrq; /**< Specifies if DBGRQ should be used to halt the target */
- bool need_bypass_before_restart; /**< Specifies if there should be a bypass before a JTAG restart */
-
- bool has_single_step;
- bool has_monitor_mode;
- bool has_vector_catch; /**< Specifies if the target has a reset vector catch */
-
- bool debug_entry_from_reset; /**< Specifies if debug entry was from a reset */
-
- bool fast_memory_access;
- bool dcc_downloads;
-
- struct working_area *dcc_working_area;
-
- int (*examine_debug_reason)(struct target *target);
- /**< Function for determining why debug state was entered */
-
- void (*change_to_arm)(struct target *target, uint32_t *r0, uint32_t *pc);
- /**< Function for changing from Thumb to ARM mode */
-
- void (*read_core_regs)(struct target *target, uint32_t mask, uint32_t *core_regs[16]);
- /**< Function for reading the core registers */
-
- void (*read_core_regs_target_buffer)(struct target *target, uint32_t mask,
- void *buffer, int size);
- void (*read_xpsr)(struct target *target, uint32_t *xpsr, int spsr);
- /**< Function for reading CPSR or SPSR */
-
- void (*write_xpsr)(struct target *target, uint32_t xpsr, int spsr);
- /**< Function for writing to CPSR or SPSR */
-
- void (*write_xpsr_im8)(struct target *target, uint8_t xpsr_im, int rot, int spsr);
- /**< Function for writing an immediate value to CPSR or SPSR */
-
- void (*write_core_regs)(struct target *target, uint32_t mask, uint32_t core_regs[16]);
-
- void (*load_word_regs)(struct target *target, uint32_t mask);
- void (*load_hword_reg)(struct target *target, int num);
- void (*load_byte_reg)(struct target *target, int num);
-
- void (*store_word_regs)(struct target *target, uint32_t mask);
- void (*store_hword_reg)(struct target *target, int num);
- void (*store_byte_reg)(struct target *target, int num);
-
- void (*write_pc)(struct target *target, uint32_t pc);
- /**< Function for writing to the program counter */
-
- void (*branch_resume)(struct target *target);
- void (*branch_resume_thumb)(struct target *target);
-
- void (*enable_single_step)(struct target *target, uint32_t next_pc);
- void (*disable_single_step)(struct target *target);
-
- void (*set_special_dbgrq)(struct target *target);
- /**< Function for setting DBGRQ if the normal way won't work */
-
- int (*post_debug_entry)(struct target *target);
- /**< Callback function called after entering debug mode */
-
- void (*pre_restore_context)(struct target *target);
- /**< Callback function called before restoring the processor context */
-
- /**
- * Variant specific memory write function that does not dispatch to bulk_write_memory.
- * Used as a fallback when bulk writes are unavailable, or for writing data needed to
- * do the bulk writes.
- */
- int (*write_memory)(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
- /**
- * Write target memory in multiples of 4 bytes, optimized for
- * writing large quantities of data.
- */
- int (*bulk_write_memory)(struct target *target, uint32_t address,
- uint32_t count, const uint8_t *buffer);
-};
-
-static inline struct arm7_9_common *target_to_arm7_9(struct target *target)
-{
- return container_of(target->arch_info, struct arm7_9_common, arm);
-}
-
-static inline bool is_arm7_9(struct arm7_9_common *arm7_9)
-{
- return arm7_9->common_magic == ARM7_9_COMMON_MAGIC;
-}
-
-extern const struct command_registration arm7_9_command_handlers[];
-
-int arm7_9_poll(struct target *target);
-
-int arm7_9_target_request_data(struct target *target, uint32_t size, uint8_t *buffer);
-
-int arm7_9_assert_reset(struct target *target);
-int arm7_9_deassert_reset(struct target *target);
-int arm7_9_reset_request_halt(struct target *target);
-int arm7_9_early_halt(struct target *target);
-int arm7_9_soft_reset_halt(struct target *target);
-
-int arm7_9_halt(struct target *target);
-int arm7_9_resume(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution);
-int arm7_9_step(struct target *target, int current, uint32_t address,
- int handle_breakpoints);
-int arm7_9_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer);
-int arm7_9_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-int arm7_9_write_memory_opt(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-int arm7_9_write_memory_no_opt(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-int arm7_9_bulk_write_memory(struct target *target, uint32_t address,
- uint32_t count, const uint8_t *buffer);
-
-int arm7_9_run_algorithm(struct target *target, int num_mem_params,
- struct mem_param *mem_params, int num_reg_prams,
- struct reg_param *reg_param, uint32_t entry_point, void *arch_info);
-
-int arm7_9_add_breakpoint(struct target *target, struct breakpoint *breakpoint);
-int arm7_9_remove_breakpoint(struct target *target, struct breakpoint *breakpoint);
-int arm7_9_add_watchpoint(struct target *target, struct watchpoint *watchpoint);
-int arm7_9_remove_watchpoint(struct target *target, struct watchpoint *watchpoint);
-
-void arm7_9_enable_eice_step(struct target *target, uint32_t next_pc);
-void arm7_9_disable_eice_step(struct target *target);
-
-int arm7_9_execute_sys_speed(struct target *target);
-
-int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9);
-int arm7_9_examine(struct target *target);
-int arm7_9_check_reset(struct target *target);
-
-int arm7_9_endianness_callback(jtag_callback_data_t pu8_in,
- jtag_callback_data_t i_size, jtag_callback_data_t i_be,
- jtag_callback_data_t i_flip);
-
-#endif /* OPENOCD_TARGET_ARM7_9_COMMON_H */
diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c
deleted file mode 100644
index 58ab027..0000000
--- a/src/target/arm7tdmi.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm7tdmi.h"
-#include "target_type.h"
-#include "register.h"
-#include "arm_opcodes.h"
-
-/*
- * For information about ARM7TDMI, see ARM DDI 0210C (r4p1)
- * or ARM DDI 0029G (r3). "Debug In Depth", Appendix B,
- * covers JTAG support.
- */
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-static int arm7tdmi_examine_debug_reason(struct target *target)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- /* only check the debug reason if we don't know it already */
- if ((target->debug_reason != DBG_REASON_DBGRQ)
- && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
- struct scan_field fields[2];
- uint8_t databus[4];
- uint8_t breakpoint;
-
- fields[0].num_bits = 1;
- fields[0].out_value = NULL;
- fields[0].in_value = &breakpoint;
-
- fields[1].num_bits = 32;
- fields[1].out_value = NULL;
- fields[1].in_value = databus;
-
- retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(arm7_9->jtag_info.tap, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].in_value = NULL;
- fields[0].out_value = &breakpoint;
- fields[1].in_value = NULL;
- fields[1].out_value = databus;
-
- jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE);
-
- if (breakpoint & 1)
- target->debug_reason = DBG_REASON_WATCHPOINT;
- else
- target->debug_reason = DBG_REASON_BREAKPOINT;
- }
-
- return ERROR_OK;
-}
-
-static const int arm7tdmi_num_bits[] = {1, 32};
-
-static inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_t out, int breakpoint)
-{
- uint8_t bp = breakpoint ? 1 : 0;
- uint8_t out_value[4];
- buf_set_u32(out_value, 0, 32, flip_u32(out, 32));
-
- struct scan_field fields[2] = {
- { .num_bits = arm7tdmi_num_bits[0], .out_value = &bp },
- { .num_bits = arm7tdmi_num_bits[1], .out_value = out_value },
- };
-
- jtag_add_dr_scan(jtag_info->tap,
- 2,
- fields,
- TAP_DRPAUSE);
-
- jtag_add_runtest(0, TAP_DRPAUSE);
-
- return ERROR_OK;
-}
-
-/* put an instruction in the ARM7TDMI pipeline or write the data bus,
- * and optionally read data
- *
- * FIXME remove the unused "deprecated" parameter
- */
-static inline int arm7tdmi_clock_out(struct arm_jtag *jtag_info,
- uint32_t out, uint32_t *deprecated, int breakpoint)
-{
- int retval;
- retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- return arm7tdmi_clock_out_inner(jtag_info, out, breakpoint);
-}
-
-/* clock the target, reading the databus */
-static int arm7tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
-{
- int retval = ERROR_OK;
- struct scan_field fields[2];
-
- retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 1;
- fields[0].out_value = NULL;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 32;
- fields[1].out_value = NULL;
- fields[1].in_value = (uint8_t *)in;
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
-
- jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
-
- jtag_add_runtest(0, TAP_DRPAUSE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (in)
- LOG_DEBUG("in: 0x%8.8x", *in);
- else
- LOG_ERROR("BUG: called with in == NULL");
-#endif
-
- return ERROR_OK;
-}
-
-/* clock the target, and read the databus
- * the *in pointer points to a buffer where elements of 'size' bytes
- * are stored in big (be == 1) or little (be == 0) endianness
- */
-static int arm7tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
- void *in, int size, int be)
-{
- int retval = ERROR_OK;
- struct scan_field fields[3];
-
- retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 1;
- fields[0].out_value = NULL;
- fields[0].in_value = NULL;
-
- if (size == 4) {
- fields[1].num_bits = 32;
- fields[1].out_value = NULL;
- fields[1].in_value = in;
- } else {
- /* Discard irrelevant bits of the scan, making sure we don't write more
- * than size bytes to in */
- fields[1].num_bits = 32 - size * 8;
- fields[1].out_value = NULL;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = size * 8;
- fields[2].out_value = NULL;
- fields[2].in_value = in;
- }
-
- jtag_add_dr_scan(jtag_info->tap, size == 4 ? 2 : 3, fields, TAP_DRPAUSE);
-
- jtag_add_callback4(arm7_9_endianness_callback,
- (jtag_callback_data_t)in,
- (jtag_callback_data_t)size,
- (jtag_callback_data_t)be,
- (jtag_callback_data_t)1);
-
- jtag_add_runtest(0, TAP_DRPAUSE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-{
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (in)
- LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in);
- else
- LOG_ERROR("BUG: called with in == NULL");
-}
-#endif
-
- return ERROR_OK;
-}
-
-static void arm7tdmi_change_to_arm(struct target *target,
- uint32_t *r0, uint32_t *pc)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* save r0 before using it and put system in ARM state
- * to allow common handling of ARM and THUMB debugging */
-
- /* fetch STR r0, [r0] */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- /* nothing fetched, STR r0, [r0] in Execute (2) */
- arm7tdmi_clock_data_in(jtag_info, r0);
-
- /* MOV r0, r15 fetched, STR in Decode */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- /* nothing fetched, STR r0, [r0] in Execute (2) */
- arm7tdmi_clock_data_in(jtag_info, pc);
-
- /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- /* nothing fetched, data for LDR r0, [PC, #0] */
- arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);
- /* nothing fetched, data from previous cycle is written to register */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-
- /* fetch BX */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);
- /* NOP fetched, BX in Decode, MOV in Execute */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- /* NOP fetched, BX in Execute (1) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-
- jtag_execute_queue();
-
- /* fix program counter:
- * MOV r0, r15 was the 4th instruction (+6)
- * reading PC in Thumb state gives address of instruction + 4
- */
- *pc -= 0xa;
-}
-
-/* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many
- * roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s?
- *
- * The solution is to arrange for a large out/in scan in this loop and
- * and convert data afterwards.
- */
-static void arm7tdmi_read_core_regs(struct target *target,
- uint32_t mask, uint32_t *core_regs[16])
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* STMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
-
- /* fetch NOP, STM in DECODE stage */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* fetch NOP, STM in EXECUTE stage (1st cycle) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, STM still in EXECUTE (1 + i cycle) */
- arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
- }
-}
-
-static void arm7tdmi_read_core_regs_target_buffer(struct target *target,
- uint32_t mask, void *buffer, int size)
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
- uint32_t *buf_u32 = buffer;
- uint16_t *buf_u16 = buffer;
- uint8_t *buf_u8 = buffer;
-
- /* STMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
-
- /* fetch NOP, STM in DECODE stage */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* fetch NOP, STM in EXECUTE stage (1st cycle) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- /* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */
- if (mask & (1 << i)) {
- switch (size) {
- case 4:
- arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
- break;
- case 2:
- arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
- break;
- case 1:
- arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
- break;
- }
- }
- }
-}
-
-static void arm7tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* MRS r0, cpsr */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0);
-
- /* STR r0, [r15] */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0);
- /* fetch NOP, STR in DECODE stage */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* fetch NOP, STR in EXECUTE stage (1st cycle) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* nothing fetched, STR still in EXECUTE (2nd cycle) */
- arm7tdmi_clock_data_in(jtag_info, xpsr);
-}
-
-static void arm7tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
-
- /* MSR1 fetched */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0);
- /* MSR2 fetched, MSR1 in DECODE */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0);
- /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0);
- /* nothing fetched, MSR1 in EXECUTE (2) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0);
- /* nothing fetched, MSR2 in EXECUTE (2) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* nothing fetched, MSR3 in EXECUTE (2) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* NOP fetched, MSR4 in EXECUTE (1) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* nothing fetched, MSR4 in EXECUTE (2) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-}
-
-static void arm7tdmi_write_xpsr_im8(struct target *target,
- uint8_t xpsr_im, int rot, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
-
- /* MSR fetched */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0);
- /* NOP fetched, MSR in DECODE */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* NOP fetched, MSR in EXECUTE (1) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* nothing fetched, MSR in EXECUTE (2) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-}
-
-static void arm7tdmi_write_core_regs(struct target *target,
- uint32_t mask, uint32_t core_regs[16])
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* LDMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0);
-
- /* fetch NOP, LDM in DECODE stage */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
- arm7tdmi_clock_out_inner(jtag_info, core_regs[i], 0);
- }
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
-}
-
-static void arm7tdmi_load_word_regs(struct target *target, uint32_t mask)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed load-multiple into the pipeline */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0);
-}
-
-static void arm7tdmi_load_hword_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed load half-word into the pipeline */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0);
-}
-
-static void arm7tdmi_load_byte_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed load byte into the pipeline */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0);
-}
-
-static void arm7tdmi_store_word_regs(struct target *target, uint32_t mask)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed store-multiple into the pipeline */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0);
-}
-
-static void arm7tdmi_store_hword_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed store half-word into the pipeline */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0);
-}
-
-static void arm7tdmi_store_byte_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed store byte into the pipeline */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0);
-}
-
-static void arm7tdmi_write_pc(struct target *target, uint32_t pc)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* LDMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0);
- /* fetch NOP, LDM in DECODE stage */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
- /* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */
- arm7tdmi_clock_out_inner(jtag_info, pc, 0);
- /* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
- /* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
- /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
- /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
-}
-
-static void arm7tdmi_branch_resume(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
- arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_B(0xfffffa, 0), 0);
-}
-
-static void arm7tdmi_branch_resume_thumb(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
- LOG_DEBUG("-");
-
- /* LDMIA r0, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0);
-
- /* fetch NOP, LDM in DECODE stage */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
- arm7tdmi_clock_out(jtag_info,
- buf_get_u32(arm->pc->value, 0, 32) | 1, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
- /* Branch and eXchange */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0);
-
- embeddedice_read_reg(dbg_stat);
-
- /* fetch NOP, BX in DECODE stage */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
- /* target is now in Thumb state */
- embeddedice_read_reg(dbg_stat);
-
- /* fetch NOP, BX in EXECUTE stage (1st cycle) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
- /* target is now in Thumb state */
- embeddedice_read_reg(dbg_stat);
-
- /* load r0 value */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
- /* fetch NOP, LDR in Decode */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- /* fetch NOP, LDR in Execute */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
- arm7tdmi_clock_out(jtag_info, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), NULL, 0);
- /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-
- embeddedice_read_reg(dbg_stat);
-
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);
- arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);
-}
-
-static void arm7tdmi_build_reg_cache(struct target *target)
-{
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct arm *arm = target_to_arm(target);
-
- (*cache_p) = arm_build_reg_cache(target, arm);
-}
-
-int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target)
-{
- arm7tdmi_build_reg_cache(target);
-
- return ERROR_OK;
-}
-
-int arm7tdmi_init_arch_info(struct target *target,
- struct arm7_9_common *arm7_9, struct jtag_tap *tap)
-{
- /* prepare JTAG information for the new target */
- arm7_9->jtag_info.tap = tap;
- arm7_9->jtag_info.scann_size = 4;
-
- /* register arch-specific functions */
- arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;
- arm7_9->change_to_arm = arm7tdmi_change_to_arm;
- arm7_9->read_core_regs = arm7tdmi_read_core_regs;
- arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;
- arm7_9->read_xpsr = arm7tdmi_read_xpsr;
-
- arm7_9->write_xpsr = arm7tdmi_write_xpsr;
- arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8;
- arm7_9->write_core_regs = arm7tdmi_write_core_regs;
-
- arm7_9->load_word_regs = arm7tdmi_load_word_regs;
- arm7_9->load_hword_reg = arm7tdmi_load_hword_reg;
- arm7_9->load_byte_reg = arm7tdmi_load_byte_reg;
-
- arm7_9->store_word_regs = arm7tdmi_store_word_regs;
- arm7_9->store_hword_reg = arm7tdmi_store_hword_reg;
- arm7_9->store_byte_reg = arm7tdmi_store_byte_reg;
-
- arm7_9->write_pc = arm7tdmi_write_pc;
- arm7_9->branch_resume = arm7tdmi_branch_resume;
- arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb;
-
- arm7_9->enable_single_step = arm7_9_enable_eice_step;
- arm7_9->disable_single_step = arm7_9_disable_eice_step;
-
- arm7_9->write_memory = arm7_9_write_memory;
- arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
-
- arm7_9->post_debug_entry = NULL;
-
- arm7_9->pre_restore_context = NULL;
-
- /* initialize arch-specific breakpoint handling */
- arm7_9->arm_bkpt = 0xdeeedeee;
- arm7_9->thumb_bkpt = 0xdeee;
-
- arm7_9->dbgreq_adjust_pc = 2;
-
- arm7_9_init_arch_info(target, arm7_9);
-
- return ERROR_OK;
-}
-
-static int arm7tdmi_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm7_9_common *arm7_9;
-
- arm7_9 = calloc(1, sizeof(struct arm7_9_common));
- arm7tdmi_init_arch_info(target, arm7_9, target->tap);
- arm7_9->arm.is_armv4 = true;
-
- return ERROR_OK;
-}
-
-/** Holds methods for ARM7TDMI targets. */
-struct target_type arm7tdmi_target = {
- .name = "arm7tdmi",
-
- .poll = arm7_9_poll,
- .arch_state = arm_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm7_9_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm7_9_read_memory,
- .write_memory = arm7_9_write_memory_opt,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm7_9_command_handlers,
- .target_create = arm7tdmi_target_create,
- .init_target = arm7tdmi_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
-};
diff --git a/src/target/arm7tdmi.h b/src/target/arm7tdmi.h
deleted file mode 100644
index 053f64d..0000000
--- a/src/target/arm7tdmi.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM7TDMI_H
-#define OPENOCD_TARGET_ARM7TDMI_H
-
-#include "embeddedice.h"
-
-int arm7tdmi_init_arch_info(struct target *target,
- struct arm7_9_common *arm7_9, struct jtag_tap *tap);
-int arm7tdmi_init_target(struct command_context *cmd_ctx,
- struct target *target);
-
-#endif /* OPENOCD_TARGET_ARM7TDMI_H */
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
deleted file mode 100644
index 2c96d19..0000000
--- a/src/target/arm920t.c
+++ /dev/null
@@ -1,1720 +0,0 @@
-
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm920t.h"
-#include <helper/time_support.h>
-#include "target_type.h"
-#include "register.h"
-#include "arm_opcodes.h"
-
-/*
- * For information about the ARM920T, see ARM DDI 0151C especially
- * Chapter 9 about debug support, which shows how to manipulate each
- * of the different scan chains:
- *
- * 0 ... ARM920 signals, e.g. to rest of SOC (unused here)
- * 1 ... debugging; watchpoint and breakpoint status, etc; also
- * MMU and cache access in conjunction with scan chain 15
- * 2 ... EmbeddedICE
- * 3 ... external boundary scan (SoC-specific, unused here)
- * 4 ... access to cache tag RAM
- * 6 ... ETM9
- * 15 ... access coprocessor 15, "physical" or "interpreted" modes
- * "interpreted" works with a few actual MRC/MCR instructions
- * "physical" provides register-like behaviors. Section 9.6.7
- * covers these details.
- *
- * The ARM922T is similar, but with smaller caches (8K each, vs 16K).
- */
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-/* Table 9-8 shows scan chain 15 format during physical access mode, using a
- * dedicated 6-bit address space (encoded in bits 33:38). Writes use one
- * JTAG scan, while reads use two.
- *
- * Table 9-9 lists the thirteen registers which support physical access.
- * ARM920T_CP15_PHYS_ADDR() constructs the 6-bit reg_addr parameter passed
- * to arm920t_read_cp15_physical() and arm920t_write_cp15_physical().
- *
- * x == bit[38]
- * y == bits[37:34]
- * z == bit[33]
- */
-#define ARM920T_CP15_PHYS_ADDR(x, y, z) ((x << 5) | (y << 1) << (z))
-
-/* Registers supporting physical Read access (from table 9-9) */
-#define CP15PHYS_CACHETYPE ARM920T_CP15_PHYS_ADDR(0, 0x0, 1)
-#define CP15PHYS_ICACHE_IDX ARM920T_CP15_PHYS_ADDR(1, 0xd, 1)
-#define CP15PHYS_DCACHE_IDX ARM920T_CP15_PHYS_ADDR(1, 0xe, 1)
-/* NOTE: several more registers support only physical read access */
-
-/* Registers supporting physical Read/Write access (from table 9-9) */
-#define CP15PHYS_CTRL ARM920T_CP15_PHYS_ADDR(0, 0x1, 0)
-#define CP15PHYS_PID ARM920T_CP15_PHYS_ADDR(0, 0xd, 0)
-#define CP15PHYS_TESTSTATE ARM920T_CP15_PHYS_ADDR(0, 0xf, 0)
-#define CP15PHYS_ICACHE ARM920T_CP15_PHYS_ADDR(1, 0x1, 1)
-#define CP15PHYS_DCACHE ARM920T_CP15_PHYS_ADDR(1, 0x2, 1)
-
-static int arm920t_read_cp15_physical(struct target *target,
- int reg_addr, uint32_t *value)
-{
- struct arm920t_common *arm920t = target_to_arm920(target);
- struct arm_jtag *jtag_info;
- struct scan_field fields[4];
- uint8_t access_type_buf = 1;
- uint8_t reg_addr_buf = reg_addr & 0x3f;
- uint8_t nr_w_buf = 0;
- int retval;
-
- jtag_info = &arm920t->arm7_9_common.jtag_info;
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 1;
- fields[0].out_value = &access_type_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 32;
- fields[1].out_value = NULL;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 6;
- fields[2].out_value = &reg_addr_buf;
- fields[2].in_value = NULL;
-
- fields[3].num_bits = 1;
- fields[3].out_value = &nr_w_buf;
- fields[3].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
-
- fields[1].in_value = (uint8_t *)value;
-
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
-
- jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- jtag_execute_queue();
- LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
-#endif
-
- return ERROR_OK;
-}
-
-static int arm920t_write_cp15_physical(struct target *target,
- int reg_addr, uint32_t value)
-{
- struct arm920t_common *arm920t = target_to_arm920(target);
- struct arm_jtag *jtag_info;
- struct scan_field fields[4];
- uint8_t access_type_buf = 1;
- uint8_t reg_addr_buf = reg_addr & 0x3f;
- uint8_t nr_w_buf = 1;
- uint8_t value_buf[4];
- int retval;
-
- jtag_info = &arm920t->arm7_9_common.jtag_info;
-
- buf_set_u32(value_buf, 0, 32, value);
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 1;
- fields[0].out_value = &access_type_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 32;
- fields[1].out_value = value_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 6;
- fields[2].out_value = &reg_addr_buf;
- fields[2].in_value = NULL;
-
- fields[3].num_bits = 1;
- fields[3].out_value = &nr_w_buf;
- fields[3].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
-#endif
-
- return ERROR_OK;
-}
-
-/* See table 9-10 for scan chain 15 format during interpreted access mode.
- * If the TESTSTATE register is set for interpreted access, certain CP15
- * MRC and MCR instructions may be executed through scan chain 15.
- *
- * Tables 9-11, 9-12, and 9-13 show which MRC and MCR instructions can be
- * executed using scan chain 15 interpreted mode.
- */
-static int arm920t_execute_cp15(struct target *target, uint32_t cp15_opcode,
- uint32_t arm_opcode)
-{
- int retval;
- struct arm920t_common *arm920t = target_to_arm920(target);
- struct arm_jtag *jtag_info;
- struct scan_field fields[4];
- uint8_t access_type_buf = 0; /* interpreted access */
- uint8_t reg_addr_buf = 0x0;
- uint8_t nr_w_buf = 0;
- uint8_t cp15_opcode_buf[4];
-
- jtag_info = &arm920t->arm7_9_common.jtag_info;
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode);
-
- fields[0].num_bits = 1;
- fields[0].out_value = &access_type_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 32;
- fields[1].out_value = cp15_opcode_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 6;
- fields[2].out_value = &reg_addr_buf;
- fields[2].in_value = NULL;
-
- fields[3].num_bits = 1;
- fields[3].out_value = &nr_w_buf;
- fields[3].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
-
- arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
- retval = arm7_9_execute_sys_speed(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed executing JTAG queue");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int arm920t_read_cp15_interpreted(struct target *target,
- uint32_t cp15_opcode, uint32_t address, uint32_t *value)
-{
- struct arm *arm = target_to_arm(target);
- uint32_t *regs_p[1];
- uint32_t regs[2];
- uint32_t cp15c15 = 0x0;
- struct reg *r = arm->core_cache->reg_list;
-
- /* load address into R1 */
- regs[1] = address;
- arm9tdmi_write_core_regs(target, 0x2, regs);
-
- /* read-modify-write CP15 test state register
- * to enable interpreted access mode */
- arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15);
- jtag_execute_queue();
- cp15c15 |= 1; /* set interpret mode */
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
- /* execute CP15 instruction and ARM load (reading from coprocessor) */
- arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_LDR(0, 1));
-
- /* disable interpreted access mode */
- cp15c15 &= ~1U; /* clear interpret mode */
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
- /* retrieve value from R0 */
- regs_p[0] = value;
- arm9tdmi_read_core_regs(target, 0x1, regs_p);
- jtag_execute_queue();
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("cp15_opcode: %8.8x, address: %8.8x, value: %8.8x",
- cp15_opcode, address, *value);
-#endif
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- r[0].dirty = 1;
- r[1].dirty = 1;
-
- return ERROR_OK;
-}
-
-static
-int arm920t_write_cp15_interpreted(struct target *target,
- uint32_t cp15_opcode, uint32_t value, uint32_t address)
-{
- uint32_t cp15c15 = 0x0;
- struct arm *arm = target_to_arm(target);
- uint32_t regs[2];
- struct reg *r = arm->core_cache->reg_list;
-
- /* load value, address into R0, R1 */
- regs[0] = value;
- regs[1] = address;
- arm9tdmi_write_core_regs(target, 0x3, regs);
-
- /* read-modify-write CP15 test state register
- * to enable interpreted access mode */
- arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15);
- jtag_execute_queue();
- cp15c15 |= 1; /* set interpret mode */
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
- /* execute CP15 instruction and ARM store (writing to coprocessor) */
- arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_STR(0, 1));
-
- /* disable interpreted access mode */
- cp15c15 &= ~1U; /* set interpret mode */
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("cp15_opcode: %8.8x, value: %8.8x, address: %8.8x",
- cp15_opcode, value, address);
-#endif
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- r[0].dirty = 1;
- r[1].dirty = 1;
-
- return ERROR_OK;
-}
-
-/* EXPORTED to FA256 */
-int arm920t_get_ttb(struct target *target, uint32_t *result)
-{
- int retval;
- uint32_t ttb = 0x0;
-
- retval = arm920t_read_cp15_interpreted(target,
- /* FIXME use opcode macro */
- 0xeebf0f51, 0x0, &ttb);
- if (retval != ERROR_OK)
- return retval;
-
- *result = ttb;
- return ERROR_OK;
-}
-
-/* EXPORTED to FA256 */
-int arm920t_disable_mmu_caches(struct target *target, int mmu,
- int d_u_cache, int i_cache)
-{
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_control);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (mmu)
- cp15_control &= ~0x1U;
-
- if (d_u_cache)
- cp15_control &= ~0x4U;
-
- if (i_cache)
- cp15_control &= ~0x1000U;
-
- retval = arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_control);
- return retval;
-}
-
-/* EXPORTED to FA256 */
-int arm920t_enable_mmu_caches(struct target *target, int mmu,
- int d_u_cache, int i_cache)
-{
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_control);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (mmu)
- cp15_control |= 0x1U;
-
- if (d_u_cache)
- cp15_control |= 0x4U;
-
- if (i_cache)
- cp15_control |= 0x1000U;
-
- retval = arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_control);
- return retval;
-}
-
-/* EXPORTED to FA256 */
-int arm920t_post_debug_entry(struct target *target)
-{
- uint32_t cp15c15;
- struct arm920t_common *arm920t = target_to_arm920(target);
- int retval;
-
- /* examine cp15 control reg */
- retval = arm920t_read_cp15_physical(target,
- CP15PHYS_CTRL, &arm920t->cp15_control_reg);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, arm920t->cp15_control_reg);
-
- if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1) {
- uint32_t cache_type_reg;
- /* identify caches */
- retval = arm920t_read_cp15_physical(target,
- CP15PHYS_CACHETYPE, &cache_type_reg);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- armv4_5_identify_cache(cache_type_reg,
- &arm920t->armv4_5_mmu.armv4_5_cache);
- }
-
- arm920t->armv4_5_mmu.mmu_enabled =
- (arm920t->cp15_control_reg & 0x1U) ? 1 : 0;
- arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
- (arm920t->cp15_control_reg & 0x4U) ? 1 : 0;
- arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
- (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;
-
- /* save i/d fault status and address register
- * FIXME use opcode macros */
- retval = arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
- if (retval != ERROR_OK)
- return retval;
- retval = arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr);
- if (retval != ERROR_OK)
- return retval;
- retval = arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far);
- if (retval != ERROR_OK)
- return retval;
- retval = arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32
- ", I FSR: 0x%8.8" PRIx32 ", I FAR: 0x%8.8" PRIx32,
- arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);
-
- if (arm920t->preserve_cache) {
- /* read-modify-write CP15 test state register
- * to disable I/D-cache linefills */
- retval = arm920t_read_cp15_physical(target,
- CP15PHYS_TESTSTATE, &cp15c15);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- cp15c15 |= 0x600;
- retval = arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
- if (retval != ERROR_OK)
- return retval;
- }
- return ERROR_OK;
-}
-
-/* EXPORTED to FA256 */
-void arm920t_pre_restore_context(struct target *target)
-{
- uint32_t cp15c15;
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- /* restore i/d fault status and address register */
- arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0);
- arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0);
- arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0);
- arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0);
-
- /* read-modify-write CP15 test state register
- * to reenable I/D-cache linefills */
- if (arm920t->preserve_cache) {
- arm920t_read_cp15_physical(target,
- CP15PHYS_TESTSTATE, &cp15c15);
- jtag_execute_queue();
- cp15c15 &= ~0x600U;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
- }
-}
-
-static const char arm920_not[] = "target is not an ARM920";
-
-static int arm920t_verify_pointer(struct command_context *cmd_ctx,
- struct arm920t_common *arm920t)
-{
- if (arm920t->common_magic != ARM920T_COMMON_MAGIC) {
- command_print(cmd_ctx, arm920_not);
- return ERROR_TARGET_INVALID;
- }
-
- return ERROR_OK;
-}
-
-/** Logs summary of ARM920 state for a halted target. */
-int arm920t_arch_state(struct target *target)
-{
- static const char *state[] = {
- "disabled", "enabled"
- };
-
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- if (arm920t->common_magic != ARM920T_COMMON_MAGIC) {
- LOG_ERROR("BUG: %s", arm920_not);
- return ERROR_TARGET_INVALID;
- }
-
- arm_arch_state(target);
- LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
- state[arm920t->armv4_5_mmu.mmu_enabled],
- state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
- state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
-
- return ERROR_OK;
-}
-
-static int arm920_mmu(struct target *target, int *enabled)
-{
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("%s: target not halted", __func__);
- return ERROR_TARGET_INVALID;
- }
-
- *enabled = target_to_arm920(target)->armv4_5_mmu.mmu_enabled;
- return ERROR_OK;
-}
-
-static int arm920_virt2phys(struct target *target,
- uint32_t virt, uint32_t *phys)
-{
- uint32_t cb;
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- uint32_t ret;
- int retval = armv4_5_mmu_translate_va(target,
- &arm920t->armv4_5_mmu, virt, &cb, &ret);
- if (retval != ERROR_OK)
- return retval;
- *phys = ret;
- return ERROR_OK;
-}
-
-/** Reads a buffer, in the specified word size, with current MMU settings. */
-int arm920t_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- int retval;
-
- retval = arm7_9_read_memory(target, address, size, count, buffer);
-
- return retval;
-}
-
-
-static int arm920t_read_phys_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- return armv4_5_mmu_read_physical(target, &arm920t->armv4_5_mmu,
- address, size, count, buffer);
-}
-
-static int arm920t_write_phys_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- return armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu,
- address, size, count, buffer);
-}
-
-/** Writes a buffer, in the specified word size, with current MMU settings. */
-int arm920t_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- int retval;
- const uint32_t cache_mask = ~0x1f; /* cache line size : 32 byte */
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- /* FIX!!!! this should be cleaned up and made much more general. The
- * plan is to write up and test on arm920t specifically and
- * then generalize and clean up afterwards.
- *
- * Also it should be moved to the callbacks that handle breakpoints
- * specifically and not the generic memory write fn's. See XScale code.
- */
- if (arm920t->armv4_5_mmu.mmu_enabled && (count == 1) &&
- ((size == 2) || (size == 4))) {
- /* special case the handling of single word writes to
- * bypass MMU, to allow implementation of breakpoints
- * in memory marked read only
- * by MMU
- */
- uint32_t cb;
- uint32_t pa;
-
- /*
- * We need physical address and cb
- */
- retval = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu,
- address, &cb, &pa);
- if (retval != ERROR_OK)
- return retval;
-
- if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
- if (cb & 0x1) {
- LOG_DEBUG("D-Cache buffered, "
- "drain write buffer");
- /*
- * Buffered ?
- * Drain write buffer - MCR p15,0,Rd,c7,c10,4
- */
-
- retval = arm920t_write_cp15_interpreted(target,
- ARMV4_5_MCR(15, 0, 0, 7, 10, 4),
- 0x0, 0);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (cb == 0x3) {
- /*
- * Write back memory ? -> clean cache
- *
- * There is no way to clean cache lines using
- * cp15 scan chain, so copy the full cache
- * line from cache to physical memory.
- */
- uint8_t data[32];
-
- LOG_DEBUG("D-Cache in 'write back' mode, "
- "flush cache line");
-
- retval = target_read_memory(target,
- address & cache_mask, 1,
- sizeof(data), &data[0]);
- if (retval != ERROR_OK)
- return retval;
-
- retval = armv4_5_mmu_write_physical(target,
- &arm920t->armv4_5_mmu,
- pa & cache_mask, 1,
- sizeof(data), &data[0]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* Cached ? */
- if (cb & 0x2) {
- /*
- * Cached ? -> Invalidate data cache using MVA
- *
- * MCR p15,0,Rd,c7,c6,1
- */
- LOG_DEBUG("D-Cache enabled, "
- "invalidate cache line");
-
- retval = arm920t_write_cp15_interpreted(target,
- ARMV4_5_MCR(15, 0, 0, 7, 6, 1), 0x0,
- address & cache_mask);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- /* write directly to physical memory,
- * bypassing any read only MMU bits, etc.
- */
- retval = armv4_5_mmu_write_physical(target,
- &arm920t->armv4_5_mmu, pa, size,
- count, buffer);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = arm7_9_write_memory(target, address, size, count, buffer);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* If ICache is enabled, we have to invalidate affected ICache lines
- * the DCache is forced to write-through,
- * so we don't have to clean it here
- */
- if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled) {
- if (count <= 1) {
- /* invalidate ICache single entry with MVA
- * mcr 15, 0, r0, cr7, cr5, {1}
- */
- LOG_DEBUG("I-Cache enabled, "
- "invalidating affected I-Cache line");
- retval = arm920t_write_cp15_interpreted(target,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
- 0x0, address & cache_mask);
- if (retval != ERROR_OK)
- return retval;
- } else {
- /* invalidate ICache
- * mcr 15, 0, r0, cr7, cr5, {0}
- */
- retval = arm920t_write_cp15_interpreted(target,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 0),
- 0x0, 0x0);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- return ERROR_OK;
-}
-
-/* EXPORTED to FA256 */
-int arm920t_soft_reset_halt(struct target *target)
-{
- int retval = ERROR_OK;
- struct arm920t_common *arm920t = target_to_arm920(target);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- bool timeout;
- while (!(timeout = ((timeval_ms()-then) > 1000))) {
- if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) {
- embeddedice_read_reg(dbg_stat);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- } else
- break;
- if (debug_level >= 3) {
- /* do not eat all CPU, time out after 1 se*/
- alive_sleep(100);
- } else
- keep_alive();
- }
- if (timeout) {
- LOG_ERROR("Failed to halt CPU after 1 sec");
- return ERROR_TARGET_TIMEOUT;
- }
-
- target->state = TARGET_HALTED;
-
- /* SVC, ARM state, IRQ and FIQ disabled */
- uint32_t cpsr;
-
- cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
- cpsr &= ~0xff;
- cpsr |= 0xd3;
- arm_set_cpsr(arm, cpsr);
- arm->cpsr->dirty = 1;
-
- /* start fetching from 0x0 */
- buf_set_u32(arm->pc->value, 0, 32, 0x0);
- arm->pc->dirty = 1;
- arm->pc->valid = 1;
-
- arm920t_disable_mmu_caches(target, 1, 1, 1);
- arm920t->armv4_5_mmu.mmu_enabled = 0;
- arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
- arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
- return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-}
-
-/* FIXME remove forward decls */
-static int arm920t_mrc(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t *value);
-static int arm920t_mcr(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t value);
-
-static int arm920t_init_arch_info(struct target *target,
- struct arm920t_common *arm920t, struct jtag_tap *tap)
-{
- struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
-
- arm7_9->arm.mrc = arm920t_mrc;
- arm7_9->arm.mcr = arm920t_mcr;
-
- /* initialize arm7/arm9 specific info (including armv4_5) */
- arm9tdmi_init_arch_info(target, arm7_9, tap);
-
- arm920t->common_magic = ARM920T_COMMON_MAGIC;
-
- arm7_9->post_debug_entry = arm920t_post_debug_entry;
- arm7_9->pre_restore_context = arm920t_pre_restore_context;
- arm7_9->write_memory = arm920t_write_memory;
-
- arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
- arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
- arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
- arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
- arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
- arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
- arm920t->armv4_5_mmu.has_tiny_pages = 1;
- arm920t->armv4_5_mmu.mmu_enabled = 0;
-
- /* disabling linefills leads to lockups, so keep them enabled for now
- * this doesn't affect correctness, but might affect timing issues, if
- * important data is evicted from the cache during the debug session
- * */
- arm920t->preserve_cache = 0;
-
- /* override hw single-step capability from ARM9TDMI */
- arm7_9->has_single_step = 1;
-
- return ERROR_OK;
-}
-
-static int arm920t_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm920t_common *arm920t;
-
- arm920t = calloc(1, sizeof(struct arm920t_common));
- return arm920t_init_arch_info(target, arm920t, target->tap);
-}
-
-COMMAND_HANDLER(arm920t_handle_read_cache_command)
-{
- int retval = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
- struct arm920t_common *arm920t = target_to_arm920(target);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- uint32_t cp15c15;
- uint32_t cp15_ctrl, cp15_ctrl_saved;
- uint32_t regs[16];
- uint32_t *regs_p[16];
- uint32_t C15_C_D_Ind, C15_C_I_Ind;
- int i;
- FILE *output;
- int segment, index_t;
- struct reg *r;
-
- retval = arm920t_verify_pointer(CMD_CTX, arm920t);
- if (retval != ERROR_OK)
- return retval;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- output = fopen(CMD_ARGV[0], "w");
- if (output == NULL) {
- LOG_DEBUG("error opening cache content file");
- return ERROR_OK;
- }
-
- for (i = 0; i < 16; i++)
- regs_p[i] = &regs[i];
-
- /* disable MMU and Caches */
- arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- cp15_ctrl_saved = cp15_ctrl;
- cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED
- | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
- arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl);
-
- /* read CP15 test state register */
- arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15);
- jtag_execute_queue();
-
- /* read DCache content */
- fprintf(output, "DCache:\n");
-
- /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
- for (segment = 0;
- segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets;
- segment++) {
- fprintf(output, "\nsegment: %i\n----------", segment);
-
- /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
- regs[0] = 0x0 | (segment << 5);
- arm9tdmi_write_core_regs(target, 0x1, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* D CAM Read, loads current victim into C15.C.D.Ind */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 2, 0, 15, 6, 2), ARMV4_5_LDR(1, 0));
-
- /* read current victim */
- arm920t_read_cp15_physical(target,
- CP15PHYS_DCACHE_IDX, &C15_C_D_Ind);
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- for (index_t = 0; index_t < 64; index_t++) {
- /* Ra:
- * r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0)
- */
- regs[0] = 0x0 | (segment << 5) | (index_t << 26);
- arm9tdmi_write_core_regs(target, 0x1, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write DCache victim */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 9, 1, 0), ARMV4_5_LDR(1, 0));
-
- /* Read D RAM */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 2, 0, 15, 10, 2),
- ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
-
- /* Read D CAM */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 2, 0, 15, 6, 2),
- ARMV4_5_LDR(9, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* read D RAM and CAM content */
- arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* mask LFSR[6] */
- regs[9] &= 0xfffffffe;
- fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8"
- PRIx32 ", content (%s):\n",
- segment, index_t, regs[9],
- (regs[9] & 0x10) ? "valid" : "invalid");
-
- for (i = 1; i < 9; i++) {
- fprintf(output, "%i: 0x%8.8" PRIx32 "\n",
- i-1, regs[i]);
- }
-
- }
-
- /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
- regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
- arm9tdmi_write_core_regs(target, 0x1, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write DCache victim */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 9, 1, 0), ARMV4_5_LDR(1, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
- }
-
- /* read ICache content */
- fprintf(output, "ICache:\n");
-
- /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */
- for (segment = 0;
- segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets;
- segment++) {
- fprintf(output, "segment: %i\n----------", segment);
-
- /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
- regs[0] = 0x0 | (segment << 5);
- arm9tdmi_write_core_regs(target, 0x1, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* I CAM Read, loads current victim into C15.C.I.Ind */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 2, 0, 15, 5, 2), ARMV4_5_LDR(1, 0));
-
- /* read current victim */
- arm920t_read_cp15_physical(target, CP15PHYS_ICACHE_IDX,
- &C15_C_I_Ind);
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- for (index_t = 0; index_t < 64; index_t++) {
- /* Ra:
- * r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0)
- */
- regs[0] = 0x0 | (segment << 5) | (index_t << 26);
- arm9tdmi_write_core_regs(target, 0x1, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write ICache victim */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 9, 1, 1), ARMV4_5_LDR(1, 0));
-
- /* Read I RAM */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 2, 0, 15, 9, 2),
- ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
-
- /* Read I CAM */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 2, 0, 15, 5, 2),
- ARMV4_5_LDR(9, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* read I RAM and CAM content */
- arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* mask LFSR[6] */
- regs[9] &= 0xfffffffe;
- fprintf(output, "\nsegment: %i, index: %i, "
- "CAM: 0x%8.8" PRIx32 ", content (%s):\n",
- segment, index_t, regs[9],
- (regs[9] & 0x10) ? "valid" : "invalid");
-
- for (i = 1; i < 9; i++) {
- fprintf(output, "%i: 0x%8.8" PRIx32 "\n",
- i-1, regs[i]);
- }
- }
-
- /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
- regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
- arm9tdmi_write_core_regs(target, 0x1, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write ICache victim */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 9, 1, 1), ARMV4_5_LDR(1, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
- }
-
- /* restore CP15 MMU and Cache settings */
- arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl_saved);
-
- command_print(CMD_CTX, "cache content successfully output to %s",
- CMD_ARGV[0]);
-
- fclose(output);
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- /* force writeback of the valid data */
- r = arm->core_cache->reg_list;
- r[0].dirty = r[0].valid;
- r[1].dirty = r[1].valid;
- r[2].dirty = r[2].valid;
- r[3].dirty = r[3].valid;
- r[4].dirty = r[4].valid;
- r[5].dirty = r[5].valid;
- r[6].dirty = r[6].valid;
- r[7].dirty = r[7].valid;
-
- r = arm_reg_current(arm, 8);
- r->dirty = r->valid;
-
- r = arm_reg_current(arm, 9);
- r->dirty = r->valid;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(arm920t_handle_read_mmu_command)
-{
- int retval = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
- struct arm920t_common *arm920t = target_to_arm920(target);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- uint32_t cp15c15;
- uint32_t cp15_ctrl, cp15_ctrl_saved;
- uint32_t regs[16];
- uint32_t *regs_p[16];
- int i;
- FILE *output;
- uint32_t Dlockdown, Ilockdown;
- struct arm920t_tlb_entry d_tlb[64], i_tlb[64];
- int victim;
- struct reg *r;
-
- retval = arm920t_verify_pointer(CMD_CTX, arm920t);
- if (retval != ERROR_OK)
- return retval;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- output = fopen(CMD_ARGV[0], "w");
- if (output == NULL) {
- LOG_DEBUG("error opening mmu content file");
- return ERROR_OK;
- }
-
- for (i = 0; i < 16; i++)
- regs_p[i] = &regs[i];
-
- /* disable MMU and Caches */
- arm920t_read_cp15_physical(target, CP15PHYS_CTRL, &cp15_ctrl);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- cp15_ctrl_saved = cp15_ctrl;
- cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED
- | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
- arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl);
-
- /* read CP15 test state register */
- arm920t_read_cp15_physical(target, CP15PHYS_TESTSTATE, &cp15c15);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* prepare reading D TLB content
- * */
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
- /* Read D TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MRC(15, 0, 0, 10, 0, 0), ARMV4_5_LDR(1, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
- /* read D TLB lockdown stored to r1 */
- arm9tdmi_read_core_regs(target, 0x2, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- Dlockdown = regs[1];
-
- for (victim = 0; victim < 64; victim += 8) {
- /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
- * base remains unchanged, victim goes through entries 0 to 63
- */
- regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
- arm9tdmi_write_core_regs(target, 0x2, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write D TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 10, 0, 0),
- ARMV4_5_STR(1, 0));
-
- /* Read D TLB CAM */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 4, 0, 15, 6, 4),
- ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* read D TLB CAM content stored to r2-r9 */
- arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < 8; i++)
- d_tlb[victim + i].cam = regs[i + 2];
- }
-
- for (victim = 0; victim < 64; victim++) {
- /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
- * base remains unchanged, victim goes through entries 0 to 63
- */
- regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
- arm9tdmi_write_core_regs(target, 0x2, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write D TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 10, 0, 0), ARMV4_5_STR(1, 0));
-
- /* Read D TLB RAM1 */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 4, 0, 15, 10, 4), ARMV4_5_LDR(2, 0));
-
- /* Read D TLB RAM2 */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 4, 0, 15, 2, 5), ARMV4_5_LDR(3, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* read D TLB RAM content stored to r2 and r3 */
- arm9tdmi_read_core_regs(target, 0xc, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- d_tlb[victim].ram1 = regs[2];
- d_tlb[victim].ram2 = regs[3];
- }
-
- /* restore D TLB lockdown */
- regs[1] = Dlockdown;
- arm9tdmi_write_core_regs(target, 0x2, regs);
-
- /* Write D TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 10, 0, 0), ARMV4_5_STR(1, 0));
-
- /* prepare reading I TLB content
- * */
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
- /* Read I TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MRC(15, 0, 0, 10, 0, 1), ARMV4_5_LDR(1, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target, CP15PHYS_TESTSTATE, cp15c15);
-
- /* read I TLB lockdown stored to r1 */
- arm9tdmi_read_core_regs(target, 0x2, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- Ilockdown = regs[1];
-
- for (victim = 0; victim < 64; victim += 8) {
- /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
- * base remains unchanged, victim goes through entries 0 to 63
- */
- regs[1] = (Ilockdown & 0xfc000000) | (victim << 20);
- arm9tdmi_write_core_regs(target, 0x2, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write I TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 10, 0, 1),
- ARMV4_5_STR(1, 0));
-
- /* Read I TLB CAM */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 4, 0, 15, 5, 4),
- ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* read I TLB CAM content stored to r2-r9 */
- arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < 8; i++)
- i_tlb[i + victim].cam = regs[i + 2];
- }
-
- for (victim = 0; victim < 64; victim++) {
- /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0]
- * base remains unchanged, victim goes through entries 0 to 63
- */
- regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
- arm9tdmi_write_core_regs(target, 0x2, regs);
-
- /* set interpret mode */
- cp15c15 |= 0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* Write I TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 10, 0, 1), ARMV4_5_STR(1, 0));
-
- /* Read I TLB RAM1 */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 4, 0, 15, 9, 4), ARMV4_5_LDR(2, 0));
-
- /* Read I TLB RAM2 */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 4, 0, 15, 1, 5), ARMV4_5_LDR(3, 0));
-
- /* clear interpret mode */
- cp15c15 &= ~0x1;
- arm920t_write_cp15_physical(target,
- CP15PHYS_TESTSTATE, cp15c15);
-
- /* read I TLB RAM content stored to r2 and r3 */
- arm9tdmi_read_core_regs(target, 0xc, regs_p);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- i_tlb[victim].ram1 = regs[2];
- i_tlb[victim].ram2 = regs[3];
- }
-
- /* restore I TLB lockdown */
- regs[1] = Ilockdown;
- arm9tdmi_write_core_regs(target, 0x2, regs);
-
- /* Write I TLB lockdown */
- arm920t_execute_cp15(target,
- ARMV4_5_MCR(15, 0, 0, 10, 0, 1), ARMV4_5_STR(1, 0));
-
- /* restore CP15 MMU and Cache settings */
- arm920t_write_cp15_physical(target, CP15PHYS_CTRL, cp15_ctrl_saved);
-
- /* output data to file */
- fprintf(output, "D TLB content:\n");
- for (i = 0; i < 64; i++) {
- fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32
- " 0x%8.8" PRIx32 " %s\n",
- i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2,
- (d_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
- }
-
- fprintf(output, "\n\nI TLB content:\n");
- for (i = 0; i < 64; i++) {
- fprintf(output, "%i: 0x%8.8" PRIx32 " 0x%8.8" PRIx32
- " 0x%8.8" PRIx32 " %s\n",
- i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2,
- (i_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
- }
-
- command_print(CMD_CTX, "mmu content successfully output to %s",
- CMD_ARGV[0]);
-
- fclose(output);
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- /* force writeback of the valid data */
- r = arm->core_cache->reg_list;
- r[0].dirty = r[0].valid;
- r[1].dirty = r[1].valid;
- r[2].dirty = r[2].valid;
- r[3].dirty = r[3].valid;
- r[4].dirty = r[4].valid;
- r[5].dirty = r[5].valid;
- r[6].dirty = r[6].valid;
- r[7].dirty = r[7].valid;
-
- r = arm_reg_current(arm, 8);
- r->dirty = r->valid;
-
- r = arm_reg_current(arm, 9);
- r->dirty = r->valid;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(arm920t_handle_cp15_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- retval = arm920t_verify_pointer(CMD_CTX, arm920t);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for "
- "\"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- /* one argument, read a register.
- * two arguments, write it.
- */
- if (CMD_ARGC >= 1) {
- int address;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
-
- if (CMD_ARGC == 1) {
- uint32_t value;
- retval = arm920t_read_cp15_physical(target, address, &value);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access reg %i", address);
- return ERROR_OK;
- }
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "%i: %8.8" PRIx32,
- address, value);
- } else if (CMD_ARGC == 2) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
- retval = arm920t_write_cp15_physical(target,
- address, value);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access reg %i", address);
- /* REVISIT why lie? "return retval"? */
- return ERROR_OK;
- }
- command_print(CMD_CTX, "%i: %8.8" PRIx32,
- address, value);
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(arm920t_handle_cp15i_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- retval = arm920t_verify_pointer(CMD_CTX, arm920t);
- if (retval != ERROR_OK)
- return retval;
-
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for "
- "\"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- /* one argument, read a register.
- * two arguments, write it.
- */
- if (CMD_ARGC >= 1) {
- uint32_t opcode;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode);
-
- if (CMD_ARGC == 1) {
- uint32_t value;
- retval = arm920t_read_cp15_interpreted(target,
- opcode, 0x0, &value);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't execute %8.8" PRIx32,
- opcode);
- /* REVISIT why lie? "return retval"? */
- return ERROR_OK;
- }
-
- command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32,
- opcode, value);
- } else if (CMD_ARGC == 2) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
- retval = arm920t_write_cp15_interpreted(target,
- opcode, value, 0);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't execute %8.8" PRIx32,
- opcode);
- /* REVISIT why lie? "return retval"? */
- return ERROR_OK;
- }
- command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32,
- opcode, value);
- } else if (CMD_ARGC == 3) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
- retval = arm920t_write_cp15_interpreted(target,
- opcode, value, address);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't execute %8.8" PRIx32, opcode);
- /* REVISIT why lie? "return retval"? */
- return ERROR_OK;
- }
- command_print(CMD_CTX, "%8.8" PRIx32 ": %8.8" PRIx32
- " %8.8" PRIx32, opcode, value, address);
- }
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(arm920t_handle_cache_info_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct arm920t_common *arm920t = target_to_arm920(target);
-
- retval = arm920t_verify_pointer(CMD_CTX, arm920t);
- if (retval != ERROR_OK)
- return retval;
-
- return armv4_5_handle_cache_info_command(CMD_CTX,
- &arm920t->armv4_5_mmu.armv4_5_cache);
-}
-
-
-static int arm920t_mrc(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t *value)
-{
- if (cpnum != 15) {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
-
- /* read "to" r0 */
- return arm920t_read_cp15_interpreted(target,
- ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
- 0, value);
-}
-
-static int arm920t_mcr(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t value)
-{
- if (cpnum != 15) {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
-
- /* write "from" r0 */
- return arm920t_write_cp15_interpreted(target,
- ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
- 0, value);
-}
-
-static const struct command_registration arm920t_exec_command_handlers[] = {
- {
- .name = "cp15",
- .handler = arm920t_handle_cp15_command,
- .mode = COMMAND_EXEC,
- .help = "display/modify cp15 register",
- .usage = "regnum [value]",
- },
- {
- .name = "cp15i",
- .handler = arm920t_handle_cp15i_command,
- .mode = COMMAND_EXEC,
- /* prefer using less error-prone "arm mcr" or "arm mrc" */
- .help = "display/modify cp15 register using ARM opcode"
- " (DEPRECATED)",
- .usage = "instruction [value [address]]",
- },
- {
- .name = "cache_info",
- .handler = arm920t_handle_cache_info_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "display information about target caches",
- },
- {
- .name = "read_cache",
- .handler = arm920t_handle_read_cache_command,
- .mode = COMMAND_EXEC,
- .help = "dump I/D cache content to file",
- .usage = "filename",
- },
- {
- .name = "read_mmu",
- .handler = arm920t_handle_read_mmu_command,
- .mode = COMMAND_EXEC,
- .help = "dump I/D mmu content to file",
- .usage = "filename",
- },
- COMMAND_REGISTRATION_DONE
-};
-const struct command_registration arm920t_command_handlers[] = {
- {
- .chain = arm9tdmi_command_handlers,
- },
- {
- .name = "arm920t",
- .mode = COMMAND_ANY,
- .help = "arm920t command group",
- .usage = "",
- .chain = arm920t_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for ARM920 targets. */
-struct target_type arm920t_target = {
- .name = "arm920t",
-
- .poll = arm7_9_poll,
- .arch_state = arm920t_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm920t_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm920t_read_memory,
- .write_memory = arm7_9_write_memory_opt,
- .read_phys_memory = arm920t_read_phys_memory,
- .write_phys_memory = arm920t_write_phys_memory,
- .mmu = arm920_mmu,
- .virt2phys = arm920_virt2phys,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm920t_command_handlers,
- .target_create = arm920t_target_create,
- .init_target = arm9tdmi_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
-};
diff --git a/src/target/arm920t.h b/src/target/arm920t.h
deleted file mode 100644
index 3401b09..0000000
--- a/src/target/arm920t.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM920T_H
-#define OPENOCD_TARGET_ARM920T_H
-
-#include "arm9tdmi.h"
-#include "armv4_5_mmu.h"
-
-#define ARM920T_COMMON_MAGIC 0xa920a920
-
-struct arm920t_common {
- struct arm7_9_common arm7_9_common;
- uint32_t common_magic;
- struct armv4_5_mmu_common armv4_5_mmu;
- uint32_t cp15_control_reg;
- uint32_t d_fsr;
- uint32_t i_fsr;
- uint32_t d_far;
- uint32_t i_far;
- int preserve_cache;
-};
-
-static inline struct arm920t_common *target_to_arm920(struct target *target)
-{
- return container_of(target->arch_info, struct arm920t_common, arm7_9_common.arm);
-}
-
-struct arm920t_cache_line {
- uint32_t cam;
- uint32_t data[8];
-};
-
-struct arm920t_tlb_entry {
- uint32_t cam;
- uint32_t ram1;
- uint32_t ram2;
-};
-
-int arm920t_arch_state(struct target *target);
-int arm920t_soft_reset_halt(struct target *target);
-int arm920t_read_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
-int arm920t_write_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-int arm920t_post_debug_entry(struct target *target);
-void arm920t_pre_restore_context(struct target *target);
-int arm920t_get_ttb(struct target *target, uint32_t *result);
-int arm920t_disable_mmu_caches(struct target *target,
- int mmu, int d_u_cache, int i_cache);
-int arm920t_enable_mmu_caches(struct target *target,
- int mmu, int d_u_cache, int i_cache);
-
-extern const struct command_registration arm920t_command_handlers[];
-
-#endif /* OPENOCD_TARGET_ARM920T_H */
diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c
deleted file mode 100644
index d7c043e..0000000
--- a/src/target/arm926ejs.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008,2009 by Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm926ejs.h"
-#include <helper/time_support.h>
-#include "target_type.h"
-#include "register.h"
-#include "arm_opcodes.h"
-
-
-/*
- * The ARM926 is built around the ARM9EJ-S core, and most JTAG docs
- * are in the ARM9EJ-S Technical Reference Manual (ARM DDI 0222B) not
- * the ARM926 manual (ARM DDI 0198E). The scan chains are:
- *
- * 1 ... core debugging
- * 2 ... EmbeddedICE
- * 3 ... external boundary scan (SoC-specific, unused here)
- * 6 ... ETM
- * 15 ... coprocessor 15
- */
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-#define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0))
-
-static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm, uint32_t *value)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- uint32_t address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
- struct scan_field fields[4];
- uint8_t address_buf[2] = {0, 0};
- uint8_t nr_w_buf = 0;
- uint8_t access_t = 1;
-
- buf_set_u32(address_buf, 0, 14, address);
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = (uint8_t *)value;
-
- fields[1].num_bits = 1;
- fields[1].out_value = &access_t;
- fields[1].in_value = &access_t;
-
- fields[2].num_bits = 14;
- fields[2].out_value = address_buf;
- fields[2].in_value = NULL;
-
- fields[3].num_bits = 1;
- fields[3].out_value = &nr_w_buf;
- fields[3].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
-
- int64_t then = timeval_ms();
-
- for (;;) {
- /* rescan with NOP, to wait for the access to complete */
- access_t = 0;
- nr_w_buf = 0;
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
-
- jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (buf_get_u32(&access_t, 0, 1) == 1)
- break;
-
- /* 10ms timeout */
- if ((timeval_ms()-then) > 10) {
- LOG_ERROR("cp15 read operation timed out");
- return ERROR_FAIL;
- }
- }
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("addr: 0x%x value: %8.8x", address, *value);
-#endif
-
- retval = arm_jtag_set_instr(jtag_info->tap, 0xc, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int arm926ejs_mrc(struct target *target, int cpnum, uint32_t op1,
- uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
-{
- if (cpnum != 15) {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
- return arm926ejs_cp15_read(target, op1, op2, CRn, CRm, value);
-}
-
-static int arm926ejs_cp15_write(struct target *target, uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm, uint32_t value)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- uint32_t address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
- struct scan_field fields[4];
- uint8_t value_buf[4];
- uint8_t address_buf[2] = {0, 0};
- uint8_t nr_w_buf = 1;
- uint8_t access_t = 1;
-
- buf_set_u32(address_buf, 0, 14, address);
- buf_set_u32(value_buf, 0, 32, value);
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = value_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 1;
- fields[1].out_value = &access_t;
- fields[1].in_value = &access_t;
-
- fields[2].num_bits = 14;
- fields[2].out_value = address_buf;
- fields[2].in_value = NULL;
-
- fields[3].num_bits = 1;
- fields[3].out_value = &nr_w_buf;
- fields[3].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
-
- int64_t then = timeval_ms();
-
- for (;;) {
- /* rescan with NOP, to wait for the access to complete */
- access_t = 0;
- nr_w_buf = 0;
- jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (buf_get_u32(&access_t, 0, 1) == 1)
- break;
-
- /* 10ms timeout */
- if ((timeval_ms()-then) > 10) {
- LOG_ERROR("cp15 write operation timed out");
- return ERROR_FAIL;
- }
- }
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("addr: 0x%x value: %8.8x", address, value);
-#endif
-
- retval = arm_jtag_set_instr(jtag_info->tap, 0xf, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int arm926ejs_mcr(struct target *target, int cpnum, uint32_t op1,
- uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
-{
- if (cpnum != 15) {
- LOG_ERROR("Only cp15 is supported");
- return ERROR_FAIL;
- }
- return arm926ejs_cp15_write(target, op1, op2, CRn, CRm, value);
-}
-
-static int arm926ejs_examine_debug_reason(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
- int debug_reason;
- int retval;
-
- embeddedice_read_reg(dbg_stat);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* Method-Of-Entry (MOE) field */
- debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
-
- switch (debug_reason) {
- case 0:
- LOG_DEBUG("no *NEW* debug entry (?missed one?)");
- /* ... since last restart or debug reset ... */
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case 1:
- LOG_DEBUG("breakpoint from EICE unit 0");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 2:
- LOG_DEBUG("breakpoint from EICE unit 1");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 3:
- LOG_DEBUG("soft breakpoint (BKPT instruction)");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 4:
- LOG_DEBUG("vector catch breakpoint");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 5:
- LOG_DEBUG("external breakpoint");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 6:
- LOG_DEBUG("watchpoint from EICE unit 0");
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- case 7:
- LOG_DEBUG("watchpoint from EICE unit 1");
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- case 8:
- LOG_DEBUG("external watchpoint");
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- case 9:
- LOG_DEBUG("internal debug request");
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case 10:
- LOG_DEBUG("external debug request");
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case 11:
- LOG_DEBUG("debug re-entry from system speed access");
- /* This is normal when connecting to something that's
- * already halted, or in some related code paths, but
- * otherwise is surprising (and presumably wrong).
- */
- switch (target->debug_reason) {
- case DBG_REASON_DBGRQ:
- break;
- default:
- LOG_ERROR("unexpected -- debug re-entry");
- /* FALLTHROUGH */
- case DBG_REASON_UNDEFINED:
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- }
- break;
- case 12:
- /* FIX!!!! here be dragons!!! We need to fail here so
- * the target will interpreted as halted but we won't
- * try to talk to it right now... a resume + halt seems
- * to sync things up again. Please send an email to
- * openocd development mailing list if you have hardware
- * to donate to look into this problem....
- */
- LOG_WARNING("WARNING: mystery debug reason MOE = 0xc. Try issuing a resume + halt.");
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- default:
- LOG_WARNING("WARNING: unknown debug reason: 0x%x", debug_reason);
- /* Oh agony! should we interpret this as a halt request or
- * that the target stopped on it's own accord?
- */
- target->debug_reason = DBG_REASON_DBGRQ;
- /* if we fail here, we won't talk to the target and it will
- * be reported to be in the halted state */
- break;
- }
-
- return ERROR_OK;
-}
-
-static int arm926ejs_get_ttb(struct target *target, uint32_t *result)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
- int retval;
- uint32_t ttb = 0x0;
-
- retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb);
- if (retval != ERROR_OK)
- return retval;
-
- *result = ttb;
-
- return ERROR_OK;
-}
-
-static int arm926ejs_disable_mmu_caches(struct target *target, int mmu,
- int d_u_cache, int i_cache)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (mmu) {
- /* invalidate TLB */
- retval = arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- cp15_control &= ~0x1U;
- }
-
- if (d_u_cache) {
- uint32_t debug_override;
- /* read-modify-write CP15 debug override register
- * to enable "test and clean all" */
- retval = arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override);
- if (retval != ERROR_OK)
- return retval;
- debug_override |= 0x80000;
- retval = arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
- if (retval != ERROR_OK)
- return retval;
-
- /* clean and invalidate DCache */
- retval = arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- /* write CP15 debug override register
- * to disable "test and clean all" */
- debug_override &= ~0x80000;
- retval = arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
- if (retval != ERROR_OK)
- return retval;
-
- cp15_control &= ~0x4U;
- }
-
- if (i_cache) {
- /* invalidate ICache */
- retval = arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- cp15_control &= ~0x1000U;
- }
-
- retval = arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
- return retval;
-}
-
-static int arm926ejs_enable_mmu_caches(struct target *target, int mmu,
- int d_u_cache, int i_cache)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (mmu)
- cp15_control |= 0x1U;
-
- if (d_u_cache)
- cp15_control |= 0x4U;
-
- if (i_cache)
- cp15_control |= 0x1000U;
-
- retval = arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
- return retval;
-}
-
-static int arm926ejs_post_debug_entry(struct target *target)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
- int retval;
-
- /* examine cp15 control reg */
- retval = arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm926ejs->cp15_control_reg);
-
- if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1) {
- uint32_t cache_type_reg;
- /* identify caches */
- retval = arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
- if (retval != ERROR_OK)
- return retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);
- }
-
- arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0;
-
- /* save i/d fault status and address register */
- retval = arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);
- if (retval != ERROR_OK)
- return retval;
- retval = arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr);
- if (retval != ERROR_OK)
- return retval;
- retval = arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("D FSR: 0x%8.8" PRIx32 ", D FAR: 0x%8.8" PRIx32 ", I FSR: 0x%8.8" PRIx32 "",
- arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);
-
- uint32_t cache_dbg_ctrl;
-
- /* read-modify-write CP15 cache debug control register
- * to disable I/D-cache linefills and force WT */
- retval = arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
- if (retval != ERROR_OK)
- return retval;
- cache_dbg_ctrl |= 0x7;
- retval = arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
- return retval;
-}
-
-static void arm926ejs_pre_restore_context(struct target *target)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- /* restore i/d fault status and address register */
- arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr);
- arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr);
- arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far);
-
- uint32_t cache_dbg_ctrl;
-
- /* read-modify-write CP15 cache debug control register
- * to reenable I/D-cache linefills and disable WT */
- arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
- cache_dbg_ctrl &= ~0x7;
- arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
-}
-
-static const char arm926_not[] = "target is not an ARM926";
-
-static int arm926ejs_verify_pointer(struct command_context *cmd_ctx,
- struct arm926ejs_common *arm926)
-{
- if (arm926->common_magic != ARM926EJS_COMMON_MAGIC) {
- command_print(cmd_ctx, arm926_not);
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-/** Logs summary of ARM926 state for a halted target. */
-int arm926ejs_arch_state(struct target *target)
-{
- static const char *state[] = {
- "disabled", "enabled"
- };
-
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC) {
- LOG_ERROR("BUG: %s", arm926_not);
- return ERROR_TARGET_INVALID;
- }
-
- arm_arch_state(target);
- LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
- state[arm926ejs->armv4_5_mmu.mmu_enabled],
- state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
- state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
-
- return ERROR_OK;
-}
-
-int arm926ejs_soft_reset_halt(struct target *target)
-{
- int retval = ERROR_OK;
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- int timeout;
- while (!(timeout = ((timeval_ms()-then) > 1000))) {
- if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) {
- embeddedice_read_reg(dbg_stat);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- } else
- break;
- if (debug_level >= 1) {
- /* do not eat all CPU, time out after 1 se*/
- alive_sleep(100);
- } else
- keep_alive();
- }
- if (timeout) {
- LOG_ERROR("Failed to halt CPU after 1 sec");
- return ERROR_TARGET_TIMEOUT;
- }
-
- target->state = TARGET_HALTED;
-
- /* SVC, ARM state, IRQ and FIQ disabled */
- uint32_t cpsr;
-
- cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
- cpsr &= ~0xff;
- cpsr |= 0xd3;
- arm_set_cpsr(arm, cpsr);
- arm->cpsr->dirty = 1;
-
- /* start fetching from 0x0 */
- buf_set_u32(arm->pc->value, 0, 32, 0x0);
- arm->pc->dirty = 1;
- arm->pc->valid = 1;
-
- retval = arm926ejs_disable_mmu_caches(target, 1, 1, 1);
- if (retval != ERROR_OK)
- return retval;
- arm926ejs->armv4_5_mmu.mmu_enabled = 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
- arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
- return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-}
-
-/** Writes a buffer, in the specified word size, with current MMU settings. */
-int arm926ejs_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- int retval;
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- /* FIX!!!! this should be cleaned up and made much more general. The
- * plan is to write up and test on arm926ejs specifically and
- * then generalize and clean up afterwards.
- *
- *
- * Also it should be moved to the callbacks that handle breakpoints
- * specifically and not the generic memory write fn's. See XScale code.
- **/
- if (arm926ejs->armv4_5_mmu.mmu_enabled && (count == 1) && ((size == 2) || (size == 4))) {
- /* special case the handling of single word writes to bypass MMU
- * to allow implementation of breakpoints in memory marked read only
- * by MMU */
- if (arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) {
- /* flush and invalidate data cache
- *
- * MCR p15,0,p,c7,c10,1 - clean cache line using virtual address
- *
- */
- retval = arm926ejs->write_cp15(target, 0, 1, 7, 10, address&~0x3);
- if (retval != ERROR_OK)
- return retval;
- }
-
- uint32_t pa;
- retval = target->type->virt2phys(target, address, &pa);
- if (retval != ERROR_OK)
- return retval;
-
- /* write directly to physical memory bypassing any read only MMU bits, etc. */
- retval = armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu, pa, size, count, buffer);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = arm7_9_write_memory(target, address, size, count, buffer);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* If ICache is enabled, we have to invalidate affected ICache lines
- * the DCache is forced to write-through, so we don't have to clean it here
- */
- if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled) {
- if (count <= 1) {
- /* invalidate ICache single entry with MVA */
- arm926ejs->write_cp15(target, 0, 1, 7, 5, address);
- } else {
- /* invalidate ICache */
- arm926ejs->write_cp15(target, 0, 0, 7, 5, address);
- }
- }
-
- return retval;
-}
-
-static int arm926ejs_write_phys_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- return armv4_5_mmu_write_physical(target, &arm926ejs->armv4_5_mmu,
- address, size, count, buffer);
-}
-
-static int arm926ejs_read_phys_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- return armv4_5_mmu_read_physical(target, &arm926ejs->armv4_5_mmu,
- address, size, count, buffer);
-}
-
-int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm926ejs,
- struct jtag_tap *tap)
-{
- struct arm7_9_common *arm7_9 = &arm926ejs->arm7_9_common;
-
- arm7_9->arm.mrc = arm926ejs_mrc;
- arm7_9->arm.mcr = arm926ejs_mcr;
-
- /* initialize arm7/arm9 specific info (including armv4_5) */
- arm9tdmi_init_arch_info(target, arm7_9, tap);
-
- arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;
-
- arm7_9->post_debug_entry = arm926ejs_post_debug_entry;
- arm7_9->pre_restore_context = arm926ejs_pre_restore_context;
- arm7_9->write_memory = arm926ejs_write_memory;
-
- arm926ejs->read_cp15 = arm926ejs_cp15_read;
- arm926ejs->write_cp15 = arm926ejs_cp15_write;
- arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;
- arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;
- arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;
- arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;
- arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;
- arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;
- arm926ejs->armv4_5_mmu.has_tiny_pages = 1;
- arm926ejs->armv4_5_mmu.mmu_enabled = 0;
-
- arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;
-
- /* The ARM926EJ-S implements the ARMv5TE architecture which
- * has the BKPT instruction, so we don't have to use a watchpoint comparator
- */
- arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
- arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
-
- return ERROR_OK;
-}
-
-static int arm926ejs_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
-
- /* ARM9EJ-S core always reports 0x1 in Capture-IR */
- target->tap->ir_capture_mask = 0x0f;
-
- return arm926ejs_init_arch_info(target, arm926ejs, target->tap);
-}
-
-COMMAND_HANDLER(arm926ejs_handle_cache_info_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- retval = arm926ejs_verify_pointer(CMD_CTX, arm926ejs);
- if (retval != ERROR_OK)
- return retval;
-
- return armv4_5_handle_cache_info_command(CMD_CTX, &arm926ejs->armv4_5_mmu.armv4_5_cache);
-}
-
-static int arm926ejs_virt2phys(struct target *target, uint32_t virtual, uint32_t *physical)
-{
- uint32_t cb;
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- uint32_t ret;
- int retval = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu,
- virtual, &cb, &ret);
- if (retval != ERROR_OK)
- return retval;
- *physical = ret;
- return ERROR_OK;
-}
-
-static int arm926ejs_mmu(struct target *target, int *enabled)
-{
- struct arm926ejs_common *arm926ejs = target_to_arm926(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_INVALID;
- }
- *enabled = arm926ejs->armv4_5_mmu.mmu_enabled;
- return ERROR_OK;
-}
-
-static const struct command_registration arm926ejs_exec_command_handlers[] = {
- {
- .name = "cache_info",
- .handler = arm926ejs_handle_cache_info_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "display information about target caches",
-
- },
- COMMAND_REGISTRATION_DONE
-};
-const struct command_registration arm926ejs_command_handlers[] = {
- {
- .chain = arm9tdmi_command_handlers,
- },
- {
- .name = "arm926ejs",
- .mode = COMMAND_ANY,
- .help = "arm926ejs command group",
- .usage = "",
- .chain = arm926ejs_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for ARM926 targets. */
-struct target_type arm926ejs_target = {
- .name = "arm926ejs",
-
- .poll = arm7_9_poll,
- .arch_state = arm926ejs_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm926ejs_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm7_9_read_memory,
- .write_memory = arm7_9_write_memory_opt,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm926ejs_command_handlers,
- .target_create = arm926ejs_target_create,
- .init_target = arm9tdmi_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
- .virt2phys = arm926ejs_virt2phys,
- .mmu = arm926ejs_mmu,
-
- .read_phys_memory = arm926ejs_read_phys_memory,
- .write_phys_memory = arm926ejs_write_phys_memory,
-};
diff --git a/src/target/arm926ejs.h b/src/target/arm926ejs.h
deleted file mode 100644
index 02b4ef8..0000000
--- a/src/target/arm926ejs.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM926EJS_H
-#define OPENOCD_TARGET_ARM926EJS_H
-
-#include "arm9tdmi.h"
-#include "armv4_5_mmu.h"
-
-#define ARM926EJS_COMMON_MAGIC 0xa926a926
-
-struct arm926ejs_common {
- struct arm7_9_common arm7_9_common;
- uint32_t common_magic;
- struct armv4_5_mmu_common armv4_5_mmu;
- int (*read_cp15)(struct target *target, uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm, uint32_t *value);
- int (*write_cp15)(struct target *target, uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm, uint32_t value);
- uint32_t cp15_control_reg;
- uint32_t d_fsr;
- uint32_t i_fsr;
- uint32_t d_far;
-};
-
-static inline struct arm926ejs_common *target_to_arm926(struct target *target)
-{
- return container_of(target->arch_info, struct arm926ejs_common, arm7_9_common.arm);
-}
-
-int arm926ejs_init_arch_info(struct target *target,
- struct arm926ejs_common *arm926ejs, struct jtag_tap *tap);
-int arm926ejs_arch_state(struct target *target);
-int arm926ejs_write_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-int arm926ejs_soft_reset_halt(struct target *target);
-
-extern const struct command_registration arm926ejs_command_handlers[];
-
-#endif /* OPENOCD_TARGET_ARM926EJS_H */
diff --git a/src/target/arm946e.c b/src/target/arm946e.c
deleted file mode 100644
index 5ee31cc..0000000
--- a/src/target/arm946e.c
+++ /dev/null
@@ -1,784 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2010 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm946e.h"
-#include "target_type.h"
-#include "arm_opcodes.h"
-
-#include "breakpoints.h"
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-#define NB_CACHE_WAYS 4
-
-#define CP15_CTL 0x02
-#define CP15_CTL_DCACHE (1<<2)
-#define CP15_CTL_ICACHE (1<<12)
-
-/**
- * flag to give info about cache manipulation during debug :
- * "0" - cache lines are invalidated "on the fly", for affected addresses.
- * This is prefered from performance point of view.
- * "1" - cache is invalidated and switched off on debug_entry, and switched back on on restore.
- * It is kept off during debugging.
- */
-static uint8_t arm946e_preserve_cache;
-
-int arm946e_post_debug_entry(struct target *target);
-void arm946e_pre_restore_context(struct target *target);
-static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value);
-
-int arm946e_init_arch_info(struct target *target,
- struct arm946e_common *arm946e,
- struct jtag_tap *tap)
-{
- struct arm7_9_common *arm7_9 = &arm946e->arm7_9_common;
-
- /* initialize arm7/arm9 specific info (including armv4_5) */
- arm9tdmi_init_arch_info(target, arm7_9, tap);
-
- arm946e->common_magic = ARM946E_COMMON_MAGIC;
-
- /**
- * The ARM946E-S implements the ARMv5TE architecture which
- * has the BKPT instruction, so we don't have to use a watchpoint comparator
- */
- arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
- arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
-
-
- arm7_9->post_debug_entry = arm946e_post_debug_entry;
- arm7_9->pre_restore_context = arm946e_pre_restore_context;
-
- /**
- * disabling linefills leads to lockups, so keep them enabled for now
- * this doesn't affect correctness, but might affect timing issues, if
- * important data is evicted from the cache during the debug session
- */
- arm946e_preserve_cache = 0;
-
- /* override hw single-step capability from ARM9TDMI */
- /* arm7_9->has_single_step = 1; */
-
- return ERROR_OK;
-}
-
-static int arm946e_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm946e_common *arm946e = calloc(1, sizeof(struct arm946e_common));
-
- arm946e_init_arch_info(target, arm946e, target->tap);
-
- return ERROR_OK;
-}
-
-static int arm946e_verify_pointer(struct command_context *cmd_ctx,
- struct arm946e_common *arm946e)
-{
- if (arm946e->common_magic != ARM946E_COMMON_MAGIC) {
- command_print(cmd_ctx, "target is not an ARM946");
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-/*
- * Update cp15_control_reg, saved on debug_entry.
- */
-static void arm946e_update_cp15_caches(struct target *target, uint32_t value)
-{
- struct arm946e_common *arm946e = target_to_arm946(target);
- arm946e->cp15_control_reg = (arm946e->cp15_control_reg & ~(CP15_CTL_DCACHE|CP15_CTL_ICACHE))
- | (value & (CP15_CTL_DCACHE|CP15_CTL_ICACHE));
-}
-
-/*
- * REVISIT: The "read_cp15" and "write_cp15" commands could hook up
- * to eventual mrc() and mcr() routines ... the reg_addr values being
- * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
- * See section 7.3 of the ARM946E-S TRM.
- */
-static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct scan_field fields[3];
- uint8_t reg_addr_buf = reg_addr & 0x3f;
- uint8_t nr_w_buf = 0;
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- /* REVISIT: table 7-2 shows that bits 31-31 need to be
- * specified for accessing BIST registers ...
- */
- fields[0].out_value = NULL;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 6;
- fields[1].out_value = &reg_addr_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- fields[2].out_value = &nr_w_buf;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
- fields[0].in_value = (uint8_t *)value;
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
- jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
-#endif
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct scan_field fields[3];
- uint8_t reg_addr_buf = reg_addr & 0x3f;
- uint8_t nr_w_buf = 1;
- uint8_t value_buf[4];
-
- buf_set_u32(value_buf, 0, 32, value);
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = value_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 6;
- fields[1].out_value = &reg_addr_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- fields[2].out_value = &nr_w_buf;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
-#endif
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-#define GET_ICACHE_SIZE 6
-#define GET_DCACHE_SIZE 18
-
-/*
- * \param target struct target pointer
- * \param idsel select GET_ICACHE_SIZE or GET_DCACHE_SIZE
- * \returns cache size, given in bytes
- */
-static uint32_t arm946e_cp15_get_csize(struct target *target, int idsel)
-{
- struct arm946e_common *arm946e = target_to_arm946(target);
- uint32_t csize = arm946e->cp15_cache_info;
- if (csize == 0) {
- if (arm946e_read_cp15(target, 0x01, &csize) == ERROR_OK)
- arm946e->cp15_cache_info = csize;
- }
- if (csize & (1<<(idsel-4))) /* cache absent */
- return 0;
- csize = (csize >> idsel) & 0x0F;
- return csize ? 1 << (12 + (csize-3)) : 0;
-}
-
-uint32_t arm946e_invalidate_whole_dcache(struct target *target)
-{
- uint32_t csize = arm946e_cp15_get_csize(target, GET_DCACHE_SIZE);
- if (csize == 0)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- /* One line (index) is 32 bytes (8 words) long, 4-way assoc
- * ARM DDI 0201D, Section 3.3.5
- */
- int nb_idx = (csize / (4*8*NB_CACHE_WAYS)); /* gives nb of lines (indexes) in the cache */
-
- /* Loop for all segmentde (i.e. ways) */
- uint32_t seg;
- for (seg = 0; seg < NB_CACHE_WAYS; seg++) {
- /* Loop for all indexes */
- int idx;
- for (idx = 0; idx < nb_idx; idx++) {
- /* Form and write cp15 index (segment + line idx) */
- uint32_t cp15_idx = seg << 30 | idx << 5;
- int retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR writing index");
- return retval;
- }
-
- /* Read dtag */
- uint32_t dtag;
- arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
-
- /* Check cache line VALID bit */
- if (!(dtag >> 4 & 0x1))
- continue;
-
- /* Clean data cache line */
- retval = arm946e_write_cp15(target, 0x35, 0x1);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR cleaning cache line");
- return retval;
- }
-
- /* Flush data cache line */
- retval = arm946e_write_cp15(target, 0x1a, 0x1);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR flushing cache line");
- return retval;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-uint32_t arm946e_invalidate_whole_icache(struct target *target)
-{
- /* Check cache presence before flushing - avoid undefined behavior */
- uint32_t csize = arm946e_cp15_get_csize(target, GET_ICACHE_SIZE);
- if (csize == 0)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- LOG_DEBUG("FLUSHING I$");
- /**
- * Invalidate (flush) I$
- * mcr 15, 0, r0, cr7, cr5, {0}
- */
- int retval = arm946e_write_cp15(target, 0x0f, 0x1);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR flushing I$");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-int arm946e_post_debug_entry(struct target *target)
-{
- uint32_t ctr_reg = 0x0;
- uint32_t retval = ERROR_OK;
- struct arm946e_common *arm946e = target_to_arm946(target);
-
- /* See if CACHES are enabled, and save that info
- * in the context bits, so that arm946e_pre_restore_context() can use them */
- arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg);
-
- /* Save control reg in the context */
- arm946e->cp15_control_reg = ctr_reg;
-
- if (arm946e_preserve_cache) {
- if (ctr_reg & CP15_CTL_DCACHE) {
- /* Clean and flush D$ */
- arm946e_invalidate_whole_dcache(target);
-
- /* Disable D$ */
- ctr_reg &= ~CP15_CTL_DCACHE;
- }
-
- if (ctr_reg & CP15_CTL_ICACHE) {
- /* Flush I$ */
- arm946e_invalidate_whole_icache(target);
-
- /* Disable I$ */
- ctr_reg &= ~CP15_CTL_ICACHE;
- }
-
- /* Write the new configuration */
- retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR disabling cache");
- return retval;
- }
- } /* if preserve_cache */
-
- return ERROR_OK;
-}
-
-void arm946e_pre_restore_context(struct target *target)
-{
- uint32_t ctr_reg = 0x0;
- uint32_t retval;
-
- if (arm946e_preserve_cache) {
- struct arm946e_common *arm946e = target_to_arm946(target);
- /* Get the contents of the CTR reg */
- arm946e_read_cp15(target, CP15_CTL, (uint32_t *) &ctr_reg);
-
- /**
- * Read-modify-write CP15 control
- * to reenable I/D-cache operation
- * NOTE: It is not possible to disable cache by CP15.
- * if arm946e_preserve_cache debugging flag enabled.
- */
- ctr_reg |= arm946e->cp15_control_reg & (CP15_CTL_DCACHE|CP15_CTL_ICACHE);
-
- /* Write the new configuration */
- retval = arm946e_write_cp15(target, CP15_CTL, ctr_reg);
- if (retval != ERROR_OK)
- LOG_DEBUG("ERROR enabling cache");
- } /* if preserve_cache */
-}
-
-uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
- uint32_t size, uint32_t count)
-{
- uint32_t cur_addr = 0x0;
- uint32_t cp15_idx, set, way, dtag;
- uint32_t i = 0;
- int retval;
-
- for (i = 0; i < count*size; i++) {
- cur_addr = address + i;
-
-
- set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
-
- for (way = 0; way < NB_CACHE_WAYS; way++) {
- /**
- * Find if the affected address is kept in the cache.
- * Because JTAG Scan Chain 15 offers limited approach,
- * we have to loop through all cache ways (segments) and
- * read cache tags, then compare them with with address.
- */
-
- /* Form and write cp15 index (segment + line idx) */
- cp15_idx = way << 30 | set << 5;
- retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR writing index");
- return retval;
- }
-
- /* Read dtag */
- arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
-
- /* Check cache line VALID bit */
- if (!(dtag >> 4 & 0x1))
- continue;
-
- /* If line is valid and corresponds to affected address - invalidate it */
- if (dtag >> 5 == cur_addr >> 5) {
- /* Clean data cache line */
- retval = arm946e_write_cp15(target, 0x35, 0x1);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR cleaning cache line");
- return retval;
- }
-
- /* Flush data cache line */
- retval = arm946e_write_cp15(target, 0x1c, 0x1);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR flushing cache line");
- return retval;
- }
-
- break;
- }
- } /* loop through all 4 ways */
- } /* loop through all addresses */
-
- return ERROR_OK;
-}
-
-uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
- uint32_t size, uint32_t count)
-{
- uint32_t cur_addr = 0x0;
- uint32_t cp15_idx, set, way, itag;
- uint32_t i = 0;
- int retval;
-
- for (i = 0; i < count*size; i++) {
- cur_addr = address + i;
-
- set = (cur_addr >> 5) & 0xff; /* set field is 8 bits long */
-
- for (way = 0; way < NB_CACHE_WAYS; way++) {
- /* Form and write cp15 index (segment + line idx) */
- cp15_idx = way << 30 | set << 5;
- retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR writing index");
- return retval;
- }
-
- /* Read itag */
- arm946e_read_cp15(target, 0x17, (uint32_t *) &itag);
-
- /* Check cache line VALID bit */
- if (!(itag >> 4 & 0x1))
- continue;
-
- /* If line is valid and corresponds to affected address - invalidate it */
- if (itag >> 5 == cur_addr >> 5) {
- /* Flush I$ line */
- retval = arm946e_write_cp15(target, 0x1d, 0x0);
- if (retval != ERROR_OK) {
- LOG_DEBUG("ERROR flushing cache line");
- return retval;
- }
-
- break;
- }
- } /* way loop */
- } /* addr loop */
-
- return ERROR_OK;
-}
-
-/** Writes a buffer, in the specified word size, with current MMU settings. */
-int arm946e_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- int retval;
-
- LOG_DEBUG("-");
-
- struct arm946e_common *arm946e = target_to_arm946(target);
- /* Invalidate D$ if it is ON */
- if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_DCACHE))
- arm946e_invalidate_dcache(target, address, size, count);
-
- /**
- * Write memory
- */
- retval = arm7_9_write_memory_opt(target, address, size, count, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- /* *
- * Invalidate I$ if it is ON.
- *
- * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
- * because arm7_9_write_memory() has seen non-valid bit in D$
- * and wrote data into physical RAM (without touching or allocating the cache line).
- * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
- * policy for both I$ and D$ (Chapter 3.2 and 3.3)
- *
- * Explanation :
- * "ARM system developer's guide: designing and optimizing system software" by
- * Andrew N. Sloss, Dominic Symes and Chris Wright,
- * Chapter 12.3.3 Allocating Policy on a Cache Miss :
- * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
- * If the victim cache line contains valid data, then it is written to main memory before the cache line
- * is filled with new data.
- * Under this strategy, a write of new data to memory does not update the contents of the cache memory
- * unless a cache line was allocated on a previous read from main memory.
- * If the cache line contains valid data, then the write updates the cache and may update the main memory if
- * the cache write policy is write-through.
- * If the data is not in the cache, the controller writes to main memory only.
- */
- if (!arm946e_preserve_cache && (arm946e->cp15_control_reg & CP15_CTL_ICACHE))
- arm946e_invalidate_icache(target, address, size, count);
-
- return ERROR_OK;
-
-}
-
-int arm946e_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- int retval;
-
- LOG_DEBUG("-");
-
- retval = arm7_9_read_memory(target, address, size, count, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int jim_arm946e_cp15(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- /* one or two arguments, access a single register (write if second argument is given) */
- if (argc < 2 || argc > 3) {
- Jim_WrongNumArgs(interp, 1, argv, "addr [value]");
- return JIM_ERR;
- }
-
- struct command_context *cmd_ctx = current_command_context(interp);
- assert(cmd_ctx != NULL);
-
- struct target *target = get_current_target(cmd_ctx);
- if (target == NULL) {
- LOG_ERROR("arm946e: no current target");
- return JIM_ERR;
- }
-
- struct arm946e_common *arm946e = target_to_arm946(target);
- int retval = arm946e_verify_pointer(cmd_ctx, arm946e);
- if (retval != ERROR_OK)
- return JIM_ERR;
-
- if (target->state != TARGET_HALTED) {
- command_print(cmd_ctx, "target %s must be stopped for \"cp15\" command", target_name(target));
- return JIM_ERR;
- }
-
- long l;
- uint32_t address;
- retval = Jim_GetLong(interp, argv[1], &l);
- address = l;
- if (JIM_OK != retval)
- return retval;
-
- if (argc == 2) {
- uint32_t value;
- retval = arm946e_read_cp15(target, address, &value);
- if (retval != ERROR_OK) {
- command_print(cmd_ctx, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address);
- return JIM_ERR;
- }
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return JIM_ERR;
- char buf[20];
- sprintf(buf, "0x%08" PRIx32, value);
- /* Return value in hex format */
- Jim_SetResultString(interp, buf, -1);
- } else if (argc == 3) {
- uint32_t value;
- retval = Jim_GetLong(interp, argv[2], &l);
- value = l;
- if (JIM_OK != retval)
- return retval;
- retval = arm946e_write_cp15(target, address, value);
- if (retval != ERROR_OK) {
- command_print(cmd_ctx, "%s cp15 reg %" PRIi32 " access failed", target_name(target), address);
- return JIM_ERR;
- }
- if (address == CP15_CTL)
- arm946e_update_cp15_caches(target, value);
- }
-
- return JIM_OK;
-}
-
-COMMAND_HANDLER(arm946e_handle_idcache)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct arm946e_common *arm946e = target_to_arm946(target);
-
- retval = arm946e_verify_pointer(CMD_CTX, arm946e);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_TARGET_NOT_HALTED;
- }
-
- bool icache = (strcmp(CMD_NAME, "icache") == 0);
- uint32_t csize = arm946e_cp15_get_csize(target, icache ? GET_ICACHE_SIZE : GET_DCACHE_SIZE) / 1024;
- if (CMD_ARGC == 0) {
- bool bena = ((arm946e->cp15_control_reg & (icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE)) != 0)
- && (arm946e->cp15_control_reg & 0x1);
- if (csize == 0)
- command_print(CMD_CTX, "%s-cache absent", icache ? "I" : "D");
- else
- command_print(CMD_CTX, "%s-cache size: %" PRIu32 "K, %s",
- icache ? "I" : "D", csize, bena ? "enabled" : "disabled");
- return ERROR_OK;
- }
-
- bool flush = false;
- bool enable = false;
- retval = command_parse_bool_arg(CMD_ARGV[0], &enable);
- if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
- if (strcmp(CMD_ARGV[0], "flush") == 0) {
- flush = true;
- retval = ERROR_OK;
- } else
- return retval;
- }
-
- /* Do not invalidate or change state, if cache is absent */
- if (csize == 0) {
- command_print(CMD_CTX, "%s-cache absent, '%s' operation undefined", icache ? "I" : "D", CMD_ARGV[0]);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* NOTE: flushing entire cache will not preserve lock-down cache regions */
- if (icache) {
- if ((arm946e->cp15_control_reg & CP15_CTL_ICACHE) && !enable)
- retval = arm946e_invalidate_whole_icache(target);
- } else {
- if ((arm946e->cp15_control_reg & CP15_CTL_DCACHE) && !enable)
- retval = arm946e_invalidate_whole_dcache(target);
- }
-
- if (retval != ERROR_OK || flush)
- return retval;
-
- uint32_t value;
- retval = arm946e_read_cp15(target, CP15_CTL, &value);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t vnew = value;
- uint32_t cmask = icache ? CP15_CTL_ICACHE : CP15_CTL_DCACHE;
- if (enable) {
- if ((value & 0x1) == 0)
- LOG_WARNING("arm946e: MPU must be enabled for cache to operate");
- vnew |= cmask;
- } else
- vnew &= ~cmask;
-
- if (vnew == value)
- return ERROR_OK;
-
- retval = arm946e_write_cp15(target, CP15_CTL, vnew);
- if (retval != ERROR_OK)
- return retval;
-
- arm946e_update_cp15_caches(target, vnew);
- return ERROR_OK;
-}
-
-static const struct command_registration arm946e_exec_command_handlers[] = {
- {
- .name = "cp15",
- .jim_handler = jim_arm946e_cp15,
- .mode = COMMAND_EXEC,
- .usage = "regnum [value]",
- .help = "read/modify cp15 register",
- },
- {
- .name = "icache",
- .handler = arm946e_handle_idcache,
- .mode = COMMAND_EXEC,
- .usage = "['enable'|'disable'|'flush']",
- .help = "I-cache info and operations",
- },
- {
- .name = "dcache",
- .handler = arm946e_handle_idcache,
- .mode = COMMAND_EXEC,
- .usage = "['enable'|'disable'|'flush']",
- .help = "D-cache info and operations",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration arm946e_command_handlers[] = {
- {
- .chain = arm9tdmi_command_handlers,
- },
- {
- .name = "arm946e",
- .mode = COMMAND_ANY,
- .help = "arm946e command group",
- .usage = "",
- .chain = arm946e_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for ARM946 targets. */
-struct target_type arm946e_target = {
- .name = "arm946e",
-
- .poll = arm7_9_poll,
- .arch_state = arm_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm7_9_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- /* .read_memory = arm7_9_read_memory, */
- /* .write_memory = arm7_9_write_memory, */
- .read_memory = arm946e_read_memory,
- .write_memory = arm946e_write_memory,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- /* .add_breakpoint = arm946e_add_breakpoint, */
- /* .remove_breakpoint = arm946e_remove_breakpoint, */
-
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm946e_command_handlers,
- .target_create = arm946e_target_create,
- .init_target = arm9tdmi_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
-};
diff --git a/src/target/arm946e.h b/src/target/arm946e.h
deleted file mode 100644
index ee1ef32..0000000
--- a/src/target/arm946e.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2010 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM946E_H
-#define OPENOCD_TARGET_ARM946E_H
-
-#include "arm9tdmi.h"
-
-#define ARM946E_COMMON_MAGIC 0x20f920f9
-
-struct arm946e_common {
- struct arm7_9_common arm7_9_common;
- int common_magic;
- uint32_t cp15_control_reg;
- uint32_t cp15_cache_info;
-};
-
-static inline struct arm946e_common *target_to_arm946(struct target *target)
-{
- return container_of(target->arch_info, struct arm946e_common,
- arm7_9_common.arm);
-}
-
-int arm946e_init_arch_info(struct target *target,
- struct arm946e_common *arm946e, struct jtag_tap *tap);
-int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value);
-
-extern const struct command_registration arm946e_command_handlers[];
-
-#endif /* OPENOCD_TARGET_ARM946E_H */
diff --git a/src/target/arm966e.c b/src/target/arm966e.c
deleted file mode 100644
index 0429c54..0000000
--- a/src/target/arm966e.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm966e.h"
-#include "target_type.h"
-#include "arm_opcodes.h"
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-int arm966e_init_arch_info(struct target *target, struct arm966e_common *arm966e, struct jtag_tap *tap)
-{
- struct arm7_9_common *arm7_9 = &arm966e->arm7_9_common;
-
- /* initialize arm7/arm9 specific info (including armv4_5) */
- arm9tdmi_init_arch_info(target, arm7_9, tap);
-
- arm966e->common_magic = ARM966E_COMMON_MAGIC;
-
- /* The ARM966E-S implements the ARMv5TE architecture which
- * has the BKPT instruction, so we don't have to use a watchpoint comparator
- */
- arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
- arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
-
- return ERROR_OK;
-}
-
-static int arm966e_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
-
- return arm966e_init_arch_info(target, arm966e, target->tap);
-}
-
-static int arm966e_verify_pointer(struct command_context *cmd_ctx,
- struct arm966e_common *arm966e)
-{
- if (arm966e->common_magic != ARM966E_COMMON_MAGIC) {
- command_print(cmd_ctx, "target is not an ARM966");
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-/*
- * REVISIT: The "read_cp15" and "write_cp15" commands could hook up
- * to eventual mrc() and mcr() routines ... the reg_addr values being
- * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
- * See section 7.3 of the ARM966E-S TRM.
- */
-
-static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *value)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct scan_field fields[3];
- uint8_t reg_addr_buf = reg_addr & 0x3f;
- uint8_t nr_w_buf = 0;
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- /* REVISIT: table 7-2 shows that bits 31-31 need to be
- * specified for accessing BIST registers ...
- */
- fields[0].out_value = NULL;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 6;
- fields[1].out_value = &reg_addr_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- fields[2].out_value = &nr_w_buf;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
- fields[1].in_value = (uint8_t *)value;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
- jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
-
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
-#endif
-
- return ERROR_OK;
-}
-
-/* EXPORTED to str9x (flash) */
-int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct scan_field fields[3];
- uint8_t reg_addr_buf = reg_addr & 0x3f;
- uint8_t nr_w_buf = 1;
- uint8_t value_buf[4];
-
- buf_set_u32(value_buf, 0, 32, value);
-
- retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = value_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 6;
- fields[1].out_value = &reg_addr_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- fields[2].out_value = &nr_w_buf;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
-#endif
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(arm966e_handle_cp15_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct arm966e_common *arm966e = target_to_arm966(target);
-
- retval = arm966e_verify_pointer(CMD_CTX, arm966e);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- /* one or more argument, access a single register (write if second argument is given */
- if (CMD_ARGC >= 1) {
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
-
- if (CMD_ARGC == 1) {
- uint32_t value;
- retval = arm966e_read_cp15(target, address, &value);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access reg %" PRIi32,
- address);
- return ERROR_OK;
- }
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
- address, value);
- } else if (CMD_ARGC == 2) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
- retval = arm966e_write_cp15(target, address, value);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access reg %" PRIi32,
- address);
- return ERROR_OK;
- }
- command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
- address, value);
- }
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration arm966e_exec_command_handlers[] = {
- {
- .name = "cp15",
- .handler = arm966e_handle_cp15_command,
- .mode = COMMAND_EXEC,
- .usage = "regnum [value]",
- .help = "display/modify cp15 register",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration arm966e_command_handlers[] = {
- {
- .chain = arm9tdmi_command_handlers,
- },
- {
- .name = "arm966e",
- .mode = COMMAND_ANY,
- .help = "arm966e command group",
- .usage = "",
- .chain = arm966e_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for ARM966 targets. */
-struct target_type arm966e_target = {
- .name = "arm966e",
-
- .poll = arm7_9_poll,
- .arch_state = arm_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm7_9_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm7_9_read_memory,
- .write_memory = arm7_9_write_memory_opt,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm966e_command_handlers,
- .target_create = arm966e_target_create,
- .init_target = arm9tdmi_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
-};
diff --git a/src/target/arm966e.h b/src/target/arm966e.h
deleted file mode 100644
index aa2e9bb..0000000
--- a/src/target/arm966e.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM966E_H
-#define OPENOCD_TARGET_ARM966E_H
-
-#include "arm9tdmi.h"
-
-#define ARM966E_COMMON_MAGIC 0x20f920f9
-
-struct arm966e_common {
- struct arm7_9_common arm7_9_common;
- int common_magic;
- uint32_t cp15_control_reg;
-};
-
-static inline struct arm966e_common *
-target_to_arm966(struct target *target)
-{
- return container_of(target->arch_info, struct arm966e_common,
- arm7_9_common.arm);
-}
-
-int arm966e_init_arch_info(struct target *target,
- struct arm966e_common *arm966e, struct jtag_tap *tap);
-int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value);
-
-extern const struct command_registration arm966e_command_handlers[];
-
-#endif /* OPENOCD_TARGET_ARM966E_H */
diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c
deleted file mode 100644
index eed965a..0000000
--- a/src/target/arm9tdmi.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by Hongtao Zheng *
- * hontor@126.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm9tdmi.h"
-#include "target_type.h"
-#include "register.h"
-#include "arm_opcodes.h"
-
-/*
- * NOTE: this holds code that's used with multiple ARM9 processors:
- * - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores
- * - ARM9E-S (ARMv5TE) ... in ARM946, ARM966, and ARM968 cores
- * - ARM9EJS (ARMv5TEJ) ... in ARM926 core
- *
- * In short, the file name is a misnomer ... it is NOT specific to
- * that first generation ARM9 processor, or cores using it.
- */
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-enum arm9tdmi_vector_bit {
- ARM9TDMI_RESET_VECTOR = 0x01,
- ARM9TDMI_UNDEF_VECTOR = 0x02,
- ARM9TDMI_SWI_VECTOR = 0x04,
- ARM9TDMI_PABT_VECTOR = 0x08,
- ARM9TDMI_DABT_VECTOR = 0x10,
- /* BIT(5) reserved -- must be zero */
- ARM9TDMI_IRQ_VECTOR = 0x40,
- ARM9TDMI_FIQ_VECTOR = 0x80,
-};
-
-static const struct arm9tdmi_vector {
- const char *name;
- uint32_t value;
-} arm9tdmi_vectors[] = {
- {"reset", ARM9TDMI_RESET_VECTOR},
- {"undef", ARM9TDMI_UNDEF_VECTOR},
- {"swi", ARM9TDMI_SWI_VECTOR},
- {"pabt", ARM9TDMI_PABT_VECTOR},
- {"dabt", ARM9TDMI_DABT_VECTOR},
- {"irq", ARM9TDMI_IRQ_VECTOR},
- {"fiq", ARM9TDMI_FIQ_VECTOR},
- {0, 0},
-};
-
-int arm9tdmi_examine_debug_reason(struct target *target)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- /* only check the debug reason if we don't know it already */
- if ((target->debug_reason != DBG_REASON_DBGRQ)
- && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
- struct scan_field fields[3];
- uint8_t databus[4];
- uint8_t instructionbus[4];
- uint8_t debug_reason;
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = databus;
-
- fields[1].num_bits = 3;
- fields[1].out_value = NULL;
- fields[1].in_value = &debug_reason;
-
- fields[2].num_bits = 32;
- fields[2].out_value = NULL;
- fields[2].in_value = instructionbus;
-
- retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(arm7_9->jtag_info.tap, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].in_value = NULL;
- fields[0].out_value = databus;
- fields[1].in_value = NULL;
- fields[1].out_value = &debug_reason;
- fields[2].in_value = NULL;
- fields[2].out_value = instructionbus;
-
- jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE);
-
- if (debug_reason & 0x4)
- if (debug_reason & 0x2)
- target->debug_reason = DBG_REASON_WPTANDBKPT;
- else
- target->debug_reason = DBG_REASON_WATCHPOINT;
- else
- target->debug_reason = DBG_REASON_BREAKPOINT;
- }
-
- return ERROR_OK;
-}
-
-/* put an instruction in the ARM9TDMI pipeline or write the data bus,
- * and optionally read data
- */
-int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr,
- uint32_t out, uint32_t *in, int sysspeed)
-{
- int retval = ERROR_OK;
- struct scan_field fields[3];
- uint8_t out_buf[4];
- uint8_t instr_buf[4];
- uint8_t sysspeed_buf = 0x0;
-
- /* prepare buffer */
- buf_set_u32(out_buf, 0, 32, out);
-
- buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
-
- if (sysspeed)
- buf_set_u32(&sysspeed_buf, 2, 1, 1);
-
- retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = out_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 3;
- fields[1].out_value = &sysspeed_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 32;
- fields[2].out_value = instr_buf;
- fields[2].in_value = NULL;
-
- if (in) {
- fields[0].in_value = (uint8_t *)in;
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
-
- jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
- } else
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
-
- jtag_add_runtest(0, TAP_DRPAUSE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- {
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (in)
- LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
- else
- LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
- }
-#endif
-
- return ERROR_OK;
-}
-
-/* just read data (instruction and data-out = don't care) */
-int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
-{
- int retval = ERROR_OK;
- struct scan_field fields[3];
-
- retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = (uint8_t *)in;
-
- fields[1].num_bits = 3;
- fields[1].out_value = NULL;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 32;
- fields[2].out_value = NULL;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
-
- jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
-
- jtag_add_runtest(0, TAP_DRPAUSE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- {
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (in)
- LOG_DEBUG("in: 0x%8.8x", *in);
- else
- LOG_ERROR("BUG: called with in == NULL");
- }
-#endif
-
- return ERROR_OK;
-}
-
-/* clock the target, and read the databus
- * the *in pointer points to a buffer where elements of 'size' bytes
- * are stored in big (be == 1) or little (be == 0) endianness
- */
-int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
- void *in, int size, int be)
-{
- int retval = ERROR_OK;
- struct scan_field fields[2];
-
- retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- if (size == 4) {
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = in;
-
- fields[1].num_bits = 3 + 32;
- fields[1].out_value = NULL;
- fields[1].in_value = NULL;
- } else {
- /* Discard irrelevant bits of the scan, making sure we don't write more
- * than size bytes to in */
- fields[0].num_bits = size * 8;
- fields[0].out_value = NULL;
- fields[0].in_value = in;
-
- fields[1].num_bits = 3 + 32 + 32 - size * 8;
- fields[1].out_value = NULL;
- fields[1].in_value = NULL;
- }
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
-
- jtag_add_callback4(arm7_9_endianness_callback,
- (jtag_callback_data_t)in,
- (jtag_callback_data_t)size,
- (jtag_callback_data_t)be,
- (jtag_callback_data_t)0);
-
- jtag_add_runtest(0, TAP_DRPAUSE);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
- {
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (in)
- LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in);
- else
- LOG_ERROR("BUG: called with in == NULL");
- }
-#endif
-
- return ERROR_OK;
-}
-
-static void arm9tdmi_change_to_arm(struct target *target,
- uint32_t *r0, uint32_t *pc)
-{
- int retval = ERROR_OK;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* save r0 before using it and put system in ARM state
- * to allow common handling of ARM and THUMB debugging */
-
- /* fetch STR r0, [r0] */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- /* STR r0, [r0] in Memory */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
-
- /* MOV r0, r15 fetched, STR in Decode */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- /* nothing fetched, STR r0, [r0] in Memory */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
-
- /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
- /* LDR in Decode */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- /* LDR in Execute */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- /* LDR in Memory (to account for interlock) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- /* fetch BX */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
- /* NOP fetched, BX in Decode, MOV in Execute */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- /* NOP fetched, BX in Execute (1) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return;
-
- /* fix program counter:
- * MOV r0, r15 was the 5th instruction (+8)
- * reading PC in Thumb state gives address of instruction + 4
- */
- *pc -= 0xc;
-}
-
-void arm9tdmi_read_core_regs(struct target *target,
- uint32_t mask, uint32_t *core_regs[16])
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* STMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, STM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, STM in MEMORY (i'th cycle) */
- arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
- }
-}
-
-static void arm9tdmi_read_core_regs_target_buffer(struct target *target,
- uint32_t mask, void *buffer, int size)
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
- uint32_t *buf_u32 = buffer;
- uint16_t *buf_u16 = buffer;
- uint8_t *buf_u8 = buffer;
-
- /* STMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, STM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, STM in MEMORY (i'th cycle) */
- switch (size) {
- case 4:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
- break;
- case 2:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
- break;
- case 1:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
- break;
- }
- }
-}
-
-static void arm9tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* MRS r0, cpsr */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- /* STR r0, [r15] */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
- /* fetch NOP, STR in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STR in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, STR in MEMORY */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
-}
-
-static void arm9tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
-
- /* MSR1 fetched */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
- /* MSR2 fetched, MSR1 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
- /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
- /* nothing fetched, MSR1 in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR1 in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
- /* nothing fetched, MSR2 in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR2 in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR3 in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR3 in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* NOP fetched, MSR4 in EXECUTE (1) */
- /* last MSR writes flags, which takes only one cycle */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void arm9tdmi_write_xpsr_im8(struct target *target,
- uint8_t xpsr_im, int rot, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
-
- /* MSR fetched */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
- /* NOP fetched, MSR in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* NOP fetched, MSR in EXECUTE (1) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- /* rot == 4 writes flags, which takes only one cycle */
- if (rot != 4) {
- /* nothing fetched, MSR in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- }
-}
-
-void arm9tdmi_write_core_regs(struct target *target,
- uint32_t mask, uint32_t core_regs[16])
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* LDMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, LDM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
- }
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-void arm9tdmi_load_word_regs(struct target *target, uint32_t mask)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed load-multiple into the pipeline */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-void arm9tdmi_load_hword_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed load half-word into the pipeline */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-void arm9tdmi_load_byte_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed load byte into the pipeline */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-void arm9tdmi_store_word_regs(struct target *target, uint32_t mask)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed store-multiple into the pipeline */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-void arm9tdmi_store_hword_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed store half-word into the pipeline */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-void arm9tdmi_store_byte_reg(struct target *target, int num)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* put system-speed store byte into the pipeline */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-static void arm9tdmi_write_pc(struct target *target, uint32_t pc)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* LDMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, LDM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-void arm9tdmi_branch_resume(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-static void arm9tdmi_branch_resume_thumb(struct target *target)
-{
- LOG_DEBUG("-");
-
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm *arm = &arm7_9->arm;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
- /* LDMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, LDM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP,
- buf_get_u32(arm->pc->value, 0, 32) | 1, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- /* Branch and eXchange */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
-
- embeddedice_read_reg(dbg_stat);
-
- /* fetch NOP, BX in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- embeddedice_read_reg(dbg_stat);
-
- /* fetch NOP, BX in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- /* target is now in Thumb state */
- embeddedice_read_reg(dbg_stat);
-
- /* load r0 value, MOV_IM in Decode*/
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
- /* fetch NOP, LDR in Decode, MOV_IM in Execute */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- /* fetch NOP, LDR in Execute */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP,
- buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), NULL, 0);
- /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- embeddedice_read_reg(dbg_stat);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-}
-
-void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (arm7_9->has_single_step) {
- buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
- } else
- arm7_9_enable_eice_step(target, next_pc);
-}
-
-void arm9tdmi_disable_single_step(struct target *target)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- if (arm7_9->has_single_step) {
- buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
- } else
- arm7_9_disable_eice_step(target);
-}
-
-static void arm9tdmi_build_reg_cache(struct target *target)
-{
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct arm *arm = target_to_arm(target);
-
- (*cache_p) = arm_build_reg_cache(target, arm);
-}
-
-int arm9tdmi_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- arm9tdmi_build_reg_cache(target);
- return ERROR_OK;
-}
-
-int arm9tdmi_init_arch_info(struct target *target,
- struct arm7_9_common *arm7_9, struct jtag_tap *tap)
-{
- /* prepare JTAG information for the new target */
- arm7_9->jtag_info.tap = tap;
- arm7_9->jtag_info.scann_size = 5;
-
- /* register arch-specific functions */
- arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
- arm7_9->change_to_arm = arm9tdmi_change_to_arm;
- arm7_9->read_core_regs = arm9tdmi_read_core_regs;
- arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
- arm7_9->read_xpsr = arm9tdmi_read_xpsr;
-
- arm7_9->write_xpsr = arm9tdmi_write_xpsr;
- arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
- arm7_9->write_core_regs = arm9tdmi_write_core_regs;
-
- arm7_9->load_word_regs = arm9tdmi_load_word_regs;
- arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
- arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
-
- arm7_9->store_word_regs = arm9tdmi_store_word_regs;
- arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
- arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
-
- arm7_9->write_pc = arm9tdmi_write_pc;
- arm7_9->branch_resume = arm9tdmi_branch_resume;
- arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
-
- arm7_9->enable_single_step = arm9tdmi_enable_single_step;
- arm7_9->disable_single_step = arm9tdmi_disable_single_step;
-
- arm7_9->write_memory = arm7_9_write_memory;
- arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
-
- arm7_9->post_debug_entry = NULL;
-
- arm7_9->pre_restore_context = NULL;
-
- /* initialize arch-specific breakpoint handling */
- arm7_9->arm_bkpt = 0xdeeedeee;
- arm7_9->thumb_bkpt = 0xdeee;
-
- arm7_9->dbgreq_adjust_pc = 3;
-
- arm7_9_init_arch_info(target, arm7_9);
-
- /* override use of DBGRQ, this is safe on ARM9TDMI */
- arm7_9->use_dbgrq = 1;
-
- /* all ARM9s have the vector catch register */
- arm7_9->has_vector_catch = 1;
-
- return ERROR_OK;
-}
-
-static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm7_9_common *arm7_9 = calloc(1, sizeof(struct arm7_9_common));
-
- arm9tdmi_init_arch_info(target, arm7_9, target->tap);
- arm7_9->arm.is_armv4 = true;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct reg *vector_catch;
- uint32_t vector_catch_value;
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- /* it's uncommon, but some ARM7 chips can support this */
- if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC
- || !arm7_9->has_vector_catch) {
- command_print(CMD_CTX, "target doesn't have EmbeddedICE "
- "with vector_catch");
- return ERROR_TARGET_INVALID;
- }
-
- vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
-
- /* read the vector catch register if necessary */
- if (!vector_catch->valid)
- embeddedice_read_reg(vector_catch);
-
- /* get the current setting */
- vector_catch_value = buf_get_u32(vector_catch->value, 0, 8);
-
- if (CMD_ARGC > 0) {
- vector_catch_value = 0x0;
- if (strcmp(CMD_ARGV[0], "all") == 0)
- vector_catch_value = 0xdf;
- else if (strcmp(CMD_ARGV[0], "none") == 0) {
- /* do nothing */
- } else {
- for (unsigned i = 0; i < CMD_ARGC; i++) {
- /* go through list of vectors */
- unsigned j;
- for (j = 0; arm9tdmi_vectors[j].name; j++) {
- if (strcmp(CMD_ARGV[i], arm9tdmi_vectors[j].name) == 0) {
- vector_catch_value |= arm9tdmi_vectors[j].value;
- break;
- }
- }
-
- /* complain if vector wasn't found */
- if (!arm9tdmi_vectors[j].name) {
- command_print(CMD_CTX, "vector '%s' not found, leaving current setting unchanged", CMD_ARGV[i]);
-
- /* reread current setting */
- vector_catch_value = buf_get_u32(
- vector_catch->value,
- 0, 8);
- break;
- }
- }
- }
-
- /* store new settings */
- buf_set_u32(vector_catch->value, 0, 8, vector_catch_value);
- embeddedice_store_reg(vector_catch);
- }
-
- /* output current settings */
- for (unsigned i = 0; arm9tdmi_vectors[i].name; i++) {
- command_print(CMD_CTX, "%s: %s", arm9tdmi_vectors[i].name,
- (vector_catch_value & arm9tdmi_vectors[i].value)
- ? "catch" : "don't catch");
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration arm9tdmi_exec_command_handlers[] = {
- {
- .name = "vector_catch",
- .handler = handle_arm9tdmi_catch_vectors_command,
- .mode = COMMAND_EXEC,
- .help = "Display, after optionally updating, configuration "
- "of vector catch unit.",
- .usage = "[all|none|(reset|undef|swi|pabt|dabt|irq|fiq)*]",
- },
- COMMAND_REGISTRATION_DONE
-};
-const struct command_registration arm9tdmi_command_handlers[] = {
- {
- .chain = arm7_9_command_handlers,
- },
- {
- .name = "arm9",
- .mode = COMMAND_ANY,
- .help = "arm9 command group",
- .usage = "",
- .chain = arm9tdmi_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for ARM9TDMI targets. */
-struct target_type arm9tdmi_target = {
- .name = "arm9tdmi",
-
- .poll = arm7_9_poll,
- .arch_state = arm_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm7_9_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm7_9_read_memory,
- .write_memory = arm7_9_write_memory_opt,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm9tdmi_command_handlers,
- .target_create = arm9tdmi_target_create,
- .init_target = arm9tdmi_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
-};
diff --git a/src/target/arm9tdmi.h b/src/target/arm9tdmi.h
deleted file mode 100644
index c6f0ccf..0000000
--- a/src/target/arm9tdmi.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM9TDMI_H
-#define OPENOCD_TARGET_ARM9TDMI_H
-
-#include "embeddedice.h"
-
-int arm9tdmi_init_target(struct command_context *cmd_ctx,
- struct target *target);
-int arm9tdmi_init_arch_info(struct target *target,
- struct arm7_9_common *arm7_9, struct jtag_tap *tap);
-extern const struct command_registration arm9tdmi_command_handlers[];
-
-int arm9tdmi_clock_out(struct arm_jtag *jtag_info,
- uint32_t instr, uint32_t out, uint32_t *in, int sysspeed);
-int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in);
-int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
- void *in, int size, int be);
-void arm9tdmi_read_core_regs(struct target *target,
- uint32_t mask, uint32_t *core_regs[16]);
-void arm9tdmi_write_core_regs(struct target *target,
- uint32_t mask, uint32_t core_regs[16]);
-
-int arm9tdmi_examine_debug_reason(struct target *target);
-
-void arm9tdmi_load_word_regs(struct target *target, uint32_t mask);
-void arm9tdmi_load_hword_reg(struct target *target, int num);
-void arm9tdmi_load_byte_reg(struct target *target, int num);
-void arm9tdmi_store_word_regs(struct target *target, uint32_t mask);
-void arm9tdmi_store_hword_reg(struct target *target, int num);
-void arm9tdmi_store_byte_reg(struct target *target, int num);
-
-void arm9tdmi_branch_resume(struct target *target);
-void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc);
-void arm9tdmi_disable_single_step(struct target *target);
-
-#endif /* OPENOCD_TARGET_ARM9TDMI_H */
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
deleted file mode 100644
index f58afdc..0000000
--- a/src/target/arm_adi_v5.c
+++ /dev/null
@@ -1,1700 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2009-2010 by Oyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009-2010 by David Brownell *
- * *
- * Copyright (C) 2013 by Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/**
- * @file
- * This file implements support for the ARM Debug Interface version 5 (ADIv5)
- * debugging architecture. Compared with previous versions, this includes
- * a low pin-count Serial Wire Debug (SWD) alternative to JTAG for message
- * transport, and focusses on memory mapped resources as defined by the
- * CoreSight architecture.
- *
- * A key concept in ADIv5 is the Debug Access Port, or DAP. A DAP has two
- * basic components: a Debug Port (DP) transporting messages to and from a
- * debugger, and an Access Port (AP) accessing resources. Three types of DP
- * are defined. One uses only JTAG for communication, and is called JTAG-DP.
- * One uses only SWD for communication, and is called SW-DP. The third can
- * use either SWD or JTAG, and is called SWJ-DP. The most common type of AP
- * is used to access memory mapped resources and is called a MEM-AP. Also a
- * JTAG-AP is also defined, bridging to JTAG resources; those are uncommon.
- *
- * This programming interface allows DAP pipelined operations through a
- * transaction queue. This primarily affects AP operations (such as using
- * a MEM-AP to access memory or registers). If the current transaction has
- * not finished by the time the next one must begin, and the ORUNDETECT bit
- * is set in the DP_CTRL_STAT register, the SSTICKYORUN status is set and
- * further AP operations will fail. There are two basic methods to avoid
- * such overrun errors. One involves polling for status instead of using
- * transaction piplining. The other involves adding delays to ensure the
- * AP has enough time to complete one operation before starting the next
- * one. (For JTAG these delays are controlled by memaccess_tck.)
- */
-
-/*
- * Relevant specifications from ARM include:
- *
- * ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031A
- * CoreSight(tm) v1.0 Architecture Specification ARM IHI 0029B
- *
- * CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D
- * Cortex-M3(tm) TRM, ARM DDI 0337G
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "arm.h"
-#include "arm_adi_v5.h"
-#include <helper/jep106.h>
-#include <helper/time_support.h>
-#include <helper/list.h>
-
-/* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */
-
-/*
- uint32_t tar_block_size(uint32_t address)
- Return the largest block starting at address that does not cross a tar block size alignment boundary
-*/
-static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address)
-{
- return tar_autoincr_block - ((tar_autoincr_block - 1) & address);
-}
-
-/***************************************************************************
- * *
- * DP and MEM-AP register access through APACC and DPACC *
- * *
-***************************************************************************/
-
-static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw)
-{
- csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT |
- ap->csw_default;
-
- if (csw != ap->csw_value) {
- /* LOG_DEBUG("DAP: Set CSW %x",csw); */
- int retval = dap_queue_ap_write(ap, MEM_AP_REG_CSW, csw);
- if (retval != ERROR_OK)
- return retval;
- ap->csw_value = csw;
- }
- return ERROR_OK;
-}
-
-static int mem_ap_setup_tar(struct adiv5_ap *ap, uint32_t tar)
-{
- if (tar != ap->tar_value ||
- (ap->csw_value & CSW_ADDRINC_MASK)) {
- /* LOG_DEBUG("DAP: Set TAR %x",tar); */
- int retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR, tar);
- if (retval != ERROR_OK)
- return retval;
- ap->tar_value = tar;
- }
- return ERROR_OK;
-}
-
-/**
- * Queue transactions setting up transfer parameters for the
- * currently selected MEM-AP.
- *
- * Subsequent transfers using registers like MEM_AP_REG_DRW or MEM_AP_REG_BD2
- * initiate data reads or writes using memory or peripheral addresses.
- * If the CSW is configured for it, the TAR may be automatically
- * incremented after each transfer.
- *
- * @param ap The MEM-AP.
- * @param csw MEM-AP Control/Status Word (CSW) register to assign. If this
- * matches the cached value, the register is not changed.
- * @param tar MEM-AP Transfer Address Register (TAR) to assign. If this
- * matches the cached address, the register is not changed.
- *
- * @return ERROR_OK if the transaction was properly queued, else a fault code.
- */
-static int mem_ap_setup_transfer(struct adiv5_ap *ap, uint32_t csw, uint32_t tar)
-{
- int retval;
- retval = mem_ap_setup_csw(ap, csw);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_setup_tar(ap, tar);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_OK;
-}
-
-/**
- * Asynchronous (queued) read of a word from memory or a system register.
- *
- * @param ap The MEM-AP to access.
- * @param address Address of the 32-bit word to read; it must be
- * readable by the currently selected MEM-AP.
- * @param value points to where the word will be stored when the
- * transaction queue is flushed (assuming no errors).
- *
- * @return ERROR_OK for success. Otherwise a fault code.
- */
-int mem_ap_read_u32(struct adiv5_ap *ap, uint32_t address,
- uint32_t *value)
-{
- int retval;
-
- /* Use banked addressing (REG_BDx) to avoid some link traffic
- * (updating TAR) when reading several consecutive addresses.
- */
- retval = mem_ap_setup_transfer(ap, CSW_32BIT | CSW_ADDRINC_OFF,
- address & 0xFFFFFFF0);
- if (retval != ERROR_OK)
- return retval;
-
- return dap_queue_ap_read(ap, MEM_AP_REG_BD0 | (address & 0xC), value);
-}
-
-/**
- * Synchronous read of a word from memory or a system register.
- * As a side effect, this flushes any queued transactions.
- *
- * @param ap The MEM-AP to access.
- * @param address Address of the 32-bit word to read; it must be
- * readable by the currently selected MEM-AP.
- * @param value points to where the result will be stored.
- *
- * @return ERROR_OK for success; *value holds the result.
- * Otherwise a fault code.
- */
-int mem_ap_read_atomic_u32(struct adiv5_ap *ap, uint32_t address,
- uint32_t *value)
-{
- int retval;
-
- retval = mem_ap_read_u32(ap, address, value);
- if (retval != ERROR_OK)
- return retval;
-
- return dap_run(ap->dap);
-}
-
-/**
- * Asynchronous (queued) write of a word to memory or a system register.
- *
- * @param ap The MEM-AP to access.
- * @param address Address to be written; it must be writable by
- * the currently selected MEM-AP.
- * @param value Word that will be written to the address when transaction
- * queue is flushed (assuming no errors).
- *
- * @return ERROR_OK for success. Otherwise a fault code.
- */
-int mem_ap_write_u32(struct adiv5_ap *ap, uint32_t address,
- uint32_t value)
-{
- int retval;
-
- /* Use banked addressing (REG_BDx) to avoid some link traffic
- * (updating TAR) when writing several consecutive addresses.
- */
- retval = mem_ap_setup_transfer(ap, CSW_32BIT | CSW_ADDRINC_OFF,
- address & 0xFFFFFFF0);
- if (retval != ERROR_OK)
- return retval;
-
- return dap_queue_ap_write(ap, MEM_AP_REG_BD0 | (address & 0xC),
- value);
-}
-
-/**
- * Synchronous write of a word to memory or a system register.
- * As a side effect, this flushes any queued transactions.
- *
- * @param ap The MEM-AP to access.
- * @param address Address to be written; it must be writable by
- * the currently selected MEM-AP.
- * @param value Word that will be written.
- *
- * @return ERROR_OK for success; the data was written. Otherwise a fault code.
- */
-int mem_ap_write_atomic_u32(struct adiv5_ap *ap, uint32_t address,
- uint32_t value)
-{
- int retval = mem_ap_write_u32(ap, address, value);
-
- if (retval != ERROR_OK)
- return retval;
-
- return dap_run(ap->dap);
-}
-
-/**
- * Synchronous write of a block of memory, using a specific access size.
- *
- * @param ap The MEM-AP to access.
- * @param buffer The data buffer to write. No particular alignment is assumed.
- * @param size Which access size to use, in bytes. 1, 2 or 4.
- * @param count The number of writes to do (in size units, not bytes).
- * @param address Address to be written; it must be writable by the currently selected MEM-AP.
- * @param addrinc Whether the target address should be increased for each write or not. This
- * should normally be true, except when writing to e.g. a FIFO.
- * @return ERROR_OK on success, otherwise an error code.
- */
-static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t size, uint32_t count,
- uint32_t address, bool addrinc)
-{
- struct adiv5_dap *dap = ap->dap;
- size_t nbytes = size * count;
- const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
- uint32_t csw_size;
- uint32_t addr_xor;
- int retval;
-
- /* TI BE-32 Quirks mode:
- * Writes on big-endian TMS570 behave very strangely. Observed behavior:
- * size write address bytes written in order
- * 4 TAR ^ 0 (val >> 24), (val >> 16), (val >> 8), (val)
- * 2 TAR ^ 2 (val >> 8), (val)
- * 1 TAR ^ 3 (val)
- * For example, if you attempt to write a single byte to address 0, the processor
- * will actually write a byte to address 3.
- *
- * To make writes of size < 4 work as expected, we xor a value with the address before
- * setting the TAP, and we set the TAP after every transfer rather then relying on
- * address increment. */
-
- if (size == 4) {
- csw_size = CSW_32BIT;
- addr_xor = 0;
- } else if (size == 2) {
- csw_size = CSW_16BIT;
- addr_xor = dap->ti_be_32_quirks ? 2 : 0;
- } else if (size == 1) {
- csw_size = CSW_8BIT;
- addr_xor = dap->ti_be_32_quirks ? 3 : 0;
- } else {
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- if (ap->unaligned_access_bad && (address % size != 0))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- retval = mem_ap_setup_tar(ap, address ^ addr_xor);
- if (retval != ERROR_OK)
- return retval;
-
- while (nbytes > 0) {
- uint32_t this_size = size;
-
- /* Select packed transfer if possible */
- if (addrinc && ap->packed_transfers && nbytes >= 4
- && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {
- this_size = 4;
- retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED);
- } else {
- retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);
- }
-
- if (retval != ERROR_OK)
- break;
-
- /* How many source bytes each transfer will consume, and their location in the DRW,
- * depends on the type of transfer and alignment. See ARM document IHI0031C. */
- uint32_t outvalue = 0;
- if (dap->ti_be_32_quirks) {
- switch (this_size) {
- case 4:
- outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
- outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
- outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
- outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (address++ & 3) ^ addr_xor);
- break;
- case 2:
- outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor);
- outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (address++ & 3) ^ addr_xor);
- break;
- case 1:
- outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (address++ & 3) ^ addr_xor);
- break;
- }
- } else {
- switch (this_size) {
- case 4:
- outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
- outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
- case 2:
- outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
- case 1:
- outvalue |= (uint32_t)*buffer++ << 8 * (address++ & 3);
- }
- }
-
- nbytes -= this_size;
-
- retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW, outvalue);
- if (retval != ERROR_OK)
- break;
-
- /* Rewrite TAR if it wrapped or we're xoring addresses */
- if (addrinc && (addr_xor || (address % ap->tar_autoincr_block < size && nbytes > 0))) {
- retval = mem_ap_setup_tar(ap, address ^ addr_xor);
- if (retval != ERROR_OK)
- break;
- }
- }
-
- /* REVISIT: Might want to have a queued version of this function that does not run. */
- if (retval == ERROR_OK)
- retval = dap_run(dap);
-
- if (retval != ERROR_OK) {
- uint32_t tar;
- if (dap_queue_ap_read(ap, MEM_AP_REG_TAR, &tar) == ERROR_OK
- && dap_run(dap) == ERROR_OK)
- LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar);
- else
- LOG_ERROR("Failed to write memory and, additionally, failed to find out where");
- }
-
- return retval;
-}
-
-/**
- * Synchronous read of a block of memory, using a specific access size.
- *
- * @param ap The MEM-AP to access.
- * @param buffer The data buffer to receive the data. No particular alignment is assumed.
- * @param size Which access size to use, in bytes. 1, 2 or 4.
- * @param count The number of reads to do (in size units, not bytes).
- * @param address Address to be read; it must be readable by the currently selected MEM-AP.
- * @param addrinc Whether the target address should be increased after each read or not. This
- * should normally be true, except when reading from e.g. a FIFO.
- * @return ERROR_OK on success, otherwise an error code.
- */
-static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint32_t count,
- uint32_t adr, bool addrinc)
-{
- struct adiv5_dap *dap = ap->dap;
- size_t nbytes = size * count;
- const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;
- uint32_t csw_size;
- uint32_t address = adr;
- int retval;
-
- /* TI BE-32 Quirks mode:
- * Reads on big-endian TMS570 behave strangely differently than writes.
- * They read from the physical address requested, but with DRW byte-reversed.
- * For example, a byte read from address 0 will place the result in the high bytes of DRW.
- * Also, packed 8-bit and 16-bit transfers seem to sometimes return garbage in some bytes,
- * so avoid them. */
-
- if (size == 4)
- csw_size = CSW_32BIT;
- else if (size == 2)
- csw_size = CSW_16BIT;
- else if (size == 1)
- csw_size = CSW_8BIT;
- else
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- if (ap->unaligned_access_bad && (adr % size != 0))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- /* Allocate buffer to hold the sequence of DRW reads that will be made. This is a significant
- * over-allocation if packed transfers are going to be used, but determining the real need at
- * this point would be messy. */
- uint32_t *read_buf = malloc(count * sizeof(uint32_t));
- uint32_t *read_ptr = read_buf;
- if (read_buf == NULL) {
- LOG_ERROR("Failed to allocate read buffer");
- return ERROR_FAIL;
- }
-
- retval = mem_ap_setup_tar(ap, address);
- if (retval != ERROR_OK) {
- free(read_buf);
- return retval;
- }
-
- /* Queue up all reads. Each read will store the entire DRW word in the read buffer. How many
- * useful bytes it contains, and their location in the word, depends on the type of transfer
- * and alignment. */
- while (nbytes > 0) {
- uint32_t this_size = size;
-
- /* Select packed transfer if possible */
- if (addrinc && ap->packed_transfers && nbytes >= 4
- && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {
- this_size = 4;
- retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED);
- } else {
- retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);
- }
- if (retval != ERROR_OK)
- break;
-
- retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW, read_ptr++);
- if (retval != ERROR_OK)
- break;
-
- nbytes -= this_size;
- address += this_size;
-
- /* Rewrite TAR if it wrapped */
- if (addrinc && address % ap->tar_autoincr_block < size && nbytes > 0) {
- retval = mem_ap_setup_tar(ap, address);
- if (retval != ERROR_OK)
- break;
- }
- }
-
- if (retval == ERROR_OK)
- retval = dap_run(dap);
-
- /* Restore state */
- address = adr;
- nbytes = size * count;
- read_ptr = read_buf;
-
- /* If something failed, read TAR to find out how much data was successfully read, so we can
- * at least give the caller what we have. */
- if (retval != ERROR_OK) {
- uint32_t tar;
- if (dap_queue_ap_read(ap, MEM_AP_REG_TAR, &tar) == ERROR_OK
- && dap_run(dap) == ERROR_OK) {
- LOG_ERROR("Failed to read memory at 0x%08"PRIx32, tar);
- if (nbytes > tar - address)
- nbytes = tar - address;
- } else {
- LOG_ERROR("Failed to read memory and, additionally, failed to find out where");
- nbytes = 0;
- }
- }
-
- /* Replay loop to populate caller's buffer from the correct word and byte lane */
- while (nbytes > 0) {
- uint32_t this_size = size;
-
- if (addrinc && ap->packed_transfers && nbytes >= 4
- && max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {
- this_size = 4;
- }
-
- if (dap->ti_be_32_quirks) {
- switch (this_size) {
- case 4:
- *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
- *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
- case 2:
- *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
- case 1:
- *buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));
- }
- } else {
- switch (this_size) {
- case 4:
- *buffer++ = *read_ptr >> 8 * (address++ & 3);
- *buffer++ = *read_ptr >> 8 * (address++ & 3);
- case 2:
- *buffer++ = *read_ptr >> 8 * (address++ & 3);
- case 1:
- *buffer++ = *read_ptr >> 8 * (address++ & 3);
- }
- }
-
- read_ptr++;
- nbytes -= this_size;
- }
-
- free(read_buf);
- return retval;
-}
-
-int mem_ap_read_buf(struct adiv5_ap *ap,
- uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
-{
- return mem_ap_read(ap, buffer, size, count, address, true);
-}
-
-int mem_ap_write_buf(struct adiv5_ap *ap,
- const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
-{
- return mem_ap_write(ap, buffer, size, count, address, true);
-}
-
-int mem_ap_read_buf_noincr(struct adiv5_ap *ap,
- uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
-{
- return mem_ap_read(ap, buffer, size, count, address, false);
-}
-
-int mem_ap_write_buf_noincr(struct adiv5_ap *ap,
- const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)
-{
- return mem_ap_write(ap, buffer, size, count, address, false);
-}
-
-/*--------------------------------------------------------------------------*/
-
-
-#define DAP_POWER_DOMAIN_TIMEOUT (10)
-
-/* FIXME don't import ... just initialize as
- * part of DAP transport setup
-*/
-extern const struct dap_ops jtag_dp_ops;
-
-/*--------------------------------------------------------------------------*/
-
-/**
- * Create a new DAP
- */
-struct adiv5_dap *dap_init(void)
-{
- struct adiv5_dap *dap = calloc(1, sizeof(struct adiv5_dap));
- int i;
- /* Set up with safe defaults */
- for (i = 0; i <= 255; i++) {
- dap->ap[i].dap = dap;
- dap->ap[i].ap_num = i;
- /* memaccess_tck max is 255 */
- dap->ap[i].memaccess_tck = 255;
- /* Number of bits for tar autoincrement, impl. dep. at least 10 */
- dap->ap[i].tar_autoincr_block = (1<<10);
- }
- INIT_LIST_HEAD(&dap->cmd_journal);
- return dap;
-}
-
-/**
- * Initialize a DAP. This sets up the power domains, prepares the DP
- * for further use and activates overrun checking.
- *
- * @param dap The DAP being initialized.
- */
-int dap_dp_init(struct adiv5_dap *dap)
-{
- int retval;
-
- LOG_DEBUG(" ");
- /* JTAG-DP or SWJ-DP, in JTAG mode
- * ... for SWD mode this is patched as part
- * of link switchover
- * FIXME: This should already be setup by the respective transport specific DAP creation.
- */
- if (!dap->ops)
- dap->ops = &jtag_dp_ops;
-
- dap->select = DP_SELECT_INVALID;
- dap->last_read = NULL;
-
- for (size_t i = 0; i < 10; i++) {
- /* DP initialization */
-
- retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
- if (retval != ERROR_OK)
- continue;
-
- retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR);
- if (retval != ERROR_OK)
- continue;
-
- retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
- if (retval != ERROR_OK)
- continue;
-
- dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;
- retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat);
- if (retval != ERROR_OK)
- continue;
-
- /* Check that we have debug power domains activated */
- LOG_DEBUG("DAP: wait CDBGPWRUPACK");
- retval = dap_dp_poll_register(dap, DP_CTRL_STAT,
- CDBGPWRUPACK, CDBGPWRUPACK,
- DAP_POWER_DOMAIN_TIMEOUT);
- if (retval != ERROR_OK)
- continue;
-
- LOG_DEBUG("DAP: wait CSYSPWRUPACK");
- retval = dap_dp_poll_register(dap, DP_CTRL_STAT,
- CSYSPWRUPACK, CSYSPWRUPACK,
- DAP_POWER_DOMAIN_TIMEOUT);
- if (retval != ERROR_OK)
- continue;
-
- retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
- if (retval != ERROR_OK)
- continue;
-
- /* With debug power on we can activate OVERRUN checking */
- dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;
- retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat);
- if (retval != ERROR_OK)
- continue;
- retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
- if (retval != ERROR_OK)
- continue;
-
- retval = dap_run(dap);
- if (retval != ERROR_OK)
- continue;
-
- break;
- }
-
- return retval;
-}
-
-/**
- * Initialize a DAP. This sets up the power domains, prepares the DP
- * for further use, and arranges to use AP #0 for all AP operations
- * until dap_ap-select() changes that policy.
- *
- * @param ap The MEM-AP being initialized.
- */
-int mem_ap_init(struct adiv5_ap *ap)
-{
- /* check that we support packed transfers */
- uint32_t csw, cfg;
- int retval;
- struct adiv5_dap *dap = ap->dap;
-
- retval = mem_ap_setup_transfer(ap, CSW_8BIT | CSW_ADDRINC_PACKED, 0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dap_queue_ap_read(ap, MEM_AP_REG_CSW, &csw);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &cfg);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dap_run(dap);
- if (retval != ERROR_OK)
- return retval;
-
- if (csw & CSW_ADDRINC_PACKED)
- ap->packed_transfers = true;
- else
- ap->packed_transfers = false;
-
- /* Packed transfers on TI BE-32 processors do not work correctly in
- * many cases. */
- if (dap->ti_be_32_quirks)
- ap->packed_transfers = false;
-
- LOG_DEBUG("MEM_AP Packed Transfers: %s",
- ap->packed_transfers ? "enabled" : "disabled");
-
- /* The ARM ADI spec leaves implementation-defined whether unaligned
- * memory accesses work, only work partially, or cause a sticky error.
- * On TI BE-32 processors, reads seem to return garbage in some bytes
- * and unaligned writes seem to cause a sticky error.
- * TODO: it would be nice to have a way to detect whether unaligned
- * operations are supported on other processors. */
- ap->unaligned_access_bad = dap->ti_be_32_quirks;
-
- LOG_DEBUG("MEM_AP CFG: large data %d, long address %d, big-endian %d",
- !!(cfg & 0x04), !!(cfg & 0x02), !!(cfg & 0x01));
-
- return ERROR_OK;
-}
-
-/* CID interpretation -- see ARM IHI 0029B section 3
- * and ARM IHI 0031A table 13-3.
- */
-static const char *class_description[16] = {
- "Reserved", "ROM table", "Reserved", "Reserved",
- "Reserved", "Reserved", "Reserved", "Reserved",
- "Reserved", "CoreSight component", "Reserved", "Peripheral Test Block",
- "Reserved", "OptimoDE DESS",
- "Generic IP component", "PrimeCell or System component"
-};
-
-static bool is_dap_cid_ok(uint32_t cid)
-{
- return (cid & 0xffff0fff) == 0xb105000d;
-}
-
-/*
- * This function checks the ID for each access port to find the requested Access Port type
- */
-int dap_find_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out)
-{
- int ap_num;
-
- /* Maximum AP number is 255 since the SELECT register is 8 bits */
- for (ap_num = 0; ap_num <= 255; ap_num++) {
-
- /* read the IDR register of the Access Port */
- uint32_t id_val = 0;
-
- int retval = dap_queue_ap_read(dap_ap(dap, ap_num), AP_REG_IDR, &id_val);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dap_run(dap);
-
- /* IDR bits:
- * 31-28 : Revision
- * 27-24 : JEDEC bank (0x4 for ARM)
- * 23-17 : JEDEC code (0x3B for ARM)
- * 16-13 : Class (0b1000=Mem-AP)
- * 12-8 : Reserved
- * 7-4 : AP Variant (non-zero for JTAG-AP)
- * 3-0 : AP Type (0=JTAG-AP 1=AHB-AP 2=APB-AP 4=AXI-AP)
- */
-
- /* Reading register for a non-existant AP should not cause an error,
- * but just to be sure, try to continue searching if an error does happen.
- */
- if ((retval == ERROR_OK) && /* Register read success */
- ((id_val & IDR_JEP106) == IDR_JEP106_ARM) && /* Jedec codes match */
- ((id_val & IDR_TYPE) == type_to_find)) { /* type matches*/
-
- LOG_DEBUG("Found %s at AP index: %d (IDR=0x%08" PRIX32 ")",
- (type_to_find == AP_TYPE_AHB_AP) ? "AHB-AP" :
- (type_to_find == AP_TYPE_APB_AP) ? "APB-AP" :
- (type_to_find == AP_TYPE_AXI_AP) ? "AXI-AP" :
- (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown",
- ap_num, id_val);
-
- *ap_out = &dap->ap[ap_num];
- return ERROR_OK;
- }
- }
-
- LOG_DEBUG("No %s found",
- (type_to_find == AP_TYPE_AHB_AP) ? "AHB-AP" :
- (type_to_find == AP_TYPE_APB_AP) ? "APB-AP" :
- (type_to_find == AP_TYPE_AXI_AP) ? "AXI-AP" :
- (type_to_find == AP_TYPE_JTAG_AP) ? "JTAG-AP" : "Unknown");
- return ERROR_FAIL;
-}
-
-int dap_get_debugbase(struct adiv5_ap *ap,
- uint32_t *dbgbase, uint32_t *apid)
-{
- struct adiv5_dap *dap = ap->dap;
- int retval;
-
- retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, dbgbase);
- if (retval != ERROR_OK)
- return retval;
- retval = dap_queue_ap_read(ap, AP_REG_IDR, apid);
- if (retval != ERROR_OK)
- return retval;
- retval = dap_run(dap);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-int dap_lookup_cs_component(struct adiv5_ap *ap,
- uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx)
-{
- uint32_t romentry, entry_offset = 0, component_base, devtype;
- int retval;
-
- *addr = 0;
-
- do {
- retval = mem_ap_read_atomic_u32(ap, (dbgbase&0xFFFFF000) |
- entry_offset, &romentry);
- if (retval != ERROR_OK)
- return retval;
-
- component_base = (dbgbase & 0xFFFFF000)
- + (romentry & 0xFFFFF000);
-
- if (romentry & 0x1) {
- uint32_t c_cid1;
- retval = mem_ap_read_atomic_u32(ap, component_base | 0xff4, &c_cid1);
- if (retval != ERROR_OK) {
- LOG_ERROR("Can't read component with base address 0x%" PRIx32
- ", the corresponding core might be turned off", component_base);
- return retval;
- }
- if (((c_cid1 >> 4) & 0x0f) == 1) {
- retval = dap_lookup_cs_component(ap, component_base,
- type, addr, idx);
- if (retval == ERROR_OK)
- break;
- if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
- return retval;
- }
-
- retval = mem_ap_read_atomic_u32(ap,
- (component_base & 0xfffff000) | 0xfcc,
- &devtype);
- if (retval != ERROR_OK)
- return retval;
- if ((devtype & 0xff) == type) {
- if (!*idx) {
- *addr = component_base;
- break;
- } else
- (*idx)--;
- }
- }
- entry_offset += 4;
- } while (romentry > 0);
-
- if (!*addr)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- return ERROR_OK;
-}
-
-static int dap_read_part_id(struct adiv5_ap *ap, uint32_t component_base, uint32_t *cid, uint64_t *pid)
-{
- assert((component_base & 0xFFF) == 0);
- assert(ap != NULL && cid != NULL && pid != NULL);
-
- uint32_t cid0, cid1, cid2, cid3;
- uint32_t pid0, pid1, pid2, pid3, pid4;
- int retval;
-
- /* IDs are in last 4K section */
- retval = mem_ap_read_u32(ap, component_base + 0xFE0, &pid0);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFE4, &pid1);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFE8, &pid2);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFEC, &pid3);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFD0, &pid4);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFF0, &cid0);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFF4, &cid1);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFF8, &cid2);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(ap, component_base + 0xFFC, &cid3);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dap_run(ap->dap);
- if (retval != ERROR_OK)
- return retval;
-
- *cid = (cid3 & 0xff) << 24
- | (cid2 & 0xff) << 16
- | (cid1 & 0xff) << 8
- | (cid0 & 0xff);
- *pid = (uint64_t)(pid4 & 0xff) << 32
- | (pid3 & 0xff) << 24
- | (pid2 & 0xff) << 16
- | (pid1 & 0xff) << 8
- | (pid0 & 0xff);
-
- return ERROR_OK;
-}
-
-/* The designer identity code is encoded as:
- * bits 11:8 : JEP106 Bank (number of continuation codes), only valid when bit 7 is 1.
- * bit 7 : Set when bits 6:0 represent a JEP106 ID and cleared when bits 6:0 represent
- * a legacy ASCII Identity Code.
- * bits 6:0 : JEP106 Identity Code (without parity) or legacy ASCII code according to bit 7.
- * JEP106 is a standard available from jedec.org
- */
-
-/* Part number interpretations are from Cortex
- * core specs, the CoreSight components TRM
- * (ARM DDI 0314H), CoreSight System Design
- * Guide (ARM DGI 0012D) and ETM specs; also
- * from chip observation (e.g. TI SDTI).
- */
-
-/* The legacy code only used the part number field to identify CoreSight peripherals.
- * This meant that the same part number from two different manufacturers looked the same.
- * It is desirable for all future additions to identify with both part number and JEP106.
- * "ANY_ID" is a wildcard (any JEP106) only to preserve legacy behavior for legacy entries.
- */
-
-#define ANY_ID 0x1000
-
-#define ARM_ID 0x4BB
-
-static const struct {
- uint16_t designer_id;
- uint16_t part_num;
- const char *type;
- const char *full;
-} dap_partnums[] = {
- { ARM_ID, 0x000, "Cortex-M3 SCS", "(System Control Space)", },
- { ARM_ID, 0x001, "Cortex-M3 ITM", "(Instrumentation Trace Module)", },
- { ARM_ID, 0x002, "Cortex-M3 DWT", "(Data Watchpoint and Trace)", },
- { ARM_ID, 0x003, "Cortex-M3 FPB", "(Flash Patch and Breakpoint)", },
- { ARM_ID, 0x008, "Cortex-M0 SCS", "(System Control Space)", },
- { ARM_ID, 0x00a, "Cortex-M0 DWT", "(Data Watchpoint and Trace)", },
- { ARM_ID, 0x00b, "Cortex-M0 BPU", "(Breakpoint Unit)", },
- { ARM_ID, 0x00c, "Cortex-M4 SCS", "(System Control Space)", },
- { ARM_ID, 0x00d, "CoreSight ETM11", "(Embedded Trace)", },
- { ARM_ID, 0x00e, "Cortex-M7 FPB", "(Flash Patch and Breakpoint)", },
- { ARM_ID, 0x490, "Cortex-A15 GIC", "(Generic Interrupt Controller)", },
- { ARM_ID, 0x4a1, "Cortex-A53 ROM", "(v8 Memory Map ROM Table)", },
- { ARM_ID, 0x4a2, "Cortex-A57 ROM", "(ROM Table)", },
- { ARM_ID, 0x4a3, "Cortex-A53 ROM", "(v7 Memory Map ROM Table)", },
- { ARM_ID, 0x4a4, "Cortex-A72 ROM", "(ROM Table)", },
- { ARM_ID, 0x4af, "Cortex-A15 ROM", "(ROM Table)", },
- { ARM_ID, 0x4c0, "Cortex-M0+ ROM", "(ROM Table)", },
- { ARM_ID, 0x4c3, "Cortex-M3 ROM", "(ROM Table)", },
- { ARM_ID, 0x4c4, "Cortex-M4 ROM", "(ROM Table)", },
- { ARM_ID, 0x4c7, "Cortex-M7 PPB ROM", "(Private Peripheral Bus ROM Table)", },
- { ARM_ID, 0x4c8, "Cortex-M7 ROM", "(ROM Table)", },
- { ARM_ID, 0x470, "Cortex-M1 ROM", "(ROM Table)", },
- { ARM_ID, 0x471, "Cortex-M0 ROM", "(ROM Table)", },
- { ARM_ID, 0x906, "CoreSight CTI", "(Cross Trigger)", },
- { ARM_ID, 0x907, "CoreSight ETB", "(Trace Buffer)", },
- { ARM_ID, 0x908, "CoreSight CSTF", "(Trace Funnel)", },
- { ARM_ID, 0x909, "CoreSight ATBR", "(Advanced Trace Bus Replicator)", },
- { ARM_ID, 0x910, "CoreSight ETM9", "(Embedded Trace)", },
- { ARM_ID, 0x912, "CoreSight TPIU", "(Trace Port Interface Unit)", },
- { ARM_ID, 0x913, "CoreSight ITM", "(Instrumentation Trace Macrocell)", },
- { ARM_ID, 0x914, "CoreSight SWO", "(Single Wire Output)", },
- { ARM_ID, 0x917, "CoreSight HTM", "(AHB Trace Macrocell)", },
- { ARM_ID, 0x920, "CoreSight ETM11", "(Embedded Trace)", },
- { ARM_ID, 0x921, "Cortex-A8 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x922, "Cortex-A8 CTI", "(Cross Trigger)", },
- { ARM_ID, 0x923, "Cortex-M3 TPIU", "(Trace Port Interface Unit)", },
- { ARM_ID, 0x924, "Cortex-M3 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x925, "Cortex-M4 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x930, "Cortex-R4 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x931, "Cortex-R5 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x932, "CoreSight MTB-M0+", "(Micro Trace Buffer)", },
- { ARM_ID, 0x941, "CoreSight TPIU-Lite", "(Trace Port Interface Unit)", },
- { ARM_ID, 0x950, "Cortex-A9 PTM", "(Program Trace Macrocell)", },
- { ARM_ID, 0x955, "Cortex-A5 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x95a, "Cortex-A72 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x95b, "Cortex-A17 PTM", "(Program Trace Macrocell)", },
- { ARM_ID, 0x95d, "Cortex-A53 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x95e, "Cortex-A57 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x95f, "Cortex-A15 PTM", "(Program Trace Macrocell)", },
- { ARM_ID, 0x961, "CoreSight TMC", "(Trace Memory Controller)", },
- { ARM_ID, 0x962, "CoreSight STM", "(System Trace Macrocell)", },
- { ARM_ID, 0x975, "Cortex-M7 ETM", "(Embedded Trace)", },
- { ARM_ID, 0x9a0, "CoreSight PMU", "(Performance Monitoring Unit)", },
- { ARM_ID, 0x9a1, "Cortex-M4 TPIU", "(Trace Port Interface Unit)", },
- { ARM_ID, 0x9a4, "CoreSight GPR", "(Granular Power Requester)", },
- { ARM_ID, 0x9a5, "Cortex-A5 PMU", "(Performance Monitor Unit)", },
- { ARM_ID, 0x9a7, "Cortex-A7 PMU", "(Performance Monitor Unit)", },
- { ARM_ID, 0x9a8, "Cortex-A53 CTI", "(Cross Trigger)", },
- { ARM_ID, 0x9a9, "Cortex-M7 TPIU", "(Trace Port Interface Unit)", },
- { ARM_ID, 0x9ae, "Cortex-A17 PMU", "(Performance Monitor Unit)", },
- { ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", },
- { ARM_ID, 0x9b7, "Cortex-R7 PMU", "(Performance Monitoring Unit)", },
- { ARM_ID, 0x9d3, "Cortex-A53 PMU", "(Performance Monitor Unit)", },
- { ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", },
- { ARM_ID, 0x9d8, "Cortex-A72 PMU", "(Performance Monitor Unit)", },
- { ARM_ID, 0xc05, "Cortex-A5 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc07, "Cortex-A7 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc08, "Cortex-A8 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc09, "Cortex-A9 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc0e, "Cortex-A17 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc0f, "Cortex-A15 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc14, "Cortex-R4 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc15, "Cortex-R5 Debug", "(Debug Unit)", },
- { ARM_ID, 0xc17, "Cortex-R7 Debug", "(Debug Unit)", },
- { ARM_ID, 0xd03, "Cortex-A53 Debug", "(Debug Unit)", },
- { ARM_ID, 0xd07, "Cortex-A57 Debug", "(Debug Unit)", },
- { ARM_ID, 0xd08, "Cortex-A72 Debug", "(Debug Unit)", },
- { 0x097, 0x9af, "MSP432 ROM", "(ROM Table)" },
- { 0x09f, 0xcd0, "Atmel CPU with DSU", "(CPU)" },
- { 0x0c1, 0x1db, "XMC4500 ROM", "(ROM Table)" },
- { 0x0c1, 0x1df, "XMC4700/4800 ROM", "(ROM Table)" },
- { 0x0c1, 0x1ed, "XMC1000 ROM", "(ROM Table)" },
- { 0x0E5, 0x000, "SHARC+/Blackfin+", "", },
- { 0x0F0, 0x440, "Qualcomm QDSS Component v1", "(Qualcomm Designed CoreSight Component v1)", },
- /* legacy comment: 0x113: what? */
- { ANY_ID, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */
- { ANY_ID, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */
-};
-
-static int dap_rom_display(struct command_context *cmd_ctx,
- struct adiv5_ap *ap, uint32_t dbgbase, int depth)
-{
- int retval;
- uint64_t pid;
- uint32_t cid;
- char tabs[7] = "";
-
- if (depth > 16) {
- command_print(cmd_ctx, "\tTables too deep");
- return ERROR_FAIL;
- }
-
- if (depth)
- snprintf(tabs, sizeof(tabs), "[L%02d] ", depth);
-
- uint32_t base_addr = dbgbase & 0xFFFFF000;
- command_print(cmd_ctx, "\t\tComponent base address 0x%08" PRIx32, base_addr);
-
- retval = dap_read_part_id(ap, base_addr, &cid, &pid);
- if (retval != ERROR_OK) {
- command_print(cmd_ctx, "\t\tCan't read component, the corresponding core might be turned off");
- return ERROR_OK; /* Don't abort recursion */
- }
-
- if (!is_dap_cid_ok(cid)) {
- command_print(cmd_ctx, "\t\tInvalid CID 0x%08" PRIx32, cid);
- return ERROR_OK; /* Don't abort recursion */
- }
-
- /* component may take multiple 4K pages */
- uint32_t size = (pid >> 36) & 0xf;
- if (size > 0)
- command_print(cmd_ctx, "\t\tStart address 0x%08" PRIx32, (uint32_t)(base_addr - 0x1000 * size));
-
- command_print(cmd_ctx, "\t\tPeripheral ID 0x%010" PRIx64, pid);
-
- uint8_t class = (cid >> 12) & 0xf;
- uint16_t part_num = pid & 0xfff;
- uint16_t designer_id = ((pid >> 32) & 0xf) << 8 | ((pid >> 12) & 0xff);
-
- if (designer_id & 0x80) {
- /* JEP106 code */
- command_print(cmd_ctx, "\t\tDesigner is 0x%03" PRIx16 ", %s",
- designer_id, jep106_manufacturer(designer_id >> 8, designer_id & 0x7f));
- } else {
- /* Legacy ASCII ID, clear invalid bits */
- designer_id &= 0x7f;
- command_print(cmd_ctx, "\t\tDesigner ASCII code 0x%02" PRIx16 ", %s",
- designer_id, designer_id == 0x41 ? "ARM" : "<unknown>");
- }
-
- /* default values to be overwritten upon finding a match */
- const char *type = "Unrecognized";
- const char *full = "";
-
- /* search dap_partnums[] array for a match */
- for (unsigned entry = 0; entry < ARRAY_SIZE(dap_partnums); entry++) {
-
- if ((dap_partnums[entry].designer_id != designer_id) && (dap_partnums[entry].designer_id != ANY_ID))
- continue;
-
- if (dap_partnums[entry].part_num != part_num)
- continue;
-
- type = dap_partnums[entry].type;
- full = dap_partnums[entry].full;
- break;
- }
-
- command_print(cmd_ctx, "\t\tPart is 0x%" PRIx16", %s %s", part_num, type, full);
- command_print(cmd_ctx, "\t\tComponent class is 0x%" PRIx8 ", %s", class, class_description[class]);
-
- if (class == 1) { /* ROM Table */
- uint32_t memtype;
- retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &memtype);
- if (retval != ERROR_OK)
- return retval;
-
- if (memtype & 0x01)
- command_print(cmd_ctx, "\t\tMEMTYPE system memory present on bus");
- else
- command_print(cmd_ctx, "\t\tMEMTYPE system memory not present: dedicated debug bus");
-
- /* Read ROM table entries from base address until we get 0x00000000 or reach the reserved area */
- for (uint16_t entry_offset = 0; entry_offset < 0xF00; entry_offset += 4) {
- uint32_t romentry;
- retval = mem_ap_read_atomic_u32(ap, base_addr | entry_offset, &romentry);
- if (retval != ERROR_OK)
- return retval;
- command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "",
- tabs, entry_offset, romentry);
- if (romentry & 0x01) {
- /* Recurse */
- retval = dap_rom_display(cmd_ctx, ap, base_addr + (romentry & 0xFFFFF000), depth + 1);
- if (retval != ERROR_OK)
- return retval;
- } else if (romentry != 0) {
- command_print(cmd_ctx, "\t\tComponent not present");
- } else {
- command_print(cmd_ctx, "\t%s\tEnd of ROM table", tabs);
- break;
- }
- }
- } else if (class == 9) { /* CoreSight component */
- const char *major = "Reserved", *subtype = "Reserved";
-
- uint32_t devtype;
- retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &devtype);
- if (retval != ERROR_OK)
- return retval;
- unsigned minor = (devtype >> 4) & 0x0f;
- switch (devtype & 0x0f) {
- case 0:
- major = "Miscellaneous";
- switch (minor) {
- case 0:
- subtype = "other";
- break;
- case 4:
- subtype = "Validation component";
- break;
- }
- break;
- case 1:
- major = "Trace Sink";
- switch (minor) {
- case 0:
- subtype = "other";
- break;
- case 1:
- subtype = "Port";
- break;
- case 2:
- subtype = "Buffer";
- break;
- case 3:
- subtype = "Router";
- break;
- }
- break;
- case 2:
- major = "Trace Link";
- switch (minor) {
- case 0:
- subtype = "other";
- break;
- case 1:
- subtype = "Funnel, router";
- break;
- case 2:
- subtype = "Filter";
- break;
- case 3:
- subtype = "FIFO, buffer";
- break;
- }
- break;
- case 3:
- major = "Trace Source";
- switch (minor) {
- case 0:
- subtype = "other";
- break;
- case 1:
- subtype = "Processor";
- break;
- case 2:
- subtype = "DSP";
- break;
- case 3:
- subtype = "Engine/Coprocessor";
- break;
- case 4:
- subtype = "Bus";
- break;
- case 6:
- subtype = "Software";
- break;
- }
- break;
- case 4:
- major = "Debug Control";
- switch (minor) {
- case 0:
- subtype = "other";
- break;
- case 1:
- subtype = "Trigger Matrix";
- break;
- case 2:
- subtype = "Debug Auth";
- break;
- case 3:
- subtype = "Power Requestor";
- break;
- }
- break;
- case 5:
- major = "Debug Logic";
- switch (minor) {
- case 0:
- subtype = "other";
- break;
- case 1:
- subtype = "Processor";
- break;
- case 2:
- subtype = "DSP";
- break;
- case 3:
- subtype = "Engine/Coprocessor";
- break;
- case 4:
- subtype = "Bus";
- break;
- case 5:
- subtype = "Memory";
- break;
- }
- break;
- case 6:
- major = "Perfomance Monitor";
- switch (minor) {
- case 0:
- subtype = "other";
- break;
- case 1:
- subtype = "Processor";
- break;
- case 2:
- subtype = "DSP";
- break;
- case 3:
- subtype = "Engine/Coprocessor";
- break;
- case 4:
- subtype = "Bus";
- break;
- case 5:
- subtype = "Memory";
- break;
- }
- break;
- }
- command_print(cmd_ctx, "\t\tType is 0x%02" PRIx8 ", %s, %s",
- (uint8_t)(devtype & 0xff),
- major, subtype);
- /* REVISIT also show 0xfc8 DevId */
- }
-
- return ERROR_OK;
-}
-
-static int dap_info_command(struct command_context *cmd_ctx,
- struct adiv5_ap *ap)
-{
- int retval;
- uint32_t dbgbase, apid;
- uint8_t mem_ap;
-
- /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */
- retval = dap_get_debugbase(ap, &dbgbase, &apid);
- if (retval != ERROR_OK)
- return retval;
-
- command_print(cmd_ctx, "AP ID register 0x%8.8" PRIx32, apid);
- if (apid == 0) {
- command_print(cmd_ctx, "No AP found at this ap 0x%x", ap->ap_num);
- return ERROR_FAIL;
- }
-
- switch (apid & (IDR_JEP106 | IDR_TYPE)) {
- case IDR_JEP106_ARM | AP_TYPE_JTAG_AP:
- command_print(cmd_ctx, "\tType is JTAG-AP");
- break;
- case IDR_JEP106_ARM | AP_TYPE_AHB_AP:
- command_print(cmd_ctx, "\tType is MEM-AP AHB");
- break;
- case IDR_JEP106_ARM | AP_TYPE_APB_AP:
- command_print(cmd_ctx, "\tType is MEM-AP APB");
- break;
- case IDR_JEP106_ARM | AP_TYPE_AXI_AP:
- command_print(cmd_ctx, "\tType is MEM-AP AXI");
- break;
- default:
- command_print(cmd_ctx, "\tUnknown AP type");
- break;
- }
-
- /* NOTE: a MEM-AP may have a single CoreSight component that's
- * not a ROM table ... or have no such components at all.
- */
- mem_ap = (apid & IDR_CLASS) == AP_CLASS_MEM_AP;
- if (mem_ap) {
- command_print(cmd_ctx, "MEM-AP BASE 0x%8.8" PRIx32, dbgbase);
-
- if (dbgbase == 0xFFFFFFFF || (dbgbase & 0x3) == 0x2) {
- command_print(cmd_ctx, "\tNo ROM table present");
- } else {
- if (dbgbase & 0x01)
- command_print(cmd_ctx, "\tValid ROM table present");
- else
- command_print(cmd_ctx, "\tROM table in legacy format");
-
- dap_rom_display(cmd_ctx, ap, dbgbase & 0xFFFFF000, 0);
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_dap_info_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
- uint32_t apsel;
-
- switch (CMD_ARGC) {
- case 0:
- apsel = dap->apsel;
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
- if (apsel >= 256)
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return dap_info_command(CMD_CTX, &dap->ap[apsel]);
-}
-
-COMMAND_HANDLER(dap_baseaddr_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t apsel, baseaddr;
- int retval;
-
- switch (CMD_ARGC) {
- case 0:
- apsel = dap->apsel;
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
- /* AP address is in bits 31:24 of DP_SELECT */
- if (apsel >= 256)
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* NOTE: assumes we're talking to a MEM-AP, which
- * has a base address. There are other kinds of AP,
- * though they're not common for now. This should
- * use the ID register to verify it's a MEM-AP.
- */
- retval = dap_queue_ap_read(dap_ap(dap, apsel), MEM_AP_REG_BASE, &baseaddr);
- if (retval != ERROR_OK)
- return retval;
- retval = dap_run(dap);
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "0x%8.8" PRIx32, baseaddr);
-
- return retval;
-}
-
-COMMAND_HANDLER(dap_memaccess_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t memaccess_tck;
-
- switch (CMD_ARGC) {
- case 0:
- memaccess_tck = dap->ap[dap->apsel].memaccess_tck;
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], memaccess_tck);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- dap->ap[dap->apsel].memaccess_tck = memaccess_tck;
-
- command_print(CMD_CTX, "memory bus access delay set to %" PRIi32 " tck",
- dap->ap[dap->apsel].memaccess_tck);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(dap_apsel_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t apsel, apid;
- int retval;
-
- switch (CMD_ARGC) {
- case 0:
- apsel = dap->apsel;
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
- /* AP address is in bits 31:24 of DP_SELECT */
- if (apsel >= 256)
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- dap->apsel = apsel;
-
- retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid);
- if (retval != ERROR_OK)
- return retval;
- retval = dap_run(dap);
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "ap %" PRIi32 " selected, identification register 0x%8.8" PRIx32,
- apsel, apid);
-
- return retval;
-}
-
-COMMAND_HANDLER(dap_apcsw_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t apcsw = dap->ap[dap->apsel].csw_default, sprot = 0;
-
- switch (CMD_ARGC) {
- case 0:
- command_print(CMD_CTX, "apsel %" PRIi32 " selected, csw 0x%8.8" PRIx32,
- (dap->apsel), apcsw);
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], sprot);
- /* AP address is in bits 31:24 of DP_SELECT */
- if (sprot > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (sprot)
- apcsw |= CSW_SPROT;
- else
- apcsw &= ~CSW_SPROT;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- dap->ap[dap->apsel].csw_default = apcsw;
-
- return 0;
-}
-
-
-
-COMMAND_HANDLER(dap_apid_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t apsel, apid;
- int retval;
-
- switch (CMD_ARGC) {
- case 0:
- apsel = dap->apsel;
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
- /* AP address is in bits 31:24 of DP_SELECT */
- if (apsel >= 256)
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid);
- if (retval != ERROR_OK)
- return retval;
- retval = dap_run(dap);
- if (retval != ERROR_OK)
- return retval;
-
- command_print(CMD_CTX, "0x%8.8" PRIx32, apid);
-
- return retval;
-}
-
-COMMAND_HANDLER(dap_apreg_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t apsel, reg, value;
- int retval;
-
- if (CMD_ARGC < 2 || CMD_ARGC > 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
- /* AP address is in bits 31:24 of DP_SELECT */
- if (apsel >= 256)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg);
- if (reg >= 256 || (reg & 3))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 3) {
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
- retval = dap_queue_ap_write(dap_ap(dap, apsel), reg, value);
- } else {
- retval = dap_queue_ap_read(dap_ap(dap, apsel), reg, &value);
- }
- if (retval == ERROR_OK)
- retval = dap_run(dap);
-
- if (retval != ERROR_OK)
- return retval;
-
- if (CMD_ARGC == 2)
- command_print(CMD_CTX, "0x%08" PRIx32, value);
-
- return retval;
-}
-
-COMMAND_HANDLER(dap_ti_be_32_quirks_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t enable = dap->ti_be_32_quirks;
-
- switch (CMD_ARGC) {
- case 0:
- break;
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], enable);
- if (enable > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- dap->ti_be_32_quirks = enable;
- command_print(CMD_CTX, "TI BE-32 quirks mode %s",
- enable ? "enabled" : "disabled");
-
- return 0;
-}
-
-static const struct command_registration dap_commands[] = {
- {
- .name = "info",
- .handler = handle_dap_info_command,
- .mode = COMMAND_EXEC,
- .help = "display ROM table for MEM-AP "
- "(default currently selected AP)",
- .usage = "[ap_num]",
- },
- {
- .name = "apsel",
- .handler = dap_apsel_command,
- .mode = COMMAND_EXEC,
- .help = "Set the currently selected AP (default 0) "
- "and display the result",
- .usage = "[ap_num]",
- },
- {
- .name = "apcsw",
- .handler = dap_apcsw_command,
- .mode = COMMAND_EXEC,
- .help = "Set csw access bit ",
- .usage = "[sprot]",
- },
-
- {
- .name = "apid",
- .handler = dap_apid_command,
- .mode = COMMAND_EXEC,
- .help = "return ID register from AP "
- "(default currently selected AP)",
- .usage = "[ap_num]",
- },
- {
- .name = "apreg",
- .handler = dap_apreg_command,
- .mode = COMMAND_EXEC,
- .help = "read/write a register from AP "
- "(reg is byte address of a word register, like 0 4 8...)",
- .usage = "ap_num reg [value]",
- },
- {
- .name = "baseaddr",
- .handler = dap_baseaddr_command,
- .mode = COMMAND_EXEC,
- .help = "return debug base address from MEM-AP "
- "(default currently selected AP)",
- .usage = "[ap_num]",
- },
- {
- .name = "memaccess",
- .handler = dap_memaccess_command,
- .mode = COMMAND_EXEC,
- .help = "set/get number of extra tck for MEM-AP memory "
- "bus access [0-255]",
- .usage = "[cycles]",
- },
- {
- .name = "ti_be_32_quirks",
- .handler = dap_ti_be_32_quirks_command,
- .mode = COMMAND_CONFIG,
- .help = "set/get quirks mode for TI TMS450/TMS570 processors",
- .usage = "[enable]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration dap_command_handlers[] = {
- {
- .name = "dap",
- .mode = COMMAND_EXEC,
- .help = "DAP command group",
- .usage = "",
- .chain = dap_commands,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h
deleted file mode 100644
index 3220d8b..0000000
--- a/src/target/arm_adi_v5.h
+++ /dev/null
@@ -1,507 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM_ADI_V5_H
-#define OPENOCD_TARGET_ARM_ADI_V5_H
-
-/**
- * @file
- * This defines formats and data structures used to talk to ADIv5 entities.
- * Those include a DAP, different types of Debug Port (DP), and memory mapped
- * resources accessed through a MEM-AP.
- */
-
-#include <helper/list.h>
-#include "arm_jtag.h"
-
-/* three-bit ACK values for SWD access (sent LSB first) */
-#define SWD_ACK_OK 0x1
-#define SWD_ACK_WAIT 0x2
-#define SWD_ACK_FAULT 0x4
-
-#define DPAP_WRITE 0
-#define DPAP_READ 1
-
-#define BANK_REG(bank, reg) (((bank) << 4) | (reg))
-
-/* A[3:0] for DP registers; A[1:0] are always zero.
- * - JTAG accesses all of these via JTAG_DP_DPACC, except for
- * IDCODE (JTAG_DP_IDCODE) and ABORT (JTAG_DP_ABORT).
- * - SWD accesses these directly, sometimes needing SELECT.DPBANKSEL
- */
-#define DP_DPIDR BANK_REG(0x0, 0x0) /* DPv1+: ro */
-#define DP_ABORT BANK_REG(0x0, 0x0) /* DPv1+: SWD: wo */
-#define DP_CTRL_STAT BANK_REG(0x0, 0x4) /* DPv0+: rw */
-#define DP_DLCR BANK_REG(0x1, 0x4) /* DPv1+: SWD: rw */
-#define DP_TARGETID BANK_REG(0x2, 0x4) /* DPv2: ro */
-#define DP_DLPIDR BANK_REG(0x3, 0x4) /* DPv2: ro */
-#define DP_EVENTSTAT BANK_REG(0x4, 0x4) /* DPv2: ro */
-#define DP_RESEND BANK_REG(0x0, 0x8) /* DPv1+: SWD: ro */
-#define DP_SELECT BANK_REG(0x0, 0x8) /* DPv0+: JTAG: rw; SWD: wo */
-#define DP_RDBUFF BANK_REG(0x0, 0xC) /* DPv0+: ro */
-#define DP_TARGETSEL BANK_REG(0x0, 0xC) /* DPv2: SWD: wo */
-
-#define DLCR_TO_TRN(dlcr) ((uint32_t)(1 + ((3 & (dlcr)) >> 8))) /* 1..4 clocks */
-
-/* Fields of the DP's AP ABORT register */
-#define DAPABORT (1UL << 0)
-#define STKCMPCLR (1UL << 1) /* SWD-only */
-#define STKERRCLR (1UL << 2) /* SWD-only */
-#define WDERRCLR (1UL << 3) /* SWD-only */
-#define ORUNERRCLR (1UL << 4) /* SWD-only */
-
-/* Fields of the DP's CTRL/STAT register */
-#define CORUNDETECT (1UL << 0)
-#define SSTICKYORUN (1UL << 1)
-/* 3:2 - transaction mode (e.g. pushed compare) */
-#define SSTICKYCMP (1UL << 4)
-#define SSTICKYERR (1UL << 5)
-#define READOK (1UL << 6) /* SWD-only */
-#define WDATAERR (1UL << 7) /* SWD-only */
-/* 11:8 - mask lanes for pushed compare or verify ops */
-/* 21:12 - transaction counter */
-#define CDBGRSTREQ (1UL << 26)
-#define CDBGRSTACK (1UL << 27)
-#define CDBGPWRUPREQ (1UL << 28)
-#define CDBGPWRUPACK (1UL << 29)
-#define CSYSPWRUPREQ (1UL << 30)
-#define CSYSPWRUPACK (1UL << 31)
-
-/* MEM-AP register addresses */
-#define MEM_AP_REG_CSW 0x00
-#define MEM_AP_REG_TAR 0x04
-#define MEM_AP_REG_TAR64 0x08 /* RW: Large Physical Address Extension */
-#define MEM_AP_REG_DRW 0x0C /* RW: Data Read/Write register */
-#define MEM_AP_REG_BD0 0x10 /* RW: Banked Data register 0-3 */
-#define MEM_AP_REG_BD1 0x14
-#define MEM_AP_REG_BD2 0x18
-#define MEM_AP_REG_BD3 0x1C
-#define MEM_AP_REG_MBT 0x20 /* --: Memory Barrier Transfer register */
-#define MEM_AP_REG_BASE64 0xF0 /* RO: Debug Base Address (LA) register */
-#define MEM_AP_REG_CFG 0xF4 /* RO: Configuration register */
-#define MEM_AP_REG_BASE 0xF8 /* RO: Debug Base Address register */
-/* Generic AP register address */
-#define AP_REG_IDR 0xFC /* RO: Identification Register */
-
-/* Fields of the MEM-AP's CSW register */
-#define CSW_8BIT 0
-#define CSW_16BIT 1
-#define CSW_32BIT 2
-#define CSW_ADDRINC_MASK (3UL << 4)
-#define CSW_ADDRINC_OFF 0UL
-#define CSW_ADDRINC_SINGLE (1UL << 4)
-#define CSW_ADDRINC_PACKED (2UL << 4)
-#define CSW_DEVICE_EN (1UL << 6)
-#define CSW_TRIN_PROG (1UL << 7)
-#define CSW_SPIDEN (1UL << 23)
-/* 30:24 - implementation-defined! */
-#define CSW_HPROT (1UL << 25) /* ? */
-#define CSW_MASTER_DEBUG (1UL << 29) /* ? */
-#define CSW_SPROT (1UL << 30)
-#define CSW_DBGSWENABLE (1UL << 31)
-
-/* Fields of the MEM-AP's IDR register */
-#define IDR_REV (0xFUL << 28)
-#define IDR_JEP106 (0x7FFUL << 17)
-#define IDR_CLASS (0xFUL << 13)
-#define IDR_VARIANT (0xFUL << 4)
-#define IDR_TYPE (0xFUL << 0)
-
-#define IDR_JEP106_ARM 0x04760000
-
-#define DP_SELECT_APSEL 0xFF000000
-#define DP_SELECT_APBANK 0x000000F0
-#define DP_SELECT_DPBANK 0x0000000F
-#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
-
-/**
- * This represents an ARM Debug Interface (v5) Access Port (AP).
- * Most common is a MEM-AP, for memory access.
- */
-struct adiv5_ap {
- /**
- * DAP this AP belongs to.
- */
- struct adiv5_dap *dap;
-
- /**
- * Number of this AP.
- */
- uint8_t ap_num;
-
- /**
- * Default value for (MEM-AP) AP_REG_CSW register.
- */
- uint32_t csw_default;
-
- /**
- * Cache for (MEM-AP) AP_REG_CSW register value. This is written to
- * configure an access mode, such as autoincrementing AP_REG_TAR during
- * word access. "-1" indicates no cached value.
- */
- uint32_t csw_value;
-
- /**
- * Cache for (MEM-AP) AP_REG_TAR register value This is written to
- * configure the address being read or written
- * "-1" indicates no cached value.
- */
- uint32_t tar_value;
-
- /**
- * Configures how many extra tck clocks are added after starting a
- * MEM-AP access before we try to read its status (and/or result).
- */
- uint32_t memaccess_tck;
-
- /* Size of TAR autoincrement block, ARM ADI Specification requires at least 10 bits */
- uint32_t tar_autoincr_block;
-
- /* true if packed transfers are supported by the MEM-AP */
- bool packed_transfers;
-
- /* true if unaligned memory access is not supported by the MEM-AP */
- bool unaligned_access_bad;
-};
-
-
-/**
- * This represents an ARM Debug Interface (v5) Debug Access Port (DAP).
- * A DAP has two types of component: one Debug Port (DP), which is a
- * transport agent; and at least one Access Port (AP), controlling
- * resource access.
- *
- * There are two basic DP transports: JTAG, and ARM's low pin-count SWD.
- * Accordingly, this interface is responsible for hiding the transport
- * differences so upper layer code can largely ignore them.
- *
- * When the chip is implemented with JTAG-DP or SW-DP, the transport is
- * fixed as JTAG or SWD, respectively. Chips incorporating SWJ-DP permit
- * a choice made at board design time (by only using the SWD pins), or
- * as part of setting up a debug session (if all the dual-role JTAG/SWD
- * signals are available).
- */
-struct adiv5_dap {
- const struct dap_ops *ops;
-
- /* dap transaction list for WAIT support */
- struct list_head cmd_journal;
-
- struct jtag_tap *tap;
- /* Control config */
- uint32_t dp_ctrl_stat;
-
- struct adiv5_ap ap[256];
-
- /* The current manually selected AP by the "dap apsel" command */
- uint32_t apsel;
-
- /**
- * Cache for DP_SELECT register. A value of DP_SELECT_INVALID
- * indicates no cached value and forces rewrite of the register.
- */
- uint32_t select;
-
- /* information about current pending SWjDP-AHBAP transaction */
- uint8_t ack;
-
- /**
- * Holds the pointer to the destination word for the last queued read,
- * for use with posted AP read sequence optimization.
- */
- uint32_t *last_read;
-
- /* The TI TMS470 and TMS570 series processors use a BE-32 memory ordering
- * despite lack of support in the ARMv7 architecture. Memory access through
- * the AHB-AP has strange byte ordering these processors, and we need to
- * swizzle appropriately. */
- bool ti_be_32_quirks;
-
- /**
- * Signals that an attempt to reestablish communication afresh
- * should be performed before the next access.
- */
- bool do_reconnect;
-};
-
-/**
- * Transport-neutral representation of queued DAP transactions, supporting
- * both JTAG and SWD transports. All submitted transactions are logically
- * queued, until the queue is executed by run(). Some implementations might
- * execute transactions as soon as they're submitted, but no status is made
- * available until run().
- */
-struct dap_ops {
- /** DP register read. */
- int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg,
- uint32_t *data);
- /** DP register write. */
- int (*queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
- uint32_t data);
-
- /** AP register read. */
- int (*queue_ap_read)(struct adiv5_ap *ap, unsigned reg,
- uint32_t *data);
- /** AP register write. */
- int (*queue_ap_write)(struct adiv5_ap *ap, unsigned reg,
- uint32_t data);
-
- /** AP operation abort. */
- int (*queue_ap_abort)(struct adiv5_dap *dap, uint8_t *ack);
-
- /** Executes all queued DAP operations. */
- int (*run)(struct adiv5_dap *dap);
-
- /** Executes all queued DAP operations but doesn't check
- * sticky error conditions */
- int (*sync)(struct adiv5_dap *dap);
-};
-
-/*
- * Access Port classes
- */
-enum ap_class {
- AP_CLASS_NONE = 0x00000, /* No class defined */
- AP_CLASS_MEM_AP = 0x10000, /* MEM-AP */
-};
-
-/*
- * Access Port types
- */
-enum ap_type {
- AP_TYPE_JTAG_AP = 0x0, /* JTAG-AP - JTAG master for controlling other JTAG devices */
- AP_TYPE_AHB_AP = 0x1, /* AHB Memory-AP */
- AP_TYPE_APB_AP = 0x2, /* APB Memory-AP */
- AP_TYPE_AXI_AP = 0x4, /* AXI Memory-AP */
-};
-
-/**
- * Queue a DP register read.
- * Note that not all DP registers are readable; also, that JTAG and SWD
- * have slight differences in DP register support.
- *
- * @param dap The DAP used for reading.
- * @param reg The two-bit number of the DP register being read.
- * @param data Pointer saying where to store the register's value
- * (in host endianness).
- *
- * @return ERROR_OK for success, else a fault code.
- */
-static inline int dap_queue_dp_read(struct adiv5_dap *dap,
- unsigned reg, uint32_t *data)
-{
- assert(dap->ops != NULL);
- return dap->ops->queue_dp_read(dap, reg, data);
-}
-
-/**
- * Queue a DP register write.
- * Note that not all DP registers are writable; also, that JTAG and SWD
- * have slight differences in DP register support.
- *
- * @param dap The DAP used for writing.
- * @param reg The two-bit number of the DP register being written.
- * @param data Value being written (host endianness)
- *
- * @return ERROR_OK for success, else a fault code.
- */
-static inline int dap_queue_dp_write(struct adiv5_dap *dap,
- unsigned reg, uint32_t data)
-{
- assert(dap->ops != NULL);
- return dap->ops->queue_dp_write(dap, reg, data);
-}
-
-/**
- * Queue an AP register read.
- *
- * @param ap The AP used for reading.
- * @param reg The number of the AP register being read.
- * @param data Pointer saying where to store the register's value
- * (in host endianness).
- *
- * @return ERROR_OK for success, else a fault code.
- */
-static inline int dap_queue_ap_read(struct adiv5_ap *ap,
- unsigned reg, uint32_t *data)
-{
- assert(ap->dap->ops != NULL);
- return ap->dap->ops->queue_ap_read(ap, reg, data);
-}
-
-/**
- * Queue an AP register write.
- *
- * @param ap The AP used for writing.
- * @param reg The number of the AP register being written.
- * @param data Value being written (host endianness)
- *
- * @return ERROR_OK for success, else a fault code.
- */
-static inline int dap_queue_ap_write(struct adiv5_ap *ap,
- unsigned reg, uint32_t data)
-{
- assert(ap->dap->ops != NULL);
- return ap->dap->ops->queue_ap_write(ap, reg, data);
-}
-
-/**
- * Queue an AP abort operation. The current AP transaction is aborted,
- * including any update of the transaction counter. The AP is left in
- * an unknown state (so it must be re-initialized). For use only after
- * the AP has reported WAIT status for an extended period.
- *
- * @param dap The DAP used for writing.
- * @param ack Pointer to where transaction status will be stored.
- *
- * @return ERROR_OK for success, else a fault code.
- */
-static inline int dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
-{
- assert(dap->ops != NULL);
- return dap->ops->queue_ap_abort(dap, ack);
-}
-
-/**
- * Perform all queued DAP operations, and clear any errors posted in the
- * CTRL_STAT register when they are done. Note that if more than one AP
- * operation will be queued, one of the first operations in the queue
- * should probably enable CORUNDETECT in the CTRL/STAT register.
- *
- * @param dap The DAP used.
- *
- * @return ERROR_OK for success, else a fault code.
- */
-static inline int dap_run(struct adiv5_dap *dap)
-{
- assert(dap->ops != NULL);
- return dap->ops->run(dap);
-}
-
-static inline int dap_sync(struct adiv5_dap *dap)
-{
- assert(dap->ops != NULL);
- if (dap->ops->sync)
- return dap->ops->sync(dap);
- return ERROR_OK;
-}
-
-static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned reg,
- uint32_t *value)
-{
- int retval;
-
- retval = dap_queue_dp_read(dap, reg, value);
- if (retval != ERROR_OK)
- return retval;
-
- return dap_run(dap);
-}
-
-static inline int dap_dp_poll_register(struct adiv5_dap *dap, unsigned reg,
- uint32_t mask, uint32_t value, int timeout)
-{
- assert(timeout > 0);
- assert((value & mask) == value);
-
- int ret;
- uint32_t regval;
- LOG_DEBUG("DAP: poll %x, mask 0x%08" PRIx32 ", value 0x%08" PRIx32,
- reg, mask, value);
- do {
- ret = dap_dp_read_atomic(dap, reg, &regval);
- if (ret != ERROR_OK)
- return ret;
-
- if ((regval & mask) == value)
- break;
-
- alive_sleep(10);
- } while (--timeout);
-
- if (!timeout) {
- LOG_DEBUG("DAP: poll %x timeout", reg);
- return ERROR_WAIT;
- } else {
- return ERROR_OK;
- }
-}
-
-/* Queued MEM-AP memory mapped single word transfers. */
-int mem_ap_read_u32(struct adiv5_ap *ap,
- uint32_t address, uint32_t *value);
-int mem_ap_write_u32(struct adiv5_ap *ap,
- uint32_t address, uint32_t value);
-
-/* Synchronous MEM-AP memory mapped single word transfers. */
-int mem_ap_read_atomic_u32(struct adiv5_ap *ap,
- uint32_t address, uint32_t *value);
-int mem_ap_write_atomic_u32(struct adiv5_ap *ap,
- uint32_t address, uint32_t value);
-
-/* Synchronous MEM-AP memory mapped bus block transfers. */
-int mem_ap_read_buf(struct adiv5_ap *ap,
- uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
-int mem_ap_write_buf(struct adiv5_ap *ap,
- const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
-
-/* Synchronous, non-incrementing buffer functions for accessing fifos. */
-int mem_ap_read_buf_noincr(struct adiv5_ap *ap,
- uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
-int mem_ap_write_buf_noincr(struct adiv5_ap *ap,
- const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
-
-/* Create DAP struct */
-struct adiv5_dap *dap_init(void);
-
-/* Initialisation of the debug system, power domains and registers */
-int dap_dp_init(struct adiv5_dap *dap);
-int mem_ap_init(struct adiv5_ap *ap);
-
-/* Probe the AP for ROM Table location */
-int dap_get_debugbase(struct adiv5_ap *ap,
- uint32_t *dbgbase, uint32_t *apid);
-
-/* Probe Access Ports to find a particular type */
-int dap_find_ap(struct adiv5_dap *dap,
- enum ap_type type_to_find,
- struct adiv5_ap **ap_out);
-
-static inline struct adiv5_ap *dap_ap(struct adiv5_dap *dap, uint8_t ap_num)
-{
- return &dap->ap[ap_num];
-}
-
-/* Lookup CoreSight component */
-int dap_lookup_cs_component(struct adiv5_ap *ap,
- uint32_t dbgbase, uint8_t type, uint32_t *addr, int32_t *idx);
-
-struct target;
-
-/* Put debug link into SWD mode */
-int dap_to_swd(struct target *target);
-
-/* Put debug link into JTAG mode */
-int dap_to_jtag(struct target *target);
-
-extern const struct command_registration dap_command_handlers[];
-
-#endif /* OPENOCD_TARGET_ARM_ADI_V5_H */
diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c
deleted file mode 100644
index 5277b94..0000000
--- a/src/target/arm_disassembler.c
+++ /dev/null
@@ -1,4465 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2009 by David Brownell *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "arm_disassembler.h"
-#include <helper/log.h>
-
-/*
- * This disassembler supports two main functions for OpenOCD:
- *
- * - Various "disassemble" commands. OpenOCD can serve as a
- * machine-language debugger, without help from GDB.
- *
- * - Single stepping. Not all ARM cores support hardware single
- * stepping. To work without that support, the debugger must
- * be able to decode instructions to find out where to put a
- * "next instruction" breakpoint.
- *
- * In addition, interpretation of ETM trace data needs some of the
- * decoding mechanisms.
- *
- * At this writing (September 2009) neither function is complete.
- *
- * - ARM decoding
- * * Old-style syntax (not UAL) is generally used
- * * VFP instructions are not understood (ARMv5 and later)
- * except as coprocessor 10/11 operations
- * * Most ARM instructions through ARMv6 are decoded, but some
- * of the post-ARMv4 opcodes may not be handled yet
- * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
- * * NEON instructions are not understood (ARMv7-A)
- *
- * - Thumb/Thumb2 decoding
- * * UAL syntax should be consistently used
- * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
- * be handled properly. Accordingly, so should the subset
- * used in Cortex-M0/M1; and "original" 16-bit Thumb from
- * ARMv4T and ARMv5T.
- * * Conditional effects of Thumb2 "IT" (if-then) instructions
- * are not handled: the affected instructions are not shown
- * with their now-conditional suffixes.
- * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
- * handled (minimally for coprocessor access).
- * * SIMD instructions, and some other Thumb2 instructions
- * from ARMv7-A, are not understood.
- *
- * - ThumbEE decoding
- * * As a Thumb2 variant, the Thumb2 comments (above) apply.
- * * Opcodes changed by ThumbEE mode are not handled; these
- * instructions wrongly decode as LDM and STM.
- *
- * - Jazelle decoding ... no support whatsoever for Jazelle mode
- * or decoding. ARM encourages use of the more generic ThumbEE
- * mode, instead of Jazelle mode, in current chips.
- *
- * - Single-step/emulation ... spotty support, which is only weakly
- * tested. Thumb2 is not supported. (Arguably a full simulator
- * is not needed to support just single stepping. Recognizing
- * branch vs non-branch instructions suffices, except when the
- * instruction faults and triggers a synchronous exception which
- * can be intercepted using other means.)
- *
- * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
- * ARM v7-R edition" gives the most complete coverage of the various
- * generations of ARM instructions. At this writing it is publicly
- * accessible to anyone willing to create an account at the ARM
- * web site; see http://www.arm.com/documentation/ for information.
- *
- * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
- * more details relevant to the Thumb2-only processors (such as
- * the Cortex-M implementations).
- */
-
-/* textual represenation of the condition field
- * ALways (default) is ommitted (empty string) */
-static const char *arm_condition_strings[] = {
- "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
-};
-
-/* make up for C's missing ROR */
-static uint32_t ror(uint32_t value, int places)
-{
- return (value >> places) | (value << (32 - places));
-}
-
-static int evaluate_unknown(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tUNDEFINED INSTRUCTION", address, opcode);
- return ERROR_OK;
-}
-
-static int evaluate_pld(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- /* PLD */
- if ((opcode & 0x0d70f000) == 0x0550f000) {
- instruction->type = ARM_PLD;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...",
- address,
- opcode);
-
- return ERROR_OK;
- }
- return evaluate_unknown(opcode, address, instruction);
-}
-
-static int evaluate_srs(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- const char *wback = (opcode & (1 << 21)) ? "!" : "";
- const char *mode = "";
-
- switch ((opcode >> 23) & 0x3) {
- case 0:
- mode = "DA";
- break;
- case 1:
- /* "IA" is default */
- break;
- case 2:
- mode = "DB";
- break;
- case 3:
- mode = "IB";
- break;
- }
-
- switch (opcode & 0x0e500000) {
- case 0x08400000:
- snprintf(instruction->text, 128, "0x%8.8" PRIx32
- "\t0x%8.8" PRIx32
- "\tSRS%s\tSP%s, #%d",
- address, opcode,
- mode, wback,
- (unsigned)(opcode & 0x1f));
- break;
- case 0x08100000:
- snprintf(instruction->text, 128, "0x%8.8" PRIx32
- "\t0x%8.8" PRIx32
- "\tRFE%s\tr%d%s",
- address, opcode,
- mode,
- (unsigned)((opcode >> 16) & 0xf), wback);
- break;
- default:
- return evaluate_unknown(opcode, address, instruction);
- }
- return ERROR_OK;
-}
-
-static int evaluate_swi(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- instruction->type = ARM_SWI;
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
- address, opcode, (opcode & 0xffffff));
-
- return ERROR_OK;
-}
-
-static int evaluate_blx_imm(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- int offset;
- uint32_t immediate;
- uint32_t target_address;
-
- instruction->type = ARM_BLX;
- immediate = opcode & 0x00ffffff;
-
- /* sign extend 24-bit immediate */
- if (immediate & 0x00800000)
- offset = 0xff000000 | immediate;
- else
- offset = immediate;
-
- /* shift two bits left */
- offset <<= 2;
-
- /* odd/event halfword */
- if (opcode & 0x01000000)
- offset |= 0x2;
-
- target_address = address + 8 + offset;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "",
- address,
- opcode,
- target_address);
-
- instruction->info.b_bl_bx_blx.reg_operand = -1;
- instruction->info.b_bl_bx_blx.target_address = target_address;
-
- return ERROR_OK;
-}
-
-static int evaluate_b_bl(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t L;
- uint32_t immediate;
- int offset;
- uint32_t target_address;
-
- immediate = opcode & 0x00ffffff;
- L = (opcode & 0x01000000) >> 24;
-
- /* sign extend 24-bit immediate */
- if (immediate & 0x00800000)
- offset = 0xff000000 | immediate;
- else
- offset = immediate;
-
- /* shift two bits left */
- offset <<= 2;
-
- target_address = address + 8 + offset;
-
- if (L)
- instruction->type = ARM_BL;
- else
- instruction->type = ARM_B;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
- address,
- opcode,
- (L) ? "L" : "",
- COND(opcode),
- target_address);
-
- instruction->info.b_bl_bx_blx.reg_operand = -1;
- instruction->info.b_bl_bx_blx.target_address = target_address;
-
- return ERROR_OK;
-}
-
-/* Coprocessor load/store and double register transfers
- * both normal and extended instruction space (condition field b1111) */
-static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t cp_num = (opcode & 0xf00) >> 8;
-
- /* MCRR or MRRC */
- if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
- uint8_t cp_opcode, Rd, Rn, CRm;
- char *mnemonic;
-
- cp_opcode = (opcode & 0xf0) >> 4;
- Rd = (opcode & 0xf000) >> 12;
- Rn = (opcode & 0xf0000) >> 16;
- CRm = (opcode & 0xf);
-
- /* MCRR */
- if ((opcode & 0x0ff00000) == 0x0c400000) {
- instruction->type = ARM_MCRR;
- mnemonic = "MCRR";
- } else if ((opcode & 0x0ff00000) == 0x0c500000) {
- /* MRRC */
- instruction->type = ARM_MRRC;
- mnemonic = "MRRC";
- } else {
- LOG_ERROR("Unknown instruction");
- return ERROR_FAIL;
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\t%s%s%s p%i, %x, r%i, r%i, c%i",
- address, opcode, mnemonic,
- ((opcode & 0xf0000000) == 0xf0000000)
- ? "2" : COND(opcode),
- COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
- } else {/* LDC or STC */
- uint8_t CRd, Rn, offset;
- uint8_t U;
- char *mnemonic;
- char addressing_mode[32];
-
- CRd = (opcode & 0xf000) >> 12;
- Rn = (opcode & 0xf0000) >> 16;
- offset = (opcode & 0xff) << 2;
-
- /* load/store */
- if (opcode & 0x00100000) {
- instruction->type = ARM_LDC;
- mnemonic = "LDC";
- } else {
- instruction->type = ARM_STC;
- mnemonic = "STC";
- }
-
- U = (opcode & 0x00800000) >> 23;
-
- /* addressing modes */
- if ((opcode & 0x01200000) == 0x01000000)/* offset */
- snprintf(addressing_mode, 32, "[r%i, #%s%d]",
- Rn, U ? "" : "-", offset);
- else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
- snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
- Rn, U ? "" : "-", offset);
- else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
- snprintf(addressing_mode, 32, "[r%i], #%s%d",
- Rn, U ? "" : "-", offset);
- else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
- snprintf(addressing_mode, 32, "[r%i], {%d}",
- Rn, offset >> 2);
-
- snprintf(instruction->text, 128, "0x%8.8" PRIx32
- "\t0x%8.8" PRIx32
- "\t%s%s%s p%i, c%i, %s",
- address, opcode, mnemonic,
- ((opcode & 0xf0000000) == 0xf0000000)
- ? "2" : COND(opcode),
- (opcode & (1 << 22)) ? "L" : "",
- cp_num, CRd, addressing_mode);
- }
-
- return ERROR_OK;
-}
-
-/* Coprocessor data processing instructions
- * Coprocessor register transfer instructions
- * both normal and extended instruction space (condition field b1111) */
-static int evaluate_cdp_mcr_mrc(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- const char *cond;
- char *mnemonic;
- uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
-
- cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
- cp_num = (opcode & 0xf00) >> 8;
- CRd_Rd = (opcode & 0xf000) >> 12;
- CRn = (opcode & 0xf0000) >> 16;
- CRm = (opcode & 0xf);
- opcode_2 = (opcode & 0xe0) >> 5;
-
- /* CDP or MRC/MCR */
- if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
- if (opcode & 0x00100000) { /* bit 20 set -> MRC */
- instruction->type = ARM_MRC;
- mnemonic = "MRC";
- } else {/* bit 20 not set -> MCR */
- instruction->type = ARM_MCR;
- mnemonic = "MCR";
- }
-
- opcode_1 = (opcode & 0x00e00000) >> 21;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
- address,
- opcode,
- mnemonic,
- cond,
- cp_num,
- opcode_1,
- CRd_Rd,
- CRn,
- CRm,
- opcode_2);
- } else {/* bit 4 not set -> CDP */
- instruction->type = ARM_CDP;
- mnemonic = "CDP";
-
- opcode_1 = (opcode & 0x00f00000) >> 20;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
- address,
- opcode,
- mnemonic,
- cond,
- cp_num,
- opcode_1,
- CRd_Rd,
- CRn,
- CRm,
- opcode_2);
- }
-
- return ERROR_OK;
-}
-
-/* Load/store instructions */
-static int evaluate_load_store(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t I, P, U, B, W, L;
- uint8_t Rn, Rd;
- char *operation;/* "LDR" or "STR" */
- char *suffix; /* "", "B", "T", "BT" */
- char offset[32];
-
- /* examine flags */
- I = (opcode & 0x02000000) >> 25;
- P = (opcode & 0x01000000) >> 24;
- U = (opcode & 0x00800000) >> 23;
- B = (opcode & 0x00400000) >> 22;
- W = (opcode & 0x00200000) >> 21;
- L = (opcode & 0x00100000) >> 20;
-
- /* target register */
- Rd = (opcode & 0xf000) >> 12;
-
- /* base register */
- Rn = (opcode & 0xf0000) >> 16;
-
- instruction->info.load_store.Rd = Rd;
- instruction->info.load_store.Rn = Rn;
- instruction->info.load_store.U = U;
-
- /* determine operation */
- if (L)
- operation = "LDR";
- else
- operation = "STR";
-
- /* determine instruction type and suffix */
- if (B) {
- if ((P == 0) && (W == 1)) {
- if (L)
- instruction->type = ARM_LDRBT;
- else
- instruction->type = ARM_STRBT;
- suffix = "BT";
- } else {
- if (L)
- instruction->type = ARM_LDRB;
- else
- instruction->type = ARM_STRB;
- suffix = "B";
- }
- } else {
- if ((P == 0) && (W == 1)) {
- if (L)
- instruction->type = ARM_LDRT;
- else
- instruction->type = ARM_STRT;
- suffix = "T";
- } else {
- if (L)
- instruction->type = ARM_LDR;
- else
- instruction->type = ARM_STR;
- suffix = "";
- }
- }
-
- if (!I) { /* #+-<offset_12> */
- uint32_t offset_12 = (opcode & 0xfff);
- if (offset_12)
- snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
- else
- snprintf(offset, 32, "%s", "");
-
- instruction->info.load_store.offset_mode = 0;
- instruction->info.load_store.offset.offset = offset_12;
- } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
- uint8_t shift_imm, shift;
- uint8_t Rm;
-
- shift_imm = (opcode & 0xf80) >> 7;
- shift = (opcode & 0x60) >> 5;
- Rm = (opcode & 0xf);
-
- /* LSR encodes a shift by 32 bit as 0x0 */
- if ((shift == 0x1) && (shift_imm == 0x0))
- shift_imm = 0x20;
-
- /* ASR encodes a shift by 32 bit as 0x0 */
- if ((shift == 0x2) && (shift_imm == 0x0))
- shift_imm = 0x20;
-
- /* ROR by 32 bit is actually a RRX */
- if ((shift == 0x3) && (shift_imm == 0x0))
- shift = 0x4;
-
- instruction->info.load_store.offset_mode = 1;
- instruction->info.load_store.offset.reg.Rm = Rm;
- instruction->info.load_store.offset.reg.shift = shift;
- instruction->info.load_store.offset.reg.shift_imm = shift_imm;
-
- if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
- snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
- else { /* +-<Rm>, <Shift>, #<shift_imm> */
- switch (shift) {
- case 0x0: /* LSL */
- snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
- break;
- case 0x1: /* LSR */
- snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
- break;
- case 0x2: /* ASR */
- snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
- break;
- case 0x3: /* ROR */
- snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
- break;
- case 0x4: /* RRX */
- snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
- break;
- }
- }
- }
-
- if (P == 1) {
- if (W == 0) { /* offset */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
- address,
- opcode,
- operation,
- COND(opcode),
- suffix,
- Rd,
- Rn,
- offset);
-
- instruction->info.load_store.index_mode = 0;
- } else {/* pre-indexed */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
- address,
- opcode,
- operation,
- COND(opcode),
- suffix,
- Rd,
- Rn,
- offset);
-
- instruction->info.load_store.index_mode = 1;
- }
- } else {/* post-indexed */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
- address,
- opcode,
- operation,
- COND(opcode),
- suffix,
- Rd,
- Rn,
- offset);
-
- instruction->info.load_store.index_mode = 2;
- }
-
- return ERROR_OK;
-}
-
-static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
-{
- unsigned rm = (opcode >> 0) & 0xf;
- unsigned rd = (opcode >> 12) & 0xf;
- unsigned rn = (opcode >> 16) & 0xf;
- char *type, *rot;
-
- switch ((opcode >> 24) & 0x3) {
- case 0:
- type = "B16";
- break;
- case 1:
- sprintf(cp, "UNDEFINED");
- return ARM_UNDEFINED_INSTRUCTION;
- case 2:
- type = "B";
- break;
- default:
- type = "H";
- break;
- }
-
- switch ((opcode >> 10) & 0x3) {
- case 0:
- rot = "";
- break;
- case 1:
- rot = ", ROR #8";
- break;
- case 2:
- rot = ", ROR #16";
- break;
- default:
- rot = ", ROR #24";
- break;
- }
-
- if (rn == 0xf) {
- sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
- (opcode & (1 << 22)) ? 'U' : 'S',
- type, COND(opcode),
- rd, rm, rot);
- return ARM_MOV;
- } else {
- sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
- (opcode & (1 << 22)) ? 'U' : 'S',
- type, COND(opcode),
- rd, rn, rm, rot);
- return ARM_ADD;
- }
-}
-
-static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
-{
- char *prefix;
- char *op;
- int type;
-
- switch ((opcode >> 20) & 0x7) {
- case 1:
- prefix = "S";
- break;
- case 2:
- prefix = "Q";
- break;
- case 3:
- prefix = "SH";
- break;
- case 5:
- prefix = "U";
- break;
- case 6:
- prefix = "UQ";
- break;
- case 7:
- prefix = "UH";
- break;
- default:
- goto undef;
- }
-
- switch ((opcode >> 5) & 0x7) {
- case 0:
- op = "ADD16";
- type = ARM_ADD;
- break;
- case 1:
- op = "ADDSUBX";
- type = ARM_ADD;
- break;
- case 2:
- op = "SUBADDX";
- type = ARM_SUB;
- break;
- case 3:
- op = "SUB16";
- type = ARM_SUB;
- break;
- case 4:
- op = "ADD8";
- type = ARM_ADD;
- break;
- case 7:
- op = "SUB8";
- type = ARM_SUB;
- break;
- default:
- goto undef;
- }
-
- sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
- (int) (opcode >> 12) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf);
- return type;
-
-undef:
- /* these opcodes might be used someday */
- sprintf(cp, "UNDEFINED");
- return ARM_UNDEFINED_INSTRUCTION;
-}
-
-/* ARMv6 and later support "media" instructions (includes SIMD) */
-static int evaluate_media(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- char *cp = instruction->text;
- char *mnemonic = NULL;
-
- sprintf(cp,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
- address, opcode);
- cp = strchr(cp, 0);
-
- /* parallel add/subtract */
- if ((opcode & 0x01800000) == 0x00000000) {
- instruction->type = evaluate_p_add_sub(opcode, address, cp);
- return ERROR_OK;
- }
-
- /* halfword pack */
- if ((opcode & 0x01f00020) == 0x00800000) {
- char *type, *shift;
- unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
-
- if (opcode & (1 << 6)) {
- type = "TB";
- shift = "ASR";
- if (imm == 0)
- imm = 32;
- } else {
- type = "BT";
- shift = "LSL";
- }
- sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
- type, COND(opcode),
- (int) (opcode >> 12) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- shift, imm);
- return ERROR_OK;
- }
-
- /* word saturate */
- if ((opcode & 0x01a00020) == 0x00a00000) {
- char *shift;
- unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
-
- if (opcode & (1 << 6)) {
- shift = "ASR";
- if (imm == 0)
- imm = 32;
- } else
- shift = "LSL";
-
- sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
- (opcode & (1 << 22)) ? 'U' : 'S',
- COND(opcode),
- (int) (opcode >> 12) & 0xf,
- (int) (opcode >> 16) & 0x1f,
- (int) (opcode >> 0) & 0xf,
- shift, imm);
- return ERROR_OK;
- }
-
- /* sign extension */
- if ((opcode & 0x018000f0) == 0x00800070) {
- instruction->type = evaluate_extend(opcode, address, cp);
- return ERROR_OK;
- }
-
- /* multiplies */
- if ((opcode & 0x01f00080) == 0x01000000) {
- unsigned rn = (opcode >> 12) & 0xf;
-
- if (rn != 0xf)
- sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
- (opcode & (1 << 6)) ? 'S' : 'A',
- (opcode & (1 << 5)) ? "X" : "",
- COND(opcode),
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 8) & 0xf,
- rn);
- else
- sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
- (opcode & (1 << 6)) ? 'S' : 'A',
- (opcode & (1 << 5)) ? "X" : "",
- COND(opcode),
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 8) & 0xf);
- return ERROR_OK;
- }
- if ((opcode & 0x01f00000) == 0x01400000) {
- sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
- (opcode & (1 << 6)) ? 'S' : 'A',
- (opcode & (1 << 5)) ? "X" : "",
- COND(opcode),
- (int) (opcode >> 12) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 8) & 0xf);
- return ERROR_OK;
- }
- if ((opcode & 0x01f00000) == 0x01500000) {
- unsigned rn = (opcode >> 12) & 0xf;
-
- switch (opcode & 0xc0) {
- case 3:
- if (rn == 0xf)
- goto undef;
- /* FALL THROUGH */
- case 0:
- break;
- default:
- goto undef;
- }
-
- if (rn != 0xf)
- sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
- (opcode & (1 << 6)) ? 'S' : 'A',
- (opcode & (1 << 5)) ? "R" : "",
- COND(opcode),
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 8) & 0xf,
- rn);
- else
- sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
- (opcode & (1 << 5)) ? "R" : "",
- COND(opcode),
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 8) & 0xf);
- return ERROR_OK;
- }
-
- /* simple matches against the remaining decode bits */
- switch (opcode & 0x01f000f0) {
- case 0x00a00030:
- case 0x00e00030:
- /* parallel halfword saturate */
- sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
- (opcode & (1 << 22)) ? 'U' : 'S',
- COND(opcode),
- (int) (opcode >> 12) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf);
- return ERROR_OK;
- case 0x00b00030:
- mnemonic = "REV";
- break;
- case 0x00b000b0:
- mnemonic = "REV16";
- break;
- case 0x00f000b0:
- mnemonic = "REVSH";
- break;
- case 0x008000b0:
- /* select bytes */
- sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
- (int) (opcode >> 12) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf);
- return ERROR_OK;
- case 0x01800010:
- /* unsigned sum of absolute differences */
- if (((opcode >> 12) & 0xf) == 0xf)
- sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 8) & 0xf);
- else
- sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 12) & 0xf);
- return ERROR_OK;
- }
- if (mnemonic) {
- unsigned rm = (opcode >> 0) & 0xf;
- unsigned rd = (opcode >> 12) & 0xf;
-
- sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
- return ERROR_OK;
- }
-
-undef:
- /* these opcodes might be used someday */
- sprintf(cp, "UNDEFINED");
- return ERROR_OK;
-}
-
-/* Miscellaneous load/store instructions */
-static int evaluate_misc_load_store(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t P, U, I, W, L, S, H;
- uint8_t Rn, Rd;
- char *operation;/* "LDR" or "STR" */
- char *suffix; /* "H", "SB", "SH", "D" */
- char offset[32];
-
- /* examine flags */
- P = (opcode & 0x01000000) >> 24;
- U = (opcode & 0x00800000) >> 23;
- I = (opcode & 0x00400000) >> 22;
- W = (opcode & 0x00200000) >> 21;
- L = (opcode & 0x00100000) >> 20;
- S = (opcode & 0x00000040) >> 6;
- H = (opcode & 0x00000020) >> 5;
-
- /* target register */
- Rd = (opcode & 0xf000) >> 12;
-
- /* base register */
- Rn = (opcode & 0xf0000) >> 16;
-
- instruction->info.load_store.Rd = Rd;
- instruction->info.load_store.Rn = Rn;
- instruction->info.load_store.U = U;
-
- /* determine instruction type and suffix */
- if (S) {/* signed */
- if (L) {/* load */
- if (H) {
- operation = "LDR";
- instruction->type = ARM_LDRSH;
- suffix = "SH";
- } else {
- operation = "LDR";
- instruction->type = ARM_LDRSB;
- suffix = "SB";
- }
- } else {/* there are no signed stores, so this is used to encode double-register
- *load/stores */
- suffix = "D";
- if (H) {
- operation = "STR";
- instruction->type = ARM_STRD;
- } else {
- operation = "LDR";
- instruction->type = ARM_LDRD;
- }
- }
- } else {/* unsigned */
- suffix = "H";
- if (L) {/* load */
- operation = "LDR";
- instruction->type = ARM_LDRH;
- } else {/* store */
- operation = "STR";
- instruction->type = ARM_STRH;
- }
- }
-
- if (I) {/* Immediate offset/index (#+-<offset_8>)*/
- uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
- snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
-
- instruction->info.load_store.offset_mode = 0;
- instruction->info.load_store.offset.offset = offset_8;
- } else {/* Register offset/index (+-<Rm>) */
- uint8_t Rm;
- Rm = (opcode & 0xf);
- snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
-
- instruction->info.load_store.offset_mode = 1;
- instruction->info.load_store.offset.reg.Rm = Rm;
- instruction->info.load_store.offset.reg.shift = 0x0;
- instruction->info.load_store.offset.reg.shift_imm = 0x0;
- }
-
- if (P == 1) {
- if (W == 0) { /* offset */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
- address,
- opcode,
- operation,
- COND(opcode),
- suffix,
- Rd,
- Rn,
- offset);
-
- instruction->info.load_store.index_mode = 0;
- } else {/* pre-indexed */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
- address,
- opcode,
- operation,
- COND(opcode),
- suffix,
- Rd,
- Rn,
- offset);
-
- instruction->info.load_store.index_mode = 1;
- }
- } else {/* post-indexed */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
- address,
- opcode,
- operation,
- COND(opcode),
- suffix,
- Rd,
- Rn,
- offset);
-
- instruction->info.load_store.index_mode = 2;
- }
-
- return ERROR_OK;
-}
-
-/* Load/store multiples instructions */
-static int evaluate_ldm_stm(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t P, U, S, W, L, Rn;
- uint32_t register_list;
- char *addressing_mode;
- char *mnemonic;
- char reg_list[69];
- char *reg_list_p;
- int i;
- int first_reg = 1;
-
- P = (opcode & 0x01000000) >> 24;
- U = (opcode & 0x00800000) >> 23;
- S = (opcode & 0x00400000) >> 22;
- W = (opcode & 0x00200000) >> 21;
- L = (opcode & 0x00100000) >> 20;
- register_list = (opcode & 0xffff);
- Rn = (opcode & 0xf0000) >> 16;
-
- instruction->info.load_store_multiple.Rn = Rn;
- instruction->info.load_store_multiple.register_list = register_list;
- instruction->info.load_store_multiple.S = S;
- instruction->info.load_store_multiple.W = W;
-
- if (L) {
- instruction->type = ARM_LDM;
- mnemonic = "LDM";
- } else {
- instruction->type = ARM_STM;
- mnemonic = "STM";
- }
-
- if (P) {
- if (U) {
- instruction->info.load_store_multiple.addressing_mode = 1;
- addressing_mode = "IB";
- } else {
- instruction->info.load_store_multiple.addressing_mode = 3;
- addressing_mode = "DB";
- }
- } else {
- if (U) {
- instruction->info.load_store_multiple.addressing_mode = 0;
- /* "IA" is the default in UAL syntax */
- addressing_mode = "";
- } else {
- instruction->info.load_store_multiple.addressing_mode = 2;
- addressing_mode = "DA";
- }
- }
-
- reg_list_p = reg_list;
- for (i = 0; i <= 15; i++) {
- if ((register_list >> i) & 1) {
- if (first_reg) {
- first_reg = 0;
- reg_list_p += snprintf(reg_list_p,
- (reg_list + 69 - reg_list_p),
- "r%i",
- i);
- } else
- reg_list_p += snprintf(reg_list_p,
- (reg_list + 69 - reg_list_p),
- ", r%i",
- i);
- }
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\t%s%s%s r%i%s, {%s}%s",
- address, opcode,
- mnemonic, addressing_mode, COND(opcode),
- Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
-
- return ERROR_OK;
-}
-
-/* Multiplies, extra load/stores */
-static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- /* Multiply (accumulate) (long) and Swap/swap byte */
- if ((opcode & 0x000000f0) == 0x00000090) {
- /* Multiply (accumulate) */
- if ((opcode & 0x0f800000) == 0x00000000) {
- uint8_t Rm, Rs, Rn, Rd, S;
- Rm = opcode & 0xf;
- Rs = (opcode & 0xf00) >> 8;
- Rn = (opcode & 0xf000) >> 12;
- Rd = (opcode & 0xf0000) >> 16;
- S = (opcode & 0x00100000) >> 20;
-
- /* examine A bit (accumulate) */
- if (opcode & 0x00200000) {
- instruction->type = ARM_MLA;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
- address,
- opcode,
- COND(opcode),
- (S) ? "S" : "",
- Rd,
- Rm,
- Rs,
- Rn);
- } else {
- instruction->type = ARM_MUL;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
- address,
- opcode,
- COND(opcode),
- (S) ? "S" : "",
- Rd,
- Rm,
- Rs);
- }
-
- return ERROR_OK;
- }
-
- /* Multiply (accumulate) long */
- if ((opcode & 0x0f800000) == 0x00800000) {
- char *mnemonic = NULL;
- uint8_t Rm, Rs, RdHi, RdLow, S;
- Rm = opcode & 0xf;
- Rs = (opcode & 0xf00) >> 8;
- RdHi = (opcode & 0xf000) >> 12;
- RdLow = (opcode & 0xf0000) >> 16;
- S = (opcode & 0x00100000) >> 20;
-
- switch ((opcode & 0x00600000) >> 21) {
- case 0x0:
- instruction->type = ARM_UMULL;
- mnemonic = "UMULL";
- break;
- case 0x1:
- instruction->type = ARM_UMLAL;
- mnemonic = "UMLAL";
- break;
- case 0x2:
- instruction->type = ARM_SMULL;
- mnemonic = "SMULL";
- break;
- case 0x3:
- instruction->type = ARM_SMLAL;
- mnemonic = "SMLAL";
- break;
- }
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
- address,
- opcode,
- mnemonic,
- COND(opcode),
- (S) ? "S" : "",
- RdLow,
- RdHi,
- Rm,
- Rs);
-
- return ERROR_OK;
- }
-
- /* Swap/swap byte */
- if ((opcode & 0x0f800000) == 0x01000000) {
- uint8_t Rm, Rd, Rn;
- Rm = opcode & 0xf;
- Rd = (opcode & 0xf000) >> 12;
- Rn = (opcode & 0xf0000) >> 16;
-
- /* examine B flag */
- instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
- address,
- opcode,
- (opcode & 0x00400000) ? "SWPB" : "SWP",
- COND(opcode),
- Rd,
- Rm,
- Rn);
- return ERROR_OK;
- }
-
- }
-
- return evaluate_misc_load_store(opcode, address, instruction);
-}
-
-static int evaluate_mrs_msr(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- int R = (opcode & 0x00400000) >> 22;
- char *PSR = (R) ? "SPSR" : "CPSR";
-
- /* Move register to status register (MSR) */
- if (opcode & 0x00200000) {
- instruction->type = ARM_MSR;
-
- /* immediate variant */
- if (opcode & 0x02000000) {
- uint8_t immediate = (opcode & 0xff);
- uint8_t rotate = (opcode & 0xf00);
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
- address,
- opcode,
- COND(opcode),
- PSR,
- (opcode & 0x10000) ? "c" : "",
- (opcode & 0x20000) ? "x" : "",
- (opcode & 0x40000) ? "s" : "",
- (opcode & 0x80000) ? "f" : "",
- ror(immediate, (rotate * 2))
- );
- } else {/* register variant */
- uint8_t Rm = opcode & 0xf;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
- address,
- opcode,
- COND(opcode),
- PSR,
- (opcode & 0x10000) ? "c" : "",
- (opcode & 0x20000) ? "x" : "",
- (opcode & 0x40000) ? "s" : "",
- (opcode & 0x80000) ? "f" : "",
- Rm
- );
- }
-
- } else {/* Move status register to register (MRS) */
- uint8_t Rd;
-
- instruction->type = ARM_MRS;
- Rd = (opcode & 0x0000f000) >> 12;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
- address,
- opcode,
- COND(opcode),
- Rd,
- PSR);
- }
-
- return ERROR_OK;
-}
-
-/* Miscellaneous instructions */
-static int evaluate_misc_instr(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- /* MRS/MSR */
- if ((opcode & 0x000000f0) == 0x00000000)
- evaluate_mrs_msr(opcode, address, instruction);
-
- /* BX */
- if ((opcode & 0x006000f0) == 0x00200010) {
- uint8_t Rm;
- instruction->type = ARM_BX;
- Rm = opcode & 0xf;
-
- snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
- address, opcode, COND(opcode), Rm);
-
- instruction->info.b_bl_bx_blx.reg_operand = Rm;
- instruction->info.b_bl_bx_blx.target_address = -1;
- }
-
- /* BXJ - "Jazelle" support (ARMv5-J) */
- if ((opcode & 0x006000f0) == 0x00200020) {
- uint8_t Rm;
- instruction->type = ARM_BX;
- Rm = opcode & 0xf;
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
- address, opcode, COND(opcode), Rm);
-
- instruction->info.b_bl_bx_blx.reg_operand = Rm;
- instruction->info.b_bl_bx_blx.target_address = -1;
- }
-
- /* CLZ */
- if ((opcode & 0x006000f0) == 0x00600010) {
- uint8_t Rm, Rd;
- instruction->type = ARM_CLZ;
- Rm = opcode & 0xf;
- Rd = (opcode & 0xf000) >> 12;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
- address,
- opcode,
- COND(opcode),
- Rd,
- Rm);
- }
-
- /* BLX(2) */
- if ((opcode & 0x006000f0) == 0x00200030) {
- uint8_t Rm;
- instruction->type = ARM_BLX;
- Rm = opcode & 0xf;
-
- snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
- address, opcode, COND(opcode), Rm);
-
- instruction->info.b_bl_bx_blx.reg_operand = Rm;
- instruction->info.b_bl_bx_blx.target_address = -1;
- }
-
- /* Enhanced DSP add/subtracts */
- if ((opcode & 0x0000000f0) == 0x00000050) {
- uint8_t Rm, Rd, Rn;
- char *mnemonic = NULL;
- Rm = opcode & 0xf;
- Rd = (opcode & 0xf000) >> 12;
- Rn = (opcode & 0xf0000) >> 16;
-
- switch ((opcode & 0x00600000) >> 21) {
- case 0x0:
- instruction->type = ARM_QADD;
- mnemonic = "QADD";
- break;
- case 0x1:
- instruction->type = ARM_QSUB;
- mnemonic = "QSUB";
- break;
- case 0x2:
- instruction->type = ARM_QDADD;
- mnemonic = "QDADD";
- break;
- case 0x3:
- instruction->type = ARM_QDSUB;
- mnemonic = "QDSUB";
- break;
- }
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
- address,
- opcode,
- mnemonic,
- COND(opcode),
- Rd,
- Rm,
- Rn);
- }
-
- /* exception return */
- if ((opcode & 0x0000000f0) == 0x00000060) {
- if (((opcode & 0x600000) >> 21) == 3)
- instruction->type = ARM_ERET;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
- address,
- opcode);
- }
-
- /* exception generate instructions */
- if ((opcode & 0x0000000f0) == 0x00000070) {
- uint32_t immediate = 0;
- char *mnemonic = NULL;
-
- switch ((opcode & 0x600000) >> 21) {
- case 0x1:
- instruction->type = ARM_BKPT;
- mnemonic = "BRKT";
- immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
- break;
- case 0x2:
- instruction->type = ARM_HVC;
- mnemonic = "HVC";
- immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
- break;
- case 0x3:
- instruction->type = ARM_SMC;
- mnemonic = "SMC";
- immediate = (opcode & 0xf);
- break;
- }
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "",
- address,
- opcode,
- mnemonic,
- immediate);
- }
-
- /* Enhanced DSP multiplies */
- if ((opcode & 0x000000090) == 0x00000080) {
- int x = (opcode & 0x20) >> 5;
- int y = (opcode & 0x40) >> 6;
-
- /* SMLA < x><y> */
- if ((opcode & 0x00600000) == 0x00000000) {
- uint8_t Rd, Rm, Rs, Rn;
- instruction->type = ARM_SMLAxy;
- Rd = (opcode & 0xf0000) >> 16;
- Rm = (opcode & 0xf);
- Rs = (opcode & 0xf00) >> 8;
- Rn = (opcode & 0xf000) >> 12;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
- address,
- opcode,
- (x) ? "T" : "B",
- (y) ? "T" : "B",
- COND(opcode),
- Rd,
- Rm,
- Rs,
- Rn);
- }
-
- /* SMLAL < x><y> */
- if ((opcode & 0x00600000) == 0x00400000) {
- uint8_t RdLow, RdHi, Rm, Rs;
- instruction->type = ARM_SMLAxy;
- RdHi = (opcode & 0xf0000) >> 16;
- RdLow = (opcode & 0xf000) >> 12;
- Rm = (opcode & 0xf);
- Rs = (opcode & 0xf00) >> 8;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
- address,
- opcode,
- (x) ? "T" : "B",
- (y) ? "T" : "B",
- COND(opcode),
- RdLow,
- RdHi,
- Rm,
- Rs);
- }
-
- /* SMLAW < y> */
- if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) {
- uint8_t Rd, Rm, Rs, Rn;
- instruction->type = ARM_SMLAWy;
- Rd = (opcode & 0xf0000) >> 16;
- Rm = (opcode & 0xf);
- Rs = (opcode & 0xf00) >> 8;
- Rn = (opcode & 0xf000) >> 12;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
- address,
- opcode,
- (y) ? "T" : "B",
- COND(opcode),
- Rd,
- Rm,
- Rs,
- Rn);
- }
-
- /* SMUL < x><y> */
- if ((opcode & 0x00600000) == 0x00300000) {
- uint8_t Rd, Rm, Rs;
- instruction->type = ARM_SMULxy;
- Rd = (opcode & 0xf0000) >> 16;
- Rm = (opcode & 0xf);
- Rs = (opcode & 0xf00) >> 8;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
- address,
- opcode,
- (x) ? "T" : "B",
- (y) ? "T" : "B",
- COND(opcode),
- Rd,
- Rm,
- Rs);
- }
-
- /* SMULW < y> */
- if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) {
- uint8_t Rd, Rm, Rs;
- instruction->type = ARM_SMULWy;
- Rd = (opcode & 0xf0000) >> 16;
- Rm = (opcode & 0xf);
- Rs = (opcode & 0xf00) >> 8;
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
- address,
- opcode,
- (y) ? "T" : "B",
- COND(opcode),
- Rd,
- Rm,
- Rs);
- }
- }
-
- return ERROR_OK;
-}
-
-static int evaluate_data_proc(uint32_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t I, op, S, Rn, Rd;
- char *mnemonic = NULL;
- char shifter_operand[32];
-
- I = (opcode & 0x02000000) >> 25;
- op = (opcode & 0x01e00000) >> 21;
- S = (opcode & 0x00100000) >> 20;
-
- Rd = (opcode & 0xf000) >> 12;
- Rn = (opcode & 0xf0000) >> 16;
-
- instruction->info.data_proc.Rd = Rd;
- instruction->info.data_proc.Rn = Rn;
- instruction->info.data_proc.S = S;
-
- switch (op) {
- case 0x0:
- instruction->type = ARM_AND;
- mnemonic = "AND";
- break;
- case 0x1:
- instruction->type = ARM_EOR;
- mnemonic = "EOR";
- break;
- case 0x2:
- instruction->type = ARM_SUB;
- mnemonic = "SUB";
- break;
- case 0x3:
- instruction->type = ARM_RSB;
- mnemonic = "RSB";
- break;
- case 0x4:
- instruction->type = ARM_ADD;
- mnemonic = "ADD";
- break;
- case 0x5:
- instruction->type = ARM_ADC;
- mnemonic = "ADC";
- break;
- case 0x6:
- instruction->type = ARM_SBC;
- mnemonic = "SBC";
- break;
- case 0x7:
- instruction->type = ARM_RSC;
- mnemonic = "RSC";
- break;
- case 0x8:
- instruction->type = ARM_TST;
- mnemonic = "TST";
- break;
- case 0x9:
- instruction->type = ARM_TEQ;
- mnemonic = "TEQ";
- break;
- case 0xa:
- instruction->type = ARM_CMP;
- mnemonic = "CMP";
- break;
- case 0xb:
- instruction->type = ARM_CMN;
- mnemonic = "CMN";
- break;
- case 0xc:
- instruction->type = ARM_ORR;
- mnemonic = "ORR";
- break;
- case 0xd:
- instruction->type = ARM_MOV;
- mnemonic = "MOV";
- break;
- case 0xe:
- instruction->type = ARM_BIC;
- mnemonic = "BIC";
- break;
- case 0xf:
- instruction->type = ARM_MVN;
- mnemonic = "MVN";
- break;
- }
-
- if (I) {/* immediate shifter operand (#<immediate>)*/
- uint8_t immed_8 = opcode & 0xff;
- uint8_t rotate_imm = (opcode & 0xf00) >> 8;
- uint32_t immediate;
-
- immediate = ror(immed_8, rotate_imm * 2);
-
- snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
-
- instruction->info.data_proc.variant = 0;
- instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
- } else {/* register-based shifter operand */
- uint8_t shift, Rm;
- shift = (opcode & 0x60) >> 5;
- Rm = (opcode & 0xf);
-
- if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
- *#<shift_immediate>") */
- uint8_t shift_imm;
- shift_imm = (opcode & 0xf80) >> 7;
-
- instruction->info.data_proc.variant = 1;
- instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
- instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
- shift_imm;
- instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
-
- /* LSR encodes a shift by 32 bit as 0x0 */
- if ((shift == 0x1) && (shift_imm == 0x0))
- shift_imm = 0x20;
-
- /* ASR encodes a shift by 32 bit as 0x0 */
- if ((shift == 0x2) && (shift_imm == 0x0))
- shift_imm = 0x20;
-
- /* ROR by 32 bit is actually a RRX */
- if ((shift == 0x3) && (shift_imm == 0x0))
- shift = 0x4;
-
- if ((shift_imm == 0x0) && (shift == 0x0))
- snprintf(shifter_operand, 32, "r%i", Rm);
- else {
- if (shift == 0x0) /* LSL */
- snprintf(shifter_operand,
- 32,
- "r%i, LSL #0x%x",
- Rm,
- shift_imm);
- else if (shift == 0x1) /* LSR */
- snprintf(shifter_operand,
- 32,
- "r%i, LSR #0x%x",
- Rm,
- shift_imm);
- else if (shift == 0x2) /* ASR */
- snprintf(shifter_operand,
- 32,
- "r%i, ASR #0x%x",
- Rm,
- shift_imm);
- else if (shift == 0x3) /* ROR */
- snprintf(shifter_operand,
- 32,
- "r%i, ROR #0x%x",
- Rm,
- shift_imm);
- else if (shift == 0x4) /* RRX */
- snprintf(shifter_operand, 32, "r%i, RRX", Rm);
- }
- } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
- uint8_t Rs = (opcode & 0xf00) >> 8;
-
- instruction->info.data_proc.variant = 2;
- instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
- instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
- instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
-
- if (shift == 0x0) /* LSL */
- snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
- else if (shift == 0x1) /* LSR */
- snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
- else if (shift == 0x2) /* ASR */
- snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
- else if (shift == 0x3) /* ROR */
- snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
- }
- }
-
- if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
- *<shifter_operand> */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
- address,
- opcode,
- mnemonic,
- COND(opcode),
- (S) ? "S" : "",
- Rd,
- Rn,
- shifter_operand);
- } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
- *<shifter_operand> */
- if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
- address,
- opcode);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
- address,
- opcode,
- mnemonic,
- COND(opcode),
- (S) ? "S" : "",
- Rd,
- shifter_operand);
- } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
- snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
- address, opcode, mnemonic, COND(opcode),
- Rn, shifter_operand);
- }
-
- return ERROR_OK;
-}
-
-int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- /* clear fields, to avoid confusion */
- memset(instruction, 0, sizeof(struct arm_instruction));
- instruction->opcode = opcode;
- instruction->instruction_size = 4;
-
- /* catch opcodes with condition field [31:28] = b1111 */
- if ((opcode & 0xf0000000) == 0xf0000000) {
- /* Undefined instruction (or ARMv5E cache preload PLD) */
- if ((opcode & 0x08000000) == 0x00000000)
- return evaluate_pld(opcode, address, instruction);
-
- /* Undefined instruction (or ARMv6+ SRS/RFE) */
- if ((opcode & 0x0e000000) == 0x08000000)
- return evaluate_srs(opcode, address, instruction);
-
- /* Branch and branch with link and change to Thumb */
- if ((opcode & 0x0e000000) == 0x0a000000)
- return evaluate_blx_imm(opcode, address, instruction);
-
- /* Extended coprocessor opcode space (ARMv5 and higher)
- * Coprocessor load/store and double register transfers */
- if ((opcode & 0x0e000000) == 0x0c000000)
- return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
-
- /* Coprocessor data processing */
- if ((opcode & 0x0f000100) == 0x0c000000)
- return evaluate_cdp_mcr_mrc(opcode, address, instruction);
-
- /* Coprocessor register transfers */
- if ((opcode & 0x0f000010) == 0x0c000010)
- return evaluate_cdp_mcr_mrc(opcode, address, instruction);
-
- /* Undefined instruction */
- if ((opcode & 0x0f000000) == 0x0f000000) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_OK;
- }
- }
-
- /* catch opcodes with [27:25] = b000 */
- if ((opcode & 0x0e000000) == 0x00000000) {
- /* Multiplies, extra load/stores */
- if ((opcode & 0x00000090) == 0x00000090)
- return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
-
- /* Miscellaneous instructions */
- if ((opcode & 0x0f900000) == 0x01000000)
- return evaluate_misc_instr(opcode, address, instruction);
-
- return evaluate_data_proc(opcode, address, instruction);
- }
-
- /* catch opcodes with [27:25] = b001 */
- if ((opcode & 0x0e000000) == 0x02000000) {
- /* Undefined instruction */
- if ((opcode & 0x0fb00000) == 0x03000000) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_OK;
- }
-
- /* Move immediate to status register */
- if ((opcode & 0x0fb00000) == 0x03200000)
- return evaluate_mrs_msr(opcode, address, instruction);
-
- return evaluate_data_proc(opcode, address, instruction);
-
- }
-
- /* catch opcodes with [27:25] = b010 */
- if ((opcode & 0x0e000000) == 0x04000000) {
- /* Load/store immediate offset */
- return evaluate_load_store(opcode, address, instruction);
- }
-
- /* catch opcodes with [27:25] = b011 */
- if ((opcode & 0x0e000000) == 0x06000000) {
- /* Load/store register offset */
- if ((opcode & 0x00000010) == 0x00000000)
- return evaluate_load_store(opcode, address, instruction);
-
- /* Architecturally Undefined instruction
- * ... don't expect these to ever be used
- */
- if ((opcode & 0x07f000f0) == 0x07f000f0) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
- address, opcode);
- return ERROR_OK;
- }
-
- /* "media" instructions */
- return evaluate_media(opcode, address, instruction);
- }
-
- /* catch opcodes with [27:25] = b100 */
- if ((opcode & 0x0e000000) == 0x08000000) {
- /* Load/store multiple */
- return evaluate_ldm_stm(opcode, address, instruction);
- }
-
- /* catch opcodes with [27:25] = b101 */
- if ((opcode & 0x0e000000) == 0x0a000000) {
- /* Branch and branch with link */
- return evaluate_b_bl(opcode, address, instruction);
- }
-
- /* catch opcodes with [27:25] = b110 */
- if ((opcode & 0x0e000000) == 0x0c000000) {
- /* Coprocessor load/store and double register transfers */
- return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
- }
-
- /* catch opcodes with [27:25] = b111 */
- if ((opcode & 0x0e000000) == 0x0e000000) {
- /* Software interrupt */
- if ((opcode & 0x0f000000) == 0x0f000000)
- return evaluate_swi(opcode, address, instruction);
-
- /* Coprocessor data processing */
- if ((opcode & 0x0f000010) == 0x0e000000)
- return evaluate_cdp_mcr_mrc(opcode, address, instruction);
-
- /* Coprocessor register transfers */
- if ((opcode & 0x0f000010) == 0x0e000010)
- return evaluate_cdp_mcr_mrc(opcode, address, instruction);
- }
-
- LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
- (unsigned) opcode);
- return -1;
-}
-
-static int evaluate_b_bl_blx_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t offset = opcode & 0x7ff;
- uint32_t opc = (opcode >> 11) & 0x3;
- uint32_t target_address;
- char *mnemonic = NULL;
-
- /* sign extend 11-bit offset */
- if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
- offset = 0xfffff800 | offset;
-
- target_address = address + 4 + (offset << 1);
-
- switch (opc) {
- /* unconditional branch */
- case 0:
- instruction->type = ARM_B;
- mnemonic = "B";
- break;
- /* BLX suffix */
- case 1:
- instruction->type = ARM_BLX;
- mnemonic = "BLX";
- target_address &= 0xfffffffc;
- break;
- /* BL/BLX prefix */
- case 2:
- instruction->type = ARM_UNKNOWN_INSTUCTION;
- mnemonic = "prefix";
- target_address = offset << 12;
- break;
- /* BL suffix */
- case 3:
- instruction->type = ARM_BL;
- mnemonic = "BL";
- break;
- }
-
- /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
- * these are effectively 32-bit instructions even in Thumb1. For
- * disassembly, it's simplest to always use the Thumb2 decoder.
- *
- * But some cores will evidently handle them as two instructions,
- * where exceptions may occur between the two. The ETMv3.2+ ID
- * register has a bit which exposes this behavior.
- */
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
- address, opcode, mnemonic, target_address);
-
- instruction->info.b_bl_bx_blx.reg_operand = -1;
- instruction->info.b_bl_bx_blx.target_address = target_address;
-
- return ERROR_OK;
-}
-
-static int evaluate_add_sub_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t Rd = (opcode >> 0) & 0x7;
- uint8_t Rn = (opcode >> 3) & 0x7;
- uint8_t Rm_imm = (opcode >> 6) & 0x7;
- uint32_t opc = opcode & (1 << 9);
- uint32_t reg_imm = opcode & (1 << 10);
- char *mnemonic;
-
- if (opc) {
- instruction->type = ARM_SUB;
- mnemonic = "SUBS";
- } else {
- /* REVISIT: if reg_imm == 0, display as "MOVS" */
- instruction->type = ARM_ADD;
- mnemonic = "ADDS";
- }
-
- instruction->info.data_proc.Rd = Rd;
- instruction->info.data_proc.Rn = Rn;
- instruction->info.data_proc.S = 1;
-
- if (reg_imm) {
- instruction->info.data_proc.variant = 0;/*immediate*/
- instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
- address, opcode, mnemonic, Rd, Rn, Rm_imm);
- } else {
- instruction->info.data_proc.variant = 1;/*immediate shift*/
- instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
- address, opcode, mnemonic, Rd, Rn, Rm_imm);
- }
-
- return ERROR_OK;
-}
-
-static int evaluate_shift_imm_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t Rd = (opcode >> 0) & 0x7;
- uint8_t Rm = (opcode >> 3) & 0x7;
- uint8_t imm = (opcode >> 6) & 0x1f;
- uint8_t opc = (opcode >> 11) & 0x3;
- char *mnemonic = NULL;
-
- switch (opc) {
- case 0:
- instruction->type = ARM_MOV;
- mnemonic = "LSLS";
- instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
- break;
- case 1:
- instruction->type = ARM_MOV;
- mnemonic = "LSRS";
- instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
- break;
- case 2:
- instruction->type = ARM_MOV;
- mnemonic = "ASRS";
- instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
- break;
- }
-
- if ((imm == 0) && (opc != 0))
- imm = 32;
-
- instruction->info.data_proc.Rd = Rd;
- instruction->info.data_proc.Rn = -1;
- instruction->info.data_proc.S = 1;
-
- instruction->info.data_proc.variant = 1;/*immediate_shift*/
- instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
- instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
- address, opcode, mnemonic, Rd, Rm, imm);
-
- return ERROR_OK;
-}
-
-static int evaluate_data_proc_imm_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t imm = opcode & 0xff;
- uint8_t Rd = (opcode >> 8) & 0x7;
- uint32_t opc = (opcode >> 11) & 0x3;
- char *mnemonic = NULL;
-
- instruction->info.data_proc.Rd = Rd;
- instruction->info.data_proc.Rn = Rd;
- instruction->info.data_proc.S = 1;
- instruction->info.data_proc.variant = 0;/*immediate*/
- instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
-
- switch (opc) {
- case 0:
- instruction->type = ARM_MOV;
- mnemonic = "MOVS";
- instruction->info.data_proc.Rn = -1;
- break;
- case 1:
- instruction->type = ARM_CMP;
- mnemonic = "CMP";
- instruction->info.data_proc.Rd = -1;
- break;
- case 2:
- instruction->type = ARM_ADD;
- mnemonic = "ADDS";
- break;
- case 3:
- instruction->type = ARM_SUB;
- mnemonic = "SUBS";
- break;
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
- address, opcode, mnemonic, Rd, imm);
-
- return ERROR_OK;
-}
-
-static int evaluate_data_proc_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t high_reg, op, Rm, Rd, H1, H2;
- char *mnemonic = NULL;
- bool nop = false;
-
- high_reg = (opcode & 0x0400) >> 10;
- op = (opcode & 0x03C0) >> 6;
-
- Rd = (opcode & 0x0007);
- Rm = (opcode & 0x0038) >> 3;
- H1 = (opcode & 0x0080) >> 7;
- H2 = (opcode & 0x0040) >> 6;
-
- instruction->info.data_proc.Rd = Rd;
- instruction->info.data_proc.Rn = Rd;
- instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
- instruction->info.data_proc.variant = 1 /*immediate shift*/;
- instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
-
- if (high_reg) {
- Rd |= H1 << 3;
- Rm |= H2 << 3;
- op >>= 2;
-
- switch (op) {
- case 0x0:
- instruction->type = ARM_ADD;
- mnemonic = "ADD";
- break;
- case 0x1:
- instruction->type = ARM_CMP;
- mnemonic = "CMP";
- break;
- case 0x2:
- instruction->type = ARM_MOV;
- mnemonic = "MOV";
- if (Rd == Rm)
- nop = true;
- break;
- case 0x3:
- if ((opcode & 0x7) == 0x0) {
- instruction->info.b_bl_bx_blx.reg_operand = Rm;
- if (H1) {
- instruction->type = ARM_BLX;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32
- " 0x%4.4x \tBLX\tr%i",
- address, opcode, Rm);
- } else {
- instruction->type = ARM_BX;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32
- " 0x%4.4x \tBX\tr%i",
- address, opcode, Rm);
- }
- } else {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32
- " 0x%4.4x \t"
- "UNDEFINED INSTRUCTION",
- address, opcode);
- }
- return ERROR_OK;
- break;
- }
- } else {
- switch (op) {
- case 0x0:
- instruction->type = ARM_AND;
- mnemonic = "ANDS";
- break;
- case 0x1:
- instruction->type = ARM_EOR;
- mnemonic = "EORS";
- break;
- case 0x2:
- instruction->type = ARM_MOV;
- mnemonic = "LSLS";
- instruction->info.data_proc.variant = 2 /*register shift*/;
- instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
- instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
- instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
- break;
- case 0x3:
- instruction->type = ARM_MOV;
- mnemonic = "LSRS";
- instruction->info.data_proc.variant = 2 /*register shift*/;
- instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
- instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
- instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
- break;
- case 0x4:
- instruction->type = ARM_MOV;
- mnemonic = "ASRS";
- instruction->info.data_proc.variant = 2 /*register shift*/;
- instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
- instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
- instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
- break;
- case 0x5:
- instruction->type = ARM_ADC;
- mnemonic = "ADCS";
- break;
- case 0x6:
- instruction->type = ARM_SBC;
- mnemonic = "SBCS";
- break;
- case 0x7:
- instruction->type = ARM_MOV;
- mnemonic = "RORS";
- instruction->info.data_proc.variant = 2 /*register shift*/;
- instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
- instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
- instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
- break;
- case 0x8:
- instruction->type = ARM_TST;
- mnemonic = "TST";
- break;
- case 0x9:
- instruction->type = ARM_RSB;
- mnemonic = "RSBS";
- instruction->info.data_proc.variant = 0 /*immediate*/;
- instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
- instruction->info.data_proc.Rn = Rm;
- break;
- case 0xA:
- instruction->type = ARM_CMP;
- mnemonic = "CMP";
- break;
- case 0xB:
- instruction->type = ARM_CMN;
- mnemonic = "CMN";
- break;
- case 0xC:
- instruction->type = ARM_ORR;
- mnemonic = "ORRS";
- break;
- case 0xD:
- instruction->type = ARM_MUL;
- mnemonic = "MULS";
- break;
- case 0xE:
- instruction->type = ARM_BIC;
- mnemonic = "BICS";
- break;
- case 0xF:
- instruction->type = ARM_MVN;
- mnemonic = "MVNS";
- break;
- }
- }
-
- if (nop)
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
- "; (%s r%i, r%i)",
- address, opcode, mnemonic, Rd, Rm);
- else
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
- address, opcode, mnemonic, Rd, Rm);
-
- return ERROR_OK;
-}
-
-/* PC-relative data addressing is word-aligned even with Thumb */
-static inline uint32_t thumb_alignpc4(uint32_t addr)
-{
- return (addr + 4) & ~3;
-}
-
-static int evaluate_load_literal_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t immediate;
- uint8_t Rd = (opcode >> 8) & 0x7;
-
- instruction->type = ARM_LDR;
- immediate = opcode & 0x000000ff;
- immediate *= 4;
-
- instruction->info.load_store.Rd = Rd;
- instruction->info.load_store.Rn = 15 /*PC*/;
- instruction->info.load_store.index_mode = 0; /*offset*/
- instruction->info.load_store.offset_mode = 0; /*immediate*/
- instruction->info.load_store.offset.offset = immediate;
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t"
- "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
- address, opcode, Rd, immediate,
- thumb_alignpc4(address) + immediate);
-
- return ERROR_OK;
-}
-
-static int evaluate_load_store_reg_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint8_t Rd = (opcode >> 0) & 0x7;
- uint8_t Rn = (opcode >> 3) & 0x7;
- uint8_t Rm = (opcode >> 6) & 0x7;
- uint8_t opc = (opcode >> 9) & 0x7;
- char *mnemonic = NULL;
-
- switch (opc) {
- case 0:
- instruction->type = ARM_STR;
- mnemonic = "STR";
- break;
- case 1:
- instruction->type = ARM_STRH;
- mnemonic = "STRH";
- break;
- case 2:
- instruction->type = ARM_STRB;
- mnemonic = "STRB";
- break;
- case 3:
- instruction->type = ARM_LDRSB;
- mnemonic = "LDRSB";
- break;
- case 4:
- instruction->type = ARM_LDR;
- mnemonic = "LDR";
- break;
- case 5:
- instruction->type = ARM_LDRH;
- mnemonic = "LDRH";
- break;
- case 6:
- instruction->type = ARM_LDRB;
- mnemonic = "LDRB";
- break;
- case 7:
- instruction->type = ARM_LDRSH;
- mnemonic = "LDRSH";
- break;
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
- address, opcode, mnemonic, Rd, Rn, Rm);
-
- instruction->info.load_store.Rd = Rd;
- instruction->info.load_store.Rn = Rn;
- instruction->info.load_store.index_mode = 0; /*offset*/
- instruction->info.load_store.offset_mode = 1; /*register*/
- instruction->info.load_store.offset.reg.Rm = Rm;
-
- return ERROR_OK;
-}
-
-static int evaluate_load_store_imm_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t offset = (opcode >> 6) & 0x1f;
- uint8_t Rd = (opcode >> 0) & 0x7;
- uint8_t Rn = (opcode >> 3) & 0x7;
- uint32_t L = opcode & (1 << 11);
- uint32_t B = opcode & (1 << 12);
- char *mnemonic;
- char suffix = ' ';
- uint32_t shift = 2;
-
- if (L) {
- instruction->type = ARM_LDR;
- mnemonic = "LDR";
- } else {
- instruction->type = ARM_STR;
- mnemonic = "STR";
- }
-
- if ((opcode&0xF000) == 0x8000) {
- suffix = 'H';
- shift = 1;
- } else if (B) {
- suffix = 'B';
- shift = 0;
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
- address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
-
- instruction->info.load_store.Rd = Rd;
- instruction->info.load_store.Rn = Rn;
- instruction->info.load_store.index_mode = 0; /*offset*/
- instruction->info.load_store.offset_mode = 0; /*immediate*/
- instruction->info.load_store.offset.offset = offset << shift;
-
- return ERROR_OK;
-}
-
-static int evaluate_load_store_stack_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t offset = opcode & 0xff;
- uint8_t Rd = (opcode >> 8) & 0x7;
- uint32_t L = opcode & (1 << 11);
- char *mnemonic;
-
- if (L) {
- instruction->type = ARM_LDR;
- mnemonic = "LDR";
- } else {
- instruction->type = ARM_STR;
- mnemonic = "STR";
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
- address, opcode, mnemonic, Rd, offset*4);
-
- instruction->info.load_store.Rd = Rd;
- instruction->info.load_store.Rn = 13 /*SP*/;
- instruction->info.load_store.index_mode = 0; /*offset*/
- instruction->info.load_store.offset_mode = 0; /*immediate*/
- instruction->info.load_store.offset.offset = offset*4;
-
- return ERROR_OK;
-}
-
-static int evaluate_add_sp_pc_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t imm = opcode & 0xff;
- uint8_t Rd = (opcode >> 8) & 0x7;
- uint8_t Rn;
- uint32_t SP = opcode & (1 << 11);
- const char *reg_name;
-
- instruction->type = ARM_ADD;
-
- if (SP) {
- reg_name = "SP";
- Rn = 13;
- } else {
- reg_name = "PC";
- Rn = 15;
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
- address, opcode, Rd, reg_name, imm * 4);
-
- instruction->info.data_proc.variant = 0 /* immediate */;
- instruction->info.data_proc.Rd = Rd;
- instruction->info.data_proc.Rn = Rn;
- instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
-
- return ERROR_OK;
-}
-
-static int evaluate_adjust_stack_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t imm = opcode & 0x7f;
- uint8_t opc = opcode & (1 << 7);
- char *mnemonic;
-
-
- if (opc) {
- instruction->type = ARM_SUB;
- mnemonic = "SUB";
- } else {
- instruction->type = ARM_ADD;
- mnemonic = "ADD";
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
- address, opcode, mnemonic, imm*4);
-
- instruction->info.data_proc.variant = 0 /* immediate */;
- instruction->info.data_proc.Rd = 13 /*SP*/;
- instruction->info.data_proc.Rn = 13 /*SP*/;
- instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
-
- return ERROR_OK;
-}
-
-static int evaluate_breakpoint_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t imm = opcode & 0xff;
-
- instruction->type = ARM_BKPT;
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
- address, opcode, imm);
-
- return ERROR_OK;
-}
-
-static int evaluate_load_store_multiple_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t reg_list = opcode & 0xff;
- uint32_t L = opcode & (1 << 11);
- uint32_t R = opcode & (1 << 8);
- uint8_t Rn = (opcode >> 8) & 7;
- uint8_t addr_mode = 0 /* IA */;
- char reg_names[40];
- char *reg_names_p;
- char *mnemonic;
- char ptr_name[7] = "";
- int i;
-
- /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
- * The STMIA and LDMIA opcodes are used for other instructions.
- */
-
- if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
- char *wback = "!";
-
- if (L) {
- instruction->type = ARM_LDM;
- mnemonic = "LDM";
- if (opcode & (1 << Rn))
- wback = "";
- } else {
- instruction->type = ARM_STM;
- mnemonic = "STM";
- }
- snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
- } else {/* push/pop */
- Rn = 13;/* SP */
- if (L) {
- instruction->type = ARM_LDM;
- mnemonic = "POP";
- if (R)
- reg_list |= (1 << 15) /*PC*/;
- } else {
- instruction->type = ARM_STM;
- mnemonic = "PUSH";
- addr_mode = 3; /*DB*/
- if (R)
- reg_list |= (1 << 14) /*LR*/;
- }
- }
-
- reg_names_p = reg_names;
- for (i = 0; i <= 15; i++) {
- if (reg_list & (1 << i))
- reg_names_p += snprintf(reg_names_p,
- (reg_names + 40 - reg_names_p),
- "r%i, ",
- i);
- }
- if (reg_names_p > reg_names)
- reg_names_p[-2] = '\0';
- else /* invalid op : no registers */
- reg_names[0] = '\0';
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
- address, opcode, mnemonic, ptr_name, reg_names);
-
- instruction->info.load_store_multiple.register_list = reg_list;
- instruction->info.load_store_multiple.Rn = Rn;
- instruction->info.load_store_multiple.addressing_mode = addr_mode;
-
- return ERROR_OK;
-}
-
-static int evaluate_cond_branch_thumb(uint16_t opcode,
- uint32_t address, struct arm_instruction *instruction)
-{
- uint32_t offset = opcode & 0xff;
- uint8_t cond = (opcode >> 8) & 0xf;
- uint32_t target_address;
-
- if (cond == 0xf) {
- instruction->type = ARM_SWI;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
- address, opcode, offset);
- return ERROR_OK;
- } else if (cond == 0xe) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
- address, opcode);
- return ERROR_OK;
- }
-
- /* sign extend 8-bit offset */
- if (offset & 0x00000080)
- offset = 0xffffff00 | offset;
-
- target_address = address + 4 + (offset << 1);
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
- address, opcode,
- arm_condition_strings[cond], target_address);
-
- instruction->type = ARM_B;
- instruction->info.b_bl_bx_blx.reg_operand = -1;
- instruction->info.b_bl_bx_blx.target_address = target_address;
-
- return ERROR_OK;
-}
-
-static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- unsigned offset;
-
- /* added in Thumb2 */
- offset = (opcode >> 3) & 0x1f;
- offset |= (opcode & 0x0200) >> 4;
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
- address, opcode,
- (opcode & 0x0800) ? "N" : "",
- opcode & 0x7, address + 4 + (offset << 1));
-
- return ERROR_OK;
-}
-
-static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- /* added in ARMv6 */
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
- address, opcode,
- (opcode & 0x0080) ? 'U' : 'S',
- (opcode & 0x0040) ? 'B' : 'H',
- opcode & 0x7, (opcode >> 3) & 0x7);
-
- return ERROR_OK;
-}
-
-static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- /* added in ARMv6 */
- if ((opcode & 0x0ff0) == 0x0650)
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
- address, opcode,
- (opcode & 0x80) ? "BE" : "LE");
- else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
- address, opcode,
- (opcode & 0x0010) ? 'D' : 'E',
- (opcode & 0x0004) ? "A" : "",
- (opcode & 0x0002) ? "I" : "",
- (opcode & 0x0001) ? "F" : "");
-
- return ERROR_OK;
-}
-
-static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- char *suffix;
-
- /* added in ARMv6 */
- switch ((opcode >> 6) & 3) {
- case 0:
- suffix = "";
- break;
- case 1:
- suffix = "16";
- break;
- default:
- suffix = "SH";
- break;
- }
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
- address, opcode, suffix,
- opcode & 0x7, (opcode >> 3) & 0x7);
-
- return ERROR_OK;
-}
-
-static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- char *hint;
-
- switch ((opcode >> 4) & 0x0f) {
- case 0:
- hint = "NOP";
- break;
- case 1:
- hint = "YIELD";
- break;
- case 2:
- hint = "WFE";
- break;
- case 3:
- hint = "WFI";
- break;
- case 4:
- hint = "SEV";
- break;
- default:
- hint = "HINT (UNRECOGNIZED)";
- break;
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \t%s",
- address, opcode, hint);
-
- return ERROR_OK;
-}
-
-static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
- struct arm_instruction *instruction)
-{
- unsigned cond = (opcode >> 4) & 0x0f;
- char *x = "", *y = "", *z = "";
-
- if (opcode & 0x01)
- z = (opcode & 0x02) ? "T" : "E";
- if (opcode & 0x03)
- y = (opcode & 0x04) ? "T" : "E";
- if (opcode & 0x07)
- x = (opcode & 0x08) ? "T" : "E";
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
- address, opcode,
- x, y, z, arm_condition_strings[cond]);
-
- /* NOTE: strictly speaking, the next 1-4 instructions should
- * now be displayed with the relevant conditional suffix...
- */
-
- return ERROR_OK;
-}
-
-int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
-{
- /* clear fields, to avoid confusion */
- memset(instruction, 0, sizeof(struct arm_instruction));
- instruction->opcode = opcode;
- instruction->instruction_size = 2;
-
- if ((opcode & 0xe000) == 0x0000) {
- /* add/substract register or immediate */
- if ((opcode & 0x1800) == 0x1800)
- return evaluate_add_sub_thumb(opcode, address, instruction);
- /* shift by immediate */
- else
- return evaluate_shift_imm_thumb(opcode, address, instruction);
- }
-
- /* Add/substract/compare/move immediate */
- if ((opcode & 0xe000) == 0x2000)
- return evaluate_data_proc_imm_thumb(opcode, address, instruction);
-
- /* Data processing instructions */
- if ((opcode & 0xf800) == 0x4000)
- return evaluate_data_proc_thumb(opcode, address, instruction);
-
- /* Load from literal pool */
- if ((opcode & 0xf800) == 0x4800)
- return evaluate_load_literal_thumb(opcode, address, instruction);
-
- /* Load/Store register offset */
- if ((opcode & 0xf000) == 0x5000)
- return evaluate_load_store_reg_thumb(opcode, address, instruction);
-
- /* Load/Store immediate offset */
- if (((opcode & 0xe000) == 0x6000)
- || ((opcode & 0xf000) == 0x8000))
- return evaluate_load_store_imm_thumb(opcode, address, instruction);
-
- /* Load/Store from/to stack */
- if ((opcode & 0xf000) == 0x9000)
- return evaluate_load_store_stack_thumb(opcode, address, instruction);
-
- /* Add to SP/PC */
- if ((opcode & 0xf000) == 0xa000)
- return evaluate_add_sp_pc_thumb(opcode, address, instruction);
-
- /* Misc */
- if ((opcode & 0xf000) == 0xb000) {
- switch ((opcode >> 8) & 0x0f) {
- case 0x0:
- return evaluate_adjust_stack_thumb(opcode, address, instruction);
- case 0x1:
- case 0x3:
- case 0x9:
- case 0xb:
- return evaluate_cb_thumb(opcode, address, instruction);
- case 0x2:
- return evaluate_extend_thumb(opcode, address, instruction);
- case 0x4:
- case 0x5:
- case 0xc:
- case 0xd:
- return evaluate_load_store_multiple_thumb(opcode, address,
- instruction);
- case 0x6:
- return evaluate_cps_thumb(opcode, address, instruction);
- case 0xa:
- if ((opcode & 0x00c0) == 0x0080)
- break;
- return evaluate_byterev_thumb(opcode, address, instruction);
- case 0xe:
- return evaluate_breakpoint_thumb(opcode, address, instruction);
- case 0xf:
- if (opcode & 0x000f)
- return evaluate_ifthen_thumb(opcode, address,
- instruction);
- else
- return evaluate_hint_thumb(opcode, address,
- instruction);
- }
-
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
- address, opcode);
- return ERROR_OK;
- }
-
- /* Load/Store multiple */
- if ((opcode & 0xf000) == 0xc000)
- return evaluate_load_store_multiple_thumb(opcode, address, instruction);
-
- /* Conditional branch + SWI */
- if ((opcode & 0xf000) == 0xd000)
- return evaluate_cond_branch_thumb(opcode, address, instruction);
-
- if ((opcode & 0xe000) == 0xe000) {
- /* Undefined instructions */
- if ((opcode & 0xf801) == 0xe801) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%8.8x\t"
- "UNDEFINED INSTRUCTION",
- address, opcode);
- return ERROR_OK;
- } else /* Branch to offset */
- return evaluate_b_bl_blx_thumb(opcode, address, instruction);
- }
-
- LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
- return -1;
-}
-
-static int t2ev_b_bl(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- unsigned offset;
- unsigned b21 = 1 << 21;
- unsigned b22 = 1 << 22;
-
- /* instead of combining two smaller 16-bit branch instructions,
- * Thumb2 uses only one larger 32-bit instruction.
- */
- offset = opcode & 0x7ff;
- offset |= (opcode & 0x03ff0000) >> 5;
- if (opcode & (1 << 26)) {
- offset |= 0xff << 23;
- if ((opcode & (1 << 11)) == 0)
- b21 = 0;
- if ((opcode & (1 << 13)) == 0)
- b22 = 0;
- } else {
- if (opcode & (1 << 11))
- b21 = 0;
- if (opcode & (1 << 13))
- b22 = 0;
- }
- offset |= b21;
- offset |= b22;
-
-
- address += 4;
- address += offset << 1;
-
- instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
- instruction->info.b_bl_bx_blx.reg_operand = -1;
- instruction->info.b_bl_bx_blx.target_address = address;
- sprintf(cp, "%s\t%#8.8" PRIx32,
- (opcode & (1 << 14)) ? "BL" : "B.W",
- address);
-
- return ERROR_OK;
-}
-
-static int t2ev_cond_b(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- unsigned offset;
- unsigned b17 = 1 << 17;
- unsigned b18 = 1 << 18;
- unsigned cond = (opcode >> 22) & 0x0f;
-
- offset = opcode & 0x7ff;
- offset |= (opcode & 0x003f0000) >> 5;
- if (opcode & (1 << 26)) {
- offset |= 0x1fff << 19;
- if ((opcode & (1 << 11)) == 0)
- b17 = 0;
- if ((opcode & (1 << 13)) == 0)
- b18 = 0;
- } else {
- if (opcode & (1 << 11))
- b17 = 0;
- if (opcode & (1 << 13))
- b18 = 0;
- }
- offset |= b17;
- offset |= b18;
-
- address += 4;
- address += offset << 1;
-
- instruction->type = ARM_B;
- instruction->info.b_bl_bx_blx.reg_operand = -1;
- instruction->info.b_bl_bx_blx.target_address = address;
- sprintf(cp, "B%s.W\t%#8.8" PRIx32,
- arm_condition_strings[cond],
- address);
-
- return ERROR_OK;
-}
-
-static const char *special_name(int number)
-{
- char *special = "(RESERVED)";
-
- switch (number) {
- case 0:
- special = "apsr";
- break;
- case 1:
- special = "iapsr";
- break;
- case 2:
- special = "eapsr";
- break;
- case 3:
- special = "xpsr";
- break;
- case 5:
- special = "ipsr";
- break;
- case 6:
- special = "epsr";
- break;
- case 7:
- special = "iepsr";
- break;
- case 8:
- special = "msp";
- break;
- case 9:
- special = "psp";
- break;
- case 16:
- special = "primask";
- break;
- case 17:
- special = "basepri";
- break;
- case 18:
- special = "basepri_max";
- break;
- case 19:
- special = "faultmask";
- break;
- case 20:
- special = "control";
- break;
- }
- return special;
-}
-
-static int t2ev_hint(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- const char *mnemonic;
-
- if (opcode & 0x0700) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- strcpy(cp, "UNDEFINED");
- return ERROR_OK;
- }
-
- if (opcode & 0x00f0) {
- sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
- return ERROR_OK;
- }
-
- switch (opcode & 0x0f) {
- case 0:
- mnemonic = "NOP.W";
- break;
- case 1:
- mnemonic = "YIELD.W";
- break;
- case 2:
- mnemonic = "WFE.W";
- break;
- case 3:
- mnemonic = "WFI.W";
- break;
- case 4:
- mnemonic = "SEV.W";
- break;
- default:
- mnemonic = "HINT.W (UNRECOGNIZED)";
- break;
- }
- strcpy(cp, mnemonic);
- return ERROR_OK;
-}
-
-static int t2ev_misc(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- const char *mnemonic;
-
- switch ((opcode >> 4) & 0x0f) {
- case 0:
- mnemonic = "LEAVEX";
- break;
- case 1:
- mnemonic = "ENTERX";
- break;
- case 2:
- mnemonic = "CLREX";
- break;
- case 4:
- mnemonic = "DSB";
- break;
- case 5:
- mnemonic = "DMB";
- break;
- case 6:
- mnemonic = "ISB";
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- strcpy(cp, mnemonic);
- return ERROR_OK;
-}
-
-static int t2ev_b_misc(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- /* permanently undefined */
- if ((opcode & 0x07f07000) == 0x07f02000) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- strcpy(cp, "UNDEFINED");
- return ERROR_OK;
- }
-
- switch ((opcode >> 12) & 0x5) {
- case 0x1:
- case 0x5:
- return t2ev_b_bl(opcode, address, instruction, cp);
- case 0x4:
- goto undef;
- case 0:
- if (((opcode >> 23) & 0x07) != 0x07)
- return t2ev_cond_b(opcode, address, instruction, cp);
- if (opcode & (1 << 26))
- goto undef;
- break;
- }
-
- switch ((opcode >> 20) & 0x7f) {
- case 0x38:
- case 0x39:
- sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
- (int) (opcode >> 16) & 0x0f);
- return ERROR_OK;
- case 0x3a:
- return t2ev_hint(opcode, address, instruction, cp);
- case 0x3b:
- return t2ev_misc(opcode, address, instruction, cp);
- case 0x3c:
- sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
- return ERROR_OK;
- case 0x3e:
- case 0x3f:
- sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
- special_name(opcode & 0xff));
- return ERROR_OK;
- }
-
-undef:
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- char *mnemonic = NULL;
- int rn = (opcode >> 16) & 0xf;
- int rd = (opcode >> 8) & 0xf;
- unsigned immed = opcode & 0xff;
- unsigned func;
- bool one = false;
- char *suffix = "";
- char *suffix2 = "";
-
- /* ARMv7-M: A5.3.2 Modified immediate constants */
- func = (opcode >> 11) & 0x0e;
- if (immed & 0x80)
- func |= 1;
- if (opcode & (1 << 26))
- func |= 0x10;
-
- /* "Modified" immediates */
- switch (func >> 1) {
- case 0:
- break;
- case 2:
- immed <<= 8;
- /* FALLTHROUGH */
- case 1:
- immed += immed << 16;
- break;
- case 3:
- immed += immed << 8;
- immed += immed << 16;
- break;
- default:
- immed |= 0x80;
- immed = ror(immed, func);
- }
-
- if (opcode & (1 << 20))
- suffix = "S";
-
- switch ((opcode >> 21) & 0xf) {
- case 0:
- if (rd == 0xf) {
- instruction->type = ARM_TST;
- mnemonic = "TST";
- one = true;
- suffix = "";
- rd = rn;
- } else {
- instruction->type = ARM_AND;
- mnemonic = "AND";
- }
- break;
- case 1:
- instruction->type = ARM_BIC;
- mnemonic = "BIC";
- break;
- case 2:
- if (rn == 0xf) {
- instruction->type = ARM_MOV;
- mnemonic = "MOV";
- one = true;
- suffix2 = ".W";
- } else {
- instruction->type = ARM_ORR;
- mnemonic = "ORR";
- }
- break;
- case 3:
- if (rn == 0xf) {
- instruction->type = ARM_MVN;
- mnemonic = "MVN";
- one = true;
- } else {
- /* instruction->type = ARM_ORN; */
- mnemonic = "ORN";
- }
- break;
- case 4:
- if (rd == 0xf) {
- instruction->type = ARM_TEQ;
- mnemonic = "TEQ";
- one = true;
- suffix = "";
- rd = rn;
- } else {
- instruction->type = ARM_EOR;
- mnemonic = "EOR";
- }
- break;
- case 8:
- if (rd == 0xf) {
- instruction->type = ARM_CMN;
- mnemonic = "CMN";
- one = true;
- suffix = "";
- rd = rn;
- } else {
- instruction->type = ARM_ADD;
- mnemonic = "ADD";
- suffix2 = ".W";
- }
- break;
- case 10:
- instruction->type = ARM_ADC;
- mnemonic = "ADC";
- suffix2 = ".W";
- break;
- case 11:
- instruction->type = ARM_SBC;
- mnemonic = "SBC";
- break;
- case 13:
- if (rd == 0xf) {
- instruction->type = ARM_CMP;
- mnemonic = "CMP";
- one = true;
- suffix = "";
- rd = rn;
- } else {
- instruction->type = ARM_SUB;
- mnemonic = "SUB";
- }
- suffix2 = ".W";
- break;
- case 14:
- instruction->type = ARM_RSB;
- mnemonic = "RSB";
- suffix2 = ".W";
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (one)
- sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
- mnemonic, suffix2, rd, immed, immed);
- else
- sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
- mnemonic, suffix, suffix2,
- rd, rn, immed, immed);
-
- return ERROR_OK;
-}
-
-static int t2ev_data_immed(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- char *mnemonic = NULL;
- int rn = (opcode >> 16) & 0xf;
- int rd = (opcode >> 8) & 0xf;
- unsigned immed;
- bool add = false;
- bool is_signed = false;
-
- immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
- if (opcode & (1 << 26))
- immed |= (1 << 11);
-
- switch ((opcode >> 20) & 0x1f) {
- case 0:
- if (rn == 0xf) {
- add = true;
- goto do_adr;
- }
- mnemonic = "ADDW";
- break;
- case 4:
- immed |= (opcode >> 4) & 0xf000;
- sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
- return ERROR_OK;
- case 0x0a:
- if (rn == 0xf)
- goto do_adr;
- mnemonic = "SUBW";
- break;
- case 0x0c:
- /* move constant to top 16 bits of register */
- immed |= (opcode >> 4) & 0xf000;
- sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
- return ERROR_OK;
- case 0x10:
- case 0x12:
- is_signed = true;
- case 0x18:
- case 0x1a:
- /* signed/unsigned saturated add */
- immed = (opcode >> 6) & 0x03;
- immed |= (opcode >> 10) & 0x1c;
- sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
- is_signed ? "S" : "U",
- rd, (int) (opcode & 0x1f) + is_signed, rn,
- (opcode & (1 << 21)) ? "ASR" : "LSL",
- immed ? immed : 32);
- return ERROR_OK;
- case 0x14:
- is_signed = true;
- /* FALLTHROUGH */
- case 0x1c:
- /* signed/unsigned bitfield extract */
- immed = (opcode >> 6) & 0x03;
- immed |= (opcode >> 10) & 0x1c;
- sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
- is_signed ? "S" : "U",
- rd, rn, immed,
- (int) (opcode & 0x1f) + 1);
- return ERROR_OK;
- case 0x16:
- immed = (opcode >> 6) & 0x03;
- immed |= (opcode >> 10) & 0x1c;
- if (rn == 0xf) /* bitfield clear */
- sprintf(cp, "BFC\tr%d, #%d, #%d\t",
- rd, immed,
- (int) (opcode & 0x1f) + 1 - immed);
- else /* bitfield insert */
- sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
- rd, rn, immed,
- (int) (opcode & 0x1f) + 1 - immed);
- return ERROR_OK;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
- rd, rn, immed, immed);
- return ERROR_OK;
-
-do_adr:
- address = thumb_alignpc4(address);
- if (add)
- address += immed;
- else
- address -= immed;
- /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
- * not hiding the pc-relative stuff will sometimes be useful.
- */
- sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
- return ERROR_OK;
-}
-
-static int t2ev_store_single(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- unsigned op = (opcode >> 20) & 0xf;
- char *size = "";
- char *suffix = "";
- char *p1 = "";
- char *p2 = "]";
- unsigned immed;
- unsigned rn = (opcode >> 16) & 0x0f;
- unsigned rt = (opcode >> 12) & 0x0f;
-
- if (rn == 0xf)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (opcode & 0x0800)
- op |= 1;
- switch (op) {
- /* byte */
- case 0x8:
- case 0x9:
- size = "B";
- goto imm12;
- case 0x1:
- size = "B";
- goto imm8;
- case 0x0:
- size = "B";
- break;
- /* halfword */
- case 0xa:
- case 0xb:
- size = "H";
- goto imm12;
- case 0x3:
- size = "H";
- goto imm8;
- case 0x2:
- size = "H";
- break;
- /* word */
- case 0xc:
- case 0xd:
- goto imm12;
- case 0x5:
- goto imm8;
- case 0x4:
- break;
- /* error */
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
- size, rt, rn, (int) opcode & 0x0f,
- (int) (opcode >> 4) & 0x03);
- return ERROR_OK;
-
-imm12:
- immed = opcode & 0x0fff;
- sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
- size, rt, rn, immed, immed);
- return ERROR_OK;
-
-imm8:
- immed = opcode & 0x00ff;
-
- switch (opcode & 0x700) {
- case 0x600:
- suffix = "T";
- break;
- case 0x000:
- case 0x200:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* two indexed modes will write back rn */
- if (opcode & 0x100) {
- if (opcode & 0x400) /* pre-indexed */
- p2 = "]!";
- else { /* post-indexed */
- p1 = "]";
- p2 = "";
- }
- }
-
- sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
- size, suffix, rt, rn, p1,
- (opcode & 0x200) ? "" : "-",
- immed, p2, immed);
- return ERROR_OK;
-}
-
-static int t2ev_mul32(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- int ra = (opcode >> 12) & 0xf;
-
- switch (opcode & 0x007000f0) {
- case 0:
- if (ra == 0xf)
- sprintf(cp, "MUL\tr%d, r%d, r%d",
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf);
- else
- sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf, ra);
- break;
- case 0x10:
- sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf, ra);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return ERROR_OK;
-}
-
-static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- int op = (opcode >> 4) & 0xf;
- char *infix = "MUL";
-
- op += (opcode >> 16) & 0x70;
- switch (op) {
- case 0x40:
- case 0x60:
- infix = "MLA";
- /* FALLTHROUGH */
- case 0:
- case 0x20:
- sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
- (op & 0x20) ? 'U' : 'S',
- infix,
- (int) (opcode >> 12) & 0xf,
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf);
- break;
- case 0x1f:
- case 0x3f:
- sprintf(cp, "%cDIV\tr%d, r%d, r%d",
- (op & 0x20) ? 'U' : 'S',
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- int rn = (opcode >> 16) & 0xf;
- int op = (opcode >> 22) & 0x6;
- int t = (opcode >> 21) & 1;
- unsigned registers = opcode & 0xffff;
- char *mode = "";
-
- if (opcode & (1 << 20))
- op |= 1;
-
- switch (op) {
- case 0:
- mode = "DB";
- /* FALL THROUGH */
- case 6:
- sprintf(cp, "SRS%s\tsp%s, #%d", mode,
- t ? "!" : "",
- (unsigned) (opcode & 0x1f));
- return ERROR_OK;
- case 1:
- mode = "DB";
- /* FALL THROUGH */
- case 7:
- sprintf(cp, "RFE%s\tr%d%s", mode,
- (unsigned) ((opcode >> 16) & 0xf),
- t ? "!" : "");
- return ERROR_OK;
- case 2:
- sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
- break;
- case 3:
- if (rn == 13 && t)
- sprintf(cp, "POP.W\t");
- else
- sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
- break;
- case 4:
- if (rn == 13 && t)
- sprintf(cp, "PUSH.W\t");
- else
- sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
- break;
- case 5:
- sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- cp = strchr(cp, 0);
- *cp++ = '{';
- for (t = 0; registers; t++, registers >>= 1) {
- if ((registers & 1) == 0)
- continue;
- registers &= ~1;
- sprintf(cp, "r%d%s", t, registers ? ", " : "");
- cp = strchr(cp, 0);
- }
- *cp++ = '}';
- *cp++ = 0;
-
- return ERROR_OK;
-}
-
-/* load/store dual or exclusive, table branch */
-static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- unsigned op1op2 = (opcode >> 20) & 0x3;
- unsigned op3 = (opcode >> 4) & 0xf;
- char *mnemonic;
- unsigned rn = (opcode >> 16) & 0xf;
- unsigned rt = (opcode >> 12) & 0xf;
- unsigned rd = (opcode >> 8) & 0xf;
- unsigned imm = opcode & 0xff;
- char *p1 = "";
- char *p2 = "]";
-
- op1op2 |= (opcode >> 21) & 0xc;
- switch (op1op2) {
- case 0:
- mnemonic = "STREX";
- goto strex;
- case 1:
- mnemonic = "LDREX";
- goto ldrex;
- case 2:
- case 6:
- case 8:
- case 10:
- case 12:
- case 14:
- mnemonic = "STRD";
- goto immediate;
- case 3:
- case 7:
- case 9:
- case 11:
- case 13:
- case 15:
- mnemonic = "LDRD";
- if (rn == 15)
- goto literal;
- else
- goto immediate;
- case 4:
- switch (op3) {
- case 4:
- mnemonic = "STREXB";
- break;
- case 5:
- mnemonic = "STREXH";
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- rd = opcode & 0xf;
- imm = 0;
- goto strex;
- case 5:
- switch (op3) {
- case 0:
- sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
- return ERROR_OK;
- case 1:
- sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
- return ERROR_OK;
- case 4:
- mnemonic = "LDREXB";
- break;
- case 5:
- mnemonic = "LDREXH";
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- imm = 0;
- goto ldrex;
- }
- return ERROR_COMMAND_SYNTAX_ERROR;
-
-strex:
- imm <<= 2;
- if (imm)
- sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
- mnemonic, rd, rt, rn, imm, imm);
- else
- sprintf(cp, "%s\tr%u, r%u, [r%u]",
- mnemonic, rd, rt, rn);
- return ERROR_OK;
-
-ldrex:
- imm <<= 2;
- if (imm)
- sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
- mnemonic, rt, rn, imm, imm);
- else
- sprintf(cp, "%s\tr%u, [r%u]",
- mnemonic, rt, rn);
- return ERROR_OK;
-
-immediate:
- /* two indexed modes will write back rn */
- if (opcode & (1 << 21)) {
- if (opcode & (1 << 24)) /* pre-indexed */
- p2 = "]!";
- else { /* post-indexed */
- p1 = "]";
- p2 = "";
- }
- }
-
- imm <<= 2;
- sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
- mnemonic, rt, rd, rn, p1,
- (opcode & (1 << 23)) ? "" : "-",
- imm, p2, imm);
- return ERROR_OK;
-
-literal:
- address = thumb_alignpc4(address);
- imm <<= 2;
- if (opcode & (1 << 23))
- address += imm;
- else
- address -= imm;
- sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
- mnemonic, rt, rd, address);
- return ERROR_OK;
-}
-
-static int t2ev_data_shift(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- int op = (opcode >> 21) & 0xf;
- int rd = (opcode >> 8) & 0xf;
- int rn = (opcode >> 16) & 0xf;
- int type = (opcode >> 4) & 0x3;
- int immed = (opcode >> 6) & 0x3;
- char *mnemonic;
- char *suffix = "";
-
- immed |= (opcode >> 10) & 0x1c;
- if (opcode & (1 << 20))
- suffix = "S";
-
- switch (op) {
- case 0:
- if (rd == 0xf) {
- if (!(opcode & (1 << 20)))
- return ERROR_COMMAND_SYNTAX_ERROR;
- instruction->type = ARM_TST;
- mnemonic = "TST";
- suffix = "";
- goto two;
- }
- instruction->type = ARM_AND;
- mnemonic = "AND";
- break;
- case 1:
- instruction->type = ARM_BIC;
- mnemonic = "BIC";
- break;
- case 2:
- if (rn == 0xf) {
- instruction->type = ARM_MOV;
- switch (type) {
- case 0:
- if (immed == 0) {
- sprintf(cp, "MOV%s.W\tr%d, r%d",
- suffix, rd,
- (int) (opcode & 0xf));
- return ERROR_OK;
- }
- mnemonic = "LSL";
- break;
- case 1:
- mnemonic = "LSR";
- break;
- case 2:
- mnemonic = "ASR";
- break;
- default:
- if (immed == 0) {
- sprintf(cp, "RRX%s\tr%d, r%d",
- suffix, rd,
- (int) (opcode & 0xf));
- return ERROR_OK;
- }
- mnemonic = "ROR";
- break;
- }
- goto immediate;
- } else {
- instruction->type = ARM_ORR;
- mnemonic = "ORR";
- }
- break;
- case 3:
- if (rn == 0xf) {
- instruction->type = ARM_MVN;
- mnemonic = "MVN";
- rn = rd;
- goto two;
- } else {
- /* instruction->type = ARM_ORN; */
- mnemonic = "ORN";
- }
- break;
- case 4:
- if (rd == 0xf) {
- if (!(opcode & (1 << 20)))
- return ERROR_COMMAND_SYNTAX_ERROR;
- instruction->type = ARM_TEQ;
- mnemonic = "TEQ";
- suffix = "";
- goto two;
- }
- instruction->type = ARM_EOR;
- mnemonic = "EOR";
- break;
- case 8:
- if (rd == 0xf) {
- if (!(opcode & (1 << 20)))
- return ERROR_COMMAND_SYNTAX_ERROR;
- instruction->type = ARM_CMN;
- mnemonic = "CMN";
- suffix = "";
- goto two;
- }
- instruction->type = ARM_ADD;
- mnemonic = "ADD";
- break;
- case 0xa:
- instruction->type = ARM_ADC;
- mnemonic = "ADC";
- break;
- case 0xb:
- instruction->type = ARM_SBC;
- mnemonic = "SBC";
- break;
- case 0xd:
- if (rd == 0xf) {
- if (!(opcode & (1 << 21)))
- return ERROR_COMMAND_SYNTAX_ERROR;
- instruction->type = ARM_CMP;
- mnemonic = "CMP";
- suffix = "";
- goto two;
- }
- instruction->type = ARM_SUB;
- mnemonic = "SUB";
- break;
- case 0xe:
- instruction->type = ARM_RSB;
- mnemonic = "RSB";
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
- mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
-
-shift:
- cp = strchr(cp, 0);
-
- switch (type) {
- case 0:
- if (immed == 0)
- return ERROR_OK;
- suffix = "LSL";
- break;
- case 1:
- suffix = "LSR";
- if (immed == 32)
- immed = 0;
- break;
- case 2:
- suffix = "ASR";
- if (immed == 32)
- immed = 0;
- break;
- case 3:
- if (immed == 0) {
- strcpy(cp, ", RRX");
- return ERROR_OK;
- }
- suffix = "ROR";
- break;
- }
- sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
- return ERROR_OK;
-
-two:
- sprintf(cp, "%s%s.W\tr%d, r%d",
- mnemonic, suffix, rn, (int) (opcode & 0xf));
- goto shift;
-
-immediate:
- sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
- mnemonic, suffix, rd,
- (int) (opcode & 0xf), immed ? immed : 32);
- return ERROR_OK;
-}
-
-static int t2ev_data_reg(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- char *mnemonic;
- char *suffix = "";
-
- if (((opcode >> 4) & 0xf) == 0) {
- switch ((opcode >> 21) & 0x7) {
- case 0:
- mnemonic = "LSL";
- break;
- case 1:
- mnemonic = "LSR";
- break;
- case 2:
- mnemonic = "ASR";
- break;
- case 3:
- mnemonic = "ROR";
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- instruction->type = ARM_MOV;
- if (opcode & (1 << 20))
- suffix = "S";
- sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
- mnemonic, suffix,
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 16) & 0xf,
- (int) (opcode >> 0) & 0xf);
-
- } else if (opcode & (1 << 7)) {
- switch ((opcode >> 20) & 0xf) {
- case 0:
- case 1:
- case 4:
- case 5:
- switch ((opcode >> 4) & 0x3) {
- case 1:
- suffix = ", ROR #8";
- break;
- case 2:
- suffix = ", ROR #16";
- break;
- case 3:
- suffix = ", ROR #24";
- break;
- }
- sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
- (opcode & (1 << 24)) ? 'U' : 'S',
- (opcode & (1 << 26)) ? 'B' : 'H',
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 0) & 0xf,
- suffix);
- break;
- case 8:
- case 9:
- case 0xa:
- case 0xb:
- if (opcode & (1 << 6))
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (((opcode >> 12) & 0xf) != 0xf)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (!(opcode & (1 << 20)))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- switch (((opcode >> 19) & 0x04)
- | ((opcode >> 4) & 0x3)) {
- case 0:
- mnemonic = "REV.W";
- break;
- case 1:
- mnemonic = "REV16.W";
- break;
- case 2:
- mnemonic = "RBIT";
- break;
- case 3:
- mnemonic = "REVSH.W";
- break;
- case 4:
- mnemonic = "CLZ";
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- sprintf(cp, "%s\tr%d, r%d",
- mnemonic,
- (int) (opcode >> 8) & 0xf,
- (int) (opcode >> 0) & 0xf);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- return ERROR_OK;
-}
-
-static int t2ev_load_word(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- int rn = (opcode >> 16) & 0xf;
- int immed;
-
- instruction->type = ARM_LDR;
-
- if (rn == 0xf) {
- immed = opcode & 0x0fff;
- if ((opcode & (1 << 23)) == 0)
- immed = -immed;
- sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
- (int) (opcode >> 12) & 0xf,
- thumb_alignpc4(address) + immed);
- return ERROR_OK;
- }
-
- if (opcode & (1 << 23)) {
- immed = opcode & 0x0fff;
- sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
- (int) (opcode >> 12) & 0xf,
- rn, immed, immed);
- return ERROR_OK;
- }
-
- if (!(opcode & (0x3f << 6))) {
- sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
- (int) (opcode >> 12) & 0xf,
- rn,
- (int) (opcode >> 0) & 0xf,
- (int) (opcode >> 4) & 0x3);
- return ERROR_OK;
- }
-
-
- if (((opcode >> 8) & 0xf) == 0xe) {
- immed = opcode & 0x00ff;
-
- sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
- (int) (opcode >> 12) & 0xf,
- rn, immed, immed);
- return ERROR_OK;
- }
-
- if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
- char *p1 = "]", *p2 = "";
-
- if (!(opcode & 0x0500))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- immed = opcode & 0x00ff;
-
- /* two indexed modes will write back rn */
- if (opcode & 0x100) {
- if (opcode & 0x400) /* pre-indexed */
- p2 = "]!";
- else { /* post-indexed */
- p1 = "]";
- p2 = "";
- }
- }
-
- sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
- (int) (opcode >> 12) & 0xf,
- rn, p1,
- (opcode & 0x200) ? "" : "-",
- immed, p2, immed);
- return ERROR_OK;
- }
-
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- int rn = (opcode >> 16) & 0xf;
- int rt = (opcode >> 12) & 0xf;
- int op2 = (opcode >> 6) & 0x3f;
- unsigned immed;
- char *p1 = "", *p2 = "]";
- char *mnemonic;
-
- switch ((opcode >> 23) & 0x3) {
- case 0:
- if ((rn & rt) == 0xf) {
-pld_literal:
- immed = opcode & 0xfff;
- address = thumb_alignpc4(address);
- if (opcode & (1 << 23))
- address += immed;
- else
- address -= immed;
- sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
- rt, address);
- return ERROR_OK;
- }
- if (rn == 0x0f && rt != 0x0f) {
-ldrb_literal:
- immed = opcode & 0xfff;
- address = thumb_alignpc4(address);
- if (opcode & (1 << 23))
- address += immed;
- else
- address -= immed;
- sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
- rt, address);
- return ERROR_OK;
- }
- if (rn == 0x0f)
- break;
- if ((op2 & 0x3c) == 0x38) {
- immed = opcode & 0xff;
- sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
- rt, rn, immed, immed);
- return ERROR_OK;
- }
- if ((op2 & 0x3c) == 0x30) {
- if (rt == 0x0f) {
- immed = opcode & 0xff;
- immed = -immed;
-preload_immediate:
- p1 = (opcode & (1 << 21)) ? "W" : "";
- sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
- p1, rn, immed, immed);
- return ERROR_OK;
- }
- mnemonic = "LDRB";
-ldrxb_immediate_t3:
- immed = opcode & 0xff;
- if (!(opcode & 0x200))
- immed = -immed;
-
- /* two indexed modes will write back rn */
- if (opcode & 0x100) {
- if (opcode & 0x400) /* pre-indexed */
- p2 = "]!";
- else { /* post-indexed */
- p1 = "]";
- p2 = "";
- }
- }
-ldrxb_immediate_t2:
- sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
- mnemonic, rt, rn, p1,
- immed, p2, immed);
- return ERROR_OK;
- }
- if ((op2 & 0x24) == 0x24) {
- mnemonic = "LDRB";
- goto ldrxb_immediate_t3;
- }
- if (op2 == 0) {
- int rm = opcode & 0xf;
-
- if (rt == 0x0f)
- sprintf(cp, "PLD\t");
- else
- sprintf(cp, "LDRB.W\tr%d, ", rt);
- immed = (opcode >> 4) & 0x3;
- cp = strchr(cp, 0);
- sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
- return ERROR_OK;
- }
- break;
- case 1:
- if ((rn & rt) == 0xf)
- goto pld_literal;
- if (rt == 0xf) {
- immed = opcode & 0xfff;
- goto preload_immediate;
- }
- if (rn == 0x0f)
- goto ldrb_literal;
- mnemonic = "LDRB.W";
- immed = opcode & 0xfff;
- goto ldrxb_immediate_t2;
- case 2:
- if ((rn & rt) == 0xf) {
- immed = opcode & 0xfff;
- address = thumb_alignpc4(address);
- if (opcode & (1 << 23))
- address += immed;
- else
- address -= immed;
- sprintf(cp, "PLI\t%#8.8" PRIx32, address);
- return ERROR_OK;
- }
- if (rn == 0xf && rt != 0xf) {
-ldrsb_literal:
- immed = opcode & 0xfff;
- address = thumb_alignpc4(address);
- if (opcode & (1 << 23))
- address += immed;
- else
- address -= immed;
- sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
- return ERROR_OK;
- }
- if (rn == 0xf)
- break;
- if ((op2 & 0x3c) == 0x38) {
- immed = opcode & 0xff;
- sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
- rt, rn, immed, immed);
- return ERROR_OK;
- }
- if ((op2 & 0x3c) == 0x30) {
- if (rt == 0xf) {
- immed = opcode & 0xff;
- immed = -immed; /* pli */
- sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
- rn, immed, -immed);
- return ERROR_OK;
- }
- mnemonic = "LDRSB";
- goto ldrxb_immediate_t3;
- }
- if ((op2 & 0x24) == 0x24) {
- mnemonic = "LDRSB";
- goto ldrxb_immediate_t3;
- }
- if (op2 == 0) {
- int rm = opcode & 0xf;
-
- if (rt == 0x0f)
- sprintf(cp, "PLI\t");
- else
- sprintf(cp, "LDRSB.W\tr%d, ", rt);
- immed = (opcode >> 4) & 0x3;
- cp = strchr(cp, 0);
- sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
- return ERROR_OK;
- }
- break;
- case 3:
- if (rt == 0xf) {
- immed = opcode & 0xfff;
- sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
- rn, immed, immed);
- return ERROR_OK;
- }
- if (rn == 0xf)
- goto ldrsb_literal;
- immed = opcode & 0xfff;
- mnemonic = "LDRSB";
- goto ldrxb_immediate_t2;
- }
-
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction, char *cp)
-{
- int rn = (opcode >> 16) & 0xf;
- int rt = (opcode >> 12) & 0xf;
- int op2 = (opcode >> 6) & 0x3f;
- char *sign = "";
- unsigned immed;
-
- if (rt == 0xf) {
- sprintf(cp, "HINT (UNALLOCATED)");
- return ERROR_OK;
- }
-
- if (opcode & (1 << 24))
- sign = "S";
-
- if ((opcode & (1 << 23)) == 0) {
- if (rn == 0xf) {
-ldrh_literal:
- immed = opcode & 0xfff;
- address = thumb_alignpc4(address);
- if (opcode & (1 << 23))
- address += immed;
- else
- address -= immed;
- sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
- sign, rt, address);
- return ERROR_OK;
- }
- if (op2 == 0) {
- int rm = opcode & 0xf;
-
- immed = (opcode >> 4) & 0x3;
- sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
- sign, rt, rn, rm, immed);
- return ERROR_OK;
- }
- if ((op2 & 0x3c) == 0x38) {
- immed = opcode & 0xff;
- sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
- sign, rt, rn, immed, immed);
- return ERROR_OK;
- }
- if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
- char *p1 = "", *p2 = "]";
-
- immed = opcode & 0xff;
- if (!(opcode & 0x200))
- immed = -immed;
-
- /* two indexed modes will write back rn */
- if (opcode & 0x100) {
- if (opcode & 0x400) /* pre-indexed */
- p2 = "]!";
- else { /* post-indexed */
- p1 = "]";
- p2 = "";
- }
- }
- sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
- sign, rt, rn, p1, immed, p2, immed);
- return ERROR_OK;
- }
- } else {
- if (rn == 0xf)
- goto ldrh_literal;
-
- immed = opcode & 0xfff;
- sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
- sign, *sign ? "" : ".W",
- rt, rn, immed, immed);
- return ERROR_OK;
- }
-
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-/*
- * REVISIT for Thumb2 instructions, instruction->type and friends aren't
- * always set. That means eventual arm_simulate_step() support for Thumb2
- * will need work in this area.
- */
-int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
-{
- int retval;
- uint16_t op;
- uint32_t opcode;
- char *cp;
-
- /* clear low bit ... it's set on function pointers */
- address &= ~1;
-
- /* clear fields, to avoid confusion */
- memset(instruction, 0, sizeof(struct arm_instruction));
-
- /* read first halfword, see if this is the only one */
- retval = target_read_u16(target, address, &op);
- if (retval != ERROR_OK)
- return retval;
-
- switch (op & 0xf800) {
- case 0xf800:
- case 0xf000:
- case 0xe800:
- /* 32-bit instructions */
- instruction->instruction_size = 4;
- opcode = op << 16;
- retval = target_read_u16(target, address + 2, &op);
- if (retval != ERROR_OK)
- return retval;
- opcode |= op;
- instruction->opcode = opcode;
- break;
- default:
- /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
- return thumb_evaluate_opcode(op, address, instruction);
- }
-
- snprintf(instruction->text, 128,
- "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
- address, opcode);
- cp = strchr(instruction->text, 0);
- retval = ERROR_FAIL;
-
- /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
- if ((opcode & 0x1a008000) == 0x10000000)
- retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
- else if ((opcode & 0x1a008000) == 0x12000000)
- retval = t2ev_data_immed(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
- else if ((opcode & 0x18008000) == 0x10008000)
- retval = t2ev_b_misc(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.5 Load/store multiple */
- else if ((opcode & 0x1e400000) == 0x08000000)
- retval = t2ev_ldm_stm(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
- else if ((opcode & 0x1e400000) == 0x08400000)
- retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.7 Load word */
- else if ((opcode & 0x1f700000) == 0x18500000)
- retval = t2ev_load_word(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
- else if ((opcode & 0x1e700000) == 0x18300000)
- retval = t2ev_load_halfword(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.9 Load byte, memory hints */
- else if ((opcode & 0x1e700000) == 0x18100000)
- retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.10 Store single data item */
- else if ((opcode & 0x1f100000) == 0x18000000)
- retval = t2ev_store_single(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.11 Data processing (shifted register) */
- else if ((opcode & 0x1e000000) == 0x0a000000)
- retval = t2ev_data_shift(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.12 Data processing (register)
- * and A5.3.13 Miscellaneous operations
- */
- else if ((opcode & 0x1f000000) == 0x1a000000)
- retval = t2ev_data_reg(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
- else if ((opcode & 0x1f800000) == 0x1b000000)
- retval = t2ev_mul32(opcode, address, instruction, cp);
-
- /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
- else if ((opcode & 0x1f800000) == 0x1b800000)
- retval = t2ev_mul64_div(opcode, address, instruction, cp);
-
- if (retval == ERROR_OK)
- return retval;
-
- /*
- * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
- * instructions; not yet handled here.
- */
-
- if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
- instruction->type = ARM_UNDEFINED_INSTRUCTION;
- strcpy(cp, "UNDEFINED OPCODE");
- return ERROR_OK;
- }
-
- LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
- opcode);
-
- strcpy(cp, "(32-bit Thumb2 ...)");
- return ERROR_OK;
-}
-
-int arm_access_size(struct arm_instruction *instruction)
-{
- if ((instruction->type == ARM_LDRB)
- || (instruction->type == ARM_LDRBT)
- || (instruction->type == ARM_LDRSB)
- || (instruction->type == ARM_STRB)
- || (instruction->type == ARM_STRBT))
- return 1;
- else if ((instruction->type == ARM_LDRH)
- || (instruction->type == ARM_LDRSH)
- || (instruction->type == ARM_STRH))
- return 2;
- else if ((instruction->type == ARM_LDR)
- || (instruction->type == ARM_LDRT)
- || (instruction->type == ARM_STR)
- || (instruction->type == ARM_STRT))
- return 4;
- else if ((instruction->type == ARM_LDRD)
- || (instruction->type == ARM_STRD))
- return 8;
- else {
- LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
- instruction->type);
- return 0;
- }
-}
diff --git a/src/target/arm_disassembler.h b/src/target/arm_disassembler.h
deleted file mode 100644
index 6f8f65d..0000000
--- a/src/target/arm_disassembler.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM_DISASSEMBLER_H
-#define OPENOCD_TARGET_ARM_DISASSEMBLER_H
-
-enum arm_instruction_type {
- ARM_UNKNOWN_INSTUCTION,
-
- /* Branch instructions */
- ARM_B,
- ARM_BL,
- ARM_BX,
- ARM_BLX,
-
- /* Data processing instructions */
- ARM_AND,
- ARM_EOR,
- ARM_SUB,
- ARM_RSB,
- ARM_ADD,
- ARM_ADC,
- ARM_SBC,
- ARM_RSC,
- ARM_TST,
- ARM_TEQ,
- ARM_CMP,
- ARM_CMN,
- ARM_ORR,
- ARM_MOV,
- ARM_BIC,
- ARM_MVN,
-
- /* Load/store instructions */
- ARM_LDR,
- ARM_LDRB,
- ARM_LDRT,
- ARM_LDRBT,
-
- ARM_LDRH,
- ARM_LDRSB,
- ARM_LDRSH,
-
- ARM_LDM,
-
- ARM_STR,
- ARM_STRB,
- ARM_STRT,
- ARM_STRBT,
-
- ARM_STRH,
-
- ARM_STM,
-
- /* Status register access instructions */
- ARM_MRS,
- ARM_MSR,
-
- /* Multiply instructions */
- ARM_MUL,
- ARM_MLA,
- ARM_SMULL,
- ARM_SMLAL,
- ARM_UMULL,
- ARM_UMLAL,
-
- /* Miscellaneous instructions */
- ARM_CLZ,
-
- /* Exception return instructions */
- ARM_ERET,
-
- /* Exception generating instructions */
- ARM_BKPT,
- ARM_SWI,
- ARM_HVC,
- ARM_SMC,
-
- /* Coprocessor instructions */
- ARM_CDP,
- ARM_LDC,
- ARM_STC,
- ARM_MCR,
- ARM_MRC,
-
- /* Semaphore instructions */
- ARM_SWP,
- ARM_SWPB,
-
- /* Enhanced DSP extensions */
- ARM_MCRR,
- ARM_MRRC,
- ARM_PLD,
- ARM_QADD,
- ARM_QDADD,
- ARM_QSUB,
- ARM_QDSUB,
- ARM_SMLAxy,
- ARM_SMLALxy,
- ARM_SMLAWy,
- ARM_SMULxy,
- ARM_SMULWy,
- ARM_LDRD,
- ARM_STRD,
-
- ARM_UNDEFINED_INSTRUCTION = 0xffffffff,
-};
-
-struct arm_b_bl_bx_blx_instr {
- int reg_operand;
- uint32_t target_address;
-};
-
-union arm_shifter_operand {
- struct {
- uint32_t immediate;
- } immediate;
- struct {
- uint8_t Rm;
- uint8_t shift; /* 0: LSL, 1: LSR, 2: ASR, 3: ROR, 4: RRX */
- uint8_t shift_imm;
- } immediate_shift;
- struct {
- uint8_t Rm;
- uint8_t shift;
- uint8_t Rs;
- } register_shift;
-};
-
-struct arm_data_proc_instr {
- int variant; /* 0: immediate, 1: immediate_shift, 2: register_shift */
- uint8_t S;
- uint8_t Rn;
- uint8_t Rd;
- union arm_shifter_operand shifter_operand;
-};
-
-struct arm_load_store_instr {
- uint8_t Rd;
- uint8_t Rn;
- uint8_t U;
- int index_mode; /* 0: offset, 1: pre-indexed, 2: post-indexed */
- int offset_mode; /* 0: immediate, 1: (scaled) register */
- union {
- uint32_t offset;
- struct {
- uint8_t Rm;
- uint8_t shift; /* 0: LSL, 1: LSR, 2: ASR, 3: ROR, 4: RRX */
- uint8_t shift_imm;
- } reg;
- } offset;
-};
-
-struct arm_load_store_multiple_instr {
- uint8_t Rn;
- uint32_t register_list;
- uint8_t addressing_mode; /* 0: IA, 1: IB, 2: DA, 3: DB */
- uint8_t S;
- uint8_t W;
-};
-
-struct arm_instruction {
- enum arm_instruction_type type;
- char text[128];
- uint32_t opcode;
-
- /* return value ... Thumb-2 sizes vary */
- unsigned instruction_size;
-
- union {
- struct arm_b_bl_bx_blx_instr b_bl_bx_blx;
- struct arm_data_proc_instr data_proc;
- struct arm_load_store_instr load_store;
- struct arm_load_store_multiple_instr load_store_multiple;
- } info;
-
-};
-
-int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
- struct arm_instruction *instruction);
-int thumb_evaluate_opcode(uint16_t opcode, uint32_t address,
- struct arm_instruction *instruction);
-int thumb2_opcode(struct target *target, uint32_t address,
- struct arm_instruction *instruction);
-int arm_access_size(struct arm_instruction *instruction);
-
-#define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000) >> 28])
-
-#endif /* OPENOCD_TARGET_ARM_DISASSEMBLER_H */
diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c
deleted file mode 100644
index 8ad6575..0000000
--- a/src/target/arm_dpm.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * Copyright (C) 2009 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "arm_dpm.h"
-#include <jtag/jtag.h>
-#include "register.h"
-#include "breakpoints.h"
-#include "target_type.h"
-#include "arm_opcodes.h"
-
-
-/**
- * @file
- * Implements various ARM DPM operations using architectural debug registers.
- * These routines layer over core-specific communication methods to cope with
- * implementation differences between cores like ARM1136 and Cortex-A8.
- *
- * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
- * Part C (Debug Architecture) of the ARM Architecture Reference Manual,
- * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
- * are abstracted through internal programming interfaces to share code and
- * to minimize needless differences in debug behavior between cores.
- */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * Coprocessor support
- */
-
-/* Read coprocessor */
-static int dpm_mrc(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
- uint32_t *value)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_dpm *dpm = arm->dpm;
- int retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum,
- (int) op1, (int) CRn,
- (int) CRm, (int) op2);
-
- /* read coprocessor register into R0; return via DCC */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
- value);
-
- /* (void) */ dpm->finish(dpm);
- return retval;
-}
-
-static int dpm_mcr(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
- uint32_t value)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_dpm *dpm = arm->dpm;
- int retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum,
- (int) op1, (int) CRn,
- (int) CRm, (int) op2);
-
- /* read DCC into r0; then write coprocessor register from R0 */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
- value);
-
- /* (void) */ dpm->finish(dpm);
- return retval;
-}
-
-/*----------------------------------------------------------------------*/
-
-/*
- * Register access utilities
- */
-
-/* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
- * Routines *must* restore the original mode before returning!!
- */
-int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
-{
- int retval;
- uint32_t cpsr;
-
- /* restore previous mode */
- if (mode == ARM_MODE_ANY)
- cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32);
-
- /* else force to the specified mode */
- else
- cpsr = mode;
-
- retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MSR_GP(0, 0xf, 0), cpsr);
- if (retval != ERROR_OK)
- return retval;
-
- if (dpm->instr_cpsr_sync)
- retval = dpm->instr_cpsr_sync(dpm);
-
- return retval;
-}
-
-/* just read the register -- rely on the core mode being right */
-static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
-{
- uint32_t value;
- int retval;
-
- switch (regnum) {
- case 0 ... 14:
- /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
- retval = dpm->instr_read_data_dcc(dpm,
- ARMV4_5_MCR(14, 0, regnum, 0, 5, 0),
- &value);
- break;
- case 15:/* PC
- * "MOV r0, pc"; then return via DCC */
- retval = dpm->instr_read_data_r0(dpm, 0xe1a0000f, &value);
-
- /* NOTE: this seems like a slightly awkward place to update
- * this value ... but if the PC gets written (the only way
- * to change what we compute), the arch spec says subsequent
- * reads return values which are "unpredictable". So this
- * is always right except in those broken-by-intent cases.
- */
- switch (dpm->arm->core_state) {
- case ARM_STATE_ARM:
- value -= 8;
- break;
- case ARM_STATE_THUMB:
- case ARM_STATE_THUMB_EE:
- value -= 4;
- break;
- case ARM_STATE_JAZELLE:
- /* core-specific ... ? */
- LOG_WARNING("Jazelle PC adjustment unknown");
- break;
- }
- break;
- default:
- /* 16: "MRS r0, CPSR"; then return via DCC
- * 17: "MRS r0, SPSR"; then return via DCC
- */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRS(0, regnum & 1),
- &value);
- break;
- }
-
- if (retval == ERROR_OK) {
- buf_set_u32(r->value, 0, 32, value);
- r->valid = true;
- r->dirty = false;
- LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value);
- }
-
- return retval;
-}
-
-/* just write the register -- rely on the core mode being right */
-static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
-{
- int retval;
- uint32_t value = buf_get_u32(r->value, 0, 32);
-
- switch (regnum) {
- case 0 ... 14:
- /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
- retval = dpm->instr_write_data_dcc(dpm,
- ARMV4_5_MRC(14, 0, regnum, 0, 5, 0),
- value);
- break;
- case 15:/* PC
- * read r0 from DCC; then "MOV pc, r0" */
- retval = dpm->instr_write_data_r0(dpm, 0xe1a0f000, value);
- break;
- default:
- /* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
- * 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
- */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MSR_GP(0, 0xf, regnum & 1),
- value);
- if (retval != ERROR_OK)
- return retval;
-
- if (regnum == 16 && dpm->instr_cpsr_sync)
- retval = dpm->instr_cpsr_sync(dpm);
-
- break;
- }
-
- if (retval == ERROR_OK) {
- r->dirty = false;
- LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value);
- }
-
- return retval;
-}
-
-/**
- * Write to program counter and switch the core state (arm/thumb) according to
- * the address.
- */
-static int dpm_write_pc_core_state(struct arm_dpm *dpm, struct reg *r)
-{
- uint32_t value = buf_get_u32(r->value, 0, 32);
-
- /* read r0 from DCC; then "BX r0" */
- return dpm->instr_write_data_r0(dpm, ARMV4_5_BX(0), value);
-}
-
-/**
- * Read basic registers of the the current context: R0 to R15, and CPSR;
- * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
- * In normal operation this is called on entry to halting debug state,
- * possibly after some other operations supporting restore of debug state
- * or making sure the CPU is fully idle (drain write buffer, etc).
- */
-int arm_dpm_read_current_registers(struct arm_dpm *dpm)
-{
- struct arm *arm = dpm->arm;
- uint32_t cpsr;
- int retval;
- struct reg *r;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- return retval;
-
- /* read R0 first (it's used for scratch), then CPSR */
- r = arm->core_cache->reg_list + 0;
- if (!r->valid) {
- retval = dpm_read_reg(dpm, r, 0);
- if (retval != ERROR_OK)
- goto fail;
- }
- r->dirty = true;
-
- retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr);
- if (retval != ERROR_OK)
- goto fail;
-
- /* update core mode and state, plus shadow mapping for R8..R14 */
- arm_set_cpsr(arm, cpsr);
-
- /* REVISIT we can probably avoid reading R1..R14, saving time... */
- for (unsigned i = 1; i < 16; i++) {
- r = arm_reg_current(arm, i);
- if (r->valid)
- continue;
-
- retval = dpm_read_reg(dpm, r, i);
- if (retval != ERROR_OK)
- goto fail;
- }
-
- /* NOTE: SPSR ignored (if it's even relevant). */
-
- /* REVISIT the debugger can trigger various exceptions. See the
- * ARMv7A architecture spec, section C5.7, for more info about
- * what defenses are needed; v6 debug has the most issues.
- */
-
-fail:
- /* (void) */ dpm->finish(dpm);
- return retval;
-}
-
-/* Avoid needless I/O ... leave breakpoints and watchpoints alone
- * unless they're removed, or need updating because of single-stepping
- * or running debugger code.
- */
-static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
- struct dpm_bpwp *xp, int *set_p)
-{
- int retval = ERROR_OK;
- bool disable;
-
- if (!set_p) {
- if (!xp->dirty)
- goto done;
- xp->dirty = false;
- /* removed or startup; we must disable it */
- disable = true;
- } else if (bpwp) {
- if (!xp->dirty)
- goto done;
- /* disabled, but we must set it */
- xp->dirty = disable = false;
- *set_p = true;
- } else {
- if (!*set_p)
- goto done;
- /* set, but we must temporarily disable it */
- xp->dirty = disable = true;
- *set_p = false;
- }
-
- if (disable)
- retval = dpm->bpwp_disable(dpm, xp->number);
- else
- retval = dpm->bpwp_enable(dpm, xp->number,
- xp->address, xp->control);
-
- if (retval != ERROR_OK)
- LOG_ERROR("%s: can't %s HW %spoint %d",
- disable ? "disable" : "enable",
- target_name(dpm->arm->target),
- (xp->number < 16) ? "break" : "watch",
- xp->number & 0xf);
-done:
- return retval;
-}
-
-static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp);
-
-/**
- * Writes all modified core registers for all processor modes. In normal
- * operation this is called on exit from halting debug state.
- *
- * @param dpm: represents the processor
- * @param bpwp: true ensures breakpoints and watchpoints are set,
- * false ensures they are cleared
- */
-int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
-{
- struct arm *arm = dpm->arm;
- struct reg_cache *cache = arm->core_cache;
- int retval;
- bool did_write;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- /* If we're managing hardware breakpoints for this core, enable
- * or disable them as requested.
- *
- * REVISIT We don't yet manage them for ANY cores. Eventually
- * we should be able to assume we handle them; but until then,
- * cope with the hand-crafted breakpoint code.
- */
- if (arm->target->type->add_breakpoint == dpm_add_breakpoint) {
- for (unsigned i = 0; i < dpm->nbp; i++) {
- struct dpm_bp *dbp = dpm->dbp + i;
- struct breakpoint *bp = dbp->bp;
-
- retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
- bp ? &bp->set : NULL);
- if (retval != ERROR_OK)
- goto done;
- }
- }
-
- /* enable/disable watchpoints */
- for (unsigned i = 0; i < dpm->nwp; i++) {
- struct dpm_wp *dwp = dpm->dwp + i;
- struct watchpoint *wp = dwp->wp;
-
- retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
- wp ? &wp->set : NULL);
- if (retval != ERROR_OK)
- goto done;
- }
-
- /* NOTE: writes to breakpoint and watchpoint registers might
- * be queued, and need (efficient/batched) flushing later.
- */
-
- /* Scan the registers until we find one that's both dirty and
- * eligible for flushing. Flush that and everything else that
- * shares the same core mode setting. Typically this won't
- * actually find anything to do...
- */
- do {
- enum arm_mode mode = ARM_MODE_ANY;
-
- did_write = false;
-
- /* check everything except our scratch register R0 */
- for (unsigned i = 1; i < cache->num_regs; i++) {
- struct arm_reg *r;
- unsigned regnum;
-
- /* also skip PC, CPSR, and non-dirty */
- if (i == 15)
- continue;
- if (arm->cpsr == cache->reg_list + i)
- continue;
- if (!cache->reg_list[i].dirty)
- continue;
-
- r = cache->reg_list[i].arch_info;
- regnum = r->num;
-
- /* may need to pick and set a mode */
- if (!did_write) {
- enum arm_mode tmode;
-
- did_write = true;
- mode = tmode = r->mode;
-
- /* cope with special cases */
- switch (regnum) {
- case 8 ... 12:
- /* r8..r12 "anything but FIQ" case;
- * we "know" core mode is accurate
- * since we haven't changed it yet
- */
- if (arm->core_mode == ARM_MODE_FIQ
- && ARM_MODE_ANY
- != mode)
- tmode = ARM_MODE_USR;
- break;
- case 16:
- /* SPSR */
- regnum++;
- break;
- }
-
- /* REVISIT error checks */
- if (tmode != ARM_MODE_ANY) {
- retval = dpm_modeswitch(dpm, tmode);
- if (retval != ERROR_OK)
- goto done;
- }
- }
- if (r->mode != mode)
- continue;
-
- retval = dpm_write_reg(dpm,
- &cache->reg_list[i],
- regnum);
- if (retval != ERROR_OK)
- goto done;
- }
-
- } while (did_write);
-
- /* Restore original CPSR ... assuming either that we changed it,
- * or it's dirty. Must write PC to ensure the return address is
- * defined, and must not write it before CPSR.
- */
- retval = dpm_modeswitch(dpm, ARM_MODE_ANY);
- if (retval != ERROR_OK)
- goto done;
- arm->cpsr->dirty = false;
-
- /* restore the PC, make sure to also switch the core state
- * to whatever it was set to with "arm core_state" command.
- * target code will have set PC to an appropriate resume address.
- */
- retval = dpm_write_pc_core_state(dpm, arm->pc);
- if (retval != ERROR_OK)
- goto done;
- /* on Cortex-A5 (as found on NXP VF610 SoC), BX instruction
- * executed in debug state doesn't appear to set the PC,
- * explicitly set it with a "MOV pc, r0". This doesn't influence
- * CPSR on Cortex-A9 so it should be OK. Maybe due to different
- * debug version?
- */
- retval = dpm_write_reg(dpm, arm->pc, 15);
- if (retval != ERROR_OK)
- goto done;
- arm->pc->dirty = false;
-
- /* flush R0 -- it's *very* dirty by now */
- retval = dpm_write_reg(dpm, &cache->reg_list[0], 0);
- if (retval != ERROR_OK)
- goto done;
- cache->reg_list[0].dirty = false;
-
- /* (void) */ dpm->finish(dpm);
-done:
- return retval;
-}
-
-/* Returns ARM_MODE_ANY or temporary mode to use while reading the
- * specified register ... works around flakiness from ARM core calls.
- * Caller already filtered out SPSR access; mode is never MODE_SYS
- * or MODE_ANY.
- */
-static enum arm_mode dpm_mapmode(struct arm *arm,
- unsigned num, enum arm_mode mode)
-{
- enum arm_mode amode = arm->core_mode;
-
- /* don't switch if the mode is already correct */
- if (amode == ARM_MODE_SYS)
- amode = ARM_MODE_USR;
- if (mode == amode)
- return ARM_MODE_ANY;
-
- switch (num) {
- /* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
- case 0 ... 7:
- case 15:
- case 16:
- break;
- /* r8..r12 aren't shadowed for anything except FIQ */
- case 8 ... 12:
- if (mode == ARM_MODE_FIQ)
- return mode;
- break;
- /* r13/sp, and r14/lr are always shadowed */
- case 13:
- case 14:
- return mode;
- default:
- LOG_WARNING("invalid register #%u", num);
- break;
- }
- return ARM_MODE_ANY;
-}
-
-
-/*
- * Standard ARM register accessors ... there are three methods
- * in "struct arm", to support individual read/write and bulk read
- * of registers.
- */
-
-static int arm_dpm_read_core_reg(struct target *target, struct reg *r,
- int regnum, enum arm_mode mode)
-{
- struct arm_dpm *dpm = target_to_arm(target)->dpm;
- int retval;
-
- if (regnum < 0 || regnum > 16)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (regnum == 16) {
- if (mode != ARM_MODE_ANY)
- regnum = 17;
- } else
- mode = dpm_mapmode(dpm->arm, regnum, mode);
-
- /* REVISIT what happens if we try to read SPSR in a core mode
- * which has no such register?
- */
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- return retval;
-
- if (mode != ARM_MODE_ANY) {
- retval = dpm_modeswitch(dpm, mode);
- if (retval != ERROR_OK)
- goto fail;
- }
-
- retval = dpm_read_reg(dpm, r, regnum);
- if (retval != ERROR_OK)
- goto fail;
- /* always clean up, regardless of error */
-
- if (mode != ARM_MODE_ANY)
- /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY);
-
-fail:
- /* (void) */ dpm->finish(dpm);
- return retval;
-}
-
-static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
- int regnum, enum arm_mode mode, uint8_t *value)
-{
- struct arm_dpm *dpm = target_to_arm(target)->dpm;
- int retval;
-
-
- if (regnum < 0 || regnum > 16)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (regnum == 16) {
- if (mode != ARM_MODE_ANY)
- regnum = 17;
- } else
- mode = dpm_mapmode(dpm->arm, regnum, mode);
-
- /* REVISIT what happens if we try to write SPSR in a core mode
- * which has no such register?
- */
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- return retval;
-
- if (mode != ARM_MODE_ANY) {
- retval = dpm_modeswitch(dpm, mode);
- if (retval != ERROR_OK)
- goto fail;
- }
-
- retval = dpm_write_reg(dpm, r, regnum);
- /* always clean up, regardless of error */
-
- if (mode != ARM_MODE_ANY)
- /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY);
-
-fail:
- /* (void) */ dpm->finish(dpm);
- return retval;
-}
-
-static int arm_dpm_full_context(struct target *target)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_dpm *dpm = arm->dpm;
- struct reg_cache *cache = arm->core_cache;
- int retval;
- bool did_read;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- do {
- enum arm_mode mode = ARM_MODE_ANY;
-
- did_read = false;
-
- /* We "know" arm_dpm_read_current_registers() was called so
- * the unmapped registers (R0..R7, PC, AND CPSR) and some
- * view of R8..R14 are current. We also "know" oddities of
- * register mapping: special cases for R8..R12 and SPSR.
- *
- * Pick some mode with unread registers and read them all.
- * Repeat until done.
- */
- for (unsigned i = 0; i < cache->num_regs; i++) {
- struct arm_reg *r;
-
- if (cache->reg_list[i].valid)
- continue;
- r = cache->reg_list[i].arch_info;
-
- /* may need to pick a mode and set CPSR */
- if (!did_read) {
- did_read = true;
- mode = r->mode;
-
- /* For regular (ARM_MODE_ANY) R8..R12
- * in case we've entered debug state
- * in FIQ mode we need to patch mode.
- */
- if (mode != ARM_MODE_ANY)
- retval = dpm_modeswitch(dpm, mode);
- else
- retval = dpm_modeswitch(dpm, ARM_MODE_USR);
-
- if (retval != ERROR_OK)
- goto done;
- }
- if (r->mode != mode)
- continue;
-
- /* CPSR was read, so "R16" must mean SPSR */
- retval = dpm_read_reg(dpm,
- &cache->reg_list[i],
- (r->num == 16) ? 17 : r->num);
- if (retval != ERROR_OK)
- goto done;
- }
-
- } while (did_read);
-
- retval = dpm_modeswitch(dpm, ARM_MODE_ANY);
- /* (void) */ dpm->finish(dpm);
-done:
- return retval;
-}
-
-
-/*----------------------------------------------------------------------*/
-
-/*
- * Breakpoint and Watchpoint support.
- *
- * Hardware {break,watch}points are usually left active, to minimize
- * debug entry/exit costs. When they are set or cleared, it's done in
- * batches. Also, DPM-conformant hardware can update debug registers
- * regardless of whether the CPU is running or halted ... though that
- * fact isn't currently leveraged.
- */
-
-static int dpm_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp,
- uint32_t addr, uint32_t length)
-{
- uint32_t control;
-
- control = (1 << 0) /* enable */
- | (3 << 1); /* both user and privileged access */
-
- /* Match 1, 2, or all 4 byte addresses in this word.
- *
- * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP.
- * Support larger length, when addr is suitably aligned. In
- * particular, allow watchpoints on 8 byte "double" values.
- *
- * REVISIT allow watchpoints on unaligned 2-bit values; and on
- * v7 hardware, unaligned 4-byte ones too.
- */
- switch (length) {
- case 1:
- control |= (1 << (addr & 3)) << 5;
- break;
- case 2:
- /* require 2-byte alignment */
- if (!(addr & 1)) {
- control |= (3 << (addr & 2)) << 5;
- break;
- }
- /* FALL THROUGH */
- case 4:
- /* require 4-byte alignment */
- if (!(addr & 3)) {
- control |= 0xf << 5;
- break;
- }
- /* FALL THROUGH */
- default:
- LOG_ERROR("unsupported {break,watch}point length/alignment");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* other shared control bits:
- * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
- * bit 20 == 0 ... not linked to a context ID
- * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
- */
-
- xp->address = addr & ~3;
- xp->control = control;
- xp->dirty = true;
-
- LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d",
- xp->address, control, xp->number);
-
- /* hardware is updated in write_dirty_registers() */
- return ERROR_OK;
-}
-
-static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_dpm *dpm = arm->dpm;
- int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- if (bp->length < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (!dpm->bpwp_enable)
- return retval;
-
- /* FIXME we need a generic solution for software breakpoints. */
- if (bp->type == BKPT_SOFT)
- LOG_DEBUG("using HW bkpt, not SW...");
-
- for (unsigned i = 0; i < dpm->nbp; i++) {
- if (!dpm->dbp[i].bp) {
- retval = dpm_bpwp_setup(dpm, &dpm->dbp[i].bpwp,
- bp->address, bp->length);
- if (retval == ERROR_OK)
- dpm->dbp[i].bp = bp;
- break;
- }
- }
-
- return retval;
-}
-
-static int dpm_remove_breakpoint(struct target *target, struct breakpoint *bp)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_dpm *dpm = arm->dpm;
- int retval = ERROR_COMMAND_SYNTAX_ERROR;
-
- for (unsigned i = 0; i < dpm->nbp; i++) {
- if (dpm->dbp[i].bp == bp) {
- dpm->dbp[i].bp = NULL;
- dpm->dbp[i].bpwp.dirty = true;
-
- /* hardware is updated in write_dirty_registers() */
- retval = ERROR_OK;
- break;
- }
- }
-
- return retval;
-}
-
-static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t,
- struct watchpoint *wp)
-{
- int retval;
- struct dpm_wp *dwp = dpm->dwp + index_t;
- uint32_t control;
-
- /* this hardware doesn't support data value matching or masking */
- if (wp->value || wp->mask != ~(uint32_t)0) {
- LOG_DEBUG("watchpoint values and masking not supported");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- retval = dpm_bpwp_setup(dpm, &dwp->bpwp, wp->address, wp->length);
- if (retval != ERROR_OK)
- return retval;
-
- control = dwp->bpwp.control;
- switch (wp->rw) {
- case WPT_READ:
- control |= 1 << 3;
- break;
- case WPT_WRITE:
- control |= 2 << 3;
- break;
- case WPT_ACCESS:
- control |= 3 << 3;
- break;
- }
- dwp->bpwp.control = control;
-
- dpm->dwp[index_t].wp = wp;
-
- return retval;
-}
-
-static int dpm_add_watchpoint(struct target *target, struct watchpoint *wp)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_dpm *dpm = arm->dpm;
- int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- if (dpm->bpwp_enable) {
- for (unsigned i = 0; i < dpm->nwp; i++) {
- if (!dpm->dwp[i].wp) {
- retval = dpm_watchpoint_setup(dpm, i, wp);
- break;
- }
- }
- }
-
- return retval;
-}
-
-static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_dpm *dpm = arm->dpm;
- int retval = ERROR_COMMAND_SYNTAX_ERROR;
-
- for (unsigned i = 0; i < dpm->nwp; i++) {
- if (dpm->dwp[i].wp == wp) {
- dpm->dwp[i].wp = NULL;
- dpm->dwp[i].bpwp.dirty = true;
-
- /* hardware is updated in write_dirty_registers() */
- retval = ERROR_OK;
- break;
- }
- }
-
- return retval;
-}
-
-void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr)
-{
- switch (dpm->arm->core_state) {
- case ARM_STATE_ARM:
- addr -= 8;
- break;
- case ARM_STATE_THUMB:
- case ARM_STATE_THUMB_EE:
- addr -= 4;
- break;
- case ARM_STATE_JAZELLE:
- /* ?? */
- break;
- }
- dpm->wp_pc = addr;
-}
-
-/*----------------------------------------------------------------------*/
-
-/*
- * Other debug and support utilities
- */
-
-void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
-{
- struct target *target = dpm->arm->target;
-
- dpm->dscr = dscr;
-
- /* Examine debug reason */
- switch (DSCR_ENTRY(dscr)) {
- case 6: /* Data abort (v6 only) */
- case 7: /* Prefetch abort (v6 only) */
- /* FALL THROUGH -- assume a v6 core in abort mode */
- case 0: /* HALT request from debugger */
- case 4: /* EDBGRQ */
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case 1: /* HW breakpoint */
- case 3: /* SW BKPT */
- case 5: /* vector catch */
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case 2: /* asynch watchpoint */
- case 10:/* precise watchpoint */
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- default:
- target->debug_reason = DBG_REASON_UNDEFINED;
- break;
- }
-}
-
-/*----------------------------------------------------------------------*/
-
-/*
- * Setup and management support.
- */
-
-/**
- * Hooks up this DPM to its associated target; call only once.
- * Initially this only covers the register cache.
- *
- * Oh, and watchpoints. Yeah.
- */
-int arm_dpm_setup(struct arm_dpm *dpm)
-{
- struct arm *arm = dpm->arm;
- struct target *target = arm->target;
- struct reg_cache *cache;
-
- arm->dpm = dpm;
-
- /* register access setup */
- arm->full_context = arm_dpm_full_context;
- arm->read_core_reg = arm_dpm_read_core_reg;
- arm->write_core_reg = arm_dpm_write_core_reg;
-
- cache = arm_build_reg_cache(target, arm);
- if (!cache)
- return ERROR_FAIL;
-
- *register_get_last_cache_p(&target->reg_cache) = cache;
-
- /* coprocessor access setup */
- arm->mrc = dpm_mrc;
- arm->mcr = dpm_mcr;
-
- /* breakpoint setup -- optional until it works everywhere */
- if (!target->type->add_breakpoint) {
- target->type->add_breakpoint = dpm_add_breakpoint;
- target->type->remove_breakpoint = dpm_remove_breakpoint;
- }
-
- /* watchpoint setup */
- target->type->add_watchpoint = dpm_add_watchpoint;
- target->type->remove_watchpoint = dpm_remove_watchpoint;
-
- /* FIXME add vector catch support */
-
- dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf);
- dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);
-
- dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf);
- dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);
-
- if (!dpm->dbp || !dpm->dwp) {
- free(dpm->dbp);
- free(dpm->dwp);
- return ERROR_FAIL;
- }
-
- LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
- target_name(target), dpm->nbp, dpm->nwp);
-
- /* REVISIT ... and some of those breakpoints could match
- * execution context IDs...
- */
-
- return ERROR_OK;
-}
-
-/**
- * Reinitializes DPM state at the beginning of a new debug session
- * or after a reset which may have affected the debug module.
- */
-int arm_dpm_initialize(struct arm_dpm *dpm)
-{
- /* Disable all breakpoints and watchpoints at startup. */
- if (dpm->bpwp_disable) {
- unsigned i;
-
- for (i = 0; i < dpm->nbp; i++) {
- dpm->dbp[i].bpwp.number = i;
- (void) dpm->bpwp_disable(dpm, i);
- }
- for (i = 0; i < dpm->nwp; i++) {
- dpm->dwp[i].bpwp.number = 16 + i;
- (void) dpm->bpwp_disable(dpm, 16 + i);
- }
- } else
- LOG_WARNING("%s: can't disable breakpoints and watchpoints",
- target_name(dpm->arm->target));
-
- return ERROR_OK;
-}
diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h
deleted file mode 100644
index fa87baf..0000000
--- a/src/target/arm_dpm.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2009 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef OPENOCD_TARGET_ARM_DPM_H
-#define OPENOCD_TARGET_ARM_DPM_H
-
-/**
- * @file
- * This is the interface to the Debug Programmers Model for ARMv6 and
- * ARMv7 processors. ARMv6 processors (such as ARM11xx implementations)
- * introduced a model which became part of the ARMv7-AR architecture
- * which is most familiar through the Cortex-A series parts. While
- * specific details differ (like how to write the instruction register),
- * the high level models easily support shared code because those
- * registers are compatible.
- */
-
-struct dpm_bpwp {
- unsigned number;
- uint32_t address;
- uint32_t control;
- /* true if hardware state needs flushing */
- bool dirty;
-};
-
-struct dpm_bp {
- struct breakpoint *bp;
- struct dpm_bpwp bpwp;
-};
-
-struct dpm_wp {
- struct watchpoint *wp;
- struct dpm_bpwp bpwp;
-};
-
-/**
- * This wraps an implementation of DPM primitives. Each interface
- * provider supplies a structure like this, which is the glue between
- * upper level code and the lower level hardware access.
- *
- * It is a PRELIMINARY AND INCOMPLETE set of primitives, starting with
- * support for CPU register access.
- */
-struct arm_dpm {
- struct arm *arm;
-
- /** Cache of DIDR */
- uint32_t didr;
-
- /** Invoke before a series of instruction operations */
- int (*prepare)(struct arm_dpm *);
-
- /** Invoke after a series of instruction operations */
- int (*finish)(struct arm_dpm *);
-
- /* WRITE TO CPU */
-
- /** Runs one instruction, writing data to DCC before execution. */
- int (*instr_write_data_dcc)(struct arm_dpm *,
- uint32_t opcode, uint32_t data);
-
- /** Runs one instruction, writing data to R0 before execution. */
- int (*instr_write_data_r0)(struct arm_dpm *,
- uint32_t opcode, uint32_t data);
-
- /** Optional core-specific operation invoked after CPSR writes. */
- int (*instr_cpsr_sync)(struct arm_dpm *dpm);
-
- /* READ FROM CPU */
-
- /** Runs one instruction, reading data from dcc after execution. */
- int (*instr_read_data_dcc)(struct arm_dpm *,
- uint32_t opcode, uint32_t *data);
-
- /** Runs one instruction, reading data from r0 after execution. */
- int (*instr_read_data_r0)(struct arm_dpm *,
- uint32_t opcode, uint32_t *data);
-
- /* BREAKPOINT/WATCHPOINT SUPPORT */
-
- /**
- * Enables one breakpoint or watchpoint by writing to the
- * hardware registers. The specified breakpoint/watchpoint
- * must currently be disabled. Indices 0..15 are used for
- * breakpoints; indices 16..31 are for watchpoints.
- */
- int (*bpwp_enable)(struct arm_dpm *, unsigned index_value,
- uint32_t addr, uint32_t control);
-
- /**
- * Disables one breakpoint or watchpoint by clearing its
- * hardware control registers. Indices are the same ones
- * accepted by bpwp_enable().
- */
- int (*bpwp_disable)(struct arm_dpm *, unsigned index_value);
-
- /* The breakpoint and watchpoint arrays are private to the
- * DPM infrastructure. There are nbp indices in the dbp
- * array. There are nwp indices in the dwp array.
- */
-
- unsigned nbp;
- unsigned nwp;
- struct dpm_bp *dbp;
- struct dpm_wp *dwp;
-
- /** Address of the instruction which triggered a watchpoint. */
- uint32_t wp_pc;
-
- /** Recent value of DSCR. */
- uint32_t dscr;
-
- /* FIXME -- read/write DCSR methods and symbols */
-};
-
-int arm_dpm_setup(struct arm_dpm *dpm);
-int arm_dpm_initialize(struct arm_dpm *dpm);
-
-int arm_dpm_read_current_registers(struct arm_dpm *);
-int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode);
-
-
-int arm_dpm_write_dirty_registers(struct arm_dpm *, bool bpwp);
-
-void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar);
-
-/* DSCR bits; see ARMv7a arch spec section C10.3.1.
- * Not all v7 bits are valid in v6.
- */
-#define DSCR_CORE_HALTED (0x1 << 0)
-#define DSCR_CORE_RESTARTED (0x1 << 1)
-#define DSCR_ENTRY_MASK (0xF << 2)
-#define DSCR_STICKY_ABORT_PRECISE (0x1 << 6)
-#define DSCR_STICKY_ABORT_IMPRECISE (0x1 << 7)
-#define DSCR_STICKY_UNDEFINED (0x1 << 8)
-#define DSCR_DBG_NOPWRDWN (0x1 << 9) /* v6 only */
-#define DSCR_DBG_ACK (0x1 << 10)
-#define DSCR_INT_DIS (0x1 << 11)
-#define DSCR_CP14_USR_COMMS (0x1 << 12)
-#define DSCR_ITR_EN (0x1 << 13)
-#define DSCR_HALT_DBG_MODE (0x1 << 14)
-#define DSCR_MON_DBG_MODE (0x1 << 15)
-#define DSCR_SEC_PRIV_INVASV_DIS (0x1 << 16)
-#define DSCR_SEC_PRIV_NINVASV_DIS (0x1 << 17)
-#define DSCR_NON_SECURE (0x1 << 18)
-#define DSCR_DSCRD_IMPRECISE_ABORT (0x1 << 19)
-#define DSCR_EXT_DCC_MASK (0x3 << 20) /* DTR mode */ /* bits 22, 23 are reserved */
-#define DSCR_INSTR_COMP (0x1 << 24)
-#define DSCR_PIPE_ADVANCE (0x1 << 25)
-#define DSCR_DTRTX_FULL_LATCHED (0x1 << 26)
-#define DSCR_DTRRX_FULL_LATCHED (0x1 << 27) /* bit 28 is reserved */
-#define DSCR_DTR_TX_FULL (0x1 << 29)
-#define DSCR_DTR_RX_FULL (0x1 << 30) /* bit 31 is reserved */
-
-#define DSCR_ENTRY(dscr) (((dscr) >> 2) & 0xf)
-#define DSCR_RUN_MODE(dscr) ((dscr) & (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED))
-
-
-/* Methods of entry into debug mode */
-#define DSCR_ENTRY_HALT_REQ (0x0 << 2)
-#define DSCR_ENTRY_BREAKPOINT (0x1 << 2)
-#define DSCR_ENTRY_IMPRECISE_WATCHPT (0x2 << 2)
-#define DSCR_ENTRY_BKPT_INSTR (0x3 << 2)
-#define DSCR_ENTRY_EXT_DBG_REQ (0x4 << 2)
-#define DSCR_ENTRY_VECT_CATCH (0x5 << 2)
-#define DSCR_ENTRY_D_SIDE_ABORT (0x6 << 2) /* v6 only */
-#define DSCR_ENTRY_I_SIDE_ABORT (0x7 << 2) /* v6 only */
-#define DSCR_ENTRY_OS_UNLOCK (0x8 << 2)
-#define DSCR_ENTRY_PRECISE_WATCHPT (0xA << 2)
-
-/* DTR modes */
-#define DSCR_EXT_DCC_NON_BLOCKING (0x0 << 20)
-#define DSCR_EXT_DCC_STALL_MODE (0x1 << 20)
-#define DSCR_EXT_DCC_FAST_MODE (0x2 << 20) /* bits 22, 23 are reserved */
-
-
-
-
-
-/* DRCR (debug run control register) bits */
-#define DRCR_HALT (1 << 0)
-#define DRCR_RESTART (1 << 1)
-#define DRCR_CLEAR_EXCEPTIONS (1 << 2)
-
-void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr);
-
-#endif /* OPENOCD_TARGET_ARM_DPM_H */
diff --git a/src/target/arm_jtag.c b/src/target/arm_jtag.c
deleted file mode 100644
index 9b73d4e..0000000
--- a/src/target/arm_jtag.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm_jtag.h"
-
-#if 0
-#define _ARM_JTAG_SCAN_N_CHECK_
-#endif
-
-int arm_jtag_set_instr_inner(struct jtag_tap *tap,
- uint32_t new_instr, void *no_verify_capture, tap_state_t end_state)
-{
- struct scan_field field;
- uint8_t t[4];
-
- field.num_bits = tap->ir_length;
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_instr);
- field.in_value = NULL;
-
- if (no_verify_capture == NULL)
- jtag_add_ir_scan(tap, &field, end_state);
- else {
- /* FIX!!!! this is a kludge!!! arm926ejs.c should reimplement this arm_jtag_set_instr to
- * have special verification code.
- */
- jtag_add_ir_scan_noverify(tap, &field, end_state);
- }
-
- return ERROR_OK;
-}
-
-int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state)
-{
- int retval = ERROR_OK;
-
- uint8_t out_value[4];
- buf_set_u32(out_value, 0, jtag_info->scann_size, new_scan_chain);
- struct scan_field field = { .num_bits = jtag_info->scann_size, .out_value = out_value, };
-
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->scann_instr, NULL, end_state);
- if (retval != ERROR_OK)
- return retval;
-
- jtag_add_dr_scan(jtag_info->tap,
- 1,
- &field,
- end_state);
-
- jtag_info->cur_scan_chain = new_scan_chain;
-
- return retval;
-}
-
-static int arm_jtag_reset_callback(enum jtag_event event, void *priv)
-{
- struct arm_jtag *jtag_info = priv;
-
- if (event == JTAG_TRST_ASSERTED)
- jtag_info->cur_scan_chain = 0;
-
- return ERROR_OK;
-}
-
-int arm_jtag_setup_connection(struct arm_jtag *jtag_info)
-{
- jtag_info->scann_instr = 0x2;
- jtag_info->cur_scan_chain = 0;
- jtag_info->intest_instr = 0xc;
-
- return jtag_register_event_callback(arm_jtag_reset_callback, jtag_info);
-}
diff --git a/src/target/arm_jtag.h b/src/target/arm_jtag.h
deleted file mode 100644
index bb92abb..0000000
--- a/src/target/arm_jtag.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM_JTAG_H
-#define OPENOCD_TARGET_ARM_JTAG_H
-
-#include <jtag/jtag.h>
-
-struct arm_jtag {
- struct jtag_tap *tap;
-
- uint32_t scann_size;
- uint32_t scann_instr;
- uint32_t cur_scan_chain;
-
- uint32_t intest_instr;
-};
-
-int arm_jtag_set_instr_inner(struct jtag_tap *tap, uint32_t new_instr,
- void *no_verify_capture,
- tap_state_t end_state);
-
-static inline int arm_jtag_set_instr(struct jtag_tap *tap,
- uint32_t new_instr, void *no_verify_capture, tap_state_t end_state)
-{
- /* inline most common code path */
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
- return arm_jtag_set_instr_inner(tap, new_instr, no_verify_capture, end_state);
-
- return ERROR_OK;
-
-}
-
-int arm_jtag_scann_inner(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state);
-static inline int arm_jtag_scann(struct arm_jtag *jtag_info, uint32_t new_scan_chain, tap_state_t end_state)
-{
- /* inline most common code path */
- int retval = ERROR_OK;
- if (jtag_info->cur_scan_chain != new_scan_chain)
- return arm_jtag_scann_inner(jtag_info, new_scan_chain, end_state);
-
- return retval;
-}
-
-int arm_jtag_setup_connection(struct arm_jtag *jtag_info);
-
-/* use this as a static so we can inline it in -O3 and refer to it via a pointer */
-static inline void arm7flip32(jtag_callback_data_t arg)
-{
- uint8_t *in = (uint8_t *)arg;
- *((uint32_t *)arg) = flip_u32(le_to_h_u32(in), 32);
-}
-
-static inline void arm_le_to_h_u32(jtag_callback_data_t arg)
-{
- uint8_t *in = (uint8_t *)arg;
- *((uint32_t *)arg) = le_to_h_u32(in);
-}
-
-#endif /* OPENOCD_TARGET_ARM_JTAG_H */
diff --git a/src/target/arm_opcodes.h b/src/target/arm_opcodes.h
deleted file mode 100644
index a53fee7..0000000
--- a/src/target/arm_opcodes.h
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2005 by Dominic Rath
- * Dominic.Rath@gmx.de
- *
- * Copyright (C) 2006 by Magnus Lundin
- * lundin@mlu.mine.nu
- *
- * Copyright (C) 2008 by Spencer Oliver
- * spen@spen-soft.co.uk
- *
- * Copyright (C) 2009 by Øyvind Harboe
- * oyvind.harboe@zylin.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef OPENOCD_TARGET_ARM_OPCODES_H
-#define OPENOCD_TARGET_ARM_OPCODES_H
-
-/**
- * @file
- * Macros used to generate various ARM or Thumb opcodes.
- */
-
-/* ARM mode instructions */
-
-/* Store multiple increment after
- * Rn: base register
- * List: for each bit in list: store register
- * S: in priviledged mode: store user-mode registers
- * W = 1: update the base register. W = 0: leave the base register untouched
- */
-#define ARMV4_5_STMIA(Rn, List, S, W) \
- (0xe8800000 | ((S) << 22) | ((W) << 21) | ((Rn) << 16) | (List))
-
-/* Load multiple increment after
- * Rn: base register
- * List: for each bit in list: store register
- * S: in priviledged mode: store user-mode registers
- * W = 1: update the base register. W = 0: leave the base register untouched
- */
-#define ARMV4_5_LDMIA(Rn, List, S, W) \
- (0xe8900000 | ((S) << 22) | ((W) << 21) | ((Rn) << 16) | (List))
-
-/* MOV r8, r8 */
-#define ARMV4_5_NOP (0xe1a08008)
-
-/* Move PSR to general purpose register
- * R = 1: SPSR R = 0: CPSR
- * Rn: target register
- */
-#define ARMV4_5_MRS(Rn, R) (0xe10f0000 | ((R) << 22) | ((Rn) << 12))
-
-/* Store register
- * Rd: register to store
- * Rn: base register
- */
-#define ARMV4_5_STR(Rd, Rn) (0xe5800000 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Load register
- * Rd: register to load
- * Rn: base register
- */
-#define ARMV4_5_LDR(Rd, Rn) (0xe5900000 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Move general purpose register to PSR
- * R = 1: SPSR R = 0: CPSR
- * Field: Field mask
- * 1: control field 2: extension field 4: status field 8: flags field
- * Rm: source register
- */
-#define ARMV4_5_MSR_GP(Rm, Field, R) \
- (0xe120f000 | (Rm) | ((Field) << 16) | ((R) << 22))
-#define ARMV4_5_MSR_IM(Im, Rotate, Field, R) \
- (0xe320f000 | (Im) | ((Rotate) << 8) | ((Field) << 16) | ((R) << 22))
-
-/* Load Register Word Immediate Post-Index
- * Rd: register to load
- * Rn: base register
- */
-#define ARMV4_5_LDRW_IP(Rd, Rn) (0xe4900004 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Load Register Halfword Immediate Post-Index
- * Rd: register to load
- * Rn: base register
- */
-#define ARMV4_5_LDRH_IP(Rd, Rn) (0xe0d000b2 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Load Register Byte Immediate Post-Index
- * Rd: register to load
- * Rn: base register
- */
-#define ARMV4_5_LDRB_IP(Rd, Rn) (0xe4d00001 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Store register Word Immediate Post-Index
- * Rd: register to store
- * Rn: base register
- */
-#define ARMV4_5_STRW_IP(Rd, Rn) (0xe4800004 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Store register Halfword Immediate Post-Index
- * Rd: register to store
- * Rn: base register
- */
-#define ARMV4_5_STRH_IP(Rd, Rn) (0xe0c000b2 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Store register Byte Immediate Post-Index
- * Rd: register to store
- * Rn: base register
- */
-#define ARMV4_5_STRB_IP(Rd, Rn) (0xe4c00001 | ((Rd) << 12) | ((Rn) << 16))
-
-/* Branch (and Link)
- * Im: Branch target (left-shifted by 2 bits, added to PC)
- * L: 1: branch and link 0: branch only
- */
-#define ARMV4_5_B(Im, L) (0xea000000 | (Im) | ((L) << 24))
-
-/* Branch and exchange (ARM state)
- * Rm: register holding branch target address
- */
-#define ARMV4_5_BX(Rm) (0xe12fff10 | (Rm))
-
-/* Store data from coprocessor to consecutive memory
- * See Armv7-A arch doc section A8.6.187
- * P: 1=index mode (offset from Rn)
- * U: 1=add, 0=subtract Rn address with imm
- * D: Opcode D encoding
- * W: write back the offset start address to the Rn register
- * CP: Coprocessor number (4 bits)
- * CRd: Coprocessor source register (4 bits)
- * Rn: Base register for memory address (4 bits)
- * imm: Immediate value (0 - 1020, must be divisible by 4)
- */
-#define ARMV4_5_STC(P, U, D, W, CP, CRd, Rn, imm) \
- (0xec000000 | ((P) << 24) | ((U) << 23) | ((D) << 22) | \
- ((W) << 21) | ((Rn) << 16) | ((CRd) << 12) | ((CP) << 8) | ((imm)>>2))
-
-/* Loads data from consecutive memory to coprocessor
- * See Armv7-A arch doc section A8.6.51
- * P: 1=index mode (offset from Rn)
- * U: 1=add, 0=subtract Rn address with imm
- * D: Opcode D encoding
- * W: write back the offset start address to the Rn register
- * CP: Coprocessor number (4 bits)
- * CRd: Coprocessor dest register (4 bits)
- * Rn: Base register for memory address (4 bits)
- * imm: Immediate value (0 - 1020, must be divisible by 4)
- */
-#define ARMV4_5_LDC(P, U, D, W, CP, CRd, Rn, imm) \
- (0xec100000 | ((P) << 24) | ((U) << 23) | ((D) << 22) | \
- ((W) << 21) | ((Rn) << 16) | ((CRd) << 12) | ((CP) << 8) | ((imm) >> 2))
-
-/* Move to ARM register from coprocessor
- * CP: Coprocessor number
- * op1: Coprocessor opcode
- * Rd: destination register
- * CRn: first coprocessor operand
- * CRm: second coprocessor operand
- * op2: Second coprocessor opcode
- */
-#define ARMV4_5_MRC(CP, op1, Rd, CRn, CRm, op2) \
- (0xee100010 | (CRm) | ((op2) << 5) | ((CP) << 8) \
- | ((Rd) << 12) | ((CRn) << 16) | ((op1) << 21))
-
-/* Move to coprocessor from ARM register
- * CP: Coprocessor number
- * op1: Coprocessor opcode
- * Rd: destination register
- * CRn: first coprocessor operand
- * CRm: second coprocessor operand
- * op2: Second coprocessor opcode
- */
-#define ARMV4_5_MCR(CP, op1, Rd, CRn, CRm, op2) \
- (0xee000010 | (CRm) | ((op2) << 5) | ((CP) << 8) \
- | ((Rd) << 12) | ((CRn) << 16) | ((op1) << 21))
-
-/* Breakpoint instruction (ARMv5)
- * Im: 16-bit immediate
- */
-#define ARMV5_BKPT(Im) (0xe1200070 | ((Im & 0xfff0) << 8) | (Im & 0xf))
-
-
-/* Thumb mode instructions
- *
- * NOTE: these 16-bit opcodes fill both halves of a word with the same
- * value. The reason for this is that when we need to execute Thumb
- * opcodes on ARM7/ARM9 cores (to switch to ARM state on debug entry),
- * we must shift 32 bits to the bus using scan chain 1 ... if we write
- * both halves, we don't need to track which half matters. On ARMv6 and
- * ARMv7 we don't execute Thumb instructions in debug mode; the ITR
- * register does not accept Thumb (or Thumb2) opcodes.
- */
-
-/* Store register (Thumb mode)
- * Rd: source register
- * Rn: base register
- */
-#define ARMV4_5_T_STR(Rd, Rn) \
- ((0x6000 | (Rd) | ((Rn) << 3)) | \
- ((0x6000 | (Rd) | ((Rn) << 3)) << 16))
-
-/* Load register (Thumb state)
- * Rd: destination register
- * Rn: base register
- */
-#define ARMV4_5_T_LDR(Rd, Rn) \
- ((0x6800 | ((Rn) << 3) | (Rd)) \
- | ((0x6800 | ((Rn) << 3) | (Rd)) << 16))
-
-/* Load multiple (Thumb state)
- * Rn: base register
- * List: for each bit in list: store register
- */
-#define ARMV4_5_T_LDMIA(Rn, List) \
- ((0xc800 | ((Rn) << 8) | (List)) \
- | ((0xc800 | ((Rn) << 8) | (List)) << 16))
-
-/* Load register with PC relative addressing
- * Rd: register to load
- */
-#define ARMV4_5_T_LDR_PCREL(Rd) \
- ((0x4800 | ((Rd) << 8)) \
- | ((0x4800 | ((Rd) << 8)) << 16))
-
-/* Move hi register (Thumb mode)
- * Rd: destination register
- * Rm: source register
- */
-#define ARMV4_5_T_MOV(Rd, Rm) \
- ((0x4600 | ((Rd) & 0x7) | (((Rd) & 0x8) << 4) | \
- (((Rm) & 0x7) << 3) | (((Rm) & 0x8) << 3)) \
- | ((0x4600 | ((Rd) & 0x7) | (((Rd) & 0x8) << 4) | \
- (((Rm) & 0x7) << 3) | (((Rm) & 0x8) << 3)) << 16))
-
-/* No operation (Thumb mode)
- * NOTE: this is "MOV r8, r8" ... Thumb2 adds two
- * architected NOPs, 16-bit and 32-bit.
- */
-#define ARMV4_5_T_NOP (0x46c0 | (0x46c0 << 16))
-
-/* Move immediate to register (Thumb state)
- * Rd: destination register
- * Im: 8-bit immediate value
- */
-#define ARMV4_5_T_MOV_IM(Rd, Im) \
- ((0x2000 | ((Rd) << 8) | (Im)) \
- | ((0x2000 | ((Rd) << 8) | (Im)) << 16))
-
-/* Branch and Exchange
- * Rm: register containing branch target
- */
-#define ARMV4_5_T_BX(Rm) \
- ((0x4700 | ((Rm) << 3)) \
- | ((0x4700 | ((Rm) << 3)) << 16))
-
-/* Branch (Thumb state)
- * Imm: Branch target
- */
-#define ARMV4_5_T_B(Imm) \
- ((0xe000 | (Imm)) \
- | ((0xe000 | (Imm)) << 16))
-
-/* Breakpoint instruction (ARMv5) (Thumb state)
- * Im: 8-bit immediate
- */
-#define ARMV5_T_BKPT(Im) \
- ((0xbe00 | (Im)) \
- | ((0xbe00 | (Im)) << 16))
-
-/* Move to Register from Special Register
- * 32 bit Thumb2 instruction
- * Rd: destination register
- * SYSm: source special register
- */
-#define ARM_T2_MRS(Rd, SYSm) \
- ((0xF3EF) | ((0x8000 | (Rd << 8) | SYSm) << 16))
-
-/* Move from Register from Special Register
- * 32 bit Thumb2 instruction
- * Rd: source register
- * SYSm: destination special register
- */
-#define ARM_T2_MSR(SYSm, Rn) \
- ((0xF380 | (Rn << 8)) | ((0x8800 | SYSm) << 16))
-
-/* Change Processor State.
- * 16 bit Thumb2 instruction
- * Rd: source register
- * IF: A_FLAG and/or I_FLAG and/or F_FLAG
- */
-#define A_FLAG 4
-#define I_FLAG 2
-#define F_FLAG 1
-#define ARM_T2_CPSID(IF) \
- ((0xB660 | (1 << 8) | ((IF)&0x3)) \
- | ((0xB660 | (1 << 8) | ((IF)&0x3)) << 16))
-#define ARM_T2_CPSIE(IF) \
- ((0xB660 | (0 << 8) | ((IF)&0x3)) \
- | ((0xB660 | (0 << 8) | ((IF)&0x3)) << 16))
-
-#endif /* OPENOCD_TARGET_ARM_OPCODES_H */
diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c
deleted file mode 100644
index 2fd6580..0000000
--- a/src/target/arm_semihosting.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Marvell Technology Group Ltd. *
- * Written by Nicolas Pitre <nico@marvell.com> *
- * *
- * Copyright (C) 2010 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/**
- * @file
- * Hold ARM semihosting support.
- *
- * Semihosting enables code running on an ARM target to use the I/O
- * facilities on the host computer. The target application must be linked
- * against a library that forwards operation requests by using the SVC
- * instruction trapped at the Supervisor Call vector by the debugger.
- * Details can be found in chapter 8 of DUI0203I_rvct_developer_guide.pdf
- * from ARM Ltd.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "armv4_5.h"
-#include "arm7_9_common.h"
-#include "armv7m.h"
-#include "cortex_m.h"
-#include "register.h"
-#include "arm_semihosting.h"
-#include <helper/binarybuffer.h>
-#include <helper/log.h>
-#include <sys/stat.h>
-
-static const int open_modeflags[12] = {
- O_RDONLY,
- O_RDONLY | O_BINARY,
- O_RDWR,
- O_RDWR | O_BINARY,
- O_WRONLY | O_CREAT | O_TRUNC,
- O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
- O_RDWR | O_CREAT | O_TRUNC,
- O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
- O_WRONLY | O_CREAT | O_APPEND,
- O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
- O_RDWR | O_CREAT | O_APPEND,
- O_RDWR | O_CREAT | O_APPEND | O_BINARY
-};
-
-static int do_semihosting(struct target *target)
-{
- struct arm *arm = target_to_arm(target);
- uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
- uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32);
- uint8_t params[16];
- int retval, result;
-
- /*
- * TODO: lots of security issues are not considered yet, such as:
- * - no validation on target provided file descriptors
- * - no safety checks on opened/deleted/renamed file paths
- * Beware the target app you use this support with.
- *
- * TODO: explore mapping requests to GDB's "File-I/O Remote
- * Protocol Extension" ... when GDB is active.
- */
- switch (r0) {
- case 0x01: /* SYS_OPEN */
- retval = target_read_memory(target, r1, 4, 3, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a = target_buffer_get_u32(target, params+0);
- uint32_t m = target_buffer_get_u32(target, params+4);
- uint32_t l = target_buffer_get_u32(target, params+8);
- if (l <= 255 && m <= 11) {
- uint8_t fn[256];
- retval = target_read_memory(target, a, 1, l, fn);
- if (retval != ERROR_OK)
- return retval;
- fn[l] = 0;
- if (strcmp((char *)fn, ":tt") == 0) {
- if (m < 4)
- result = dup(STDIN_FILENO);
- else
- result = dup(STDOUT_FILENO);
- } else {
- /* cygwin requires the permission setting
- * otherwise it will fail to reopen a previously
- * written file */
- result = open((char *)fn, open_modeflags[m], 0644);
- }
- arm->semihosting_errno = errno;
- } else {
- result = -1;
- arm->semihosting_errno = EINVAL;
- }
- }
- break;
-
- case 0x02: /* SYS_CLOSE */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- result = close(fd);
- arm->semihosting_errno = errno;
- }
- break;
-
- case 0x03: /* SYS_WRITEC */
- {
- unsigned char c;
- retval = target_read_memory(target, r1, 1, 1, &c);
- if (retval != ERROR_OK)
- return retval;
- putchar(c);
- result = 0;
- }
- break;
-
- case 0x04: /* SYS_WRITE0 */
- do {
- unsigned char c;
- retval = target_read_memory(target, r1++, 1, 1, &c);
- if (retval != ERROR_OK)
- return retval;
- if (!c)
- break;
- putchar(c);
- } while (1);
- result = 0;
- break;
-
- case 0x05: /* SYS_WRITE */
- retval = target_read_memory(target, r1, 4, 3, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- uint32_t a = target_buffer_get_u32(target, params+4);
- size_t l = target_buffer_get_u32(target, params+8);
- uint8_t *buf = malloc(l);
- if (!buf) {
- result = -1;
- arm->semihosting_errno = ENOMEM;
- } else {
- retval = target_read_buffer(target, a, l, buf);
- if (retval != ERROR_OK) {
- free(buf);
- return retval;
- }
- result = write(fd, buf, l);
- arm->semihosting_errno = errno;
- if (result >= 0)
- result = l - result;
- free(buf);
- }
- }
- break;
-
- case 0x06: /* SYS_READ */
- retval = target_read_memory(target, r1, 4, 3, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- uint32_t a = target_buffer_get_u32(target, params+4);
- ssize_t l = target_buffer_get_u32(target, params+8);
- uint8_t *buf = malloc(l);
- if (!buf) {
- result = -1;
- arm->semihosting_errno = ENOMEM;
- } else {
- result = read(fd, buf, l);
- arm->semihosting_errno = errno;
- if (result >= 0) {
- retval = target_write_buffer(target, a, result, buf);
- if (retval != ERROR_OK) {
- free(buf);
- return retval;
- }
- result = l - result;
- }
- free(buf);
- }
- }
- break;
-
- case 0x07: /* SYS_READC */
- result = getchar();
- break;
-
- case 0x08: /* SYS_ISERROR */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- result = (target_buffer_get_u32(target, params+0) != 0);
- break;
-
- case 0x09: /* SYS_ISTTY */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- result = isatty(target_buffer_get_u32(target, params+0));
- break;
-
- case 0x0a: /* SYS_SEEK */
- retval = target_read_memory(target, r1, 4, 2, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- off_t pos = target_buffer_get_u32(target, params+4);
- result = lseek(fd, pos, SEEK_SET);
- arm->semihosting_errno = errno;
- if (result == pos)
- result = 0;
- }
- break;
-
- case 0x0c: /* SYS_FLEN */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- int fd = target_buffer_get_u32(target, params+0);
- struct stat buf;
- result = fstat(fd, &buf);
- if (result == -1) {
- arm->semihosting_errno = errno;
- result = -1;
- break;
- }
- result = buf.st_size;
- }
- break;
-
- case 0x0e: /* SYS_REMOVE */
- retval = target_read_memory(target, r1, 4, 2, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a = target_buffer_get_u32(target, params+0);
- uint32_t l = target_buffer_get_u32(target, params+4);
- if (l <= 255) {
- uint8_t fn[256];
- retval = target_read_memory(target, a, 1, l, fn);
- if (retval != ERROR_OK)
- return retval;
- fn[l] = 0;
- result = remove((char *)fn);
- arm->semihosting_errno = errno;
- } else {
- result = -1;
- arm->semihosting_errno = EINVAL;
- }
- }
- break;
-
- case 0x0f: /* SYS_RENAME */
- retval = target_read_memory(target, r1, 4, 4, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a1 = target_buffer_get_u32(target, params+0);
- uint32_t l1 = target_buffer_get_u32(target, params+4);
- uint32_t a2 = target_buffer_get_u32(target, params+8);
- uint32_t l2 = target_buffer_get_u32(target, params+12);
- if (l1 <= 255 && l2 <= 255) {
- uint8_t fn1[256], fn2[256];
- retval = target_read_memory(target, a1, 1, l1, fn1);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_memory(target, a2, 1, l2, fn2);
- if (retval != ERROR_OK)
- return retval;
- fn1[l1] = 0;
- fn2[l2] = 0;
- result = rename((char *)fn1, (char *)fn2);
- arm->semihosting_errno = errno;
- } else {
- result = -1;
- arm->semihosting_errno = EINVAL;
- }
- }
- break;
-
- case 0x11: /* SYS_TIME */
- result = time(NULL);
- break;
-
- case 0x13: /* SYS_ERRNO */
- result = arm->semihosting_errno;
- break;
-
- case 0x15: /* SYS_GET_CMDLINE */
- retval = target_read_memory(target, r1, 4, 2, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a = target_buffer_get_u32(target, params+0);
- uint32_t l = target_buffer_get_u32(target, params+4);
- char *arg = "foobar";
- uint32_t s = strlen(arg) + 1;
- if (l < s)
- result = -1;
- else {
- retval = target_write_buffer(target, a, s, (uint8_t *)arg);
- if (retval != ERROR_OK)
- return retval;
- result = 0;
- }
- }
- break;
-
- case 0x16: /* SYS_HEAPINFO */
- retval = target_read_memory(target, r1, 4, 1, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t a = target_buffer_get_u32(target, params+0);
- /* tell the remote we have no idea */
- memset(params, 0, 4*4);
- retval = target_write_memory(target, a, 4, 4, params);
- if (retval != ERROR_OK)
- return retval;
- result = 0;
- }
- break;
-
- case 0x18: /* angel_SWIreason_ReportException */
- switch (r1) {
- case 0x20026: /* ADP_Stopped_ApplicationExit */
- fprintf(stderr, "semihosting: *** application exited ***\n");
- break;
- case 0x20000: /* ADP_Stopped_BranchThroughZero */
- case 0x20001: /* ADP_Stopped_UndefinedInstr */
- case 0x20002: /* ADP_Stopped_SoftwareInterrupt */
- case 0x20003: /* ADP_Stopped_PrefetchAbort */
- case 0x20004: /* ADP_Stopped_DataAbort */
- case 0x20005: /* ADP_Stopped_AddressException */
- case 0x20006: /* ADP_Stopped_IRQ */
- case 0x20007: /* ADP_Stopped_FIQ */
- case 0x20020: /* ADP_Stopped_BreakPoint */
- case 0x20021: /* ADP_Stopped_WatchPoint */
- case 0x20022: /* ADP_Stopped_StepComplete */
- case 0x20023: /* ADP_Stopped_RunTimeErrorUnknown */
- case 0x20024: /* ADP_Stopped_InternalError */
- case 0x20025: /* ADP_Stopped_UserInterruption */
- case 0x20027: /* ADP_Stopped_StackOverflow */
- case 0x20028: /* ADP_Stopped_DivisionByZero */
- case 0x20029: /* ADP_Stopped_OSSpecific */
- default:
- fprintf(stderr, "semihosting: exception %#x\n",
- (unsigned) r1);
- }
- return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- case 0x12: /* SYS_SYSTEM */
- /* Provide SYS_SYSTEM functionality. Uses the
- * libc system command, there may be a reason *NOT*
- * to use this, but as I can't think of one, I
- * implemented it this way.
- */
- retval = target_read_memory(target, r1, 4, 2, params);
- if (retval != ERROR_OK)
- return retval;
- else {
- uint32_t len = target_buffer_get_u32(target, params+4);
- uint32_t c_ptr = target_buffer_get_u32(target, params);
- uint8_t cmd[256];
- if (len > 255) {
- result = -1;
- arm->semihosting_errno = EINVAL;
- } else {
- memset(cmd, 0x0, 256);
- retval = target_read_memory(target, c_ptr, 1, len, cmd);
- if (retval != ERROR_OK)
- return retval;
- else
- result = system((const char *)cmd);
- }
- }
- break;
- case 0x0d: /* SYS_TMPNAM */
- case 0x10: /* SYS_CLOCK */
- case 0x17: /* angel_SWIreason_EnterSVC */
- case 0x30: /* SYS_ELAPSED */
- case 0x31: /* SYS_TICKFREQ */
- default:
- fprintf(stderr, "semihosting: unsupported call %#x\n",
- (unsigned) r0);
- result = -1;
- arm->semihosting_errno = ENOTSUP;
- }
-
- /* resume execution to the original mode */
-
- /* REVISIT this looks wrong ... ARM11 and Cortex-A8
- * should work this way at least sometimes.
- */
- if (is_arm7_9(target_to_arm7_9(target))) {
- uint32_t spsr;
-
- /* return value in R0 */
- buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result);
- arm->core_cache->reg_list[0].dirty = 1;
-
- /* LR --> PC */
- buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32,
- buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32));
- arm->core_cache->reg_list[15].dirty = 1;
-
- /* saved PSR --> current PSR */
- spsr = buf_get_u32(arm->spsr->value, 0, 32);
-
- /* REVISIT should this be arm_set_cpsr(arm, spsr)
- * instead of a partially unrolled version?
- */
-
- buf_set_u32(arm->cpsr->value, 0, 32, spsr);
- arm->cpsr->dirty = 1;
- arm->core_mode = spsr & 0x1f;
- if (spsr & 0x20)
- arm->core_state = ARM_STATE_THUMB;
-
- } else {
- /* resume execution, this will be pc+2 to skip over the
- * bkpt instruction */
-
- /* return result in R0 */
- buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result);
- arm->core_cache->reg_list[0].dirty = 1;
- }
-
- return target_resume(target, 1, 0, 0, 0);
-}
-
-/**
- * Checks for and processes an ARM semihosting request. This is meant
- * to be called when the target is stopped due to a debug mode entry.
- * If the value 0 is returned then there was nothing to process. A non-zero
- * return value signifies that a request was processed and the target resumed,
- * or an error was encountered, in which case the caller must return
- * immediately.
- *
- * @param target Pointer to the ARM target to process. This target must
- * not represent an ARMv6-M or ARMv7-M processor.
- * @param retval Pointer to a location where the return code will be stored
- * @return non-zero value if a request was processed or an error encountered
- */
-int arm_semihosting(struct target *target, int *retval)
-{
- struct arm *arm = target_to_arm(target);
- uint32_t pc, lr, spsr;
- struct reg *r;
-
- if (!arm->is_semihosting)
- return 0;
-
- if (is_arm7_9(target_to_arm7_9(target))) {
- if (arm->core_mode != ARM_MODE_SVC)
- return 0;
-
- /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */
- r = arm->pc;
- pc = buf_get_u32(r->value, 0, 32);
- if (pc != 0x00000008 && pc != 0xffff0008)
- return 0;
-
- r = arm_reg_current(arm, 14);
- lr = buf_get_u32(r->value, 0, 32);
-
- /* Core-specific code should make sure SPSR is retrieved
- * when the above checks pass...
- */
- if (!arm->spsr->valid) {
- LOG_ERROR("SPSR not valid!");
- *retval = ERROR_FAIL;
- return 1;
- }
-
- spsr = buf_get_u32(arm->spsr->value, 0, 32);
-
- /* check instruction that triggered this trap */
- if (spsr & (1 << 5)) {
- /* was in Thumb (or ThumbEE) mode */
- uint8_t insn_buf[2];
- uint16_t insn;
-
- *retval = target_read_memory(target, lr-2, 2, 1, insn_buf);
- if (*retval != ERROR_OK)
- return 1;
- insn = target_buffer_get_u16(target, insn_buf);
-
- /* SVC 0xab */
- if (insn != 0xDFAB)
- return 0;
- } else if (spsr & (1 << 24)) {
- /* was in Jazelle mode */
- return 0;
- } else {
- /* was in ARM mode */
- uint8_t insn_buf[4];
- uint32_t insn;
-
- *retval = target_read_memory(target, lr-4, 4, 1, insn_buf);
- if (*retval != ERROR_OK)
- return 1;
- insn = target_buffer_get_u32(target, insn_buf);
-
- /* SVC 0x123456 */
- if (insn != 0xEF123456)
- return 0;
- }
- } else if (is_armv7m(target_to_armv7m(target))) {
- uint16_t insn;
-
- if (target->debug_reason != DBG_REASON_BREAKPOINT)
- return 0;
-
- r = arm->pc;
- pc = buf_get_u32(r->value, 0, 32);
-
- pc &= ~1;
- *retval = target_read_u16(target, pc, &insn);
- if (*retval != ERROR_OK)
- return 1;
-
- /* bkpt 0xAB */
- if (insn != 0xBEAB)
- return 0;
- } else {
- LOG_ERROR("Unsupported semi-hosting Target");
- return 0;
- }
-
- *retval = do_semihosting(target);
- return 1;
-}
diff --git a/src/target/arm_semihosting.h b/src/target/arm_semihosting.h
deleted file mode 100644
index 7b5c0b2..0000000
--- a/src/target/arm_semihosting.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Marvell Technology Group Ltd. *
- * Written by Nicolas Pitre <nico@marvell.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM_SEMIHOSTING_H
-#define OPENOCD_TARGET_ARM_SEMIHOSTING_H
-
-int arm_semihosting(struct target *target, int *retval);
-
-#endif /* OPENOCD_TARGET_ARM_SEMIHOSTING_H */
diff --git a/src/target/arm_simulator.c b/src/target/arm_simulator.c
deleted file mode 100644
index 245e108..0000000
--- a/src/target/arm_simulator.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Hongtao Zheng *
- * hontor@126.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "armv4_5.h"
-#include "arm_disassembler.h"
-#include "arm_simulator.h"
-#include <helper/binarybuffer.h>
-#include "register.h"
-#include <helper/log.h>
-
-static uint32_t arm_shift(uint8_t shift, uint32_t Rm,
- uint32_t shift_amount, uint8_t *carry)
-{
- uint32_t return_value = 0;
- shift_amount &= 0xff;
-
- if (shift == 0x0) { /* LSL */
- if ((shift_amount > 0) && (shift_amount <= 32)) {
- return_value = Rm << shift_amount;
- *carry = Rm >> (32 - shift_amount);
- } else if (shift_amount > 32) {
- return_value = 0x0;
- *carry = 0x0;
- } else /* (shift_amount == 0) */
- return_value = Rm;
- } else if (shift == 0x1) { /* LSR */
- if ((shift_amount > 0) && (shift_amount <= 32)) {
- return_value = Rm >> shift_amount;
- *carry = (Rm >> (shift_amount - 1)) & 1;
- } else if (shift_amount > 32) {
- return_value = 0x0;
- *carry = 0x0;
- } else /* (shift_amount == 0) */
- return_value = Rm;
- } else if (shift == 0x2) { /* ASR */
- if ((shift_amount > 0) && (shift_amount <= 32)) {
- /* C right shifts of unsigned values are guaranteed to
- * be logical (shift in zeroes); simulate an arithmetic
- * shift (shift in signed-bit) by adding the sign bit
- * manually
- */
- return_value = Rm >> shift_amount;
- if (Rm & 0x80000000)
- return_value |= 0xffffffff << (32 - shift_amount);
- } else if (shift_amount > 32) {
- if (Rm & 0x80000000) {
- return_value = 0xffffffff;
- *carry = 0x1;
- } else {
- return_value = 0x0;
- *carry = 0x0;
- }
- } else /* (shift_amount == 0) */
- return_value = Rm;
- } else if (shift == 0x3) { /* ROR */
- if (shift_amount == 0)
- return_value = Rm;
- else {
- shift_amount = shift_amount % 32;
- return_value = (Rm >> shift_amount) | (Rm << (32 - shift_amount));
- *carry = (return_value >> 31) & 0x1;
- }
- } else if (shift == 0x4) { /* RRX */
- return_value = Rm >> 1;
- if (*carry)
- Rm |= 0x80000000;
- *carry = Rm & 0x1;
- }
-
- return return_value;
-}
-
-
-static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
- int variant, union arm_shifter_operand shifter_operand,
- uint8_t *shifter_carry_out)
-{
- uint32_t return_value;
- int instruction_size;
-
- if (sim->get_state(sim) == ARM_STATE_ARM)
- instruction_size = 4;
- else
- instruction_size = 2;
-
- *shifter_carry_out = sim->get_cpsr(sim, 29, 1);
-
- if (variant == 0) /* 32-bit immediate */
- return_value = shifter_operand.immediate.immediate;
- else if (variant == 1) {/* immediate shift */
- uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.immediate_shift.Rm);
-
- /* adjust RM in case the PC is being read */
- if (shifter_operand.immediate_shift.Rm == 15)
- Rm += 2 * instruction_size;
-
- return_value = arm_shift(shifter_operand.immediate_shift.shift,
- Rm, shifter_operand.immediate_shift.shift_imm,
- shifter_carry_out);
- } else if (variant == 2) { /* register shift */
- uint32_t Rm = sim->get_reg_mode(sim, shifter_operand.register_shift.Rm);
- uint32_t Rs = sim->get_reg_mode(sim, shifter_operand.register_shift.Rs);
-
- /* adjust RM in case the PC is being read */
- if (shifter_operand.register_shift.Rm == 15)
- Rm += 2 * instruction_size;
-
- return_value = arm_shift(shifter_operand.immediate_shift.shift,
- Rm, Rs, shifter_carry_out);
- } else {
- LOG_ERROR("BUG: shifter_operand.variant not 0, 1 or 2");
- return_value = 0xffffffff;
- }
-
- return return_value;
-}
-
-static int pass_condition(uint32_t cpsr, uint32_t opcode)
-{
- switch ((opcode & 0xf0000000) >> 28) {
- case 0x0: /* EQ */
- if (cpsr & 0x40000000)
- return 1;
- else
- return 0;
- case 0x1: /* NE */
- if (!(cpsr & 0x40000000))
- return 1;
- else
- return 0;
- case 0x2: /* CS */
- if (cpsr & 0x20000000)
- return 1;
- else
- return 0;
- case 0x3: /* CC */
- if (!(cpsr & 0x20000000))
- return 1;
- else
- return 0;
- case 0x4: /* MI */
- if (cpsr & 0x80000000)
- return 1;
- else
- return 0;
- case 0x5: /* PL */
- if (!(cpsr & 0x80000000))
- return 1;
- else
- return 0;
- case 0x6: /* VS */
- if (cpsr & 0x10000000)
- return 1;
- else
- return 0;
- case 0x7: /* VC */
- if (!(cpsr & 0x10000000))
- return 1;
- else
- return 0;
- case 0x8: /* HI */
- if ((cpsr & 0x20000000) && !(cpsr & 0x40000000))
- return 1;
- else
- return 0;
- case 0x9: /* LS */
- if (!(cpsr & 0x20000000) || (cpsr & 0x40000000))
- return 1;
- else
- return 0;
- case 0xa: /* GE */
- if (((cpsr & 0x80000000) && (cpsr & 0x10000000))
- || (!(cpsr & 0x80000000) && !(cpsr & 0x10000000)))
- return 1;
- else
- return 0;
- case 0xb: /* LT */
- if (((cpsr & 0x80000000) && !(cpsr & 0x10000000))
- || (!(cpsr & 0x80000000) && (cpsr & 0x10000000)))
- return 1;
- else
- return 0;
- case 0xc: /* GT */
- if (!(cpsr & 0x40000000) &&
- (((cpsr & 0x80000000) && (cpsr & 0x10000000))
- || (!(cpsr & 0x80000000) && !(cpsr & 0x10000000))))
- return 1;
- else
- return 0;
- case 0xd: /* LE */
- if ((cpsr & 0x40000000) ||
- ((cpsr & 0x80000000) && !(cpsr & 0x10000000))
- || (!(cpsr & 0x80000000) && (cpsr & 0x10000000)))
- return 1;
- else
- return 0;
- case 0xe:
- case 0xf:
- return 1;
-
- }
-
- LOG_ERROR("BUG: should never get here");
- return 0;
-}
-
-static int thumb_pass_branch_condition(uint32_t cpsr, uint16_t opcode)
-{
- return pass_condition(cpsr, (opcode & 0x0f00) << 20);
-}
-
-/* simulate a single step (if possible)
- * if the dry_run_pc argument is provided, no state is changed,
- * but the new pc is stored in the variable pointed at by the argument
- */
-static int arm_simulate_step_core(struct target *target,
- uint32_t *dry_run_pc, struct arm_sim_interface *sim)
-{
- uint32_t current_pc = sim->get_reg(sim, 15);
- struct arm_instruction instruction;
- int instruction_size;
- int retval = ERROR_OK;
-
- if (sim->get_state(sim) == ARM_STATE_ARM) {
- uint32_t opcode;
-
- /* get current instruction, and identify it */
- retval = target_read_u32(target, current_pc, &opcode);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_evaluate_opcode(opcode, current_pc, &instruction);
- if (retval != ERROR_OK)
- return retval;
- instruction_size = 4;
-
- /* check condition code (for all instructions) */
- if (!pass_condition(sim->get_cpsr(sim, 0, 32), opcode)) {
- if (dry_run_pc)
- *dry_run_pc = current_pc + instruction_size;
- else
- sim->set_reg(sim, 15, current_pc + instruction_size);
-
- return ERROR_OK;
- }
- } else {
- uint16_t opcode;
-
- retval = target_read_u16(target, current_pc, &opcode);
- if (retval != ERROR_OK)
- return retval;
- retval = thumb_evaluate_opcode(opcode, current_pc, &instruction);
- if (retval != ERROR_OK)
- return retval;
- instruction_size = 2;
-
- /* check condition code (only for branch (1) instructions) */
- if ((opcode & 0xf000) == 0xd000
- && !thumb_pass_branch_condition(
- sim->get_cpsr(sim, 0, 32), opcode)) {
- if (dry_run_pc)
- *dry_run_pc = current_pc + instruction_size;
- else
- sim->set_reg(sim, 15, current_pc + instruction_size);
-
- return ERROR_OK;
- }
-
- /* Deal with 32-bit BL/BLX */
- if ((opcode & 0xf800) == 0xf000) {
- uint32_t high = instruction.info.b_bl_bx_blx.target_address;
- retval = target_read_u16(target, current_pc+2, &opcode);
- if (retval != ERROR_OK)
- return retval;
- retval = thumb_evaluate_opcode(opcode, current_pc, &instruction);
- if (retval != ERROR_OK)
- return retval;
- instruction.info.b_bl_bx_blx.target_address += high;
- }
- }
-
- /* examine instruction type */
-
- /* branch instructions */
- if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX)) {
- uint32_t target_address;
-
- if (instruction.info.b_bl_bx_blx.reg_operand == -1)
- target_address = instruction.info.b_bl_bx_blx.target_address;
- else {
- target_address = sim->get_reg_mode(sim,
- instruction.info.b_bl_bx_blx.reg_operand);
- if (instruction.info.b_bl_bx_blx.reg_operand == 15)
- target_address += 2 * instruction_size;
- }
-
- if (dry_run_pc) {
- *dry_run_pc = target_address & ~1;
- return ERROR_OK;
- } else {
- if (instruction.type == ARM_B)
- sim->set_reg(sim, 15, target_address);
- else if (instruction.type == ARM_BL) {
- uint32_t old_pc = sim->get_reg(sim, 15);
- int T = (sim->get_state(sim) == ARM_STATE_THUMB);
- sim->set_reg_mode(sim, 14, old_pc + 4 + T);
- sim->set_reg(sim, 15, target_address);
- } else if (instruction.type == ARM_BX) {
- if (target_address & 0x1)
- sim->set_state(sim, ARM_STATE_THUMB);
- else
- sim->set_state(sim, ARM_STATE_ARM);
- sim->set_reg(sim, 15, target_address & 0xfffffffe);
- } else if (instruction.type == ARM_BLX) {
- uint32_t old_pc = sim->get_reg(sim, 15);
- int T = (sim->get_state(sim) == ARM_STATE_THUMB);
- sim->set_reg_mode(sim, 14, old_pc + 4 + T);
-
- if (target_address & 0x1)
- sim->set_state(sim, ARM_STATE_THUMB);
- else
- sim->set_state(sim, ARM_STATE_ARM);
- sim->set_reg(sim, 15, target_address & 0xfffffffe);
- }
-
- return ERROR_OK;
- }
- }
- /* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
- else if (((instruction.type >= ARM_AND) && (instruction.type <= ARM_RSC))
- || ((instruction.type >= ARM_ORR) && (instruction.type <= ARM_MVN))) {
- uint32_t Rd, Rn, shifter_operand;
- uint8_t C = sim->get_cpsr(sim, 29, 1);
- uint8_t carry_out;
-
- Rd = 0x0;
- /* ARM_MOV and ARM_MVN does not use Rn */
- if ((instruction.type != ARM_MOV) && (instruction.type != ARM_MVN))
- Rn = sim->get_reg_mode(sim, instruction.info.data_proc.Rn);
- else
- Rn = 0;
-
- shifter_operand = arm_shifter_operand(sim,
- instruction.info.data_proc.variant,
- instruction.info.data_proc.shifter_operand,
- &carry_out);
-
- /* adjust Rn in case the PC is being read */
- if (instruction.info.data_proc.Rn == 15)
- Rn += 2 * instruction_size;
-
- if (instruction.type == ARM_AND)
- Rd = Rn & shifter_operand;
- else if (instruction.type == ARM_EOR)
- Rd = Rn ^ shifter_operand;
- else if (instruction.type == ARM_SUB)
- Rd = Rn - shifter_operand;
- else if (instruction.type == ARM_RSB)
- Rd = shifter_operand - Rn;
- else if (instruction.type == ARM_ADD)
- Rd = Rn + shifter_operand;
- else if (instruction.type == ARM_ADC)
- Rd = Rn + shifter_operand + (C & 1);
- else if (instruction.type == ARM_SBC)
- Rd = Rn - shifter_operand - (C & 1) ? 0 : 1;
- else if (instruction.type == ARM_RSC)
- Rd = shifter_operand - Rn - (C & 1) ? 0 : 1;
- else if (instruction.type == ARM_ORR)
- Rd = Rn | shifter_operand;
- else if (instruction.type == ARM_BIC)
- Rd = Rn & ~(shifter_operand);
- else if (instruction.type == ARM_MOV)
- Rd = shifter_operand;
- else if (instruction.type == ARM_MVN)
- Rd = ~shifter_operand;
- else
- LOG_WARNING("unhandled instruction type");
-
- if (dry_run_pc) {
- if (instruction.info.data_proc.Rd == 15)
- *dry_run_pc = Rd & ~1;
- else
- *dry_run_pc = current_pc + instruction_size;
-
- return ERROR_OK;
- } else {
- if (instruction.info.data_proc.Rd == 15) {
- sim->set_reg_mode(sim, 15, Rd & ~1);
- if (Rd & 1)
- sim->set_state(sim, ARM_STATE_THUMB);
- else
- sim->set_state(sim, ARM_STATE_ARM);
- return ERROR_OK;
- }
- sim->set_reg_mode(sim, instruction.info.data_proc.Rd, Rd);
- LOG_WARNING("no updating of flags yet");
- }
- }
- /* compare instructions (CMP, CMN, TST, TEQ) */
- else if ((instruction.type >= ARM_TST) && (instruction.type <= ARM_CMN)) {
- if (dry_run_pc) {
- *dry_run_pc = current_pc + instruction_size;
- return ERROR_OK;
- } else
- LOG_WARNING("no updating of flags yet");
- }
- /* load register instructions */
- else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH)) {
- uint32_t load_address = 0, modified_address = 0, load_value = 0;
- uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store.Rn);
-
- /* adjust Rn in case the PC is being read */
- if (instruction.info.load_store.Rn == 15)
- Rn += 2 * instruction_size;
-
- if (instruction.info.load_store.offset_mode == 0) {
- if (instruction.info.load_store.U)
- modified_address = Rn + instruction.info.load_store.offset.offset;
- else
- modified_address = Rn - instruction.info.load_store.offset.offset;
- } else if (instruction.info.load_store.offset_mode == 1) {
- uint32_t offset;
- uint32_t Rm = sim->get_reg_mode(sim,
- instruction.info.load_store.offset.reg.Rm);
- uint8_t shift = instruction.info.load_store.offset.reg.shift;
- uint8_t shift_imm = instruction.info.load_store.offset.reg.shift_imm;
- uint8_t carry = sim->get_cpsr(sim, 29, 1);
-
- offset = arm_shift(shift, Rm, shift_imm, &carry);
-
- if (instruction.info.load_store.U)
- modified_address = Rn + offset;
- else
- modified_address = Rn - offset;
- } else
- LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
-
- if (instruction.info.load_store.index_mode == 0) {
- /* offset mode
- * we load from the modified address, but don't change
- * the base address register
- */
- load_address = modified_address;
- modified_address = Rn;
- } else if (instruction.info.load_store.index_mode == 1) {
- /* pre-indexed mode
- * we load from the modified address, and write it
- * back to the base address register
- */
- load_address = modified_address;
- } else if (instruction.info.load_store.index_mode == 2) {
- /* post-indexed mode
- * we load from the unmodified address, and write the
- * modified address back
- */
- load_address = Rn;
- }
-
- if ((!dry_run_pc) || (instruction.info.load_store.Rd == 15)) {
- retval = target_read_u32(target, load_address, &load_value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (dry_run_pc) {
- if (instruction.info.load_store.Rd == 15)
- *dry_run_pc = load_value & ~1;
- else
- *dry_run_pc = current_pc + instruction_size;
- return ERROR_OK;
- } else {
- if ((instruction.info.load_store.index_mode == 1) ||
- (instruction.info.load_store.index_mode == 2))
- sim->set_reg_mode(sim,
- instruction.info.load_store.Rn,
- modified_address);
-
- if (instruction.info.load_store.Rd == 15) {
- sim->set_reg_mode(sim, 15, load_value & ~1);
- if (load_value & 1)
- sim->set_state(sim, ARM_STATE_THUMB);
- else
- sim->set_state(sim, ARM_STATE_ARM);
- return ERROR_OK;
- }
- sim->set_reg_mode(sim, instruction.info.load_store.Rd, load_value);
- }
- }
- /* load multiple instruction */
- else if (instruction.type == ARM_LDM) {
- int i;
- uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store_multiple.Rn);
- uint32_t load_values[16];
- int bits_set = 0;
-
- for (i = 0; i < 16; i++) {
- if (instruction.info.load_store_multiple.register_list & (1 << i))
- bits_set++;
- }
-
- switch (instruction.info.load_store_multiple.addressing_mode) {
- case 0: /* Increment after */
- /* Rn = Rn; */
- break;
- case 1: /* Increment before */
- Rn = Rn + 4;
- break;
- case 2: /* Decrement after */
- Rn = Rn - (bits_set * 4) + 4;
- break;
- case 3: /* Decrement before */
- Rn = Rn - (bits_set * 4);
- break;
- }
-
- for (i = 0; i < 16; i++) {
- if (instruction.info.load_store_multiple.register_list & (1 << i)) {
- if ((!dry_run_pc) || (i == 15))
- target_read_u32(target, Rn, &load_values[i]);
- Rn += 4;
- }
- }
-
- if (dry_run_pc) {
- if (instruction.info.load_store_multiple.register_list & 0x8000) {
- *dry_run_pc = load_values[15] & ~1;
- return ERROR_OK;
- }
- } else {
- int update_cpsr = 0;
-
- if (instruction.info.load_store_multiple.S) {
- if (instruction.info.load_store_multiple.register_list & 0x8000)
- update_cpsr = 1;
- }
-
- for (i = 0; i < 16; i++) {
- if (instruction.info.load_store_multiple.register_list & (1 << i)) {
- if (i == 15) {
- uint32_t val = load_values[i];
- sim->set_reg_mode(sim, i, val & ~1);
- if (val & 1)
- sim->set_state(sim, ARM_STATE_THUMB);
- else
- sim->set_state(sim, ARM_STATE_ARM);
- } else
- sim->set_reg_mode(sim, i, load_values[i]);
- }
- }
-
- if (update_cpsr) {
- uint32_t spsr = sim->get_reg_mode(sim, 16);
- sim->set_reg(sim, ARMV4_5_CPSR, spsr);
- }
-
- /* base register writeback */
- if (instruction.info.load_store_multiple.W)
- sim->set_reg_mode(sim, instruction.info.load_store_multiple.Rn, Rn);
-
-
- if (instruction.info.load_store_multiple.register_list & 0x8000)
- return ERROR_OK;
- }
- }
- /* store multiple instruction */
- else if (instruction.type == ARM_STM) {
- int i;
-
- if (dry_run_pc) {
- /* STM wont affect PC (advance by instruction size */
- } else {
- uint32_t Rn = sim->get_reg_mode(sim,
- instruction.info.load_store_multiple.Rn);
- int bits_set = 0;
-
- for (i = 0; i < 16; i++) {
- if (instruction.info.load_store_multiple.register_list & (1 << i))
- bits_set++;
- }
-
- switch (instruction.info.load_store_multiple.addressing_mode) {
- case 0: /* Increment after */
- /* Rn = Rn; */
- break;
- case 1: /* Increment before */
- Rn = Rn + 4;
- break;
- case 2: /* Decrement after */
- Rn = Rn - (bits_set * 4) + 4;
- break;
- case 3: /* Decrement before */
- Rn = Rn - (bits_set * 4);
- break;
- }
-
- for (i = 0; i < 16; i++) {
- if (instruction.info.load_store_multiple.register_list & (1 << i)) {
- target_write_u32(target, Rn, sim->get_reg_mode(sim, i));
- Rn += 4;
- }
- }
-
- /* base register writeback */
- if (instruction.info.load_store_multiple.W)
- sim->set_reg_mode(sim,
- instruction.info.load_store_multiple.Rn, Rn);
-
- }
- } else if (!dry_run_pc) {
- /* the instruction wasn't handled, but we're supposed to simulate it
- */
- LOG_ERROR("Unimplemented instruction, could not simulate it.");
- return ERROR_FAIL;
- }
-
- if (dry_run_pc) {
- *dry_run_pc = current_pc + instruction_size;
- return ERROR_OK;
- } else {
- sim->set_reg(sim, 15, current_pc + instruction_size);
- return ERROR_OK;
- }
-
-}
-
-static uint32_t armv4_5_get_reg(struct arm_sim_interface *sim, int reg)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- return buf_get_u32(arm->core_cache->reg_list[reg].value, 0, 32);
-}
-
-static void armv4_5_set_reg(struct arm_sim_interface *sim, int reg, uint32_t value)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- buf_set_u32(arm->core_cache->reg_list[reg].value, 0, 32, value);
-}
-
-static uint32_t armv4_5_get_reg_mode(struct arm_sim_interface *sim, int reg)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- return buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
- arm->core_mode, reg).value, 0, 32);
-}
-
-static void armv4_5_set_reg_mode(struct arm_sim_interface *sim, int reg, uint32_t value)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
- arm->core_mode, reg).value, 0, 32, value);
-}
-
-static uint32_t armv4_5_get_cpsr(struct arm_sim_interface *sim, int pos, int bits)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- return buf_get_u32(arm->cpsr->value, pos, bits);
-}
-
-static enum arm_state armv4_5_get_state(struct arm_sim_interface *sim)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- return arm->core_state;
-}
-
-static void armv4_5_set_state(struct arm_sim_interface *sim, enum arm_state mode)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- arm->core_state = mode;
-}
-
-static enum arm_mode armv4_5_get_mode(struct arm_sim_interface *sim)
-{
- struct arm *arm = (struct arm *)sim->user_data;
-
- return arm->core_mode;
-}
-
-int arm_simulate_step(struct target *target, uint32_t *dry_run_pc)
-{
- struct arm *arm = target_to_arm(target);
- struct arm_sim_interface sim;
-
- sim.user_data = arm;
- sim.get_reg = &armv4_5_get_reg;
- sim.set_reg = &armv4_5_set_reg;
- sim.get_reg_mode = &armv4_5_get_reg_mode;
- sim.set_reg_mode = &armv4_5_set_reg_mode;
- sim.get_cpsr = &armv4_5_get_cpsr;
- sim.get_mode = &armv4_5_get_mode;
- sim.get_state = &armv4_5_get_state;
- sim.set_state = &armv4_5_set_state;
-
- return arm_simulate_step_core(target, dry_run_pc, &sim);
-}
diff --git a/src/target/arm_simulator.h b/src/target/arm_simulator.h
deleted file mode 100644
index 5bdbf56..0000000
--- a/src/target/arm_simulator.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM_SIMULATOR_H
-#define OPENOCD_TARGET_ARM_SIMULATOR_H
-
-struct target;
-
-struct arm_sim_interface {
- void *user_data;
- uint32_t (*get_reg)(struct arm_sim_interface *sim, int reg);
- void (*set_reg)(struct arm_sim_interface *sim, int reg, uint32_t value);
- uint32_t (*get_reg_mode)(struct arm_sim_interface *sim, int reg);
- void (*set_reg_mode)(struct arm_sim_interface *sim, int reg, uint32_t value);
- uint32_t (*get_cpsr)(struct arm_sim_interface *sim, int pos, int bits);
- enum arm_state (*get_state)(struct arm_sim_interface *sim);
- void (*set_state)(struct arm_sim_interface *sim, enum arm_state mode);
- enum arm_mode (*get_mode)(struct arm_sim_interface *sim);
-};
-
-/* armv4_5 version */
-int arm_simulate_step(struct target *target, uint32_t *dry_run_pc);
-
-#endif /* OPENOCD_TARGET_ARM_SIMULATOR_H */
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
deleted file mode 100644
index e6ecfc8..0000000
--- a/src/target/armv4_5.c
+++ /dev/null
@@ -1,1612 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by Oyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "armv4_5.h"
-#include "arm_jtag.h"
-#include "breakpoints.h"
-#include "arm_disassembler.h"
-#include <helper/binarybuffer.h>
-#include "algorithm.h"
-#include "register.h"
-
-/* offsets into armv4_5 core register cache */
-enum {
-/* ARMV4_5_CPSR = 31, */
- ARMV4_5_SPSR_FIQ = 32,
- ARMV4_5_SPSR_IRQ = 33,
- ARMV4_5_SPSR_SVC = 34,
- ARMV4_5_SPSR_ABT = 35,
- ARMV4_5_SPSR_UND = 36,
- ARM_SPSR_MON = 41,
-};
-
-static const uint8_t arm_usr_indices[17] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ARMV4_5_CPSR,
-};
-
-static const uint8_t arm_fiq_indices[8] = {
- 16, 17, 18, 19, 20, 21, 22, ARMV4_5_SPSR_FIQ,
-};
-
-static const uint8_t arm_irq_indices[3] = {
- 23, 24, ARMV4_5_SPSR_IRQ,
-};
-
-static const uint8_t arm_svc_indices[3] = {
- 25, 26, ARMV4_5_SPSR_SVC,
-};
-
-static const uint8_t arm_abt_indices[3] = {
- 27, 28, ARMV4_5_SPSR_ABT,
-};
-
-static const uint8_t arm_und_indices[3] = {
- 29, 30, ARMV4_5_SPSR_UND,
-};
-
-static const uint8_t arm_mon_indices[3] = {
- 39, 40, ARM_SPSR_MON,
-};
-
-static const struct {
- const char *name;
- unsigned short psr;
- /* For user and system modes, these list indices for all registers.
- * otherwise they're just indices for the shadow registers and SPSR.
- */
- unsigned short n_indices;
- const uint8_t *indices;
-} arm_mode_data[] = {
- /* Seven modes are standard from ARM7 on. "System" and "User" share
- * the same registers; other modes shadow from 3 to 8 registers.
- */
- {
- .name = "User",
- .psr = ARM_MODE_USR,
- .n_indices = ARRAY_SIZE(arm_usr_indices),
- .indices = arm_usr_indices,
- },
- {
- .name = "FIQ",
- .psr = ARM_MODE_FIQ,
- .n_indices = ARRAY_SIZE(arm_fiq_indices),
- .indices = arm_fiq_indices,
- },
- {
- .name = "Supervisor",
- .psr = ARM_MODE_SVC,
- .n_indices = ARRAY_SIZE(arm_svc_indices),
- .indices = arm_svc_indices,
- },
- {
- .name = "Abort",
- .psr = ARM_MODE_ABT,
- .n_indices = ARRAY_SIZE(arm_abt_indices),
- .indices = arm_abt_indices,
- },
- {
- .name = "IRQ",
- .psr = ARM_MODE_IRQ,
- .n_indices = ARRAY_SIZE(arm_irq_indices),
- .indices = arm_irq_indices,
- },
- {
- .name = "Undefined instruction",
- .psr = ARM_MODE_UND,
- .n_indices = ARRAY_SIZE(arm_und_indices),
- .indices = arm_und_indices,
- },
- {
- .name = "System",
- .psr = ARM_MODE_SYS,
- .n_indices = ARRAY_SIZE(arm_usr_indices),
- .indices = arm_usr_indices,
- },
- /* TrustZone "Security Extensions" add a secure monitor mode.
- * This is distinct from a "debug monitor" which can support
- * non-halting debug, in conjunction with some debuggers.
- */
- {
- .name = "Secure Monitor",
- .psr = ARM_MODE_MON,
- .n_indices = ARRAY_SIZE(arm_mon_indices),
- .indices = arm_mon_indices,
- },
- {
- .name = "Secure Monitor ARM1176JZF-S",
- .psr = ARM_MODE_1176_MON,
- .n_indices = ARRAY_SIZE(arm_mon_indices),
- .indices = arm_mon_indices,
- },
-
- /* These special modes are currently only supported
- * by ARMv6M and ARMv7M profiles */
- {
- .name = "Thread",
- .psr = ARM_MODE_THREAD,
- },
- {
- .name = "Thread (User)",
- .psr = ARM_MODE_USER_THREAD,
- },
- {
- .name = "Handler",
- .psr = ARM_MODE_HANDLER,
- },
-};
-
-/** Map PSR mode bits to the name of an ARM processor operating mode. */
-const char *arm_mode_name(unsigned psr_mode)
-{
- for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) {
- if (arm_mode_data[i].psr == psr_mode)
- return arm_mode_data[i].name;
- }
- LOG_ERROR("unrecognized psr mode: %#02x", psr_mode);
- return "UNRECOGNIZED";
-}
-
-/** Return true iff the parameter denotes a valid ARM processor mode. */
-bool is_arm_mode(unsigned psr_mode)
-{
- for (unsigned i = 0; i < ARRAY_SIZE(arm_mode_data); i++) {
- if (arm_mode_data[i].psr == psr_mode)
- return true;
- }
- return false;
-}
-
-/** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */
-int arm_mode_to_number(enum arm_mode mode)
-{
- switch (mode) {
- case ARM_MODE_ANY:
- /* map MODE_ANY to user mode */
- case ARM_MODE_USR:
- return 0;
- case ARM_MODE_FIQ:
- return 1;
- case ARM_MODE_IRQ:
- return 2;
- case ARM_MODE_SVC:
- return 3;
- case ARM_MODE_ABT:
- return 4;
- case ARM_MODE_UND:
- return 5;
- case ARM_MODE_SYS:
- return 6;
- case ARM_MODE_MON:
- case ARM_MODE_1176_MON:
- return 7;
- default:
- LOG_ERROR("invalid mode value encountered %d", mode);
- return -1;
- }
-}
-
-/** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */
-enum arm_mode armv4_5_number_to_mode(int number)
-{
- switch (number) {
- case 0:
- return ARM_MODE_USR;
- case 1:
- return ARM_MODE_FIQ;
- case 2:
- return ARM_MODE_IRQ;
- case 3:
- return ARM_MODE_SVC;
- case 4:
- return ARM_MODE_ABT;
- case 5:
- return ARM_MODE_UND;
- case 6:
- return ARM_MODE_SYS;
- case 7:
- return ARM_MODE_MON;
- default:
- LOG_ERROR("mode index out of bounds %d", number);
- return ARM_MODE_ANY;
- }
-}
-
-static const char *arm_state_strings[] = {
- "ARM", "Thumb", "Jazelle", "ThumbEE",
-};
-
-/* Templates for ARM core registers.
- *
- * NOTE: offsets in this table are coupled to the arm_mode_data
- * table above, the armv4_5_core_reg_map array below, and also to
- * the ARMV4_5_CPSR symbol (which should vanish after ARM11 updates).
- */
-static const struct {
- /* The name is used for e.g. the "regs" command. */
- const char *name;
-
- /* The {cookie, mode} tuple uniquely identifies one register.
- * In a given mode, cookies 0..15 map to registers R0..R15,
- * with R13..R15 usually called SP, LR, PC.
- *
- * MODE_ANY is used as *input* to the mapping, and indicates
- * various special cases (sigh) and errors.
- *
- * Cookie 16 is (currently) confusing, since it indicates
- * CPSR -or- SPSR depending on whether 'mode' is MODE_ANY.
- * (Exception modes have both CPSR and SPSR registers ...)
- */
- unsigned cookie;
- unsigned gdb_index;
- enum arm_mode mode;
-} arm_core_regs[] = {
- /* IMPORTANT: we guarantee that the first eight cached registers
- * correspond to r0..r7, and the fifteenth to PC, so that callers
- * don't need to map them.
- */
- { .name = "r0", .cookie = 0, .mode = ARM_MODE_ANY, .gdb_index = 0, },
- { .name = "r1", .cookie = 1, .mode = ARM_MODE_ANY, .gdb_index = 1, },
- { .name = "r2", .cookie = 2, .mode = ARM_MODE_ANY, .gdb_index = 2, },
- { .name = "r3", .cookie = 3, .mode = ARM_MODE_ANY, .gdb_index = 3, },
- { .name = "r4", .cookie = 4, .mode = ARM_MODE_ANY, .gdb_index = 4, },
- { .name = "r5", .cookie = 5, .mode = ARM_MODE_ANY, .gdb_index = 5, },
- { .name = "r6", .cookie = 6, .mode = ARM_MODE_ANY, .gdb_index = 6, },
- { .name = "r7", .cookie = 7, .mode = ARM_MODE_ANY, .gdb_index = 7, },
-
- /* NOTE: regs 8..12 might be shadowed by FIQ ... flagging
- * them as MODE_ANY creates special cases. (ANY means
- * "not mapped" elsewhere; here it's "everything but FIQ".)
- */
- { .name = "r8", .cookie = 8, .mode = ARM_MODE_ANY, .gdb_index = 8, },
- { .name = "r9", .cookie = 9, .mode = ARM_MODE_ANY, .gdb_index = 9, },
- { .name = "r10", .cookie = 10, .mode = ARM_MODE_ANY, .gdb_index = 10, },
- { .name = "r11", .cookie = 11, .mode = ARM_MODE_ANY, .gdb_index = 11, },
- { .name = "r12", .cookie = 12, .mode = ARM_MODE_ANY, .gdb_index = 12, },
-
- /* Historical GDB mapping of indices:
- * - 13-14 are sp and lr, but banked counterparts are used
- * - 16-24 are left for deprecated 8 FPA + 1 FPS
- * - 25 is the cpsr
- */
-
- /* NOTE all MODE_USR registers are equivalent to MODE_SYS ones */
- { .name = "sp_usr", .cookie = 13, .mode = ARM_MODE_USR, .gdb_index = 26, },
- { .name = "lr_usr", .cookie = 14, .mode = ARM_MODE_USR, .gdb_index = 27, },
-
- /* guaranteed to be at index 15 */
- { .name = "pc", .cookie = 15, .mode = ARM_MODE_ANY, .gdb_index = 15, },
- { .name = "r8_fiq", .cookie = 8, .mode = ARM_MODE_FIQ, .gdb_index = 28, },
- { .name = "r9_fiq", .cookie = 9, .mode = ARM_MODE_FIQ, .gdb_index = 29, },
- { .name = "r10_fiq", .cookie = 10, .mode = ARM_MODE_FIQ, .gdb_index = 30, },
- { .name = "r11_fiq", .cookie = 11, .mode = ARM_MODE_FIQ, .gdb_index = 31, },
- { .name = "r12_fiq", .cookie = 12, .mode = ARM_MODE_FIQ, .gdb_index = 32, },
-
- { .name = "sp_fiq", .cookie = 13, .mode = ARM_MODE_FIQ, .gdb_index = 33, },
- { .name = "lr_fiq", .cookie = 14, .mode = ARM_MODE_FIQ, .gdb_index = 34, },
-
- { .name = "sp_irq", .cookie = 13, .mode = ARM_MODE_IRQ, .gdb_index = 35, },
- { .name = "lr_irq", .cookie = 14, .mode = ARM_MODE_IRQ, .gdb_index = 36, },
-
- { .name = "sp_svc", .cookie = 13, .mode = ARM_MODE_SVC, .gdb_index = 37, },
- { .name = "lr_svc", .cookie = 14, .mode = ARM_MODE_SVC, .gdb_index = 38, },
-
- { .name = "sp_abt", .cookie = 13, .mode = ARM_MODE_ABT, .gdb_index = 39, },
- { .name = "lr_abt", .cookie = 14, .mode = ARM_MODE_ABT, .gdb_index = 40, },
-
- { .name = "sp_und", .cookie = 13, .mode = ARM_MODE_UND, .gdb_index = 41, },
- { .name = "lr_und", .cookie = 14, .mode = ARM_MODE_UND, .gdb_index = 42, },
-
- { .name = "cpsr", .cookie = 16, .mode = ARM_MODE_ANY, .gdb_index = 25, },
- { .name = "spsr_fiq", .cookie = 16, .mode = ARM_MODE_FIQ, .gdb_index = 43, },
- { .name = "spsr_irq", .cookie = 16, .mode = ARM_MODE_IRQ, .gdb_index = 44, },
- { .name = "spsr_svc", .cookie = 16, .mode = ARM_MODE_SVC, .gdb_index = 45, },
- { .name = "spsr_abt", .cookie = 16, .mode = ARM_MODE_ABT, .gdb_index = 46, },
- { .name = "spsr_und", .cookie = 16, .mode = ARM_MODE_UND, .gdb_index = 47, },
-
- /* These are only used for GDB target description, banked registers are accessed instead */
- { .name = "sp", .cookie = 13, .mode = ARM_MODE_ANY, .gdb_index = 13, },
- { .name = "lr", .cookie = 14, .mode = ARM_MODE_ANY, .gdb_index = 14, },
-
- /* These exist only when the Security Extension (TrustZone) is present */
- { .name = "sp_mon", .cookie = 13, .mode = ARM_MODE_MON, .gdb_index = 48, },
- { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, .gdb_index = 49, },
- { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, .gdb_index = 50, },
-
-};
-
-/* map core mode (USR, FIQ, ...) and register number to
- * indices into the register cache
- */
-const int armv4_5_core_reg_map[8][17] = {
- { /* USR */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
- },
- { /* FIQ (8 shadows of USR, vs normal 3) */
- 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
- },
- { /* IRQ */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
- },
- { /* SVC */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
- },
- { /* ABT */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
- },
- { /* UND */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
- },
- { /* SYS (same registers as USR) */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
- },
- { /* MON */
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39,
- }
-};
-
-/**
- * Configures host-side ARM records to reflect the specified CPSR.
- * Later, code can use arm_reg_current() to map register numbers
- * according to how they are exposed by this mode.
- */
-void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
-{
- enum arm_mode mode = cpsr & 0x1f;
- int num;
-
- /* NOTE: this may be called very early, before the register
- * cache is set up. We can't defend against many errors, in
- * particular against CPSRs that aren't valid *here* ...
- */
- if (arm->cpsr) {
- buf_set_u32(arm->cpsr->value, 0, 32, cpsr);
- arm->cpsr->valid = 1;
- arm->cpsr->dirty = 0;
- }
-
- arm->core_mode = mode;
-
- /* mode_to_number() warned; set up a somewhat-sane mapping */
- num = arm_mode_to_number(mode);
- if (num < 0) {
- mode = ARM_MODE_USR;
- num = 0;
- }
-
- arm->map = &armv4_5_core_reg_map[num][0];
- arm->spsr = (mode == ARM_MODE_USR || mode == ARM_MODE_SYS)
- ? NULL
- : arm->core_cache->reg_list + arm->map[16];
-
- /* Older ARMs won't have the J bit */
- enum arm_state state;
-
- if (cpsr & (1 << 5)) { /* T */
- if (cpsr & (1 << 24)) { /* J */
- LOG_WARNING("ThumbEE -- incomplete support");
- state = ARM_STATE_THUMB_EE;
- } else
- state = ARM_STATE_THUMB;
- } else {
- if (cpsr & (1 << 24)) { /* J */
- LOG_ERROR("Jazelle state handling is BROKEN!");
- state = ARM_STATE_JAZELLE;
- } else
- state = ARM_STATE_ARM;
- }
- arm->core_state = state;
-
- LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr,
- arm_mode_name(mode),
- arm_state_strings[arm->core_state]);
-}
-
-/**
- * Returns handle to the register currently mapped to a given number.
- * Someone must have called arm_set_cpsr() before.
- *
- * \param arm This core's state and registers are used.
- * \param regnum From 0..15 corresponding to R0..R14 and PC.
- * Note that R0..R7 don't require mapping; you may access those
- * as the first eight entries in the register cache. Likewise
- * R15 (PC) doesn't need mapping; you may also access it directly.
- * However, R8..R14, and SPSR (arm->spsr) *must* be mapped.
- * CPSR (arm->cpsr) is also not mapped.
- */
-struct reg *arm_reg_current(struct arm *arm, unsigned regnum)
-{
- struct reg *r;
-
- if (regnum > 16)
- return NULL;
-
- if (!arm->map) {
- LOG_ERROR("Register map is not available yet, the target is not fully initialised");
- r = arm->core_cache->reg_list + regnum;
- } else
- r = arm->core_cache->reg_list + arm->map[regnum];
-
- /* e.g. invalid CPSR said "secure monitor" mode on a core
- * that doesn't support it...
- */
- if (!r) {
- LOG_ERROR("Invalid CPSR mode");
- r = arm->core_cache->reg_list + regnum;
- }
-
- return r;
-}
-
-static const uint8_t arm_gdb_dummy_fp_value[12];
-
-static struct reg_feature arm_gdb_dummy_fp_features = {
- .name = "net.sourceforge.openocd.fake_fpa"
-};
-
-/**
- * Dummy FPA registers are required to support GDB on ARM.
- * Register packets require eight obsolete FPA register values.
- * Modern ARM cores use Vector Floating Point (VFP), if they
- * have any floating point support. VFP is not FPA-compatible.
- */
-struct reg arm_gdb_dummy_fp_reg = {
- .name = "GDB dummy FPA register",
- .value = (uint8_t *) arm_gdb_dummy_fp_value,
- .valid = 1,
- .size = 96,
- .exist = false,
- .number = 16,
- .feature = &arm_gdb_dummy_fp_features,
- .group = "fake_fpa",
-};
-
-static const uint8_t arm_gdb_dummy_fps_value[4];
-
-/**
- * Dummy FPA status registers are required to support GDB on ARM.
- * Register packets require an obsolete FPA status register.
- */
-struct reg arm_gdb_dummy_fps_reg = {
- .name = "GDB dummy FPA status register",
- .value = (uint8_t *) arm_gdb_dummy_fps_value,
- .valid = 1,
- .size = 32,
- .exist = false,
- .number = 24,
- .feature = &arm_gdb_dummy_fp_features,
- .group = "fake_fpa",
-};
-
-static void arm_gdb_dummy_init(void) __attribute__ ((constructor));
-
-static void arm_gdb_dummy_init(void)
-{
- register_init_dummy(&arm_gdb_dummy_fp_reg);
- register_init_dummy(&arm_gdb_dummy_fps_reg);
-}
-
-static int armv4_5_get_core_reg(struct reg *reg)
-{
- int retval;
- struct arm_reg *reg_arch_info = reg->arch_info;
- struct target *target = reg_arch_info->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- retval = reg_arch_info->arm->read_core_reg(target, reg,
- reg_arch_info->num, reg_arch_info->mode);
- if (retval == ERROR_OK) {
- reg->valid = 1;
- reg->dirty = 0;
- }
-
- return retval;
-}
-
-static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- struct arm_reg *reg_arch_info = reg->arch_info;
- struct target *target = reg_arch_info->target;
- struct arm *armv4_5_target = target_to_arm(target);
- uint32_t value = buf_get_u32(buf, 0, 32);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Except for CPSR, the "reg" command exposes a writeback model
- * for the register cache.
- */
- if (reg == armv4_5_target->cpsr) {
- arm_set_cpsr(armv4_5_target, value);
-
- /* Older cores need help to be in ARM mode during halt
- * mode debug, so we clear the J and T bits if we flush.
- * For newer cores (v6/v7a/v7r) we don't need that, but
- * it won't hurt since CPSR is always flushed anyway.
- */
- if (armv4_5_target->core_mode !=
- (enum arm_mode)(value & 0x1f)) {
- LOG_DEBUG("changing ARM core mode to '%s'",
- arm_mode_name(value & 0x1f));
- value &= ~((1 << 24) | (1 << 5));
- uint8_t t[4];
- buf_set_u32(t, 0, 32, value);
- armv4_5_target->write_core_reg(target, reg,
- 16, ARM_MODE_ANY, t);
- }
- } else {
- buf_set_u32(reg->value, 0, 32, value);
- reg->valid = 1;
- }
- reg->dirty = 1;
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type arm_reg_type = {
- .get = armv4_5_get_core_reg,
- .set = armv4_5_set_core_reg,
-};
-
-struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
-{
- int num_regs = ARRAY_SIZE(arm_core_regs);
- struct reg_cache *cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
- struct arm_reg *reg_arch_info = calloc(num_regs, sizeof(struct arm_reg));
- int i;
-
- if (!cache || !reg_list || !reg_arch_info) {
- free(cache);
- free(reg_list);
- free(reg_arch_info);
- return NULL;
- }
-
- cache->name = "ARM registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = 0;
-
- for (i = 0; i < num_regs; i++) {
- /* Skip registers this core doesn't expose */
- if (arm_core_regs[i].mode == ARM_MODE_MON
- && arm->core_type != ARM_MODE_MON)
- continue;
-
- /* REVISIT handle Cortex-M, which only shadows R13/SP */
-
- reg_arch_info[i].num = arm_core_regs[i].cookie;
- reg_arch_info[i].mode = arm_core_regs[i].mode;
- reg_arch_info[i].target = target;
- reg_arch_info[i].arm = arm;
-
- reg_list[i].name = arm_core_regs[i].name;
- reg_list[i].number = arm_core_regs[i].gdb_index;
- reg_list[i].size = 32;
- reg_list[i].value = reg_arch_info[i].value;
- reg_list[i].type = &arm_reg_type;
- reg_list[i].arch_info = &reg_arch_info[i];
- reg_list[i].exist = true;
-
- /* This really depends on the calling convention in use */
- reg_list[i].caller_save = false;
-
- /* Registers data type, as used by GDB target description */
- reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type));
- switch (arm_core_regs[i].cookie) {
- case 13:
- reg_list[i].reg_data_type->type = REG_TYPE_DATA_PTR;
- break;
- case 14:
- case 15:
- reg_list[i].reg_data_type->type = REG_TYPE_CODE_PTR;
- break;
- default:
- reg_list[i].reg_data_type->type = REG_TYPE_UINT32;
- break;
- }
-
- /* let GDB shows banked registers only in "info all-reg" */
- reg_list[i].feature = malloc(sizeof(struct reg_feature));
- if (reg_list[i].number <= 15 || reg_list[i].number == 25) {
- reg_list[i].feature->name = "org.gnu.gdb.arm.core";
- reg_list[i].group = "general";
- } else {
- reg_list[i].feature->name = "net.sourceforge.openocd.banked";
- reg_list[i].group = "banked";
- }
-
- cache->num_regs++;
- }
-
- arm->pc = reg_list + 15;
- arm->cpsr = reg_list + ARMV4_5_CPSR;
- arm->core_cache = cache;
- return cache;
-}
-
-int arm_arch_state(struct target *target)
-{
- struct arm *arm = target_to_arm(target);
-
- if (arm->common_magic != ARM_COMMON_MAGIC) {
- LOG_ERROR("BUG: called for a non-ARM target");
- return ERROR_FAIL;
- }
-
- LOG_USER("target halted in %s state due to %s, current mode: %s\n"
- "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s",
- arm_state_strings[arm->core_state],
- debug_reason_name(target),
- arm_mode_name(arm->core_mode),
- buf_get_u32(arm->cpsr->value, 0, 32),
- buf_get_u32(arm->pc->value, 0, 32),
- arm->is_semihosting ? ", semihosting" : "");
-
- return ERROR_OK;
-}
-
-#define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
- (cache->reg_list[armv4_5_core_reg_map[mode][num]])
-
-COMMAND_HANDLER(handle_armv4_5_reg_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct reg *regs;
-
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "error: target must be halted for register accesses");
- return ERROR_FAIL;
- }
-
- if (arm->core_type != ARM_MODE_ANY) {
- command_print(CMD_CTX,
- "Microcontroller Profile not supported - use standard reg cmd");
- return ERROR_OK;
- }
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- if (!arm->full_context) {
- command_print(CMD_CTX, "error: target doesn't support %s",
- CMD_NAME);
- return ERROR_FAIL;
- }
-
- regs = arm->core_cache->reg_list;
-
- for (unsigned mode = 0; mode < ARRAY_SIZE(arm_mode_data); mode++) {
- const char *name;
- char *sep = "\n";
- char *shadow = "";
-
- /* label this bank of registers (or shadows) */
- switch (arm_mode_data[mode].psr) {
- case ARM_MODE_SYS:
- continue;
- case ARM_MODE_USR:
- name = "System and User";
- sep = "";
- break;
- case ARM_MODE_MON:
- if (arm->core_type != ARM_MODE_MON)
- continue;
- /* FALLTHROUGH */
- default:
- name = arm_mode_data[mode].name;
- shadow = "shadow ";
- break;
- }
- command_print(CMD_CTX, "%s%s mode %sregisters",
- sep, name, shadow);
-
- /* display N rows of up to 4 registers each */
- for (unsigned i = 0; i < arm_mode_data[mode].n_indices; ) {
- char output[80];
- int output_len = 0;
-
- for (unsigned j = 0; j < 4; j++, i++) {
- uint32_t value;
- struct reg *reg = regs;
-
- if (i >= arm_mode_data[mode].n_indices)
- break;
-
- reg += arm_mode_data[mode].indices[i];
-
- /* REVISIT be smarter about faults... */
- if (!reg->valid)
- arm->full_context(target);
-
- value = buf_get_u32(reg->value, 0, 32);
- output_len += snprintf(output + output_len,
- sizeof(output) - output_len,
- "%8s: %8.8" PRIx32 " ",
- reg->name, value);
- }
- command_print(CMD_CTX, "%s", output);
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_armv4_5_core_state_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
-
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- if (arm->core_type == ARM_MODE_THREAD) {
- /* armv7m not supported */
- command_print(CMD_CTX, "Unsupported Command");
- return ERROR_OK;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "arm") == 0)
- arm->core_state = ARM_STATE_ARM;
- if (strcmp(CMD_ARGV[0], "thumb") == 0)
- arm->core_state = ARM_STATE_THUMB;
- }
-
- command_print(CMD_CTX, "core state: %s", arm_state_strings[arm->core_state]);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_arm_disassemble_command)
-{
- int retval = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
-
- if (target == NULL) {
- LOG_ERROR("No target selected");
- return ERROR_FAIL;
- }
-
- struct arm *arm = target_to_arm(target);
- uint32_t address;
- int count = 1;
- int thumb = 0;
-
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- if (arm->core_type == ARM_MODE_THREAD) {
- /* armv7m is always thumb mode */
- thumb = 1;
- }
-
- switch (CMD_ARGC) {
- case 3:
- if (strcmp(CMD_ARGV[2], "thumb") != 0)
- goto usage;
- thumb = 1;
- /* FALL THROUGH */
- case 2:
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
- /* FALL THROUGH */
- case 1:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- if (address & 0x01) {
- if (!thumb) {
- command_print(CMD_CTX, "Disassemble as Thumb");
- thumb = 1;
- }
- address &= ~1;
- }
- break;
- default:
-usage:
- count = 0;
- retval = ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- while (count-- > 0) {
- struct arm_instruction cur_instruction;
-
- if (thumb) {
- /* Always use Thumb2 disassembly for best handling
- * of 32-bit BL/BLX, and to work with newer cores
- * (some ARMv6, all ARMv7) that use Thumb2.
- */
- retval = thumb2_opcode(target, address,
- &cur_instruction);
- if (retval != ERROR_OK)
- break;
- } else {
- uint32_t opcode;
-
- retval = target_read_u32(target, address, &opcode);
- if (retval != ERROR_OK)
- break;
- retval = arm_evaluate_opcode(opcode, address,
- &cur_instruction) != ERROR_OK;
- if (retval != ERROR_OK)
- break;
- }
- command_print(CMD_CTX, "%s", cur_instruction.text);
- address += cur_instruction.instruction_size;
- }
-
- return retval;
-}
-
-static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- struct command_context *context;
- struct target *target;
- struct arm *arm;
- int retval;
-
- context = current_command_context(interp);
- assert(context != NULL);
-
- target = get_current_target(context);
- if (target == NULL) {
- LOG_ERROR("%s: no current target", __func__);
- return JIM_ERR;
- }
- if (!target_was_examined(target)) {
- LOG_ERROR("%s: not yet examined", target_name(target));
- return JIM_ERR;
- }
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- LOG_ERROR("%s: not an ARM", target_name(target));
- return JIM_ERR;
- }
-
- if ((argc < 6) || (argc > 7)) {
- /* FIXME use the command name to verify # params... */
- LOG_ERROR("%s: wrong number of arguments", __func__);
- return JIM_ERR;
- }
-
- int cpnum;
- uint32_t op1;
- uint32_t op2;
- uint32_t CRn;
- uint32_t CRm;
- uint32_t value;
- long l;
-
- /* NOTE: parameter sequence matches ARM instruction set usage:
- * MCR pNUM, op1, rX, CRn, CRm, op2 ; write CP from rX
- * MRC pNUM, op1, rX, CRn, CRm, op2 ; read CP into rX
- * The "rX" is necessarily omitted; it uses Tcl mechanisms.
- */
- retval = Jim_GetLong(interp, argv[1], &l);
- if (retval != JIM_OK)
- return retval;
- if (l & ~0xf) {
- LOG_ERROR("%s: %s %d out of range", __func__,
- "coprocessor", (int) l);
- return JIM_ERR;
- }
- cpnum = l;
-
- retval = Jim_GetLong(interp, argv[2], &l);
- if (retval != JIM_OK)
- return retval;
- if (l & ~0x7) {
- LOG_ERROR("%s: %s %d out of range", __func__,
- "op1", (int) l);
- return JIM_ERR;
- }
- op1 = l;
-
- retval = Jim_GetLong(interp, argv[3], &l);
- if (retval != JIM_OK)
- return retval;
- if (l & ~0xf) {
- LOG_ERROR("%s: %s %d out of range", __func__,
- "CRn", (int) l);
- return JIM_ERR;
- }
- CRn = l;
-
- retval = Jim_GetLong(interp, argv[4], &l);
- if (retval != JIM_OK)
- return retval;
- if (l & ~0xf) {
- LOG_ERROR("%s: %s %d out of range", __func__,
- "CRm", (int) l);
- return JIM_ERR;
- }
- CRm = l;
-
- retval = Jim_GetLong(interp, argv[5], &l);
- if (retval != JIM_OK)
- return retval;
- if (l & ~0x7) {
- LOG_ERROR("%s: %s %d out of range", __func__,
- "op2", (int) l);
- return JIM_ERR;
- }
- op2 = l;
-
- value = 0;
-
- /* FIXME don't assume "mrc" vs "mcr" from the number of params;
- * that could easily be a typo! Check both...
- *
- * FIXME change the call syntax here ... simplest to just pass
- * the MRC() or MCR() instruction to be executed. That will also
- * let us support the "mrc2" and "mcr2" opcodes (toggling one bit)
- * if that's ever needed.
- */
- if (argc == 7) {
- retval = Jim_GetLong(interp, argv[6], &l);
- if (retval != JIM_OK)
- return retval;
- value = l;
-
- /* NOTE: parameters reordered! */
- /* ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2) */
- retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value);
- if (retval != ERROR_OK)
- return JIM_ERR;
- } else {
- /* NOTE: parameters reordered! */
- /* ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2) */
- retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value);
- if (retval != ERROR_OK)
- return JIM_ERR;
-
- Jim_SetResult(interp, Jim_NewIntObj(interp, value));
- }
-
- return JIM_OK;
-}
-
-COMMAND_HANDLER(handle_arm_semihosting_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- if (target == NULL) {
- LOG_ERROR("No target selected");
- return ERROR_FAIL;
- }
-
- struct arm *arm = target_to_arm(target);
-
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- if (!arm->setup_semihosting) {
- command_print(CMD_CTX, "semihosting not supported for current target");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- int semihosting;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting);
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- if (arm->setup_semihosting(target, semihosting) != ERROR_OK) {
- LOG_ERROR("Failed to Configure semihosting");
- return ERROR_FAIL;
- }
-
- /* FIXME never let that "catch" be dropped! */
- arm->is_semihosting = semihosting;
- }
-
- command_print(CMD_CTX, "semihosting is %s",
- arm->is_semihosting
- ? "enabled" : "disabled");
-
- return ERROR_OK;
-}
-
-static const struct command_registration arm_exec_command_handlers[] = {
- {
- .name = "reg",
- .handler = handle_armv4_5_reg_command,
- .mode = COMMAND_EXEC,
- .help = "display ARM core registers",
- .usage = "",
- },
- {
- .name = "core_state",
- .handler = handle_armv4_5_core_state_command,
- .mode = COMMAND_EXEC,
- .usage = "['arm'|'thumb']",
- .help = "display/change ARM core state",
- },
- {
- .name = "disassemble",
- .handler = handle_arm_disassemble_command,
- .mode = COMMAND_EXEC,
- .usage = "address [count ['thumb']]",
- .help = "disassemble instructions ",
- },
- {
- .name = "mcr",
- .mode = COMMAND_EXEC,
- .jim_handler = &jim_mcrmrc,
- .help = "write coprocessor register",
- .usage = "cpnum op1 CRn CRm op2 value",
- },
- {
- .name = "mrc",
- .jim_handler = &jim_mcrmrc,
- .help = "read coprocessor register",
- .usage = "cpnum op1 CRn CRm op2",
- },
- {
- "semihosting",
- .handler = handle_arm_semihosting_command,
- .mode = COMMAND_EXEC,
- .usage = "['enable'|'disable']",
- .help = "activate support for semihosting operations",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-const struct command_registration arm_command_handlers[] = {
- {
- .name = "arm",
- .mode = COMMAND_ANY,
- .help = "ARM command group",
- .usage = "",
- .chain = arm_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int arm_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class)
-{
- struct arm *arm = target_to_arm(target);
- unsigned int i;
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- switch (reg_class) {
- case REG_CLASS_GENERAL:
- *reg_list_size = 26;
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
-
- for (i = 0; i < 16; i++)
- (*reg_list)[i] = arm_reg_current(arm, i);
-
- /* For GDB compatibility, take FPA registers size into account and zero-fill it*/
- for (i = 16; i < 24; i++)
- (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
- (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
-
- (*reg_list)[25] = arm->cpsr;
-
- return ERROR_OK;
- break;
-
- case REG_CLASS_ALL:
- *reg_list_size = (arm->core_type != ARM_MODE_MON ? 48 : 51);
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
-
- for (i = 0; i < 16; i++)
- (*reg_list)[i] = arm_reg_current(arm, i);
-
- for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) {
- int reg_index = arm->core_cache->reg_list[i].number;
- if (!(arm_core_regs[i].mode == ARM_MODE_MON
- && arm->core_type != ARM_MODE_MON))
- (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]);
- }
-
- /* When we supply the target description, there is no need for fake FPA */
- for (i = 16; i < 24; i++) {
- (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
- (*reg_list)[i]->size = 0;
- }
- (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
- (*reg_list)[24]->size = 0;
-
- return ERROR_OK;
- break;
-
- default:
- LOG_ERROR("not a valid register class type in query.");
- return ERROR_FAIL;
- break;
- }
-}
-
-/* wait for execution to complete and check exit point */
-static int armv4_5_run_algorithm_completion(struct target *target,
- uint32_t exit_point,
- int timeout_ms,
- void *arch_info)
-{
- int retval;
- struct arm *arm = target_to_arm(target);
-
- retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
- if (retval != ERROR_OK)
- return retval;
- if (target->state != TARGET_HALTED) {
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- retval = target_wait_state(target, TARGET_HALTED, 500);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_TARGET_TIMEOUT;
- }
-
- /* fast exit: ARMv5+ code can use BKPT */
- if (exit_point && buf_get_u32(arm->pc->value, 0, 32) != exit_point) {
- LOG_WARNING(
- "target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
- buf_get_u32(arm->pc->value, 0, 32));
- return ERROR_TARGET_TIMEOUT;
- }
-
- return ERROR_OK;
-}
-
-int armv4_5_run_algorithm_inner(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info,
- int (*run_it)(struct target *target, uint32_t exit_point,
- int timeout_ms, void *arch_info))
-{
- struct arm *arm = target_to_arm(target);
- struct arm_algorithm *arm_algorithm_info = arch_info;
- enum arm_state core_state = arm->core_state;
- uint32_t context[17];
- uint32_t cpsr;
- int exit_breakpoint_size = 0;
- int i;
- int retval = ERROR_OK;
-
- LOG_DEBUG("Running algorithm");
-
- if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC) {
- LOG_ERROR("current target isn't an ARMV4/5 target");
- return ERROR_TARGET_INVALID;
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!is_arm_mode(arm->core_mode)) {
- LOG_ERROR("not a valid arm core mode - communication failure?");
- return ERROR_FAIL;
- }
-
- /* armv5 and later can terminate with BKPT instruction; less overhead */
- if (!exit_point && arm->is_armv4) {
- LOG_ERROR("ARMv4 target needs HW breakpoint location");
- return ERROR_FAIL;
- }
-
- /* save r0..pc, cpsr-or-spsr, and then cpsr-for-sure;
- * they'll be restored later.
- */
- for (i = 0; i <= 16; i++) {
- struct reg *r;
-
- r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
- arm_algorithm_info->core_mode, i);
- if (!r->valid)
- arm->read_core_reg(target, r, i,
- arm_algorithm_info->core_mode);
- context[i] = buf_get_u32(r->value, 0, 32);
- }
- cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
-
- for (i = 0; i < num_mem_params; i++) {
- retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size,
- mem_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- for (i = 0; i < num_reg_params; i++) {
- struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- retval = armv4_5_set_core_reg(reg, reg_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- arm->core_state = arm_algorithm_info->core_state;
- if (arm->core_state == ARM_STATE_ARM)
- exit_breakpoint_size = 4;
- else if (arm->core_state == ARM_STATE_THUMB)
- exit_breakpoint_size = 2;
- else {
- LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (arm_algorithm_info->core_mode != ARM_MODE_ANY) {
- LOG_DEBUG("setting core_mode: 0x%2.2x",
- arm_algorithm_info->core_mode);
- buf_set_u32(arm->cpsr->value, 0, 5,
- arm_algorithm_info->core_mode);
- arm->cpsr->dirty = 1;
- arm->cpsr->valid = 1;
- }
-
- /* terminate using a hardware or (ARMv5+) software breakpoint */
- if (exit_point) {
- retval = breakpoint_add(target, exit_point,
- exit_breakpoint_size, BKPT_HARD);
- if (retval != ERROR_OK) {
- LOG_ERROR("can't add HW breakpoint to terminate algorithm");
- return ERROR_TARGET_FAILURE;
- }
- }
-
- retval = target_resume(target, 0, entry_point, 1, 1);
- if (retval != ERROR_OK)
- return retval;
- retval = run_it(target, exit_point, timeout_ms, arch_info);
-
- if (exit_point)
- breakpoint_remove(target, exit_point);
-
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < num_mem_params; i++) {
- if (mem_params[i].direction != PARAM_OUT) {
- int retvaltemp = target_read_buffer(target, mem_params[i].address,
- mem_params[i].size,
- mem_params[i].value);
- if (retvaltemp != ERROR_OK)
- retval = retvaltemp;
- }
- }
-
- for (i = 0; i < num_reg_params; i++) {
- if (reg_params[i].direction != PARAM_OUT) {
-
- struct reg *reg = register_get_by_name(arm->core_cache,
- reg_params[i].reg_name,
- 0);
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- retval = ERROR_COMMAND_SYNTAX_ERROR;
- continue;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR(
- "BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- retval = ERROR_COMMAND_SYNTAX_ERROR;
- continue;
- }
-
- buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
- }
- }
-
- /* restore everything we saved before (17 or 18 registers) */
- for (i = 0; i <= 16; i++) {
- uint32_t regvalue;
- regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
- arm_algorithm_info->core_mode, i).value, 0, 32);
- if (regvalue != context[i]) {
- LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "",
- ARMV4_5_CORE_REG_MODE(arm->core_cache,
- arm_algorithm_info->core_mode, i).name, context[i]);
- buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
- arm_algorithm_info->core_mode, i).value, 0, 32, context[i]);
- ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
- i).valid = 1;
- ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
- i).dirty = 1;
- }
- }
-
- arm_set_cpsr(arm, cpsr);
- arm->cpsr->dirty = 1;
-
- arm->core_state = core_state;
-
- return retval;
-}
-
-int armv4_5_run_algorithm(struct target *target,
- int num_mem_params,
- struct mem_param *mem_params,
- int num_reg_params,
- struct reg_param *reg_params,
- uint32_t entry_point,
- uint32_t exit_point,
- int timeout_ms,
- void *arch_info)
-{
- return armv4_5_run_algorithm_inner(target,
- num_mem_params,
- mem_params,
- num_reg_params,
- reg_params,
- entry_point,
- exit_point,
- timeout_ms,
- arch_info,
- armv4_5_run_algorithm_completion);
-}
-
-/**
- * Runs ARM code in the target to calculate a CRC32 checksum.
- *
- */
-int arm_checksum_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *checksum)
-{
- struct working_area *crc_algorithm;
- struct arm_algorithm arm_algo;
- struct arm *arm = target_to_arm(target);
- struct reg_param reg_params[2];
- int retval;
- uint32_t i;
- uint32_t exit_var = 0;
-
- static const uint8_t arm_crc_code_le[] = {
-#include "../../contrib/loaders/checksum/armv4_5_crc.inc"
- };
-
- assert(sizeof(arm_crc_code_le) % 4 == 0);
-
- retval = target_alloc_working_area(target,
- sizeof(arm_crc_code_le), &crc_algorithm);
- if (retval != ERROR_OK)
- return retval;
-
- /* convert code into a buffer in target endianness */
- for (i = 0; i < ARRAY_SIZE(arm_crc_code_le) / 4; i++) {
- retval = target_write_u32(target,
- crc_algorithm->address + i * sizeof(uint32_t),
- le_to_h_u32(&arm_crc_code_le[i * 4]));
- if (retval != ERROR_OK)
- goto cleanup;
- }
-
- 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_IN_OUT);
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-
- buf_set_u32(reg_params[0].value, 0, 32, address);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- /* 20 second timeout/megabyte */
- int timeout = 20000 * (1 + (count / (1024 * 1024)));
-
- /* armv4 must exit using a hardware breakpoint */
- if (arm->is_armv4)
- exit_var = crc_algorithm->address + sizeof(arm_crc_code_le) - 8;
-
- retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
- crc_algorithm->address,
- exit_var,
- timeout, &arm_algo);
-
- if (retval == ERROR_OK)
- *checksum = buf_get_u32(reg_params[0].value, 0, 32);
- else
- LOG_ERROR("error executing ARM crc algorithm");
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
-
-cleanup:
- target_free_working_area(target, crc_algorithm);
-
- return retval;
-}
-
-/**
- * Runs ARM code in the target to check whether a memory block holds
- * all ones. NOR flash which has been erased, and thus may be written,
- * holds all ones.
- *
- */
-int arm_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank)
-{
- struct working_area *check_algorithm;
- struct reg_param reg_params[3];
- struct arm_algorithm arm_algo;
- struct arm *arm = target_to_arm(target);
- int retval;
- uint32_t i;
- uint32_t exit_var = 0;
-
- static const uint8_t check_code_le[] = {
-#include "../../contrib/loaders/erase_check/armv4_5_erase_check.inc"
- };
-
- assert(sizeof(check_code_le) % 4 == 0);
-
- /* make sure we have a working area */
- retval = target_alloc_working_area(target,
- sizeof(check_code_le), &check_algorithm);
- if (retval != ERROR_OK)
- return retval;
-
- /* convert code into a buffer in target endianness */
- for (i = 0; i < ARRAY_SIZE(check_code_le) / 4; i++) {
- retval = target_write_u32(target,
- check_algorithm->address
- + i * sizeof(uint32_t),
- le_to_h_u32(&check_code_le[i * 4]));
- if (retval != ERROR_OK)
- goto cleanup;
- }
-
- 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);
- buf_set_u32(reg_params[0].value, 0, 32, address);
-
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
- buf_set_u32(reg_params[2].value, 0, 32, 0xff);
-
- /* armv4 must exit using a hardware breakpoint */
- if (arm->is_armv4)
- exit_var = check_algorithm->address + sizeof(check_code_le) - 4;
-
- retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- check_algorithm->address,
- exit_var,
- 10000, &arm_algo);
-
- if (retval == ERROR_OK)
- *blank = buf_get_u32(reg_params[2].value, 0, 32);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
-cleanup:
- target_free_working_area(target, check_algorithm);
-
- return retval;
-}
-
-static int arm_full_context(struct target *target)
-{
- struct arm *arm = target_to_arm(target);
- unsigned num_regs = arm->core_cache->num_regs;
- struct reg *reg = arm->core_cache->reg_list;
- int retval = ERROR_OK;
-
- for (; num_regs && retval == ERROR_OK; num_regs--, reg++) {
- if (reg->valid)
- continue;
- retval = armv4_5_get_core_reg(reg);
- }
- return retval;
-}
-
-static int arm_default_mrc(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t *value)
-{
- LOG_ERROR("%s doesn't implement MRC", target_type_name(target));
- return ERROR_FAIL;
-}
-
-static int arm_default_mcr(struct target *target, int cpnum,
- uint32_t op1, uint32_t op2,
- uint32_t CRn, uint32_t CRm,
- uint32_t value)
-{
- LOG_ERROR("%s doesn't implement MCR", target_type_name(target));
- return ERROR_FAIL;
-}
-
-int arm_init_arch_info(struct target *target, struct arm *arm)
-{
- target->arch_info = arm;
- arm->target = target;
-
- arm->common_magic = ARM_COMMON_MAGIC;
-
- /* core_type may be overridden by subtype logic */
- if (arm->core_type != ARM_MODE_THREAD) {
- arm->core_type = ARM_MODE_ANY;
- arm_set_cpsr(arm, ARM_MODE_USR);
- }
-
- /* default full_context() has no core-specific optimizations */
- if (!arm->full_context && arm->read_core_reg)
- arm->full_context = arm_full_context;
-
- if (!arm->mrc)
- arm->mrc = arm_default_mrc;
- if (!arm->mcr)
- arm->mcr = arm_default_mcr;
-
- return ERROR_OK;
-}
diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h
deleted file mode 100644
index 3ce4ed0..0000000
--- a/src/target/armv4_5.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2009 by Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARMV4_5_H
-#define OPENOCD_TARGET_ARMV4_5_H
-
-/* This stuff "knows" that its callers aren't talking
- * to microcontroller profile (current Cortex-M) parts.
- * We want to phase it out so core code can be shared.
- */
-
-/* OBSOLETE, DO NOT USE IN NEW CODE! The "number" of an arm_mode is an
- * index into the armv4_5_core_reg_map array. Its remaining users are
- * remnants which could as easily walk * the register cache directly as
- * use the expensive ARMV4_5_CORE_REG_MODE() macro.
- */
-int arm_mode_to_number(enum arm_mode mode);
-enum arm_mode armv4_5_number_to_mode(int number);
-
-extern const int armv4_5_core_reg_map[8][17];
-
-#define ARMV4_5_CORE_REG_MODE(cache, mode, num) \
- (cache->reg_list[armv4_5_core_reg_map[arm_mode_to_number(mode)][num]])
-
-/* offset into armv4_5 core register cache -- OBSOLETE, DO NOT USE! */
-enum { ARMV4_5_CPSR = 31, };
-
-#endif /* OPENOCD_TARGET_ARMV4_5_H */
diff --git a/src/target/armv4_5_cache.c b/src/target/armv4_5_cache.c
deleted file mode 100644
index bd0091d..0000000
--- a/src/target/armv4_5_cache.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "armv4_5_cache.h"
-#include <helper/log.h>
-
-int armv4_5_identify_cache(uint32_t cache_type_reg, struct armv4_5_cache_common *cache)
-{
- int size, assoc, M, len, multiplier;
-
- cache->ctype = (cache_type_reg & 0x1e000000U) >> 25;
- cache->separate = (cache_type_reg & 0x01000000U) >> 24;
-
- size = (cache_type_reg & 0x1c0000) >> 18;
- assoc = (cache_type_reg & 0x38000) >> 15;
- M = (cache_type_reg & 0x4000) >> 14;
- len = (cache_type_reg & 0x3000) >> 12;
- multiplier = 2 + M;
-
- if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ {
- /* cache is present */
- cache->d_u_size.linelen = 1 << (len + 3);
- cache->d_u_size.associativity = multiplier << (assoc - 1);
- cache->d_u_size.nsets = 1 << (size + 6 - assoc - len);
- cache->d_u_size.cachesize = multiplier << (size + 8);
- } else {
- /* cache is absent */
- cache->d_u_size.linelen = -1;
- cache->d_u_size.associativity = -1;
- cache->d_u_size.nsets = -1;
- cache->d_u_size.cachesize = -1;
- }
-
- if (cache->separate) {
- size = (cache_type_reg & 0x1c0) >> 6;
- assoc = (cache_type_reg & 0x38) >> 3;
- M = (cache_type_reg & 0x4) >> 2;
- len = (cache_type_reg & 0x3);
- multiplier = 2 + M;
-
- if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ {
- /* cache is present */
- cache->i_size.linelen = 1 << (len + 3);
- cache->i_size.associativity = multiplier << (assoc - 1);
- cache->i_size.nsets = 1 << (size + 6 - assoc - len);
- cache->i_size.cachesize = multiplier << (size + 8);
- } else {
- /* cache is absent */
- cache->i_size.linelen = -1;
- cache->i_size.associativity = -1;
- cache->i_size.nsets = -1;
- cache->i_size.cachesize = -1;
- }
- } else
- cache->i_size = cache->d_u_size;
-
- return ERROR_OK;
-}
-
-int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx, struct armv4_5_cache_common *armv4_5_cache)
-{
- if (armv4_5_cache->ctype == -1) {
- command_print(cmd_ctx, "cache not yet identified");
- return ERROR_OK;
- }
-
- command_print(cmd_ctx, "cache type: 0x%1.1x, %s", armv4_5_cache->ctype,
- (armv4_5_cache->separate) ? "separate caches" : "unified cache");
-
- command_print(cmd_ctx, "D-Cache: linelen %i, associativity %i, nsets %i, cachesize 0x%x",
- armv4_5_cache->d_u_size.linelen,
- armv4_5_cache->d_u_size.associativity,
- armv4_5_cache->d_u_size.nsets,
- armv4_5_cache->d_u_size.cachesize);
-
- command_print(cmd_ctx, "I-Cache: linelen %i, associativity %i, nsets %i, cachesize 0x%x",
- armv4_5_cache->i_size.linelen,
- armv4_5_cache->i_size.associativity,
- armv4_5_cache->i_size.nsets,
- armv4_5_cache->i_size.cachesize);
-
- return ERROR_OK;
-}
diff --git a/src/target/armv4_5_cache.h b/src/target/armv4_5_cache.h
deleted file mode 100644
index 2fd1ca3..0000000
--- a/src/target/armv4_5_cache.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARMV4_5_CACHE_H
-#define OPENOCD_TARGET_ARMV4_5_CACHE_H
-
-struct command_context;
-
-struct armv4_5_cachesize {
- int linelen;
- int associativity;
- int nsets;
- int cachesize;
-};
-
-struct armv4_5_cache_common {
- int ctype; /* specify supported cache operations */
- int separate; /* separate caches or unified cache */
- struct armv4_5_cachesize d_u_size; /* data cache */
- struct armv4_5_cachesize i_size; /* instruction cache */
- int i_cache_enabled;
- int d_u_cache_enabled;
-};
-
-int armv4_5_identify_cache(uint32_t cache_type_reg,
- struct armv4_5_cache_common *cache);
-int armv4_5_cache_state(uint32_t cp15_control_reg,
- struct armv4_5_cache_common *cache);
-
-int armv4_5_handle_cache_info_command(struct command_context *cmd_ctx,
- struct armv4_5_cache_common *armv4_5_cache);
-
-enum {
- ARMV4_5_D_U_CACHE_ENABLED = 0x4,
- ARMV4_5_I_CACHE_ENABLED = 0x1000,
- ARMV4_5_WRITE_BUFFER_ENABLED = 0x8,
- ARMV4_5_CACHE_RR_BIT = 0x5000,
-};
-
-#endif /* OPENOCD_TARGET_ARMV4_5_CACHE_H */
diff --git a/src/target/armv4_5_mmu.c b/src/target/armv4_5_mmu.c
deleted file mode 100644
index 115a489..0000000
--- a/src/target/armv4_5_mmu.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include "target.h"
-#include "armv4_5_mmu.h"
-
-int armv4_5_mmu_translate_va(struct target *target,
- struct armv4_5_mmu_common *armv4_5_mmu, uint32_t va, uint32_t *cb, uint32_t *val)
-{
- uint32_t first_lvl_descriptor = 0x0;
- uint32_t second_lvl_descriptor = 0x0;
- uint32_t ttb;
- int retval;
- retval = armv4_5_mmu->get_ttb(target, &ttb);
- if (retval != ERROR_OK)
- return retval;
-
- retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
- (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
- 4, 1, (uint8_t *)&first_lvl_descriptor);
- if (retval != ERROR_OK)
- return retval;
- first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)&first_lvl_descriptor);
-
- LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
-
- if ((first_lvl_descriptor & 0x3) == 0) {
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
-
- if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3)) {
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
-
- if ((first_lvl_descriptor & 0x3) == 2) {
- /* section descriptor */
- *cb = (first_lvl_descriptor & 0xc) >> 2;
- *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
- return ERROR_OK;
- }
-
- if ((first_lvl_descriptor & 0x3) == 1) {
- /* coarse page table */
- retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
- (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
- 4, 1, (uint8_t *)&second_lvl_descriptor);
- if (retval != ERROR_OK)
- return retval;
- } else if ((first_lvl_descriptor & 0x3) == 3) {
- /* fine page table */
- retval = armv4_5_mmu_read_physical(target, armv4_5_mmu,
- (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
- 4, 1, (uint8_t *)&second_lvl_descriptor);
- if (retval != ERROR_OK)
- return retval;
- }
-
- second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)&second_lvl_descriptor);
-
- LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
-
- if ((second_lvl_descriptor & 0x3) == 0) {
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
-
- /* cacheable/bufferable is always specified in bits 3-2 */
- *cb = (second_lvl_descriptor & 0xc) >> 2;
-
- if ((second_lvl_descriptor & 0x3) == 1) {
- /* large page descriptor */
- *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
- return ERROR_OK;
- }
-
- if ((second_lvl_descriptor & 0x3) == 2) {
- /* small page descriptor */
- *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
- return ERROR_OK;
- }
-
- if ((second_lvl_descriptor & 0x3) == 3) {
- /* tiny page descriptor */
- *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
- return ERROR_OK;
- }
-
- /* should not happen */
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
-}
-
-int armv4_5_mmu_read_physical(struct target *target,
- struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- int retval;
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- /* disable MMU and data (or unified) cache */
- retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = armv4_5_mmu->read_memory(target, address, size, count, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- /* reenable MMU / cache */
- retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
- armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
- armv4_5_mmu->armv4_5_cache.i_cache_enabled);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
-
-int armv4_5_mmu_write_physical(struct target *target,
- struct armv4_5_mmu_common *armv4_5_mmu, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- int retval;
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- /* disable MMU and data (or unified) cache */
- retval = armv4_5_mmu->disable_mmu_caches(target, 1, 1, 0);
- if (retval != ERROR_OK)
- return retval;
-
- retval = armv4_5_mmu->write_memory(target, address, size, count, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- /* reenable MMU / cache */
- retval = armv4_5_mmu->enable_mmu_caches(target, armv4_5_mmu->mmu_enabled,
- armv4_5_mmu->armv4_5_cache.d_u_cache_enabled,
- armv4_5_mmu->armv4_5_cache.i_cache_enabled);
- if (retval != ERROR_OK)
- return retval;
-
- return retval;
-}
diff --git a/src/target/armv4_5_mmu.h b/src/target/armv4_5_mmu.h
deleted file mode 100644
index 0f52121..0000000
--- a/src/target/armv4_5_mmu.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARMV4_5_MMU_H
-#define OPENOCD_TARGET_ARMV4_5_MMU_H
-
-#include "armv4_5_cache.h"
-
-struct target;
-
-struct armv4_5_mmu_common {
- int (*get_ttb)(struct target *target, uint32_t *result);
- int (*read_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
- int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
- int (*disable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache);
- int (*enable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache);
- struct armv4_5_cache_common armv4_5_cache;
- int has_tiny_pages;
- int mmu_enabled;
-};
-
-int armv4_5_mmu_translate_va(struct target *target,
- struct armv4_5_mmu_common *armv4_5_mmu, uint32_t va,
- uint32_t *cb, uint32_t *val);
-
-int armv4_5_mmu_read_physical(struct target *target,
- struct armv4_5_mmu_common *armv4_5_mmu,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
-
-int armv4_5_mmu_write_physical(struct target *target,
- struct armv4_5_mmu_common *armv4_5_mmu,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-
-enum {
- ARMV4_5_MMU_ENABLED = 0x1,
- ARMV4_5_ALIGNMENT_CHECK = 0x2,
- ARMV4_5_MMU_S_BIT = 0x100,
- ARMV4_5_MMU_R_BIT = 0x200
-};
-
-#endif /* OPENOCD_TARGET_ARMV4_5_MMU_H */
diff --git a/src/target/armv7a.c b/src/target/armv7a.c
deleted file mode 100644
index 37eb1b5..0000000
--- a/src/target/armv7a.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by David Brownell *
- * *
- * Copyright (C) ST-Ericsson SA 2011 michel.jaouen@stericsson.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/replacements.h>
-
-#include "armv7a.h"
-#include "arm_disassembler.h"
-
-#include "register.h"
-#include <helper/binarybuffer.h>
-#include <helper/command.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "arm_opcodes.h"
-#include "target.h"
-#include "target_type.h"
-
-static void armv7a_show_fault_registers(struct target *target)
-{
- uint32_t dfsr, ifsr, dfar, ifar;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- int retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- return;
-
- /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */
-
- /* c5/c0 - {data, instruction} fault status registers */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
- &dfsr);
- if (retval != ERROR_OK)
- goto done;
-
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
- &ifsr);
- if (retval != ERROR_OK)
- goto done;
-
- /* c6/c0 - {data, instruction} fault address registers */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 6, 0, 0),
- &dfar);
- if (retval != ERROR_OK)
- goto done;
-
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
- &ifar);
- if (retval != ERROR_OK)
- goto done;
-
- LOG_USER("Data fault registers DFSR: %8.8" PRIx32
- ", DFAR: %8.8" PRIx32, dfsr, dfar);
- LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
- ", IFAR: %8.8" PRIx32, ifsr, ifar);
-
-done:
- /* (void) */ dpm->finish(dpm);
-}
-
-
-/* retrieve main id register */
-static int armv7a_read_midr(struct target *target)
-{
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t midr;
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
- /* MRC p15,0,<Rd>,c0,c0,0; read main id register*/
-
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 0, 0, 0),
- &midr);
- if (retval != ERROR_OK)
- goto done;
-
- armv7a->rev = (midr & 0xf);
- armv7a->partnum = (midr >> 4) & 0xfff;
- armv7a->arch = (midr >> 16) & 0xf;
- armv7a->variant = (midr >> 20) & 0xf;
- armv7a->implementor = (midr >> 24) & 0xff;
- LOG_INFO("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32
- ", variant %" PRIx32 ", implementor %" PRIx32,
- target->cmd_name,
- armv7a->rev,
- armv7a->partnum,
- armv7a->arch,
- armv7a->variant,
- armv7a->implementor);
-
-done:
- dpm->finish(dpm);
- return retval;
-}
-
-static int armv7a_read_ttbcr(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t ttbcr, ttbcr_n;
- int retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
- /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
- &ttbcr);
- if (retval != ERROR_OK)
- goto done;
-
- LOG_DEBUG("ttbcr %" PRIx32, ttbcr);
-
- ttbcr_n = ttbcr & 0x7;
- armv7a->armv7a_mmu.ttbcr = ttbcr;
- armv7a->armv7a_mmu.cached = 1;
-
- /*
- * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
- * document # ARM DDI 0406C
- */
- armv7a->armv7a_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n;
- armv7a->armv7a_mmu.ttbr_range[1] = 0xffffffff;
- armv7a->armv7a_mmu.ttbr_mask[0] = 0xffffffff << (14 - ttbcr_n);
- armv7a->armv7a_mmu.ttbr_mask[1] = 0xffffffff << 14;
- armv7a->armv7a_mmu.cached = 1;
-
- retval = armv7a_read_midr(target);
- if (retval != ERROR_OK)
- goto done;
-
- /* FIXME: why this special case based on part number? */
- if ((armv7a->partnum & 0xf) == 0) {
- /* ARM DDI 0344H , ARM DDI 0407F */
- armv7a->armv7a_mmu.ttbr_mask[0] = 7 << (32 - ttbcr_n);
- }
-
- LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32,
- (ttbcr_n != 0) ? "used" : "not used",
- armv7a->armv7a_mmu.ttbr_mask[0],
- armv7a->armv7a_mmu.ttbr_mask[1]);
-
-done:
- dpm->finish(dpm);
- return retval;
-}
-
-/* method adapted to Cortex-A : reused ARM v4 v5 method */
-int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
-{
- uint32_t first_lvl_descriptor = 0x0;
- uint32_t second_lvl_descriptor = 0x0;
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t ttbidx = 0; /* default to ttbr0 */
- uint32_t ttb_mask;
- uint32_t va_mask;
- uint32_t ttbcr;
- uint32_t ttb;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
- &ttbcr);
- if (retval != ERROR_OK)
- goto done;
-
- /* if ttbcr has changed or was not read before, re-read the information */
- if ((armv7a->armv7a_mmu.cached == 0) ||
- (armv7a->armv7a_mmu.ttbcr != ttbcr)) {
- armv7a_read_ttbcr(target);
- }
-
- /* if va is above the range handled by ttbr0, select ttbr1 */
- if (va > armv7a->armv7a_mmu.ttbr_range[0]) {
- /* select ttb 1 */
- ttbidx = 1;
- }
- /* MRC p15,0,<Rt>,c2,c0,ttbidx */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx),
- &ttb);
- if (retval != ERROR_OK)
- return retval;
-
- ttb_mask = armv7a->armv7a_mmu.ttbr_mask[ttbidx];
- va_mask = 0xfff00000 & armv7a->armv7a_mmu.ttbr_range[ttbidx];
-
- LOG_DEBUG("ttb_mask %" PRIx32 " va_mask %" PRIx32 " ttbidx %i",
- ttb_mask, va_mask, ttbidx);
- retval = armv7a->armv7a_mmu.read_physical_memory(target,
- (ttb & ttb_mask) | ((va & va_mask) >> 18),
- 4, 1, (uint8_t *)&first_lvl_descriptor);
- if (retval != ERROR_OK)
- return retval;
- first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
- &first_lvl_descriptor);
- /* reuse armv4_5 piece of code, specific armv7a changes may come later */
- LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
-
- if ((first_lvl_descriptor & 0x3) == 0) {
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
-
-
- if ((first_lvl_descriptor & 0x40002) == 2) {
- /* section descriptor */
- *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
- return ERROR_OK;
- } else if ((first_lvl_descriptor & 0x40002) == 0x40002) {
- /* supersection descriptor */
- if (first_lvl_descriptor & 0x00f001e0) {
- LOG_ERROR("Physical address does not fit into 32 bits");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
- *val = (first_lvl_descriptor & 0xff000000) | (va & 0x00ffffff);
- return ERROR_OK;
- }
-
- /* page table */
- retval = armv7a->armv7a_mmu.read_physical_memory(target,
- (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
- 4, 1, (uint8_t *)&second_lvl_descriptor);
- if (retval != ERROR_OK)
- return retval;
-
- second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
- &second_lvl_descriptor);
-
- LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
-
- if ((second_lvl_descriptor & 0x3) == 0) {
- LOG_ERROR("Address translation failure");
- return ERROR_TARGET_TRANSLATION_FAULT;
- }
-
- if ((second_lvl_descriptor & 0x3) == 1) {
- /* large page descriptor */
- *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
- } else {
- /* small page descriptor */
- *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
- }
-
- return ERROR_OK;
-
-done:
- return retval;
-}
-
-/* V7 method VA TO PA */
-int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
- uint32_t *val, int meminfo)
-{
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t virt = va & ~0xfff;
- uint32_t NOS, NS, INNER, OUTER;
- *val = 0xdeadbeef;
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
- /* mmu must be enable in order to get a correct translation
- * use VA to PA CP15 register for conversion */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
- virt);
- if (retval != ERROR_OK)
- goto done;
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
- val);
- /* decode memory attribute */
- NOS = (*val >> 10) & 1; /* Not Outer shareable */
- NS = (*val >> 9) & 1; /* Non secure */
- INNER = (*val >> 4) & 0x7;
- OUTER = (*val >> 2) & 0x3;
-
- if (retval != ERROR_OK)
- goto done;
- *val = (*val & ~0xfff) + (va & 0xfff);
- if (*val == va)
- LOG_WARNING("virt = phys : MMU disable !!");
- if (meminfo) {
- LOG_INFO("%" PRIx32 " : %" PRIx32 " %s outer shareable %s secured",
- va, *val,
- NOS == 1 ? "not" : " ",
- NS == 1 ? "not" : "");
- switch (OUTER) {
- case 0:
- LOG_INFO("outer: Non-Cacheable");
- break;
- case 1:
- LOG_INFO("outer: Write-Back, Write-Allocate");
- break;
- case 2:
- LOG_INFO("outer: Write-Through, No Write-Allocate");
- break;
- case 3:
- LOG_INFO("outer: Write-Back, no Write-Allocate");
- break;
- }
- switch (INNER) {
- case 0:
- LOG_INFO("inner: Non-Cacheable");
- break;
- case 1:
- LOG_INFO("inner: Strongly-ordered");
- break;
- case 3:
- LOG_INFO("inner: Device");
- break;
- case 5:
- LOG_INFO("inner: Write-Back, Write-Allocate");
- break;
- case 6:
- LOG_INFO("inner: Write-Through");
- break;
- case 7:
- LOG_INFO("inner: Write-Back, no Write-Allocate");
-
- default:
- LOG_INFO("inner: %" PRIx32 " ???", INNER);
- }
- }
-
-done:
- dpm->finish(dpm);
-
- return retval;
-}
-
-/* FIXME: remove it */
-static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
-{
- struct armv7a_l2x_cache *l2x_cache;
- struct target_list *head = target->head;
- struct target *curr;
-
- struct armv7a_common *armv7a = target_to_armv7a(target);
- l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache));
- l2x_cache->base = base;
- l2x_cache->way = way;
- /*LOG_INFO("cache l2 initialized base %x way %d",
- l2x_cache->base,l2x_cache->way);*/
- if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
- LOG_INFO("outer cache already initialized\n");
- armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
- /* initialize all target in this cluster (smp target)
- * l2 cache must be configured after smp declaration */
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if (curr != target) {
- armv7a = target_to_armv7a(curr);
- if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
- LOG_ERROR("smp target : outer cache already initialized\n");
- armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
- }
- head = head->next;
- }
- return JIM_OK;
-}
-
-/* FIXME: remove it */
-COMMAND_HANDLER(handle_cache_l2x)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t base, way;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
-
- /* AP address is in bits 31:24 of DP_SELECT */
- armv7a_l2x_cache_init(target, base, way);
-
- return ERROR_OK;
-}
-
-int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
- struct armv7a_cache_common *armv7a_cache)
-{
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a_cache->outer_cache);
-
- int cl;
-
- if (armv7a_cache->info == -1) {
- command_print(cmd_ctx, "cache not yet identified");
- return ERROR_OK;
- }
-
- for (cl = 0; cl < armv7a_cache->loc; cl++) {
- struct armv7a_arch_cache *arch = &(armv7a_cache->arch[cl]);
-
- if (arch->ctype & 1) {
- command_print(cmd_ctx,
- "L%d I-Cache: linelen %" PRIi32
- ", associativity %" PRIi32
- ", nsets %" PRIi32
- ", cachesize %" PRId32 " KBytes",
- cl+1,
- arch->i_size.linelen,
- arch->i_size.associativity,
- arch->i_size.nsets,
- arch->i_size.cachesize);
- }
-
- if (arch->ctype >= 2) {
- command_print(cmd_ctx,
- "L%d D-Cache: linelen %" PRIi32
- ", associativity %" PRIi32
- ", nsets %" PRIi32
- ", cachesize %" PRId32 " KBytes",
- cl+1,
- arch->d_u_size.linelen,
- arch->d_u_size.associativity,
- arch->d_u_size.nsets,
- arch->d_u_size.cachesize);
- }
- }
-
- if (l2x_cache != NULL)
- command_print(cmd_ctx, "Outer unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways",
- l2x_cache->base, l2x_cache->way);
-
- return ERROR_OK;
-}
-
-/* retrieve core id cluster id */
-static int armv7a_read_mpidr(struct target *target)
-{
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t mpidr;
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
- /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
-
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
- &mpidr);
- if (retval != ERROR_OK)
- goto done;
-
- /* ARMv7R uses a different format for MPIDR.
- * When configured uniprocessor (most R cores) it reads as 0.
- * This will need to be implemented for multiprocessor ARMv7R cores. */
- if (armv7a->is_armv7r) {
- if (mpidr)
- LOG_ERROR("MPIDR nonzero in ARMv7-R target");
- goto done;
- }
-
- if (mpidr & 1<<31) {
- armv7a->multi_processor_system = (mpidr >> 30) & 1;
- armv7a->cluster_id = (mpidr >> 8) & 0xf;
- armv7a->cpu_id = mpidr & 0x3;
- LOG_INFO("%s cluster %x core %x %s", target_name(target),
- armv7a->cluster_id,
- armv7a->cpu_id,
- armv7a->multi_processor_system == 0 ? "multi core" : "mono core");
-
- } else
- LOG_ERROR("MPIDR not in multiprocessor format");
-
-done:
- dpm->finish(dpm);
- return retval;
-
-
-}
-
-static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg)
-{
- int retval = ERROR_OK;
-
- /* select cache level */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 2, 0, 0, 0, 0),
- (cl << 1) | (ct == 1 ? 1 : 0));
- if (retval != ERROR_OK)
- goto done;
-
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
- cache_reg);
- done:
- return retval;
-}
-
-static struct armv7a_cachesize decode_cache_reg(uint32_t cache_reg)
-{
- struct armv7a_cachesize size;
- int i = 0;
-
- size.linelen = 16 << (cache_reg & 0x7);
- size.associativity = ((cache_reg >> 3) & 0x3ff) + 1;
- size.nsets = ((cache_reg >> 13) & 0x7fff) + 1;
- size.cachesize = size.linelen * size.associativity * size.nsets / 1024;
-
- /* compute info for set way operation on cache */
- size.index_shift = (cache_reg & 0x7) + 4;
- size.index = (cache_reg >> 13) & 0x7fff;
- size.way = ((cache_reg >> 3) & 0x3ff);
-
- while (((size.way << i) & 0x80000000) == 0)
- i++;
- size.way_shift = i;
-
- return size;
-}
-
-int armv7a_identify_cache(struct target *target)
-{
- /* read cache descriptor */
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- uint32_t csselr, clidr, ctr;
- uint32_t cache_reg;
- int cl, ctype;
- struct armv7a_cache_common *cache =
- &(armv7a->armv7a_mmu.armv7a_cache);
-
- if (!armv7a->is_armv7r)
- armv7a_read_ttbcr(target);
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- /* retrieve CTR
- * mrc p15, 0, r0, c0, c0, 1 @ read ctr */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 0, 0, 1),
- &ctr);
- if (retval != ERROR_OK)
- goto done;
-
- cache->iminline = 4UL << (ctr & 0xf);
- cache->dminline = 4UL << ((ctr & 0xf0000) >> 16);
- LOG_DEBUG("ctr %" PRIx32 " ctr.iminline %" PRId32 " ctr.dminline %" PRId32,
- ctr, cache->iminline, cache->dminline);
-
- /* retrieve CLIDR
- * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
- &clidr);
- if (retval != ERROR_OK)
- goto done;
-
- cache->loc = (clidr & 0x7000000) >> 24;
- LOG_DEBUG("Number of cache levels to PoC %" PRId32, cache->loc);
-
- /* retrieve selected cache for later restore
- * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
- &csselr);
- if (retval != ERROR_OK)
- goto done;
-
- /* retrieve all available inner caches */
- for (cl = 0; cl < cache->loc; clidr >>= 3, cl++) {
-
- /* isolate cache type at current level */
- ctype = clidr & 7;
-
- /* skip reserved values */
- if (ctype > CACHE_LEVEL_HAS_UNIFIED_CACHE)
- continue;
-
- /* separate d or unified d/i cache at this level ? */
- if (ctype & (CACHE_LEVEL_HAS_UNIFIED_CACHE | CACHE_LEVEL_HAS_D_CACHE)) {
- /* retrieve d-cache info */
- retval = get_cache_info(dpm, cl, 0, &cache_reg);
- if (retval != ERROR_OK)
- goto done;
- cache->arch[cl].d_u_size = decode_cache_reg(cache_reg);
-
- LOG_DEBUG("data/unified cache index %d << %d, way %d << %d",
- cache->arch[cl].d_u_size.index,
- cache->arch[cl].d_u_size.index_shift,
- cache->arch[cl].d_u_size.way,
- cache->arch[cl].d_u_size.way_shift);
-
- LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways",
- cache->arch[cl].d_u_size.linelen,
- cache->arch[cl].d_u_size.cachesize,
- cache->arch[cl].d_u_size.associativity);
- }
-
- /* separate i-cache at this level ? */
- if (ctype & CACHE_LEVEL_HAS_I_CACHE) {
- /* retrieve i-cache info */
- retval = get_cache_info(dpm, cl, 1, &cache_reg);
- if (retval != ERROR_OK)
- goto done;
- cache->arch[cl].i_size = decode_cache_reg(cache_reg);
-
- LOG_DEBUG("instruction cache index %d << %d, way %d << %d",
- cache->arch[cl].i_size.index,
- cache->arch[cl].i_size.index_shift,
- cache->arch[cl].i_size.way,
- cache->arch[cl].i_size.way_shift);
-
- LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways",
- cache->arch[cl].i_size.linelen,
- cache->arch[cl].i_size.cachesize,
- cache->arch[cl].i_size.associativity);
- }
-
- cache->arch[cl].ctype = ctype;
- }
-
- /* restore selected cache */
- dpm->instr_write_data_r0(dpm,
- ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
- csselr);
-
- if (retval != ERROR_OK)
- goto done;
-
- /* if no l2 cache initialize l1 data cache flush function function */
- if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL) {
- armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
- armv7a_cache_auto_flush_all_data;
- }
-
- armv7a->armv7a_mmu.armv7a_cache.info = 1;
-done:
- dpm->finish(dpm);
- armv7a_read_mpidr(target);
- return retval;
-
-}
-
-int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
-{
- struct arm *arm = &armv7a->arm;
- arm->arch_info = armv7a;
- target->arch_info = &armv7a->arm;
- /* target is useful in all function arm v4 5 compatible */
- armv7a->arm.target = target;
- armv7a->arm.common_magic = ARM_COMMON_MAGIC;
- armv7a->common_magic = ARMV7_COMMON_MAGIC;
- armv7a->armv7a_mmu.armv7a_cache.info = -1;
- armv7a->armv7a_mmu.armv7a_cache.outer_cache = NULL;
- armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL;
- armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = 1;
- return ERROR_OK;
-}
-
-int armv7a_arch_state(struct target *target)
-{
- static const char *state[] = {
- "disabled", "enabled"
- };
-
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
-
- if (armv7a->common_magic != ARMV7_COMMON_MAGIC) {
- LOG_ERROR("BUG: called for a non-ARMv7A target");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- arm_arch_state(target);
-
- if (armv7a->is_armv7r) {
- LOG_USER("D-Cache: %s, I-Cache: %s",
- state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
- state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
- } else {
- LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
- state[armv7a->armv7a_mmu.mmu_enabled],
- state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
- state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
- }
-
- if (arm->core_mode == ARM_MODE_ABT)
- armv7a_show_fault_registers(target);
- if (target->debug_reason == DBG_REASON_WATCHPOINT)
- LOG_USER("Watchpoint triggered at PC %#08x",
- (unsigned) armv7a->dpm.wp_pc);
-
- return ERROR_OK;
-}
-
-static const struct command_registration l2_cache_commands[] = {
- {
- .name = "l2x",
- .handler = handle_cache_l2x,
- .mode = COMMAND_EXEC,
- .help = "configure l2x cache "
- "",
- .usage = "[base_addr] [number_of_way]",
- },
- COMMAND_REGISTRATION_DONE
-
-};
-
-const struct command_registration l2x_cache_command_handlers[] = {
- {
- .name = "cache_config",
- .mode = COMMAND_EXEC,
- .help = "cache configuration for a target",
- .usage = "",
- .chain = l2_cache_commands,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration armv7a_command_handlers[] = {
- {
- .chain = dap_command_handlers,
- },
- {
- .chain = l2x_cache_command_handlers,
- },
- {
- .chain = arm7a_cache_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/armv7a.h b/src/target/armv7a.h
deleted file mode 100644
index 6461ba9..0000000
--- a/src/target/armv7a.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by David Brownell *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARMV7A_H
-#define OPENOCD_TARGET_ARMV7A_H
-
-#include "arm_adi_v5.h"
-#include "armv7a_cache.h"
-#include "arm.h"
-#include "armv4_5_mmu.h"
-#include "armv4_5_cache.h"
-#include "arm_dpm.h"
-
-enum {
- ARM_PC = 15,
- ARM_CPSR = 16
-};
-
-#define ARMV7_COMMON_MAGIC 0x0A450999
-
-/* VA to PA translation operations opc2 values*/
-#define V2PCWPR 0
-#define V2PCWPW 1
-#define V2PCWUR 2
-#define V2PCWUW 3
-#define V2POWPR 4
-#define V2POWPW 5
-#define V2POWUR 6
-#define V2POWUW 7
-/* L210/L220 cache controller support */
-struct armv7a_l2x_cache {
- uint32_t base;
- uint32_t way;
-};
-
-struct armv7a_cachesize {
- uint32_t level_num;
- /* cache dimensionning */
- uint32_t linelen;
- uint32_t associativity;
- uint32_t nsets;
- uint32_t cachesize;
- /* info for set way operation on cache */
- uint32_t index;
- uint32_t index_shift;
- uint32_t way;
- uint32_t way_shift;
-};
-
-/* information about one architecture cache at any level */
-struct armv7a_arch_cache {
- int ctype; /* cache type, CLIDR encoding */
- struct armv7a_cachesize d_u_size; /* data cache */
- struct armv7a_cachesize i_size; /* instruction cache */
-};
-
-/* common cache information */
-struct armv7a_cache_common {
- int info; /* -1 invalid, else valid */
- int loc; /* level of coherency */
- uint32_t dminline; /* minimum d-cache linelen */
- uint32_t iminline; /* minimum i-cache linelen */
- struct armv7a_arch_cache arch[6]; /* cache info, L1 - L7 */
- int i_cache_enabled;
- int d_u_cache_enabled;
- int auto_cache_enabled; /* openocd automatic
- * cache handling */
- /* outer unified cache if some */
- void *outer_cache;
- int (*flush_all_data_cache)(struct target *target);
-};
-
-struct armv7a_mmu_common {
- /* following field mmu working way */
- int32_t cached; /* 0: not initialized, 1: initialized */
- uint32_t ttbcr; /* cache for ttbcr register */
- uint32_t ttbr_mask[2];
- uint32_t ttbr_range[2];
-
- int (*read_physical_memory)(struct target *target, uint32_t address, uint32_t size,
- uint32_t count, uint8_t *buffer);
- struct armv7a_cache_common armv7a_cache;
- uint32_t mmu_enabled;
-};
-
-struct armv7a_common {
- struct arm arm;
- int common_magic;
- struct reg_cache *core_cache;
-
- /* Core Debug Unit */
- struct arm_dpm dpm;
- uint32_t debug_base;
- struct adiv5_ap *debug_ap;
- struct adiv5_ap *memory_ap;
- bool memory_ap_available;
- /* mdir */
- uint8_t multi_processor_system;
- uint8_t cluster_id;
- uint8_t cpu_id;
- bool is_armv7r;
- uint32_t rev;
- uint32_t partnum;
- uint32_t arch;
- uint32_t variant;
- uint32_t implementor;
-
- /* cache specific to V7 Memory Management Unit compatible with v4_5*/
- struct armv7a_mmu_common armv7a_mmu;
-
- int (*examine_debug_reason)(struct target *target);
- int (*post_debug_entry)(struct target *target);
-
- void (*pre_restore_context)(struct target *target);
-};
-
-static inline struct armv7a_common *
-target_to_armv7a(struct target *target)
-{
- return container_of(target->arch_info, struct armv7a_common, arm);
-}
-
-/* register offsets from armv7a.debug_base */
-
-/* See ARMv7a arch spec section C10.2 */
-#define CPUDBG_DIDR 0x000
-
-/* See ARMv7a arch spec section C10.3 */
-#define CPUDBG_WFAR 0x018
-/* PCSR at 0x084 -or- 0x0a0 -or- both ... based on flags in DIDR */
-#define CPUDBG_DSCR 0x088
-#define CPUDBG_DRCR 0x090
-#define CPUDBG_PRCR 0x310
-#define CPUDBG_PRSR 0x314
-
-/* See ARMv7a arch spec section C10.4 */
-#define CPUDBG_DTRRX 0x080
-#define CPUDBG_ITR 0x084
-#define CPUDBG_DTRTX 0x08c
-
-/* See ARMv7a arch spec section C10.5 */
-#define CPUDBG_BVR_BASE 0x100
-#define CPUDBG_BCR_BASE 0x140
-#define CPUDBG_WVR_BASE 0x180
-#define CPUDBG_WCR_BASE 0x1C0
-#define CPUDBG_VCR 0x01C
-
-/* See ARMv7a arch spec section C10.6 */
-#define CPUDBG_OSLAR 0x300
-#define CPUDBG_OSLSR 0x304
-#define CPUDBG_OSSRR 0x308
-#define CPUDBG_ECR 0x024
-
-/* See ARMv7a arch spec section C10.7 */
-#define CPUDBG_DSCCR 0x028
-#define CPUDBG_DSMCR 0x02C
-
-/* See ARMv7a arch spec section C10.8 */
-#define CPUDBG_AUTHSTATUS 0xFB8
-
-int armv7a_arch_state(struct target *target);
-int armv7a_identify_cache(struct target *target);
-int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a);
-int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
- uint32_t *val, int meminfo);
-int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val);
-
-int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
- struct armv7a_cache_common *armv7a_cache);
-
-extern const struct command_registration armv7a_command_handlers[];
-
-#endif /* OPENOCD_TARGET_ARMV7A_H */
diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c
deleted file mode 100644
index 7af3e6d..0000000
--- a/src/target/armv7a_cache.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Oleksij Rempel *
- * linux@rempel-privat.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "arm.h"
-#include "armv7a.h"
-#include "armv7a_cache.h"
-#include <helper/time_support.h>
-#include "arm_opcodes.h"
-
-static int armv7a_l1_d_cache_sanity_check(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("%s: target not halted", __func__);
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* check that cache data is on at target halt */
- if (!armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled) {
- LOG_DEBUG("data cache is not enabled");
- return ERROR_TARGET_INVALID;
- }
-
- return ERROR_OK;
-}
-
-static int armv7a_l1_i_cache_sanity_check(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("%s: target not halted", __func__);
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* check that cache data is on at target halt */
- if (!armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled) {
- LOG_DEBUG("instruction cache is not enabled");
- return ERROR_TARGET_INVALID;
- }
-
- return ERROR_OK;
-}
-
-static int armv7a_l1_d_cache_flush_level(struct arm_dpm *dpm, struct armv7a_cachesize *size, int cl)
-{
- int retval = ERROR_OK;
- int32_t c_way, c_index = size->index;
-
- LOG_DEBUG("cl %" PRId32, cl);
- do {
- c_way = size->way;
- do {
- uint32_t value = (c_index << size->index_shift)
- | (c_way << size->way_shift) | (cl << 1);
- /*
- * DCCISW - Clean and invalidate data cache
- * line by Set/Way.
- */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
- value);
- if (retval != ERROR_OK)
- goto done;
- c_way -= 1;
- } while (c_way >= 0);
- c_index -= 1;
- } while (c_index >= 0);
-
- done:
- return retval;
-}
-
-static int armv7a_l1_d_cache_clean_inval_all(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv7a_cache_common *cache = &(armv7a->armv7a_mmu.armv7a_cache);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- int cl;
- int retval;
-
- retval = armv7a_l1_d_cache_sanity_check(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- for (cl = 0; cl < cache->loc; cl++) {
- /* skip i-only caches */
- if (cache->arch[cl].ctype < CACHE_LEVEL_HAS_D_CACHE)
- continue;
-
- armv7a_l1_d_cache_flush_level(dpm, &cache->arch[cl].d_u_size, cl);
- }
-
- retval = dpm->finish(dpm);
- return retval;
-
-done:
- LOG_ERROR("clean invalidate failed");
- dpm->finish(dpm);
-
- return retval;
-}
-
-int armv7a_cache_auto_flush_all_data(struct target *target)
-{
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled)
- return ERROR_OK;
-
- if (target->smp) {
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if (curr->state == TARGET_HALTED)
- retval = armv7a_l1_d_cache_clean_inval_all(curr);
-
- head = head->next;
- }
- } else
- retval = armv7a_l1_d_cache_clean_inval_all(target);
-
- /* do outer cache flushing after inner caches have been flushed */
- retval = arm7a_l2x_flush_all_data(target);
-
- return retval;
-}
-
-
-int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt,
- uint32_t size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache;
- uint32_t linelen = armv7a_cache->dminline;
- uint32_t va_line, va_end;
- int retval;
-
- retval = armv7a_l1_d_cache_sanity_check(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- va_line = virt & (-linelen);
- va_end = virt + size;
-
- /* handle unaligned start */
- if (virt != va_line) {
- /* DCCIMVAC */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_line);
- if (retval != ERROR_OK)
- goto done;
- va_line += linelen;
- }
-
- /* handle unaligned end */
- if ((va_end & (linelen-1)) != 0) {
- va_end &= (-linelen);
- /* DCCIMVAC */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_end);
- if (retval != ERROR_OK)
- goto done;
- }
-
- while (va_line < va_end) {
- /* DCIMVAC - Invalidate data cache line by VA to PoC. */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 6, 1), va_line);
- if (retval != ERROR_OK)
- goto done;
- va_line += linelen;
- }
-
- dpm->finish(dpm);
- return retval;
-
-done:
- LOG_ERROR("d-cache invalidate failed");
- dpm->finish(dpm);
-
- return retval;
-}
-
-int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt,
- unsigned int size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache;
- uint32_t linelen = armv7a_cache->dminline;
- uint32_t va_line, va_end;
- int retval;
-
- retval = armv7a_l1_d_cache_sanity_check(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- va_line = virt & (-linelen);
- va_end = virt + size;
-
- while (va_line < va_end) {
- /* DCCMVAC - Data Cache Clean by MVA to PoC */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 10, 1), va_line);
- if (retval != ERROR_OK)
- goto done;
- va_line += linelen;
- }
-
- dpm->finish(dpm);
- return retval;
-
-done:
- LOG_ERROR("d-cache invalidate failed");
- dpm->finish(dpm);
-
- return retval;
-}
-
-int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt,
- unsigned int size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache;
- uint32_t linelen = armv7a_cache->dminline;
- uint32_t va_line, va_end;
- int retval;
-
- retval = armv7a_l1_d_cache_sanity_check(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- va_line = virt & (-linelen);
- va_end = virt + size;
-
- while (va_line < va_end) {
- /* DCCIMVAC */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_line);
- if (retval != ERROR_OK)
- goto done;
- va_line += linelen;
- }
-
- dpm->finish(dpm);
- return retval;
-
-done:
- LOG_ERROR("d-cache invalidate failed");
- dpm->finish(dpm);
-
- return retval;
-}
-
-int armv7a_l1_i_cache_inval_all(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- int retval;
-
- retval = armv7a_l1_i_cache_sanity_check(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- if (target->smp) {
- /* ICIALLUIS */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 1, 0), 0);
- } else {
- /* ICIALLU */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 0), 0);
- }
-
- if (retval != ERROR_OK)
- goto done;
-
- dpm->finish(dpm);
- return retval;
-
-done:
- LOG_ERROR("i-cache invalidate failed");
- dpm->finish(dpm);
-
- return retval;
-}
-
-int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt,
- uint32_t size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
- struct armv7a_cache_common *armv7a_cache =
- &armv7a->armv7a_mmu.armv7a_cache;
- uint32_t linelen = armv7a_cache->iminline;
- uint32_t va_line, va_end;
- int retval;
-
- retval = armv7a_l1_i_cache_sanity_check(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- va_line = virt & (-linelen);
- va_end = virt + size;
-
- while (va_line < va_end) {
- /* ICIMVAU - Invalidate instruction cache by VA to PoU. */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 1), va_line);
- if (retval != ERROR_OK)
- goto done;
- /* BPIMVA */
- retval = dpm->instr_write_data_r0(dpm,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 7), va_line);
- if (retval != ERROR_OK)
- goto done;
- va_line += linelen;
- }
- return retval;
-
-done:
- LOG_ERROR("i-cache invalidate failed");
- dpm->finish(dpm);
-
- return retval;
-}
-
-int armv7a_cache_flush_virt(struct target *target, uint32_t virt,
- uint32_t size)
-{
- armv7a_l1_d_cache_flush_virt(target, virt, size);
- armv7a_l2x_cache_flush_virt(target, virt, size);
-
- return ERROR_OK;
-}
-
-/*
- * We assume that target core was chosen correctly. It means if same data
- * was handled by two cores, other core will loose the changes. Since it
- * is impossible to know (FIXME) which core has correct data, keep in mind
- * that some kind of data lost or korruption is possible.
- * Possible scenario:
- * - core1 loaded and changed data on 0x12345678
- * - we halted target and modified same data on core0
- * - data on core1 will be lost.
- */
-int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt,
- uint32_t size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled)
- return ERROR_OK;
-
- return armv7a_cache_flush_virt(target, virt, size);
-}
-
-COMMAND_HANDLER(arm7a_l1_cache_info_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- return armv7a_handle_cache_info_command(CMD_CTX,
- &armv7a->armv7a_mmu.armv7a_cache);
-}
-
-COMMAND_HANDLER(armv7a_l1_d_cache_clean_inval_all_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- armv7a_l1_d_cache_clean_inval_all(target);
-
- return 0;
-}
-
-COMMAND_HANDLER(arm7a_l1_d_cache_inval_virt_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t virt, size;
-
- if (CMD_ARGC == 0 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
- else
- size = 1;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt);
-
- return armv7a_l1_d_cache_inval_virt(target, virt, size);
-}
-
-COMMAND_HANDLER(arm7a_l1_d_cache_clean_virt_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t virt, size;
-
- if (CMD_ARGC == 0 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
- else
- size = 1;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt);
-
- return armv7a_l1_d_cache_clean_virt(target, virt, size);
-}
-
-COMMAND_HANDLER(armv7a_i_cache_clean_inval_all_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- armv7a_l1_i_cache_inval_all(target);
-
- return 0;
-}
-
-COMMAND_HANDLER(arm7a_l1_i_cache_inval_virt_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t virt, size;
-
- if (CMD_ARGC == 0 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
- else
- size = 1;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt);
-
- return armv7a_l1_i_cache_inval_virt(target, virt, size);
-}
-
-COMMAND_HANDLER(arm7a_cache_disable_auto_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (CMD_ARGC == 0) {
- command_print(CMD_CTX, "auto cache is %s",
- armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled ? "enabled" : "disabled");
- return ERROR_OK;
- }
-
- if (CMD_ARGC == 1) {
- uint32_t set;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], set);
- armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = !!set;
- return ERROR_OK;
- }
-
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static const struct command_registration arm7a_l1_d_cache_commands[] = {
- {
- .name = "flush_all",
- .handler = armv7a_l1_d_cache_clean_inval_all_cmd,
- .mode = COMMAND_ANY,
- .help = "flush (clean and invalidate) complete l1 d-cache",
- .usage = "",
- },
- {
- .name = "inval",
- .handler = arm7a_l1_d_cache_inval_virt_cmd,
- .mode = COMMAND_ANY,
- .help = "invalidate l1 d-cache by virtual address offset and range size",
- .usage = "<virt_addr> [size]",
- },
- {
- .name = "clean",
- .handler = arm7a_l1_d_cache_clean_virt_cmd,
- .mode = COMMAND_ANY,
- .help = "clean l1 d-cache by virtual address address offset and range size",
- .usage = "<virt_addr> [size]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration arm7a_l1_i_cache_commands[] = {
- {
- .name = "inval_all",
- .handler = armv7a_i_cache_clean_inval_all_cmd,
- .mode = COMMAND_ANY,
- .help = "invalidate complete l1 i-cache",
- .usage = "",
- },
- {
- .name = "inval",
- .handler = arm7a_l1_i_cache_inval_virt_cmd,
- .mode = COMMAND_ANY,
- .help = "invalidate l1 i-cache by virtual address offset and range size",
- .usage = "<virt_addr> [size]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration arm7a_l1_di_cache_group_handlers[] = {
- {
- .name = "info",
- .handler = arm7a_l1_cache_info_cmd,
- .mode = COMMAND_ANY,
- .help = "print cache realted information",
- .usage = "",
- },
- {
- .name = "d",
- .mode = COMMAND_ANY,
- .help = "l1 d-cache command group",
- .usage = "",
- .chain = arm7a_l1_d_cache_commands,
- },
- {
- .name = "i",
- .mode = COMMAND_ANY,
- .help = "l1 i-cache command group",
- .usage = "",
- .chain = arm7a_l1_i_cache_commands,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration arm7a_cache_group_handlers[] = {
- {
- .name = "auto",
- .handler = arm7a_cache_disable_auto_cmd,
- .mode = COMMAND_ANY,
- .help = "disable or enable automatic cache handling.",
- .usage = "(1|0)",
- },
- {
- .name = "l1",
- .mode = COMMAND_ANY,
- .help = "l1 cache command group",
- .usage = "",
- .chain = arm7a_l1_di_cache_group_handlers,
- },
- {
- .chain = arm7a_l2x_cache_command_handler,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration arm7a_cache_command_handlers[] = {
- {
- .name = "cache",
- .mode = COMMAND_ANY,
- .help = "cache command group",
- .usage = "",
- .chain = arm7a_cache_group_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h
deleted file mode 100644
index e0f7eb3..0000000
--- a/src/target/armv7a_cache.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 Oleksij Rempel *
- * linux@rempel-privat.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM7A_CACHE_H
-#define OPENOCD_TARGET_ARM7A_CACHE_H
-
-#include "arm_jtag.h"
-#include "armv7a_cache_l2x.h"
-
-int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt,
- unsigned int size);
-int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt,
- unsigned int size);
-int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt,
- unsigned int size);
-int armv7a_l1_i_cache_inval_all(struct target *target);
-int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt,
- uint32_t size);
-int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt,
- uint32_t size);
-int armv7a_cache_auto_flush_all_data(struct target *target);
-int armv7a_cache_flush_virt(struct target *target, uint32_t virt,
- uint32_t size);
-extern const struct command_registration arm7a_cache_command_handlers[];
-
-/* CLIDR cache types */
-#define CACHE_LEVEL_HAS_UNIFIED_CACHE 0x4
-#define CACHE_LEVEL_HAS_D_CACHE 0x2
-#define CACHE_LEVEL_HAS_I_CACHE 0x1
-
-#endif /* OPENOCD_TARGET_ARM7A_CACHE_H */
diff --git a/src/target/armv7a_cache_l2x.c b/src/target/armv7a_cache_l2x.c
deleted file mode 100644
index 7988438..0000000
--- a/src/target/armv7a_cache_l2x.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Oleksij Rempel *
- * linux@rempel-privat.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "arm.h"
-#include "armv7a.h"
-#include "armv7a_cache.h"
-#include <helper/time_support.h>
-#include "target.h"
-#include "target_type.h"
-
-static int arm7a_l2x_sanity_check(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a->armv7a_mmu.armv7a_cache.outer_cache);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("%s: target not halted", __func__);
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!l2x_cache || !l2x_cache->base) {
- LOG_DEBUG("l2x is not configured!");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-/*
- * clean and invalidate complete l2x cache
- */
-int arm7a_l2x_flush_all_data(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a->armv7a_mmu.armv7a_cache.outer_cache);
- uint32_t l2_way_val;
- int retval;
-
- retval = arm7a_l2x_sanity_check(target);
- if (retval)
- return retval;
-
- l2_way_val = (1 << l2x_cache->way) - 1;
-
- return target_write_phys_memory(target,
- l2x_cache->base + L2X0_CLEAN_INV_WAY,
- 4, 1, (uint8_t *)&l2_way_val);
-}
-
-int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt,
- uint32_t size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a->armv7a_mmu.armv7a_cache.outer_cache);
- /* FIXME: different controllers have different linelen? */
- uint32_t i, linelen = 32;
- int retval;
-
- retval = arm7a_l2x_sanity_check(target);
- if (retval)
- return retval;
-
- for (i = 0; i < size; i += linelen) {
- uint32_t pa, offs = virt + i;
-
- /* FIXME: use less verbose virt2phys? */
- retval = target->type->virt2phys(target, offs, &pa);
- if (retval != ERROR_OK)
- goto done;
-
- retval = target_write_phys_memory(target,
- l2x_cache->base + L2X0_CLEAN_INV_LINE_PA,
- 4, 1, (uint8_t *)&pa);
- if (retval != ERROR_OK)
- goto done;
- }
- return retval;
-
-done:
- LOG_ERROR("d-cache invalidate failed");
-
- return retval;
-}
-
-static int armv7a_l2x_cache_inval_virt(struct target *target, uint32_t virt,
- uint32_t size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a->armv7a_mmu.armv7a_cache.outer_cache);
- /* FIXME: different controllers have different linelen */
- uint32_t i, linelen = 32;
- int retval;
-
- retval = arm7a_l2x_sanity_check(target);
- if (retval)
- return retval;
-
- for (i = 0; i < size; i += linelen) {
- uint32_t pa, offs = virt + i;
-
- /* FIXME: use less verbose virt2phys? */
- retval = target->type->virt2phys(target, offs, &pa);
- if (retval != ERROR_OK)
- goto done;
-
- retval = target_write_phys_memory(target,
- l2x_cache->base + L2X0_INV_LINE_PA,
- 4, 1, (uint8_t *)&pa);
- if (retval != ERROR_OK)
- goto done;
- }
- return retval;
-
-done:
- LOG_ERROR("d-cache invalidate failed");
-
- return retval;
-}
-
-static int armv7a_l2x_cache_clean_virt(struct target *target, uint32_t virt,
- unsigned int size)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a->armv7a_mmu.armv7a_cache.outer_cache);
- /* FIXME: different controllers have different linelen */
- uint32_t i, linelen = 32;
- int retval;
-
- retval = arm7a_l2x_sanity_check(target);
- if (retval)
- return retval;
-
- for (i = 0; i < size; i += linelen) {
- uint32_t pa, offs = virt + i;
-
- /* FIXME: use less verbose virt2phys? */
- retval = target->type->virt2phys(target, offs, &pa);
- if (retval != ERROR_OK)
- goto done;
-
- retval = target_write_phys_memory(target,
- l2x_cache->base + L2X0_CLEAN_LINE_PA,
- 4, 1, (uint8_t *)&pa);
- if (retval != ERROR_OK)
- goto done;
- }
- return retval;
-
-done:
- LOG_ERROR("d-cache invalidate failed");
-
- return retval;
-}
-
-static int arm7a_handle_l2x_cache_info_command(struct command_context *cmd_ctx,
- struct armv7a_cache_common *armv7a_cache)
-{
- struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
- (armv7a_cache->outer_cache);
-
- if (armv7a_cache->info == -1) {
- command_print(cmd_ctx, "cache not yet identified");
- return ERROR_OK;
- }
-
- command_print(cmd_ctx,
- "L2 unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways",
- l2x_cache->base, l2x_cache->way);
-
- return ERROR_OK;
-}
-
-static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
-{
- struct armv7a_l2x_cache *l2x_cache;
- struct target_list *head = target->head;
- struct target *curr;
-
- struct armv7a_common *armv7a = target_to_armv7a(target);
- if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) {
- LOG_ERROR("L2 cache was already initialised\n");
- return ERROR_FAIL;
- }
-
- l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache));
- l2x_cache->base = base;
- l2x_cache->way = way;
- armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
-
- /* initialize all targets in this cluster (smp target)
- * l2 cache must be configured after smp declaration */
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if (curr != target) {
- armv7a = target_to_armv7a(curr);
- if (armv7a->armv7a_mmu.armv7a_cache.outer_cache) {
- LOG_ERROR("smp target : cache l2 already initialized\n");
- return ERROR_FAIL;
- }
- armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
- }
- head = head->next;
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(arm7a_l2x_cache_info_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval;
-
- retval = arm7a_l2x_sanity_check(target);
- if (retval)
- return retval;
-
- return arm7a_handle_l2x_cache_info_command(CMD_CTX,
- &armv7a->armv7a_mmu.armv7a_cache);
-}
-
-COMMAND_HANDLER(arm7a_l2x_cache_flush_all_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- return arm7a_l2x_flush_all_data(target);
-}
-
-COMMAND_HANDLER(arm7a_l2x_cache_flush_virt_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t virt, size;
-
- if (CMD_ARGC == 0 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
- else
- size = 1;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt);
-
- return armv7a_l2x_cache_flush_virt(target, virt, size);
-}
-
-COMMAND_HANDLER(arm7a_l2x_cache_inval_virt_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t virt, size;
-
- if (CMD_ARGC == 0 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
- else
- size = 1;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt);
-
- return armv7a_l2x_cache_inval_virt(target, virt, size);
-}
-
-COMMAND_HANDLER(arm7a_l2x_cache_clean_virt_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t virt, size;
-
- if (CMD_ARGC == 0 || CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (CMD_ARGC == 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
- else
- size = 1;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt);
-
- return armv7a_l2x_cache_clean_virt(target, virt, size);
-}
-
-/* FIXME: should we configure way size? or controller type? */
-COMMAND_HANDLER(armv7a_l2x_cache_conf_cmd)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t base, way;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
-
- /* AP address is in bits 31:24 of DP_SELECT */
- return armv7a_l2x_cache_init(target, base, way);
-}
-
-static const struct command_registration arm7a_l2x_cache_commands[] = {
- {
- .name = "conf",
- .handler = armv7a_l2x_cache_conf_cmd,
- .mode = COMMAND_ANY,
- .help = "configure l2x cache ",
- .usage = "<base_addr> <number_of_way>",
- },
- {
- .name = "info",
- .handler = arm7a_l2x_cache_info_command,
- .mode = COMMAND_ANY,
- .help = "print cache realted information",
- .usage = "",
- },
- {
- .name = "flush_all",
- .handler = arm7a_l2x_cache_flush_all_command,
- .mode = COMMAND_ANY,
- .help = "flush complete l2x cache",
- .usage = "",
- },
- {
- .name = "flush",
- .handler = arm7a_l2x_cache_flush_virt_cmd,
- .mode = COMMAND_ANY,
- .help = "flush (clean and invalidate) l2x cache by virtual address offset and range size",
- .usage = "<virt_addr> [size]",
- },
- {
- .name = "inval",
- .handler = arm7a_l2x_cache_inval_virt_cmd,
- .mode = COMMAND_ANY,
- .help = "invalidate l2x cache by virtual address offset and range size",
- .usage = "<virt_addr> [size]",
- },
- {
- .name = "clean",
- .handler = arm7a_l2x_cache_clean_virt_cmd,
- .mode = COMMAND_ANY,
- .help = "clean l2x cache by virtual address address offset and range size",
- .usage = "<virt_addr> [size]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration arm7a_l2x_cache_command_handler[] = {
- {
- .name = "l2x",
- .mode = COMMAND_ANY,
- .help = "l2x cache command group",
- .usage = "",
- .chain = arm7a_l2x_cache_commands,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/armv7a_cache_l2x.h b/src/target/armv7a_cache_l2x.h
deleted file mode 100644
index 3d9ad81..0000000
--- a/src/target/armv7a_cache_l2x.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 Oleksij Rempel *
- * linux@rempel-privat.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARM7A_CACHE_L2X_H
-#define OPENOCD_TARGET_ARM7A_CACHE_L2X_H
-
-#define L2X0_CACHE_LINE_SIZE 32
-
-/* source: linux/arch/arm/include/asm/hardware/cache-l2x0.h */
-#define L2X0_CACHE_ID 0x000
-#define L2X0_CACHE_TYPE 0x004
-#define L2X0_CTRL 0x100
-#define L2X0_AUX_CTRL 0x104
-#define L2X0_TAG_LATENCY_CTRL 0x108
-#define L2X0_DATA_LATENCY_CTRL 0x10C
-#define L2X0_EVENT_CNT_CTRL 0x200
-#define L2X0_EVENT_CNT1_CFG 0x204
-#define L2X0_EVENT_CNT0_CFG 0x208
-#define L2X0_EVENT_CNT1_VAL 0x20C
-#define L2X0_EVENT_CNT0_VAL 0x210
-#define L2X0_INTR_MASK 0x214
-#define L2X0_MASKED_INTR_STAT 0x218
-#define L2X0_RAW_INTR_STAT 0x21C
-#define L2X0_INTR_CLEAR 0x220
-#define L2X0_CACHE_SYNC 0x730
-#define L2X0_DUMMY_REG 0x740
-#define L2X0_INV_LINE_PA 0x770
-#define L2X0_INV_WAY 0x77C
-#define L2X0_CLEAN_LINE_PA 0x7B0
-#define L2X0_CLEAN_LINE_IDX 0x7B8
-#define L2X0_CLEAN_WAY 0x7BC
-#define L2X0_CLEAN_INV_LINE_PA 0x7F0
-#define L2X0_CLEAN_INV_LINE_IDX 0x7F8
-#define L2X0_CLEAN_INV_WAY 0x7FC
-/*
- * The lockdown registers repeat 8 times for L310, the L210 has only one
- * D and one I lockdown register at 0x0900 and 0x0904.
- */
-#define L2X0_LOCKDOWN_WAY_D_BASE 0x900
-#define L2X0_LOCKDOWN_WAY_I_BASE 0x904
-#define L2X0_LOCKDOWN_STRIDE 0x08
-#define L2X0_ADDR_FILTER_START 0xC00
-#define L2X0_ADDR_FILTER_END 0xC04
-#define L2X0_TEST_OPERATION 0xF00
-#define L2X0_LINE_DATA 0xF10
-#define L2X0_LINE_TAG 0xF30
-#define L2X0_DEBUG_CTRL 0xF40
-#define L2X0_PREFETCH_CTRL 0xF60
-#define L2X0_POWER_CTRL 0xF80
-#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1)
-#define L2X0_STNDBY_MODE_EN (1 << 0)
-
-/* Registers shifts and masks */
-#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
-#define L2X0_CACHE_ID_PART_L210 (1 << 6)
-#define L2X0_CACHE_ID_PART_L310 (3 << 6)
-#define L2X0_CACHE_ID_RTL_MASK 0x3f
-#define L2X0_CACHE_ID_RTL_R0P0 0x0
-#define L2X0_CACHE_ID_RTL_R1P0 0x2
-#define L2X0_CACHE_ID_RTL_R2P0 0x4
-#define L2X0_CACHE_ID_RTL_R3P0 0x5
-#define L2X0_CACHE_ID_RTL_R3P1 0x6
-#define L2X0_CACHE_ID_RTL_R3P2 0x8
-
-#define L2X0_AUX_CTRL_MASK 0xc0000fff
-#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0
-#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7
-#define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3
-#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3)
-#define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6
-#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6)
-#define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9
-#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9)
-#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16
-#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17
-#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17)
-#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT 22
-#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT 26
-#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT 27
-#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28
-#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29
-#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30
-
-#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0
-#define L2X0_LATENCY_CTRL_RD_SHIFT 4
-#define L2X0_LATENCY_CTRL_WR_SHIFT 8
-
-#define L2X0_ADDR_FILTER_EN 1
-
-#define L2X0_CTRL_EN 1
-
-#define L2X0_WAY_SIZE_SHIFT 3
-
-struct l2x0_regs {
- unsigned long phy_base;
- unsigned long aux_ctrl;
- /*
- * Whether the following registers need to be saved/restored
- * depends on platform
- */
- unsigned long tag_latency;
- unsigned long data_latency;
- unsigned long filter_start;
- unsigned long filter_end;
- unsigned long prefetch_ctrl;
- unsigned long pwr_ctrl;
- unsigned long ctrl;
- unsigned long aux2_ctrl;
-};
-
-struct outer_cache_fns {
- void (*inv_range)(unsigned long, unsigned long);
- void (*clean_range)(unsigned long, unsigned long);
- void (*flush_range)(unsigned long, unsigned long);
- void (*flush_all)(void);
- void (*disable)(void);
-
- void (*resume)(void);
-
- /* This is an ARM L2C thing */
- void (*write_sec)(unsigned long, unsigned);
- void (*configure)(const struct l2x0_regs *);
-};
-
-struct l2c_init_data {
- const char *type;
- unsigned way_size_0;
- unsigned num_lock;
-
- void (*enable)(uint32_t, uint32_t, unsigned);
- void (*fixup)(uint32_t, uint32_t, struct outer_cache_fns *);
- void (*save)(uint32_t);
- void (*configure)(uint32_t);
- struct outer_cache_fns outer_cache;
-};
-
-extern const struct command_registration arm7a_l2x_cache_command_handler[];
-
-int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt,
- uint32_t size);
-int arm7a_l2x_flush_all_data(struct target *target);
-
-#endif /* OPENOCD_TARGET_ARM7A_CACHE_L2X_H */
diff --git a/src/target/armv7m.c b/src/target/armv7m.c
deleted file mode 100644
index e2f710f..0000000
--- a/src/target/armv7m.c
+++ /dev/null
@@ -1,829 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- * *
- * ARMv7-M Architecture, Application Level Reference Manual *
- * ARM DDI 0405C (September 2008) *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "armv7m.h"
-#include "algorithm.h"
-#include "register.h"
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-static const char * const armv7m_exception_strings[] = {
- "", "Reset", "NMI", "HardFault",
- "MemManage", "BusFault", "UsageFault", "RESERVED",
- "RESERVED", "RESERVED", "RESERVED", "SVCall",
- "DebugMonitor", "RESERVED", "PendSV", "SysTick"
-};
-
-/* PSP is used in some thread modes */
-const int armv7m_psp_reg_map[ARMV7M_NUM_CORE_REGS] = {
- ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
- ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
- ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
- ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
- ARMV7M_xPSR,
-};
-
-/* MSP is used in handler and some thread modes */
-const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = {
- ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
- ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
- ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
- ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
- ARMV7M_xPSR,
-};
-
-/*
- * These registers are not memory-mapped. The ARMv7-M profile includes
- * memory mapped registers too, such as for the NVIC (interrupt controller)
- * and SysTick (timer) modules; those can mostly be treated as peripherals.
- *
- * The ARMv6-M profile is almost identical in this respect, except that it
- * doesn't include basepri or faultmask registers.
- */
-static const struct {
- unsigned id;
- const char *name;
- unsigned bits;
- enum reg_type type;
- const char *group;
- const char *feature;
-} armv7m_regs[] = {
- { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" },
- { ARMV7M_xPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
-
- { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
- { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
-
- { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
- { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
- { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
- { ARMV7M_CONTROL, "control", 2, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
-
- { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
- { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
-
- { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" },
-};
-
-#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
-
-/**
- * Restores target context using the cache of core registers set up
- * by armv7m_build_reg_cache(), calling optional core-specific hooks.
- */
-int armv7m_restore_context(struct target *target)
-{
- int i;
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct reg_cache *cache = armv7m->arm.core_cache;
-
- LOG_DEBUG(" ");
-
- if (armv7m->pre_restore_context)
- armv7m->pre_restore_context(target);
-
- for (i = cache->num_regs - 1; i >= 0; i--) {
- if (cache->reg_list[i].dirty) {
- armv7m->arm.write_core_reg(target, &cache->reg_list[i], i,
- ARM_MODE_ANY, cache->reg_list[i].value);
- }
- }
-
- return ERROR_OK;
-}
-
-/* Core state functions */
-
-/**
- * Maps ISR number (from xPSR) to name.
- * Note that while names and meanings for the first sixteen are standardized
- * (with zero not a true exception), external interrupts are only numbered.
- * They are assigned by vendors, which generally assign different numbers to
- * peripherals (such as UART0 or a USB peripheral controller).
- */
-const char *armv7m_exception_string(int number)
-{
- static char enamebuf[32];
-
- if ((number < 0) | (number > 511))
- return "Invalid exception";
- if (number < 16)
- return armv7m_exception_strings[number];
- sprintf(enamebuf, "External Interrupt(%i)", number - 16);
- return enamebuf;
-}
-
-static int armv7m_get_core_reg(struct reg *reg)
-{
- int retval;
- struct arm_reg *armv7m_reg = reg->arch_info;
- struct target *target = armv7m_reg->target;
- struct arm *arm = target_to_arm(target);
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- retval = arm->read_core_reg(target, reg, armv7m_reg->num, arm->core_mode);
-
- return retval;
-}
-
-static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- struct arm_reg *armv7m_reg = reg->arch_info;
- struct target *target = armv7m_reg->target;
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- buf_cpy(buf, reg->value, reg->size);
- reg->dirty = 1;
- reg->valid = 1;
-
- return ERROR_OK;
-}
-
-static int armv7m_read_core_reg(struct target *target, struct reg *r,
- int num, enum arm_mode mode)
-{
- uint32_t reg_value;
- int retval;
- struct arm_reg *armv7m_core_reg;
- struct armv7m_common *armv7m = target_to_armv7m(target);
-
- assert(num < (int)armv7m->arm.core_cache->num_regs);
-
- armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
-
- if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) {
- /* map D0..D15 to S0..S31 */
- size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0);
- retval = armv7m->load_core_reg_u32(target, regidx, &reg_value);
- if (retval != ERROR_OK)
- return retval;
- buf_set_u32(armv7m->arm.core_cache->reg_list[num].value,
- 0, 32, reg_value);
- retval = armv7m->load_core_reg_u32(target, regidx + 1, &reg_value);
- if (retval != ERROR_OK)
- return retval;
- buf_set_u32(armv7m->arm.core_cache->reg_list[num].value + 4,
- 0, 32, reg_value);
- } else {
- retval = armv7m->load_core_reg_u32(target,
- armv7m_core_reg->num, &reg_value);
- if (retval != ERROR_OK)
- return retval;
- buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
- }
-
- armv7m->arm.core_cache->reg_list[num].valid = 1;
- armv7m->arm.core_cache->reg_list[num].dirty = 0;
-
- return retval;
-}
-
-static int armv7m_write_core_reg(struct target *target, struct reg *r,
- int num, enum arm_mode mode, uint8_t *value)
-{
- int retval;
- struct arm_reg *armv7m_core_reg;
- struct armv7m_common *armv7m = target_to_armv7m(target);
-
- assert(num < (int)armv7m->arm.core_cache->num_regs);
-
- armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
-
- if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) {
- /* map D0..D15 to S0..S31 */
- size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0);
-
- uint32_t t = buf_get_u32(value, 0, 32);
- retval = armv7m->store_core_reg_u32(target, regidx, t);
- if (retval != ERROR_OK)
- goto out_error;
-
- t = buf_get_u32(value + 4, 0, 32);
- retval = armv7m->store_core_reg_u32(target, regidx + 1, t);
- if (retval != ERROR_OK)
- goto out_error;
- } else {
- uint32_t t = buf_get_u32(value, 0, 32);
-
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, t);
- retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->num, t);
- if (retval != ERROR_OK)
- goto out_error;
- }
-
- armv7m->arm.core_cache->reg_list[num].valid = 1;
- armv7m->arm.core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-
-out_error:
- LOG_ERROR("Error setting register");
- armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
- return ERROR_JTAG_DEVICE_ERROR;
-}
-
-/**
- * Returns generic ARM userspace registers to GDB.
- */
-int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
- int *reg_list_size, enum target_register_class reg_class)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- int i;
-
- if (reg_class == REG_CLASS_ALL)
- *reg_list_size = armv7m->arm.core_cache->num_regs;
- else
- *reg_list_size = ARMV7M_NUM_CORE_REGS;
-
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
- if (*reg_list == NULL)
- return ERROR_FAIL;
-
- for (i = 0; i < *reg_list_size; i++)
- (*reg_list)[i] = &armv7m->arm.core_cache->reg_list[i];
-
- return ERROR_OK;
-}
-
-/** Runs a Thumb algorithm in the target. */
-int armv7m_run_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info)
-{
- int retval;
-
- retval = armv7m_start_algorithm(target,
- num_mem_params, mem_params,
- num_reg_params, reg_params,
- entry_point, exit_point,
- arch_info);
-
- if (retval == ERROR_OK)
- retval = armv7m_wait_algorithm(target,
- num_mem_params, mem_params,
- num_reg_params, reg_params,
- exit_point, timeout_ms,
- arch_info);
-
- return retval;
-}
-
-/** Starts a Thumb algorithm in the target. */
-int armv7m_start_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- void *arch_info)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
- enum arm_mode core_mode = armv7m->arm.core_mode;
- int retval = ERROR_OK;
-
- /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
- * at the exit point */
-
- if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
- LOG_ERROR("current target isn't an ARMV7M target");
- return ERROR_TARGET_INVALID;
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* refresh core register cache
- * Not needed if core register cache is always consistent with target process state */
- for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) {
-
- armv7m_algorithm_info->context[i] = buf_get_u32(
- armv7m->arm.core_cache->reg_list[i].value,
- 0,
- 32);
- }
-
- for (int i = 0; i < num_mem_params; i++) {
- /* TODO: Write only out params */
- retval = target_write_buffer(target, mem_params[i].address,
- mem_params[i].size,
- mem_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- for (int i = 0; i < num_reg_params; i++) {
- struct reg *reg =
- register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0);
-/* uint32_t regvalue; */
-
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
-/* regvalue = buf_get_u32(reg_params[i].value, 0, 32); */
- armv7m_set_core_reg(reg, reg_params[i].value);
- }
-
- if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
- armv7m_algorithm_info->core_mode != core_mode) {
-
- /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */
- if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) {
- armv7m_algorithm_info->core_mode = ARM_MODE_THREAD;
- LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead");
- }
-
- LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
- buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
- 0, 1, armv7m_algorithm_info->core_mode);
- armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
- armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
- }
-
- /* save previous core mode */
- armv7m_algorithm_info->core_mode = core_mode;
-
- retval = target_resume(target, 0, entry_point, 1, 1);
-
- return retval;
-}
-
-/** Waits for an algorithm in the target. */
-int armv7m_wait_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t exit_point, int timeout_ms,
- void *arch_info)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
- int retval = ERROR_OK;
- uint32_t pc;
-
- /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
- * at the exit point */
-
- if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
- LOG_ERROR("current target isn't an ARMV7M target");
- return ERROR_TARGET_INVALID;
- }
-
- retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
- /* If the target fails to halt due to the breakpoint, force a halt */
- if (retval != ERROR_OK || target->state != TARGET_HALTED) {
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- retval = target_wait_state(target, TARGET_HALTED, 500);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_TARGET_TIMEOUT;
- }
-
- armv7m->load_core_reg_u32(target, 15, &pc);
- if (exit_point && (pc != exit_point)) {
- LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32,
- pc,
- exit_point);
- return ERROR_TARGET_TIMEOUT;
- }
-
- /* Read memory values to mem_params[] */
- for (int i = 0; i < num_mem_params; i++) {
- if (mem_params[i].direction != PARAM_OUT) {
- retval = target_read_buffer(target, mem_params[i].address,
- mem_params[i].size,
- mem_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- /* Copy core register values to reg_params[] */
- for (int i = 0; i < num_reg_params; i++) {
- if (reg_params[i].direction != PARAM_OUT) {
- struct reg *reg = register_get_by_name(armv7m->arm.core_cache,
- reg_params[i].reg_name,
- 0);
-
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR(
- "BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
- }
- }
-
- for (int i = armv7m->arm.core_cache->num_regs - 1; i >= 0; i--) {
- uint32_t regvalue;
- regvalue = buf_get_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32);
- if (regvalue != armv7m_algorithm_info->context[i]) {
- LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
- armv7m->arm.core_cache->reg_list[i].name,
- armv7m_algorithm_info->context[i]);
- buf_set_u32(armv7m->arm.core_cache->reg_list[i].value,
- 0, 32, armv7m_algorithm_info->context[i]);
- armv7m->arm.core_cache->reg_list[i].valid = 1;
- armv7m->arm.core_cache->reg_list[i].dirty = 1;
- }
- }
-
- /* restore previous core mode */
- if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) {
- LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
- buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
- 0, 1, armv7m_algorithm_info->core_mode);
- armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
- armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
- }
-
- armv7m->arm.core_mode = armv7m_algorithm_info->core_mode;
-
- return retval;
-}
-
-/** Logs summary of ARMv7-M state for a halted target. */
-int armv7m_arch_state(struct target *target)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct arm *arm = &armv7m->arm;
- uint32_t ctrl, sp;
-
- ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
- sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
-
- LOG_USER("target halted due to %s, current mode: %s %s\n"
- "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s",
- debug_reason_name(target),
- arm_mode_name(arm->core_mode),
- armv7m_exception_string(armv7m->exception_number),
- buf_get_u32(arm->cpsr->value, 0, 32),
- buf_get_u32(arm->pc->value, 0, 32),
- (ctrl & 0x02) ? 'p' : 'm',
- sp,
- arm->is_semihosting ? ", semihosting" : "");
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type armv7m_reg_type = {
- .get = armv7m_get_core_reg,
- .set = armv7m_set_core_reg,
-};
-
-/** Builds cache of architecturally defined registers. */
-struct reg_cache *armv7m_build_reg_cache(struct target *target)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct arm *arm = &armv7m->arm;
- int num_regs = ARMV7M_NUM_REGS;
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct reg_cache *cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
- struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
- struct reg_feature *feature;
- int i;
-
- /* Build the process context cache */
- cache->name = "arm v7m registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = num_regs;
- (*cache_p) = cache;
-
- for (i = 0; i < num_regs; i++) {
- arch_info[i].num = armv7m_regs[i].id;
- arch_info[i].target = target;
- arch_info[i].arm = arm;
-
- reg_list[i].name = armv7m_regs[i].name;
- reg_list[i].size = armv7m_regs[i].bits;
- size_t storage_size = DIV_ROUND_UP(armv7m_regs[i].bits, 8);
- if (storage_size < 4)
- storage_size = 4;
- reg_list[i].value = calloc(1, storage_size);
- reg_list[i].dirty = 0;
- reg_list[i].valid = 0;
- reg_list[i].type = &armv7m_reg_type;
- reg_list[i].arch_info = &arch_info[i];
-
- reg_list[i].group = armv7m_regs[i].group;
- reg_list[i].number = i;
- reg_list[i].exist = true;
- reg_list[i].caller_save = true; /* gdb defaults to true */
-
- feature = calloc(1, sizeof(struct reg_feature));
- if (feature) {
- feature->name = armv7m_regs[i].feature;
- reg_list[i].feature = feature;
- } else
- LOG_ERROR("unable to allocate feature list");
-
- reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
- if (reg_list[i].reg_data_type)
- reg_list[i].reg_data_type->type = armv7m_regs[i].type;
- else
- LOG_ERROR("unable to allocate reg type list");
- }
-
- arm->cpsr = reg_list + ARMV7M_xPSR;
- arm->pc = reg_list + ARMV7M_PC;
- arm->core_cache = cache;
-
- return cache;
-}
-
-void armv7m_free_reg_cache(struct target *target)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct arm *arm = &armv7m->arm;
- struct reg_cache *cache;
- struct reg *reg;
- unsigned int i;
-
- cache = arm->core_cache;
-
- if (!cache)
- return;
-
- for (i = 0; i < cache->num_regs; i++) {
- reg = &cache->reg_list[i];
-
- free(reg->feature);
- free(reg->reg_data_type);
- free(reg->value);
- }
-
- free(cache->reg_list[0].arch_info);
- free(cache->reg_list);
- free(cache);
-
- arm->core_cache = NULL;
-}
-
-static int armv7m_setup_semihosting(struct target *target, int enable)
-{
- /* nothing todo for armv7m */
- return ERROR_OK;
-}
-
-/** Sets up target as a generic ARMv7-M core */
-int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
-{
- struct arm *arm = &armv7m->arm;
-
- armv7m->common_magic = ARMV7M_COMMON_MAGIC;
- armv7m->fp_feature = FP_NONE;
- armv7m->trace_config.trace_bus_id = 1;
- /* Enable stimulus port #0 by default */
- armv7m->trace_config.itm_ter[0] = 1;
-
- arm->core_type = ARM_MODE_THREAD;
- arm->arch_info = armv7m;
- arm->setup_semihosting = armv7m_setup_semihosting;
-
- arm->read_core_reg = armv7m_read_core_reg;
- arm->write_core_reg = armv7m_write_core_reg;
-
- return arm_init_arch_info(target, arm);
-}
-
-/** Generates a CRC32 checksum of a memory region. */
-int armv7m_checksum_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *checksum)
-{
- struct working_area *crc_algorithm;
- struct armv7m_algorithm armv7m_info;
- struct reg_param reg_params[2];
- int retval;
-
- static const uint8_t cortex_m_crc_code[] = {
-#include "../../contrib/loaders/checksum/armv7m_crc.inc"
- };
-
- retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_buffer(target, crc_algorithm->address,
- sizeof(cortex_m_crc_code), (uint8_t *)cortex_m_crc_code);
- if (retval != ERROR_OK)
- goto cleanup;
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-
- buf_set_u32(reg_params[0].value, 0, 32, address);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- int timeout = 20000 * (1 + (count / (1024 * 1024)));
-
- retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
- crc_algorithm->address + (sizeof(cortex_m_crc_code) - 6),
- timeout, &armv7m_info);
-
- if (retval == ERROR_OK)
- *checksum = buf_get_u32(reg_params[0].value, 0, 32);
- else
- LOG_ERROR("error executing cortex_m crc algorithm");
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
-
-cleanup:
- target_free_working_area(target, crc_algorithm);
-
- return retval;
-}
-
-/** Checks whether a memory region is zeroed. */
-int armv7m_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank)
-{
- struct working_area *erase_check_algorithm;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
- int retval;
-
- static const uint8_t erase_check_code[] = {
-#include "../../contrib/loaders/erase_check/armv7m_erase_check.inc"
- };
-
- /* make sure we have a working area */
- if (target_alloc_working_area(target, sizeof(erase_check_code),
- &erase_check_algorithm) != ERROR_OK)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- retval = target_write_buffer(target, erase_check_algorithm->address,
- sizeof(erase_check_code), (uint8_t *)erase_check_code);
- if (retval != ERROR_OK)
- goto cleanup;
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
- buf_set_u32(reg_params[0].value, 0, 32, address);
-
- init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
- buf_set_u32(reg_params[2].value, 0, 32, 0xff);
-
- retval = target_run_algorithm(target,
- 0,
- NULL,
- 3,
- reg_params,
- erase_check_algorithm->address,
- erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
- 10000,
- &armv7m_info);
-
- if (retval == ERROR_OK)
- *blank = buf_get_u32(reg_params[2].value, 0, 32);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
-cleanup:
- target_free_working_area(target, erase_check_algorithm);
-
- return retval;
-}
-
-int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct reg *r = armv7m->arm.pc;
- bool result = false;
-
-
- /* if we halted last time due to a bkpt instruction
- * then we have to manually step over it, otherwise
- * the core will break again */
-
- if (target->debug_reason == DBG_REASON_BREAKPOINT) {
- uint16_t op;
- uint32_t pc = buf_get_u32(r->value, 0, 32);
-
- pc &= ~1;
- if (target_read_u16(target, pc, &op) == ERROR_OK) {
- if ((op & 0xFF00) == 0xBE00) {
- pc = buf_get_u32(r->value, 0, 32) + 2;
- buf_set_u32(r->value, 0, 32, pc);
- r->dirty = true;
- r->valid = true;
- result = true;
- LOG_DEBUG("Skipping over BKPT instruction");
- }
- }
- }
-
- if (inst_found)
- *inst_found = result;
-
- return ERROR_OK;
-}
-
-const struct command_registration armv7m_command_handlers[] = {
- {
- .chain = arm_command_handlers,
- },
- {
- .chain = dap_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/armv7m.h b/src/target/armv7m.h
deleted file mode 100644
index 90cad00..0000000
--- a/src/target/armv7m.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARMV7M_H
-#define OPENOCD_TARGET_ARMV7M_H
-
-#include "arm_adi_v5.h"
-#include "arm.h"
-#include "armv7m_trace.h"
-
-extern const int armv7m_psp_reg_map[];
-extern const int armv7m_msp_reg_map[];
-
-const char *armv7m_exception_string(int number);
-
-/* offsets into armv7m core register cache */
-enum {
- /* for convenience, the first set of indices match
- * the Cortex-M3/-M4 DCRSR selectors
- */
- ARMV7M_R0,
- ARMV7M_R1,
- ARMV7M_R2,
- ARMV7M_R3,
-
- ARMV7M_R4,
- ARMV7M_R5,
- ARMV7M_R6,
- ARMV7M_R7,
-
- ARMV7M_R8,
- ARMV7M_R9,
- ARMV7M_R10,
- ARMV7M_R11,
-
- ARMV7M_R12,
- ARMV7M_R13,
- ARMV7M_R14,
- ARMV7M_PC = 15,
-
- ARMV7M_xPSR = 16,
- ARMV7M_MSP,
- ARMV7M_PSP,
-
- /* this next set of indices is arbitrary */
- ARMV7M_PRIMASK,
- ARMV7M_BASEPRI,
- ARMV7M_FAULTMASK,
- ARMV7M_CONTROL,
-
- /* 32bit Floating-point registers */
- ARMV7M_S0,
- ARMV7M_S1,
- ARMV7M_S2,
- ARMV7M_S3,
- ARMV7M_S4,
- ARMV7M_S5,
- ARMV7M_S6,
- ARMV7M_S7,
- ARMV7M_S8,
- ARMV7M_S9,
- ARMV7M_S10,
- ARMV7M_S11,
- ARMV7M_S12,
- ARMV7M_S13,
- ARMV7M_S14,
- ARMV7M_S15,
- ARMV7M_S16,
- ARMV7M_S17,
- ARMV7M_S18,
- ARMV7M_S19,
- ARMV7M_S20,
- ARMV7M_S21,
- ARMV7M_S22,
- ARMV7M_S23,
- ARMV7M_S24,
- ARMV7M_S25,
- ARMV7M_S26,
- ARMV7M_S27,
- ARMV7M_S28,
- ARMV7M_S29,
- ARMV7M_S30,
- ARMV7M_S31,
-
- /* 64bit Floating-point registers */
- ARMV7M_D0,
- ARMV7M_D1,
- ARMV7M_D2,
- ARMV7M_D3,
- ARMV7M_D4,
- ARMV7M_D5,
- ARMV7M_D6,
- ARMV7M_D7,
- ARMV7M_D8,
- ARMV7M_D9,
- ARMV7M_D10,
- ARMV7M_D11,
- ARMV7M_D12,
- ARMV7M_D13,
- ARMV7M_D14,
- ARMV7M_D15,
-
- /* Floating-point status registers */
- ARMV7M_FPSID,
- ARMV7M_FPSCR,
- ARMV7M_FPEXC,
-
- ARMV7M_LAST_REG,
-};
-
-enum {
- FP_NONE = 0,
- FPv4_SP,
- FPv5_SP,
- FPv5_DP,
-};
-
-#define ARMV7M_NUM_CORE_REGS (ARMV7M_xPSR + 1)
-#define ARMV7M_NUM_CORE_REGS_NOFP (ARMV7M_NUM_CORE_REGS + 6)
-
-#define ARMV7M_COMMON_MAGIC 0x2A452A45
-
-struct armv7m_common {
- struct arm arm;
-
- int common_magic;
- int exception_number;
-
- /* AP this processor is connected to in the DAP */
- struct adiv5_ap *debug_ap;
-
- int fp_feature;
- uint32_t demcr;
-
- /* stlink is a high level adapter, does not support all functions */
- bool stlink;
-
- struct armv7m_trace_config trace_config;
-
- /* Direct processor core register read and writes */
- int (*load_core_reg_u32)(struct target *target, uint32_t num, uint32_t *value);
- int (*store_core_reg_u32)(struct target *target, uint32_t num, uint32_t value);
-
- int (*examine_debug_reason)(struct target *target);
- int (*post_debug_entry)(struct target *target);
-
- void (*pre_restore_context)(struct target *target);
-};
-
-static inline struct armv7m_common *
-target_to_armv7m(struct target *target)
-{
- return container_of(target->arch_info, struct armv7m_common, arm);
-}
-
-static inline bool is_armv7m(struct armv7m_common *armv7m)
-{
- return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
-}
-
-struct armv7m_algorithm {
- int common_magic;
-
- enum arm_mode core_mode;
-
- uint32_t context[ARMV7M_LAST_REG]; /* ARMV7M_NUM_REGS */
-};
-
-struct reg_cache *armv7m_build_reg_cache(struct target *target);
-void armv7m_free_reg_cache(struct target *target);
-
-enum armv7m_mode armv7m_number_to_mode(int number);
-int armv7m_mode_to_number(enum armv7m_mode mode);
-
-int armv7m_arch_state(struct target *target);
-int armv7m_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class);
-
-int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m);
-
-int armv7m_run_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info);
-
-int armv7m_start_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- void *arch_info);
-
-int armv7m_wait_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t exit_point, int timeout_ms,
- void *arch_info);
-
-int armv7m_invalidate_core_regs(struct target *target);
-
-int armv7m_restore_context(struct target *target);
-
-int armv7m_checksum_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *checksum);
-int armv7m_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank);
-
-int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found);
-
-extern const struct command_registration armv7m_command_handlers[];
-
-#endif /* OPENOCD_TARGET_ARMV7M_H */
diff --git a/src/target/armv7m_trace.c b/src/target/armv7m_trace.c
deleted file mode 100644
index c1e4f5b..0000000
--- a/src/target/armv7m_trace.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 Paul Fertser <fercerpav@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <target/target.h>
-#include <target/armv7m.h>
-#include <target/cortex_m.h>
-#include <target/armv7m_trace.h>
-#include <jtag/interface.h>
-
-#define TRACE_BUF_SIZE 4096
-
-static int armv7m_poll_trace(void *target)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- uint8_t buf[TRACE_BUF_SIZE];
- size_t size = sizeof(buf);
- int retval;
-
- retval = adapter_poll_trace(buf, &size);
- if (retval != ERROR_OK || !size)
- return retval;
-
- target_call_trace_callbacks(target, size, buf);
-
- if (armv7m->trace_config.trace_file != NULL) {
- if (fwrite(buf, 1, size, armv7m->trace_config.trace_file) == size)
- fflush(armv7m->trace_config.trace_file);
- else {
- LOG_ERROR("Error writing to the trace destination file");
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-int armv7m_trace_tpiu_config(struct target *target)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct armv7m_trace_config *trace_config = &armv7m->trace_config;
- int prescaler;
- int retval;
-
- target_unregister_timer_callback(armv7m_poll_trace, target);
-
-
- retval = adapter_config_trace(trace_config->config_type == INTERNAL,
- trace_config->pin_protocol,
- trace_config->port_size,
- &trace_config->trace_freq);
- if (retval != ERROR_OK)
- return retval;
-
- if (!trace_config->trace_freq) {
- LOG_ERROR("Trace port frequency is 0, can't enable TPIU");
- return ERROR_FAIL;
- }
-
- prescaler = trace_config->traceclkin_freq / trace_config->trace_freq;
-
- if (trace_config->traceclkin_freq % trace_config->trace_freq) {
- prescaler++;
- int trace_freq = trace_config->traceclkin_freq / prescaler;
- LOG_INFO("Can not obtain %u trace port frequency from %u TRACECLKIN frequency, using %u instead",
- trace_config->trace_freq, trace_config->traceclkin_freq,
- trace_freq);
- trace_config->trace_freq = trace_freq;
- retval = adapter_config_trace(trace_config->config_type == INTERNAL,
- trace_config->pin_protocol,
- trace_config->port_size,
- &trace_config->trace_freq);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = target_write_u32(target, TPIU_CSPSR, 1 << trace_config->port_size);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, TPIU_ACPR, prescaler - 1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_write_u32(target, TPIU_SPPR, trace_config->pin_protocol);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t ffcr;
- retval = target_read_u32(target, TPIU_FFCR, &ffcr);
- if (retval != ERROR_OK)
- return retval;
- if (trace_config->formatter)
- ffcr |= (1 << 1);
- else
- ffcr &= ~(1 << 1);
- retval = target_write_u32(target, TPIU_FFCR, ffcr);
- if (retval != ERROR_OK)
- return retval;
-
- if (trace_config->config_type == INTERNAL)
- target_register_timer_callback(armv7m_poll_trace, 1, 1, target);
-
- target_call_event_callbacks(target, TARGET_EVENT_TRACE_CONFIG);
-
- return ERROR_OK;
-}
-
-int armv7m_trace_itm_config(struct target *target)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct armv7m_trace_config *trace_config = &armv7m->trace_config;
- int retval;
-
- retval = target_write_u32(target, ITM_LAR, ITM_LAR_KEY);
- if (retval != ERROR_OK)
- return retval;
-
- /* Enable ITM, TXENA, set TraceBusID and other parameters */
- retval = target_write_u32(target, ITM_TCR, (1 << 0) | (1 << 3) |
- (trace_config->itm_diff_timestamps << 1) |
- (trace_config->itm_synchro_packets << 2) |
- (trace_config->itm_async_timestamps << 4) |
- (trace_config->itm_ts_prescale << 8) |
- (trace_config->trace_bus_id << 16));
- if (retval != ERROR_OK)
- return retval;
-
- for (unsigned int i = 0; i < 8; i++) {
- retval = target_write_u32(target, ITM_TER0 + i * 4,
- trace_config->itm_ter[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static void close_trace_file(struct armv7m_common *armv7m)
-{
- if (armv7m->trace_config.trace_file)
- fclose(armv7m->trace_config.trace_file);
- armv7m->trace_config.trace_file = NULL;
-}
-
-COMMAND_HANDLER(handle_tpiu_config_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7m_common *armv7m = target_to_armv7m(target);
-
- unsigned int cmd_idx = 0;
-
- if (CMD_ARGC == cmd_idx)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (!strcmp(CMD_ARGV[cmd_idx], "disable")) {
- if (CMD_ARGC == cmd_idx + 1) {
- close_trace_file(armv7m);
-
- armv7m->trace_config.config_type = DISABLED;
- if (CMD_CTX->mode == COMMAND_EXEC)
- return armv7m_trace_tpiu_config(target);
- else
- return ERROR_OK;
- }
- } else if (!strcmp(CMD_ARGV[cmd_idx], "external") ||
- !strcmp(CMD_ARGV[cmd_idx], "internal")) {
- close_trace_file(armv7m);
-
- armv7m->trace_config.config_type = EXTERNAL;
- if (!strcmp(CMD_ARGV[cmd_idx], "internal")) {
- cmd_idx++;
- if (CMD_ARGC == cmd_idx)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- armv7m->trace_config.config_type = INTERNAL;
-
- if (strcmp(CMD_ARGV[cmd_idx], "-") != 0) {
- armv7m->trace_config.trace_file = fopen(CMD_ARGV[cmd_idx], "ab");
- if (!armv7m->trace_config.trace_file) {
- LOG_ERROR("Can't open trace destination file");
- return ERROR_FAIL;
- }
- }
- }
- cmd_idx++;
- if (CMD_ARGC == cmd_idx)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (!strcmp(CMD_ARGV[cmd_idx], "sync")) {
- armv7m->trace_config.pin_protocol = SYNC;
-
- cmd_idx++;
- if (CMD_ARGC == cmd_idx)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[cmd_idx], armv7m->trace_config.port_size);
- } else {
- if (!strcmp(CMD_ARGV[cmd_idx], "manchester"))
- armv7m->trace_config.pin_protocol = ASYNC_MANCHESTER;
- else if (!strcmp(CMD_ARGV[cmd_idx], "uart"))
- armv7m->trace_config.pin_protocol = ASYNC_UART;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- cmd_idx++;
- if (CMD_ARGC == cmd_idx)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_ON_OFF(CMD_ARGV[cmd_idx], armv7m->trace_config.formatter);
- }
-
- cmd_idx++;
- if (CMD_ARGC == cmd_idx)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[cmd_idx], armv7m->trace_config.traceclkin_freq);
-
- cmd_idx++;
- if (CMD_ARGC != cmd_idx) {
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[cmd_idx], armv7m->trace_config.trace_freq);
- cmd_idx++;
- } else {
- if (armv7m->trace_config.config_type != INTERNAL) {
- LOG_ERROR("Trace port frequency can't be omitted in external capture mode");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- armv7m->trace_config.trace_freq = 0;
- }
-
- if (CMD_ARGC == cmd_idx) {
- if (CMD_CTX->mode == COMMAND_EXEC)
- return armv7m_trace_tpiu_config(target);
- else
- return ERROR_OK;
- }
- }
-
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-COMMAND_HANDLER(handle_itm_port_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- unsigned int reg_idx;
- uint8_t port;
- bool enable;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], port);
- COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
- reg_idx = port / 32;
- port = port % 32;
- if (enable)
- armv7m->trace_config.itm_ter[reg_idx] |= (1 << port);
- else
- armv7m->trace_config.itm_ter[reg_idx] &= ~(1 << port);
-
- if (CMD_CTX->mode == COMMAND_EXEC)
- return armv7m_trace_itm_config(target);
- else
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_itm_ports_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- bool enable;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
- memset(armv7m->trace_config.itm_ter, enable ? 0xff : 0,
- sizeof(armv7m->trace_config.itm_ter));
-
- if (CMD_CTX->mode == COMMAND_EXEC)
- return armv7m_trace_itm_config(target);
- else
- return ERROR_OK;
-}
-
-static const struct command_registration tpiu_command_handlers[] = {
- {
- .name = "config",
- .handler = handle_tpiu_config_command,
- .mode = COMMAND_ANY,
- .help = "Configure TPIU features",
- .usage = "(disable | "
- "((external | internal <filename>) "
- "(sync <port width> | ((manchester | uart) <formatter enable>)) "
- "<TRACECLKIN freq> [<trace freq>]))",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration itm_command_handlers[] = {
- {
- .name = "port",
- .handler = handle_itm_port_command,
- .mode = COMMAND_ANY,
- .help = "Enable or disable ITM stimulus port",
- .usage = "<port> (0|1|on|off)",
- },
- {
- .name = "ports",
- .handler = handle_itm_ports_command,
- .mode = COMMAND_ANY,
- .help = "Enable or disable all ITM stimulus ports",
- .usage = "(0|1|on|off)",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration armv7m_trace_command_handlers[] = {
- {
- .name = "tpiu",
- .mode = COMMAND_ANY,
- .help = "tpiu command group",
- .usage = "",
- .chain = tpiu_command_handlers,
- },
- {
- .name = "itm",
- .mode = COMMAND_ANY,
- .help = "itm command group",
- .usage = "",
- .chain = itm_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/armv7m_trace.h b/src/target/armv7m_trace.h
deleted file mode 100644
index 4f99394..0000000
--- a/src/target/armv7m_trace.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 Paul Fertser <fercerpav@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ARMV7M_TRACE_H
-#define OPENOCD_TARGET_ARMV7M_TRACE_H
-
-#include <target/target.h>
-#include <command.h>
-
-/**
- * @file
- * Holds the interface to TPIU, ITM and DWT configuration functions.
- */
-
-enum trace_config_type {
- DISABLED, /**< tracing is disabled */
- EXTERNAL, /**< trace output is captured externally */
- INTERNAL /**< trace output is handled by OpenOCD adapter driver */
-};
-
-enum tpio_pin_protocol {
- SYNC, /**< synchronous trace output */
- ASYNC_MANCHESTER, /**< asynchronous output with Manchester coding */
- ASYNC_UART /**< asynchronous output with NRZ coding */
-};
-
-enum itm_ts_prescaler {
- ITM_TS_PRESCALE1, /**< no prescaling for the timestamp counter */
- ITM_TS_PRESCALE4, /**< refclock divided by 4 for the timestamp counter */
- ITM_TS_PRESCALE16, /**< refclock divided by 16 for the timestamp counter */
- ITM_TS_PRESCALE64, /**< refclock divided by 64 for the timestamp counter */
-};
-
-struct armv7m_trace_config {
- /** Currently active trace capture mode */
- enum trace_config_type config_type;
-
- /** Currently active trace output mode */
- enum tpio_pin_protocol pin_protocol;
- /** TPIU formatter enable/disable (in async mode) */
- bool formatter;
- /** Synchronous output port width */
- uint32_t port_size;
-
- /** Bitmask of currenty enabled ITM stimuli */
- uint32_t itm_ter[8];
- /** Identifier for multi-source trace stream formatting */
- unsigned int trace_bus_id;
- /** Prescaler for the timestamp counter */
- enum itm_ts_prescaler itm_ts_prescale;
- /** Enable differential timestamps */
- bool itm_diff_timestamps;
- /** Enable async timestamps model */
- bool itm_async_timestamps;
- /** Enable synchronisation packet transmission (for sync port only) */
- bool itm_synchro_packets;
-
- /** Current frequency of TRACECLKIN (usually matches HCLK) */
- unsigned int traceclkin_freq;
- /** Current frequency of trace port */
- unsigned int trace_freq;
- /** Handle to output trace data in INTERNAL capture mode */
- FILE *trace_file;
-};
-
-extern const struct command_registration armv7m_trace_command_handlers[];
-
-/**
- * Configure hardware accordingly to the current TPIU target settings
- */
-int armv7m_trace_tpiu_config(struct target *target);
-/**
- * Configure hardware accordingly to the current ITM target settings
- */
-int armv7m_trace_itm_config(struct target *target);
-
-#endif /* OPENOCD_TARGET_ARMV7M_TRACE_H */
diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c
deleted file mode 100644
index e5634f2..0000000
--- a/src/target/avr32_ap7k.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * Based on mips_m4k code: *
- * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/jtag.h"
-#include "register.h"
-#include "algorithm.h"
-#include "target.h"
-#include "breakpoints.h"
-#include "target_type.h"
-#include "avr32_jtag.h"
-#include "avr32_mem.h"
-#include "avr32_regs.h"
-#include "avr32_ap7k.h"
-
-static const char * const avr32_core_reg_list[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
- "r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr"
-};
-
-static const struct avr32_core_reg
- avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] = {
- {0, NULL, NULL},
- {1, NULL, NULL},
- {2, NULL, NULL},
- {3, NULL, NULL},
- {4, NULL, NULL},
- {5, NULL, NULL},
- {6, NULL, NULL},
- {7, NULL, NULL},
- {8, NULL, NULL},
- {9, NULL, NULL},
- {10, NULL, NULL},
- {11, NULL, NULL},
- {12, NULL, NULL},
- {13, NULL, NULL},
- {14, NULL, NULL},
- {15, NULL, NULL},
- {16, NULL, NULL},
-};
-
-
-static int avr32_read_core_reg(struct target *target, int num);
-static int avr32_write_core_reg(struct target *target, int num);
-
-int avr32_ap7k_save_context(struct target *target)
-{
- int retval, i;
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- retval = avr32_jtag_read_regs(&ap7k->jtag, ap7k->core_regs);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < AVR32NUMCOREREGS; i++) {
- if (!ap7k->core_cache->reg_list[i].valid)
- avr32_read_core_reg(target, i);
- }
-
- return ERROR_OK;
-}
-
-int avr32_ap7k_restore_context(struct target *target)
-{
- int i;
-
- /* get pointers to arch-specific information */
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- for (i = 0; i < AVR32NUMCOREREGS; i++) {
- if (ap7k->core_cache->reg_list[i].dirty)
- avr32_write_core_reg(target, i);
- }
-
- /* write core regs */
- avr32_jtag_write_regs(&ap7k->jtag, ap7k->core_regs);
-
- return ERROR_OK;
-}
-
-static int avr32_read_core_reg(struct target *target, int num)
-{
- uint32_t reg_value;
-
- /* get pointers to arch-specific information */
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- if ((num < 0) || (num >= AVR32NUMCOREREGS))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- reg_value = ap7k->core_regs[num];
- buf_set_u32(ap7k->core_cache->reg_list[num].value, 0, 32, reg_value);
- ap7k->core_cache->reg_list[num].valid = 1;
- ap7k->core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-}
-
-static int avr32_write_core_reg(struct target *target, int num)
-{
- uint32_t reg_value;
-
- /* get pointers to arch-specific information */
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- if ((num < 0) || (num >= AVR32NUMCOREREGS))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32);
- ap7k->core_regs[num] = reg_value;
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
- ap7k->core_cache->reg_list[num].valid = 1;
- ap7k->core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-}
-
-static int avr32_get_core_reg(struct reg *reg)
-{
- int retval;
- struct avr32_core_reg *avr32_reg = reg->arch_info;
- struct target *target = avr32_reg->target;
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- retval = avr32_read_core_reg(target, avr32_reg->num);
-
- return retval;
-}
-
-static int avr32_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- struct avr32_core_reg *avr32_reg = reg->arch_info;
- struct target *target = avr32_reg->target;
- uint32_t value = buf_get_u32(buf, 0, 32);
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- buf_set_u32(reg->value, 0, 32, value);
- reg->dirty = 1;
- reg->valid = 1;
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type avr32_reg_type = {
- .get = avr32_get_core_reg,
- .set = avr32_set_core_reg,
-};
-
-static struct reg_cache *avr32_build_reg_cache(struct target *target)
-{
- int num_regs = AVR32NUMCOREREGS;
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct reg_cache *cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
- struct avr32_core_reg *arch_info =
- malloc(sizeof(struct avr32_core_reg) * num_regs);
- int i;
-
- /* Build the process context cache */
- cache->name = "avr32 registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = num_regs;
- (*cache_p) = cache;
- ap7k->core_cache = cache;
-
- for (i = 0; i < num_regs; i++) {
- arch_info[i] = avr32_core_reg_list_arch_info[i];
- arch_info[i].target = target;
- arch_info[i].avr32_common = ap7k;
- reg_list[i].name = avr32_core_reg_list[i];
- reg_list[i].size = 32;
- reg_list[i].value = calloc(1, 4);
- reg_list[i].dirty = 0;
- reg_list[i].valid = 0;
- reg_list[i].type = &avr32_reg_type;
- reg_list[i].arch_info = &arch_info[i];
- }
-
- return cache;
-}
-
-static int avr32_ap7k_debug_entry(struct target *target)
-{
-
- uint32_t dpc, dinst;
- int retval;
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DPC, &dpc);
- if (retval != ERROR_OK)
- return retval;
-
- retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DINST, &dinst);
- if (retval != ERROR_OK)
- return retval;
-
- ap7k->jtag.dpc = dpc;
-
- avr32_ap7k_save_context(target);
-
- return ERROR_OK;
-}
-
-
-static int avr32_ap7k_poll(struct target *target)
-{
- uint32_t ds;
- int retval;
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
- if (retval != ERROR_OK)
- return retval;
-
- /* check for processor halted */
- if (ds & OCDREG_DS_DBA) {
- if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) {
- target->state = TARGET_HALTED;
-
- retval = avr32_ap7k_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- } else if (target->state == TARGET_DEBUG_RUNNING) {
- target->state = TARGET_HALTED;
-
- retval = avr32_ap7k_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
- }
- } else
- target->state = TARGET_RUNNING;
-
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_halt(struct target *target)
-{
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- if (target->state == TARGET_UNKNOWN)
- LOG_WARNING("target was in unknown state when halt was requested");
-
- if (target->state == TARGET_RESET) {
- if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
- LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
- return ERROR_TARGET_FAILURE;
- } else {
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
- }
- }
-
-
- avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR);
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_assert_reset(struct target *target)
-{
- LOG_ERROR("%s: implement me", __func__);
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_deassert_reset(struct target *target)
-{
- LOG_ERROR("%s: implement me", __func__);
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
- struct breakpoint *breakpoint = NULL;
- uint32_t resume_pc;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!debug_execution) {
- target_free_all_working_areas(target);
- /*
- avr32_ap7k_enable_breakpoints(target);
- avr32_ap7k_enable_watchpoints(target);
- */
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current) {
-#if 0
- if (retval != ERROR_OK)
- return retval;
-#endif
- }
-
- resume_pc = buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
- avr32_ap7k_restore_context(target);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- /* Single step past breakpoint at current address */
- breakpoint = breakpoint_find(target, resume_pc);
- if (breakpoint) {
- LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
-#if 0
- avr32_ap7k_unset_breakpoint(target, breakpoint);
- avr32_ap7k_single_step_core(target);
- avr32_ap7k_set_breakpoint(target, breakpoint);
-#endif
- }
- }
-
-#if 0
- /* enable interrupts if we are running */
- avr32_ap7k_enable_interrupts(target, !debug_execution);
-
- /* exit debug mode */
- mips_ejtag_exit_debug(ejtag_info);
-#endif
-
-
- retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC,
- OCDREG_DC_DBR);
- if (retval != ERROR_OK)
- return retval;
-
- retval = avr32_jtag_exec(&ap7k->jtag, RETD);
- if (retval != ERROR_OK)
- return retval;
-
- target->debug_reason = DBG_REASON_NOTHALTED;
-
- /* registers are now invalid */
- register_cache_invalidate(ap7k->core_cache);
-
- if (!debug_execution) {
- target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
- }
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- LOG_ERROR("%s: implement me", __func__);
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- LOG_ERROR("%s: implement me", __func__);
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- LOG_ERROR("%s: implement me", __func__);
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- LOG_ERROR("%s: implement me", __func__);
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- LOG_ERROR("%s: implement me", __func__);
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
- address,
- size,
- count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- switch (size) {
- case 4:
- return avr32_jtag_read_memory32(&ap7k->jtag, address, count,
- (uint32_t *)(void *)buffer);
- break;
- case 2:
- return avr32_jtag_read_memory16(&ap7k->jtag, address, count,
- (uint16_t *)(void *)buffer);
- break;
- case 1:
- return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
- break;
- default:
- break;
- }
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
- address,
- size,
- count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- switch (size) {
- case 4:
- return avr32_jtag_write_memory32(&ap7k->jtag, address, count,
- (uint32_t *)(void *)buffer);
- break;
- case 2:
- return avr32_jtag_write_memory16(&ap7k->jtag, address, count,
- (uint16_t *)(void *)buffer);
- break;
- case 1:
- return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
- break;
- default:
- break;
- }
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- ap7k->jtag.tap = target->tap;
- avr32_build_reg_cache(target);
- return ERROR_OK;
-}
-
-static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
-{
- struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
- avr32_ap7k_common));
-
- ap7k->common_magic = AP7k_COMMON_MAGIC;
- target->arch_info = ap7k;
-
- return ERROR_OK;
-}
-
-static int avr32_ap7k_examine(struct target *target)
-{
- uint32_t devid, ds;
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- if (!target_was_examined(target)) {
- target_set_examined(target);
- avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
- LOG_INFO("device id: %08" PRIx32, devid);
- avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBE);
- avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
-
- /* check for processor halted */
- if (ds & OCDREG_DS_DBA) {
- LOG_INFO("target is halted");
- target->state = TARGET_HALTED;
- } else
- target->state = TARGET_RUNNING;
- }
-
- return ERROR_OK;
-}
-
-int avr32_ap7k_arch_state(struct target *target)
-{
- struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
-
- LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
- debug_reason_name(target), ap7k->jtag.dpc);
-
- return ERROR_OK;
-}
-
-int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
- int *reg_list_size, enum target_register_class reg_class)
-{
-#if 0
- /* get pointers to arch-specific information */
- int i;
-
- /* include floating point registers */
- *reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
-
- for (i = 0; i < AVR32NUMCOREREGS; i++)
- (*reg_list)[i] = &mips32->core_cache->reg_list[i];
-
- /* add dummy floating points regs */
- for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
- (*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
-
-#endif
-
- LOG_ERROR("%s: implement me", __func__);
- return ERROR_FAIL;
-}
-
-struct target_type avr32_ap7k_target = {
- .name = "avr32_ap7k",
-
- .poll = avr32_ap7k_poll,
- .arch_state = avr32_ap7k_arch_state,
-
- .halt = avr32_ap7k_halt,
- .resume = avr32_ap7k_resume,
- .step = avr32_ap7k_step,
-
- .assert_reset = avr32_ap7k_assert_reset,
- .deassert_reset = avr32_ap7k_deassert_reset,
-
- .get_gdb_reg_list = avr32_ap7k_get_gdb_reg_list,
-
- .read_memory = avr32_ap7k_read_memory,
- .write_memory = avr32_ap7k_write_memory,
- /* .checksum_memory = avr32_ap7k_checksum_memory, */
- /* .blank_check_memory = avr32_ap7k_blank_check_memory, */
-
- /* .run_algorithm = avr32_ap7k_run_algorithm, */
-
- .add_breakpoint = avr32_ap7k_add_breakpoint,
- .remove_breakpoint = avr32_ap7k_remove_breakpoint,
- .add_watchpoint = avr32_ap7k_add_watchpoint,
- .remove_watchpoint = avr32_ap7k_remove_watchpoint,
-
- .target_create = avr32_ap7k_target_create,
- .init_target = avr32_ap7k_init_target,
- .examine = avr32_ap7k_examine,
-};
diff --git a/src/target/avr32_ap7k.h b/src/target/avr32_ap7k.h
deleted file mode 100644
index 3f27534..0000000
--- a/src/target/avr32_ap7k.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_AVR32_AP7K_H
-#define OPENOCD_TARGET_AVR32_AP7K_H
-
-struct target;
-
-#define AP7k_COMMON_MAGIC 0x4150374b
-struct avr32_ap7k_common {
- int common_magic;
- struct avr32_jtag jtag;
- struct reg_cache *core_cache;
- uint32_t core_regs[AVR32NUMCOREREGS];
-};
-
-static inline struct avr32_ap7k_common *
-target_to_ap7k(struct target *target)
-{
- return (struct avr32_ap7k_common *)target->arch_info;
-}
-
-struct avr32_core_reg {
- uint32_t num;
- struct target *target;
- struct avr32_ap7k_common *avr32_common;
-};
-
-#endif /* OPENOCD_TARGET_AVR32_AP7K_H */
diff --git a/src/target/avr32_jtag.c b/src/target/avr32_jtag.c
deleted file mode 100644
index 6526810..0000000
--- a/src/target/avr32_jtag.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "jtag/jtag.h"
-#include "avr32_jtag.h"
-
-static int avr32_jtag_set_instr(struct avr32_jtag *jtag_info, int new_instr)
-{
- struct jtag_tap *tap;
- int busy = 0;
-
- tap = jtag_info->tap;
- if (tap == NULL)
- return ERROR_FAIL;
-
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) {
- do {
- struct scan_field field;
- uint8_t t[4];
- uint8_t ret[4];
-
- field.num_bits = tap->ir_length;
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_instr);
- field.in_value = ret;
-
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_ERROR("%s: setting address failed", __func__);
- return ERROR_FAIL;
- }
- busy = buf_get_u32(ret, 2, 1);
- } while (busy); /* check for busy bit */
- }
-
- return ERROR_OK;
-}
-
-int avr32_jtag_nexus_set_address(struct avr32_jtag *jtag_info,
- uint32_t addr, int mode)
-{
- struct scan_field fields[2];
- uint8_t addr_buf[4];
- uint8_t busy_buf[4];
- int busy;
-
- memset(fields, 0, sizeof(fields));
-
- do {
- memset(addr_buf, 0, sizeof(addr_buf));
- memset(busy_buf, 0, sizeof(busy_buf));
-
- buf_set_u32(addr_buf, 0, 1, mode);
- buf_set_u32(addr_buf, 1, 7, addr);
-
- fields[0].num_bits = 26;
- fields[0].in_value = NULL;
- fields[0].out_value = NULL;
-
- fields[1].num_bits = 8;
- fields[1].in_value = busy_buf;
- fields[1].out_value = addr_buf;
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_ERROR("%s: setting address failed", __func__);
- return ERROR_FAIL;
- }
- busy = buf_get_u32(busy_buf, 6, 1);
- } while (busy);
-
- return ERROR_OK;
-}
-
-
-int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info,
- uint32_t *pdata)
-{
-
- struct scan_field fields[2];
- uint8_t data_buf[4];
- uint8_t busy_buf[4];
- int busy;
-
- do {
- memset(data_buf, 0, sizeof(data_buf));
- memset(busy_buf, 0, sizeof(busy_buf));
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = data_buf;
-
-
- fields[1].num_bits = 2;
- fields[1].in_value = busy_buf;
- fields[1].out_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
-
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_ERROR("%s: reading data failed", __func__);
- return ERROR_FAIL;
- }
-
- busy = buf_get_u32(busy_buf, 0, 1);
- } while (busy);
-
- *pdata = buf_get_u32(data_buf, 0, 32);
-
- return ERROR_OK;
-}
-
-int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info,
- uint32_t data)
-{
-
- struct scan_field fields[2];
- uint8_t data_buf[4];
- uint8_t busy_buf[4];
- uint8_t dummy_buf[4];
- int busy;
-
- do {
- memset(data_buf, 0, sizeof(data_buf));
- memset(busy_buf, 0, sizeof(busy_buf));
- memset(dummy_buf, 0, sizeof(dummy_buf));
-
- fields[0].num_bits = 2;
- fields[0].in_value = busy_buf;
- fields[0].out_value = dummy_buf;
-
-
- buf_set_u32(data_buf, 0, 32, data);
- fields[1].num_bits = 32;
- fields[1].in_value = NULL;
- fields[1].out_value = data_buf;
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
-
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_ERROR("%s: reading data failed", __func__);
- return ERROR_FAIL;
- }
-
- busy = buf_get_u32(busy_buf, 0, 0);
- } while (busy);
-
-
- return ERROR_OK;
-}
-
-int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info,
- uint32_t addr, uint32_t *value)
-{
- avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS);
- avr32_jtag_nexus_set_address(jtag_info, addr, MODE_READ);
- avr32_jtag_nexus_read_data(jtag_info, value);
-
- return ERROR_OK;
-
-}
-int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info,
- uint32_t addr, uint32_t value)
-{
- avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS);
- avr32_jtag_nexus_set_address(jtag_info, addr, MODE_WRITE);
- avr32_jtag_nexus_write_data(jtag_info, value);
-
- return ERROR_OK;
-}
-
-int avr32_jtag_mwa_set_address(struct avr32_jtag *jtag_info, int slave,
- uint32_t addr, int mode)
-{
- struct scan_field fields[2];
- uint8_t addr_buf[4];
- uint8_t slave_buf[4];
- uint8_t busy_buf[4];
- int busy;
-
- memset(fields, 0, sizeof(fields));
-
- do {
- memset(addr_buf, 0, sizeof(addr_buf));
- memset(busy_buf, 0, sizeof(busy_buf));
- memset(slave_buf, 0, sizeof(slave_buf));
-
- buf_set_u32(slave_buf, 0, 4, slave);
- buf_set_u32(addr_buf, 0, 1, mode);
- buf_set_u32(addr_buf, 1, 30, addr >> 2);
-
- fields[0].num_bits = 31;
- fields[0].in_value = NULL;
- fields[0].out_value = addr_buf;
-
- fields[1].num_bits = 4;
- fields[1].in_value = busy_buf;
- fields[1].out_value = slave_buf;
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_ERROR("%s: setting address failed", __func__);
- return ERROR_FAIL;
- }
- busy = buf_get_u32(busy_buf, 1, 1);
- } while (busy);
-
- return ERROR_OK;
-}
-
-int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info,
- uint32_t *pdata)
-{
-
- struct scan_field fields[2];
- uint8_t data_buf[4];
- uint8_t busy_buf[4];
- int busy;
-
- do {
- memset(data_buf, 0, sizeof(data_buf));
- memset(busy_buf, 0, sizeof(busy_buf));
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = data_buf;
-
-
- fields[1].num_bits = 3;
- fields[1].in_value = busy_buf;
- fields[1].out_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
-
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_ERROR("%s: reading data failed", __func__);
- return ERROR_FAIL;
- }
-
- busy = buf_get_u32(busy_buf, 0, 1);
- } while (busy);
-
- *pdata = buf_get_u32(data_buf, 0, 32);
-
- return ERROR_OK;
-}
-
-int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info,
- uint32_t data)
-{
-
- struct scan_field fields[2];
- uint8_t data_buf[4];
- uint8_t busy_buf[4];
- uint8_t zero_buf[4];
- int busy;
-
- do {
- memset(data_buf, 0, sizeof(data_buf));
- memset(busy_buf, 0, sizeof(busy_buf));
- memset(zero_buf, 0, sizeof(zero_buf));
-
- buf_set_u32(data_buf, 0, 32, data);
- fields[0].num_bits = 3;
- fields[0].in_value = busy_buf;
- fields[0].out_value = zero_buf;
-
- fields[1].num_bits = 32;
- fields[1].out_value = data_buf;
- fields[1].in_value = NULL;
-
-
- jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
-
- if (jtag_execute_queue() != ERROR_OK) {
- LOG_ERROR("%s: reading data failed", __func__);
- return ERROR_FAIL;
- }
-
- busy = buf_get_u32(busy_buf, 0, 1);
- } while (busy);
-
- return ERROR_OK;
-}
-
-int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave,
- uint32_t addr, uint32_t *value)
-{
- avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS);
- avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_READ);
- avr32_jtag_mwa_read_data(jtag_info, value);
-
- return ERROR_OK;
-}
-
-int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave,
- uint32_t addr, uint32_t value)
-{
- avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS);
- avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_WRITE);
- avr32_jtag_mwa_write_data(jtag_info, value);
-
- return ERROR_OK;
-}
-
-int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst)
-{
- int retval;
- uint32_t ds;
-
- retval = avr32_jtag_nexus_write(jtag_info, AVR32_OCDREG_DINST, inst);
- if (retval != ERROR_OK)
- return retval;
-
- do {
- retval = avr32_jtag_nexus_read(jtag_info, AVR32_OCDREG_DS, &ds);
- if (retval != ERROR_OK)
- return retval;
- } while ((ds & OCDREG_DS_DBA) && !(ds & OCDREG_DS_INC));
-
- return ERROR_OK;
-}
-
-int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits)
-{
- uint32_t value;
- int res;
-
- res = avr32_jtag_nexus_read(jtag, reg, &value);
- if (res)
- return res;
-
- value |= bits;
- res = avr32_jtag_nexus_write(jtag, reg, value);
- if (res)
- return res;
-
- return ERROR_OK;
-}
-
-int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits)
-{
- uint32_t value;
- int res;
-
- res = avr32_jtag_nexus_read(jtag, reg, &value);
- if (res)
- return res;
-
- value &= ~bits;
- res = avr32_jtag_nexus_write(jtag, reg, value);
- if (res)
- return res;
-
- return ERROR_OK;
-}
-
diff --git a/src/target/avr32_jtag.h b/src/target/avr32_jtag.h
deleted file mode 100644
index b431ef4..0000000
--- a/src/target/avr32_jtag.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_AVR32_JTAG_H
-#define OPENOCD_TARGET_AVR32_JTAG_H
-
-#define AVR32NUMCOREREGS 17
-
-/* tap instructions */
-#define AVR32_INST_IDCODE 0x01
-#define AVR32_INST_NEXUS_ACCESS 0x10
-#define AVR32_INST_MW_ACCESS 0x11
-#define AVR32_INST_MB_ACCESS 0x12
-
-#define SLAVE_OCD 0x01
-#define SLAVE_HSB_CACHED 0x04
-#define SLAVE_HSB_UNCACHED 0x05
-
-/*
- * Registers
- */
-
-#define AVR32_OCDREG_DID 0x00
-#define AVR32_OCDREG_DC 0x02
-#define OCDREG_DC_SS (1 << 8)
-#define OCDREG_DC_DBR (1 << 12)
-#define OCDREG_DC_DBE (1 << 13)
-#define OCDREG_DC_SQA (1 << 22)
-#define OCDREG_DC_RES (1 << 30)
-#define OCDREG_DC_ABORT (1 << 31)
-#define AVR32_OCDREG_DS 0x04
-#define OCDREG_DS_SSS (1 << 0)
-#define OCDREG_DS_SWB (1 << 1)
-#define OCDREG_DS_HWB (1 << 2)
-#define OCDREG_DS_STP (1 << 4)
-#define OCDREG_DS_DBS (1 << 5)
-#define OCDREG_DS_BP_SHIFT 8
-#define OCDREG_DS_BP_MASK 0xff
-#define OCDREG_DS_INC (1 << 24)
-#define OCDREG_DS_BOZ (1 << 25)
-#define OCDREG_DS_DBA (1 << 26)
-#define OCDREG_DS_EXB (1 << 27)
-#define OCDREG_DS_NTBF (1 << 28)
-
-#define AVR32_OCDREG_DINST 0x41
-#define AVR32_OCDREG_DPC 0x42
-#define AVR32_OCDREG_DCCPU 0x44
-#define AVR32_OCDREG_DCEMU 0x45
-#define AVR32_OCDREG_DCSR 0x46
-#define OCDREG_DCSR_CPUD (1 << 0)
-#define OCDREG_DCSR_EMUD (1 << 1)
-
-/*
- * Direction bit
- */
-#define MODE_WRITE 0x00
-#define MODE_READ 0x01
-
-/*
- * Some instructions
- */
-
-#define RETD 0xd703d623
-#define MTDR(dreg, reg) (0xe7b00044 | ((reg) << 16) | dreg)
-#define MFDR(reg, dreg) (0xe5b00044 | ((reg) << 16) | dreg)
-#define MTSR(sysreg, reg) (0xe3b00002 | ((reg) << 16) | sysreg)
-#define MFSR(reg, sysreg) (0xe1b00002 | ((reg) << 16) | sysreg)
-
-struct avr32_jtag {
- struct jtag_tap *tap;
- uint32_t dpc; /* Debug PC value */
-};
-
-int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info,
- uint32_t addr, uint32_t *value);
-int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info,
- uint32_t addr, uint32_t value);
-
-int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave,
- uint32_t addr, uint32_t *value);
-int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave,
- uint32_t addr, uint32_t value);
-
-int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
-int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
-
-int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst);
-
-#endif /* OPENOCD_TARGET_AVR32_JTAG_H */
diff --git a/src/target/avr32_mem.c b/src/target/avr32_mem.c
deleted file mode 100644
index 71ec0b4..0000000
--- a/src/target/avr32_mem.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "jtag/jtag.h"
-#include "avr32_jtag.h"
-#include "avr32_mem.h"
-
-int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, uint32_t *buffer)
-{
- int i, retval;
- uint32_t data;
-
- for (i = 0; i < count; i++) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*4, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- /* XXX: Assume AVR32 is BE */
- buffer[i] = be_to_h_u32((uint8_t *)&data);
- }
-
- return ERROR_OK;
-}
-
-int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, uint16_t *buffer)
-{
- int i, retval;
- uint32_t data;
-
- i = 0;
-
- /* any unaligned half-words? */
- if (addr & 3) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*2, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- /* XXX: Assume AVR32 is BE */
- data = be_to_h_u32((uint8_t *)&data);
- buffer[i] = (data >> 16) & 0xffff;
- i++;
- }
-
- /* read all complete words */
- for (; i < (count & ~1); i += 2) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*2, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- /* XXX: Assume AVR32 is BE */
- data = be_to_h_u32((uint8_t *)&data);
- buffer[i] = data & 0xffff;
- buffer[i+1] = (data >> 16) & 0xffff;
- }
-
- /* last halfword */
- if (i < count) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*2, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- /* XXX: Assume AVR32 is BE */
- data = be_to_h_u32((uint8_t *)&data);
- buffer[i] = data & 0xffff;
- }
-
- return ERROR_OK;
-}
-
-int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, uint8_t *buffer)
-{
- int i, j, retval;
- uint8_t data[4];
- i = 0;
-
- /* Do we have non-aligned bytes? */
- if (addr & 3) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i, (uint32_t *)(void *)data);
-
- if (retval != ERROR_OK)
- return retval;
-
- for (j = addr & 3; (j < 4) && (i < count); j++, i++)
- buffer[i] = data[3-j];
- }
-
- /* read all complete words */
- for (; i < (count & ~3); i += 4) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i, (uint32_t *)(void *)data);
-
- if (retval != ERROR_OK)
- return retval;
-
- for (j = 0; j < 4; j++)
- buffer[i+j] = data[3-j];
- }
-
- /* remaining bytes */
- if (i < count) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i, (uint32_t *)(void *)data);
-
- if (retval != ERROR_OK)
- return retval;
-
- for (j = 0; i + j < count; j++)
- buffer[i+j] = data[3-j];
- }
-
- return ERROR_OK;
-}
-
-int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, const uint32_t *buffer)
-{
- int i, retval;
- uint32_t data;
-
- for (i = 0; i < count; i++) {
- /* XXX: Assume AVR32 is BE */
- h_u32_to_be((uint8_t *)&data, buffer[i]);
- retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*4, data);
-
- if (retval != ERROR_OK)
- return retval;
-
- }
-
- return ERROR_OK;
-}
-
-int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, const uint16_t *buffer)
-{
- int i, retval;
- uint32_t data;
- uint32_t data_out;
-
- i = 0;
-
- /*
- * Do we have any non-aligned half-words?
- */
- if (addr & 3) {
- /*
- * mwa_read will read whole world, no nead to fiddle
- * with address. It will be truncated in set_addr
- */
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- data = be_to_h_u32((uint8_t *)&data);
- data = (buffer[i] << 16) | (data & 0xffff);
- h_u32_to_be((uint8_t *)&data_out, data);
-
- retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
- addr, data_out);
-
- if (retval != ERROR_OK)
- return retval;
-
- i++;
- }
-
- /* write all complete words */
- for (; i < (count & ~1); i += 2) {
- /* XXX: Assume AVR32 is BE */
- data = (buffer[i+1] << 16) | buffer[i];
- h_u32_to_be((uint8_t *)&data_out, data);
-
- retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*2, data_out);
-
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* last halfword */
- if (i < count) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*2, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- data = be_to_h_u32((uint8_t *)&data);
- data &= ~0xffff;
- data |= buffer[i];
- h_u32_to_be((uint8_t *)&data_out, data);
-
- retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i*2, data_out);
-
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, const uint8_t *buffer)
-{
- int i, j, retval;
- uint32_t data;
- uint32_t data_out;
-
- i = 0;
-
- /*
- * Do we have any non-aligned bytes?
- */
- if (addr & 3) {
- /*
- * mwa_read will read whole world, no nead to fiddle
- * with address. It will be truncated in set_addr
- */
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- data = be_to_h_u32((uint8_t *)&data);
- for (j = addr & 3; (j < 4) && (i < count); j++, i++) {
- data &= ~(0xff << j*8);
- data |= (buffer[i] << j*8);
- }
-
- h_u32_to_be((uint8_t *)&data_out, data);
- retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
- addr, data_out);
-
- if (retval != ERROR_OK)
- return retval;
- }
-
-
- /* write all complete words */
- for (; i < (count & ~3); i += 4) {
- data = 0;
-
- for (j = 0; j < 4; j++)
- data |= (buffer[j+i] << j*8);
-
- h_u32_to_be((uint8_t *)&data_out, data);
-
- retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i, data_out);
-
- if (retval != ERROR_OK)
- return retval;
- }
-
- /*
- * Write trailing bytes
- */
- if (i < count) {
- retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
- addr + i, &data);
-
- if (retval != ERROR_OK)
- return retval;
-
- data = be_to_h_u32((uint8_t *)&data);
- for (j = 0; i < count; j++, i++) {
- data &= ~(0xff << j*8);
- data |= (buffer[j+i] << j*8);
- }
-
- h_u32_to_be((uint8_t *)&data_out, data);
-
- retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
- addr+i, data_out);
-
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
diff --git a/src/target/avr32_mem.h b/src/target/avr32_mem.h
deleted file mode 100644
index f60a121..0000000
--- a/src/target/avr32_mem.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_AVR32_MEM_H
-#define OPENOCD_TARGET_AVR32_MEM_H
-
-int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, uint32_t *buffer);
-int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, uint16_t *buffer);
-int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, uint8_t *buffer);
-
-int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, const uint32_t *buffer);
-int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, const uint16_t *buffer);
-int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info,
- uint32_t addr, int count, const uint8_t *buffer);
-
-#endif /* OPENOCD_TARGET_AVR32_MEM_H */
diff --git a/src/target/avr32_regs.c b/src/target/avr32_regs.c
deleted file mode 100644
index 7273822..0000000
--- a/src/target/avr32_regs.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "jtag/jtag.h"
-#include "avr32_jtag.h"
-#include "avr32_regs.h"
-
-static int avr32_jtag_read_reg(struct avr32_jtag *jtag_info, int reg,
- uint32_t *val)
-{
- int retval;
- uint32_t dcsr;
-
- retval = avr32_jtag_exec(jtag_info, MTDR(AVR32_OCDREG_DCCPU, reg));
- if (retval != ERROR_OK)
- return retval;
-
- do {
- retval = avr32_jtag_nexus_read(jtag_info,
- AVR32_OCDREG_DCSR, &dcsr);
-
- if (retval != ERROR_OK)
- return retval;
- } while (!(dcsr & OCDREG_DCSR_CPUD));
-
- retval = avr32_jtag_nexus_read(jtag_info,
- AVR32_OCDREG_DCCPU, val);
-
- return retval;
-}
-
-static int avr32_jtag_write_reg(struct avr32_jtag *jtag_info, int reg,
- uint32_t val)
-{
- int retval;
- uint32_t dcsr;
-
- /* Restore Status reg */
- retval = avr32_jtag_nexus_write(jtag_info,
- AVR32_OCDREG_DCEMU, val);
- if (retval != ERROR_OK)
- return retval;
-
- retval = avr32_jtag_exec(jtag_info, MFDR(reg, AVR32_OCDREG_DCEMU));
- if (retval != ERROR_OK)
- return retval;
- do {
- retval = avr32_jtag_nexus_read(jtag_info,
- AVR32_OCDREG_DCSR, &dcsr);
- } while (!(dcsr & OCDREG_DCSR_EMUD) && (retval == ERROR_OK));
-
- return retval;
-}
-
-
-
-int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs)
-{
- int i, retval;
-
- /* read core registers */
- for (i = 0; i < AVR32NUMCOREREGS - 1; i++)
- avr32_jtag_read_reg(jtag_info, i, regs + i);
-
- /* read status register */
- retval = avr32_jtag_exec(jtag_info, MFSR(0, 0));
- if (retval != ERROR_OK)
- return retval;
-
- retval = avr32_jtag_read_reg(jtag_info, 0, regs + AVR32_REG_SR);
-
- return retval;
-}
-
-int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs)
-{
- int i, retval;
-
- retval = avr32_jtag_write_reg(jtag_info, 0, regs[AVR32_REG_SR]);
- if (retval != ERROR_OK)
- return retval;
-
- /* Restore Status reg */
- retval = avr32_jtag_exec(jtag_info, MTSR(0, 0));
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * And now the rest of registers
- */
- for (i = 0; i < AVR32NUMCOREREGS - 1; i++)
- avr32_jtag_write_reg(jtag_info, i, regs[i]);
-
- return ERROR_OK;
-}
diff --git a/src/target/avr32_regs.h b/src/target/avr32_regs.h
deleted file mode 100644
index cb492a9..0000000
--- a/src/target/avr32_regs.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_AVR32_REGS_H
-#define OPENOCD_TARGET_AVR32_REGS_H
-
-enum avr32_reg_nums {
- AVR32_REG_R0 = 0,
- AVR32_REG_R1,
- AVR32_REG_R2,
- AVR32_REG_R3,
- AVR32_REG_R4,
- AVR32_REG_R5,
- AVR32_REG_R6,
- AVR32_REG_R7,
- AVR32_REG_R8,
- AVR32_REG_R9,
- AVR32_REG_R10,
- AVR32_REG_R11,
- AVR32_REG_R12,
- AVR32_REG_SP,
- AVR32_REG_LR,
- AVR32_REG_PC,
- AVR32_REG_SR,
-};
-
-int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs);
-int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs);
-
-#endif /* OPENOCD_TARGET_AVR32_REGS_H */
diff --git a/src/target/avrt.c b/src/target/avrt.c
deleted file mode 100644
index 40a1297..0000000
--- a/src/target/avrt.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Simon Qian *
- * SimonQian@SimonQian.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "avrt.h"
-#include "target.h"
-#include "target_type.h"
-
-#define AVR_JTAG_INS_LEN 4
-
-/* forward declarations */
-static int avr_target_create(struct target *target, Jim_Interp *interp);
-static int avr_init_target(struct command_context *cmd_ctx, struct target *target);
-
-static int avr_arch_state(struct target *target);
-static int avr_poll(struct target *target);
-static int avr_halt(struct target *target);
-static int avr_resume(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution);
-static int avr_step(struct target *target, int current, uint32_t address,
- int handle_breakpoints);
-
-static int avr_assert_reset(struct target *target);
-static int avr_deassert_reset(struct target *target);
-
-/* IR and DR functions */
-static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out, int ir_len, int rti);
-static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out, int dr_len, int rti);
-static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out, int ir_len, int rti);
-static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *ir_in, uint32_t ir_out, int dr_len, int rti);
-
-struct target_type avr_target = {
- .name = "avr",
-
- .poll = avr_poll,
- .arch_state = avr_arch_state,
-
- .halt = avr_halt,
- .resume = avr_resume,
- .step = avr_step,
-
- .assert_reset = avr_assert_reset,
- .deassert_reset = avr_deassert_reset,
-/*
- .get_gdb_reg_list = avr_get_gdb_reg_list,
-
- .read_memory = avr_read_memory,
- .write_memory = avr_write_memory,
- .bulk_write_memory = avr_bulk_write_memory,
- .checksum_memory = avr_checksum_memory,
- .blank_check_memory = avr_blank_check_memory,
-
- .run_algorithm = avr_run_algorithm,
-
- .add_breakpoint = avr_add_breakpoint,
- .remove_breakpoint = avr_remove_breakpoint,
- .add_watchpoint = avr_add_watchpoint,
- .remove_watchpoint = avr_remove_watchpoint,
-*/
- .target_create = avr_target_create,
- .init_target = avr_init_target,
-};
-
-static int avr_target_create(struct target *target, Jim_Interp *interp)
-{
- struct avr_common *avr = calloc(1, sizeof(struct avr_common));
-
- avr->jtag_info.tap = target->tap;
- target->arch_info = avr;
-
- return ERROR_OK;
-}
-
-static int avr_init_target(struct command_context *cmd_ctx, struct target *target)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int avr_arch_state(struct target *target)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int avr_poll(struct target *target)
-{
- if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))
- target->state = TARGET_HALTED;
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int avr_halt(struct target *target)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int avr_resume(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int avr_assert_reset(struct target *target)
-{
- target->state = TARGET_RESET;
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int avr_deassert_reset(struct target *target)
-{
- target->state = TARGET_RUNNING;
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-int avr_jtag_senddat(struct jtag_tap *tap, uint32_t* dr_in, uint32_t dr_out,
- int len)
-{
- return mcu_write_dr_u32(tap, dr_in, dr_out, len, 1);
-}
-
-int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out)
-{
- return mcu_write_ir_u8(tap, ir_in, ir_out, AVR_JTAG_INS_LEN, 1);
-}
-
-/* IR and DR functions */
-static int mcu_write_ir(struct jtag_tap *tap, uint8_t *ir_in, uint8_t *ir_out,
- int ir_len, int rti)
-{
- if (NULL == tap) {
- LOG_ERROR("invalid tap");
- return ERROR_FAIL;
- }
- if (ir_len != tap->ir_length) {
- LOG_ERROR("invalid ir_len");
- return ERROR_FAIL;
- }
-
- {
- jtag_add_plain_ir_scan(tap->ir_length, ir_out, ir_in, TAP_IDLE);
- }
-
- return ERROR_OK;
-}
-
-static int mcu_write_dr(struct jtag_tap *tap, uint8_t *dr_in, uint8_t *dr_out,
- int dr_len, int rti)
-{
- if (NULL == tap) {
- LOG_ERROR("invalid tap");
- return ERROR_FAIL;
- }
-
- {
- jtag_add_plain_dr_scan(dr_len, dr_out, dr_in, TAP_IDLE);
- }
-
- return ERROR_OK;
-}
-
-static int mcu_write_ir_u8(struct jtag_tap *tap, uint8_t *ir_in,
- uint8_t ir_out, int ir_len, int rti)
-{
- if (ir_len > 8) {
- LOG_ERROR("ir_len overflow, maxium is 8");
- return ERROR_FAIL;
- }
-
- mcu_write_ir(tap, ir_in, &ir_out, ir_len, rti);
-
- return ERROR_OK;
-}
-
-static int mcu_write_dr_u32(struct jtag_tap *tap, uint32_t *dr_in,
- uint32_t dr_out, int dr_len, int rti)
-{
- if (dr_len > 32) {
- LOG_ERROR("dr_len overflow, maxium is 32");
- return ERROR_FAIL;
- }
-
- mcu_write_dr(tap, (uint8_t *)dr_in, (uint8_t *)&dr_out, dr_len, rti);
-
- return ERROR_OK;
-}
-
-int mcu_execute_queue(void)
-{
- return jtag_execute_queue();
-}
diff --git a/src/target/avrt.h b/src/target/avrt.h
deleted file mode 100644
index 3610eb5..0000000
--- a/src/target/avrt.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Simon Qian *
- * SimonQian@SimonQian.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_AVRT_H
-#define OPENOCD_TARGET_AVRT_H
-
-#include <jtag/jtag.h>
-
-struct mcu_jtag {
- struct jtag_tap *tap;
-};
-
-struct avr_common {
- struct mcu_jtag jtag_info;
-};
-
-int mcu_execute_queue(void);
-int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out);
-int avr_jtag_senddat(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out,
- int len);
-
-#endif /* OPENOCD_TARGET_AVRT_H */
diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c
deleted file mode 100644
index 9591714..0000000
--- a/src/target/breakpoints.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) ST-Ericsson SA 2011 *
- * michel.jaouen@stericsson.com : smp minimum support *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include <helper/log.h>
-#include "breakpoints.h"
-
-static const char * const breakpoint_type_strings[] = {
- "hardware",
- "software"
-};
-
-static const char * const watchpoint_rw_strings[] = {
- "read",
- "write",
- "access"
-};
-
-/* monotonic counter/id-number for breakpoints and watch points */
-static int bpwp_unique_id;
-
-int breakpoint_add_internal(struct target *target,
- uint32_t address,
- uint32_t length,
- enum breakpoint_type type)
-{
- struct breakpoint *breakpoint = target->breakpoints;
- struct breakpoint **breakpoint_p = &target->breakpoints;
- const char *reason;
- int retval;
- int n;
-
- n = 0;
- while (breakpoint) {
- n++;
- if (breakpoint->address == address) {
- /* FIXME don't assume "same address" means "same
- * breakpoint" ... check all the parameters before
- * succeeding.
- */
- LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %" PRIu32 ")",
- address, breakpoint->unique_id);
- return ERROR_OK;
- }
- breakpoint_p = &breakpoint->next;
- breakpoint = breakpoint->next;
- }
-
- (*breakpoint_p) = malloc(sizeof(struct breakpoint));
- (*breakpoint_p)->address = address;
- (*breakpoint_p)->asid = 0;
- (*breakpoint_p)->length = length;
- (*breakpoint_p)->type = type;
- (*breakpoint_p)->set = 0;
- (*breakpoint_p)->orig_instr = malloc(length);
- (*breakpoint_p)->next = NULL;
- (*breakpoint_p)->unique_id = bpwp_unique_id++;
-
- retval = target_add_breakpoint(target, *breakpoint_p);
- switch (retval) {
- case ERROR_OK:
- break;
- case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
- reason = "resource not available";
- goto fail;
- case ERROR_TARGET_NOT_HALTED:
- reason = "target running";
- goto fail;
- default:
- reason = "unknown reason";
-fail:
- LOG_ERROR("can't add breakpoint: %s", reason);
- free((*breakpoint_p)->orig_instr);
- free(*breakpoint_p);
- *breakpoint_p = NULL;
- return retval;
- }
-
- LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")",
- breakpoint_type_strings[(*breakpoint_p)->type],
- (*breakpoint_p)->address, (*breakpoint_p)->length,
- (*breakpoint_p)->unique_id);
-
- return ERROR_OK;
-}
-
-int context_breakpoint_add_internal(struct target *target,
- uint32_t asid,
- uint32_t length,
- enum breakpoint_type type)
-{
- struct breakpoint *breakpoint = target->breakpoints;
- struct breakpoint **breakpoint_p = &target->breakpoints;
- int retval;
- int n;
-
- n = 0;
- while (breakpoint) {
- n++;
- if (breakpoint->asid == asid) {
- /* FIXME don't assume "same address" means "same
- * breakpoint" ... check all the parameters before
- * succeeding.
- */
- LOG_DEBUG("Duplicate Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
- asid, breakpoint->unique_id);
- return -1;
- }
- breakpoint_p = &breakpoint->next;
- breakpoint = breakpoint->next;
- }
-
- (*breakpoint_p) = malloc(sizeof(struct breakpoint));
- (*breakpoint_p)->address = 0;
- (*breakpoint_p)->asid = asid;
- (*breakpoint_p)->length = length;
- (*breakpoint_p)->type = type;
- (*breakpoint_p)->set = 0;
- (*breakpoint_p)->orig_instr = malloc(length);
- (*breakpoint_p)->next = NULL;
- (*breakpoint_p)->unique_id = bpwp_unique_id++;
- retval = target_add_context_breakpoint(target, *breakpoint_p);
- if (retval != ERROR_OK) {
- LOG_ERROR("could not add breakpoint");
- free((*breakpoint_p)->orig_instr);
- free(*breakpoint_p);
- *breakpoint_p = NULL;
- return retval;
- }
-
- LOG_DEBUG("added %s Context breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")",
- breakpoint_type_strings[(*breakpoint_p)->type],
- (*breakpoint_p)->asid, (*breakpoint_p)->length,
- (*breakpoint_p)->unique_id);
-
- return ERROR_OK;
-}
-
-int hybrid_breakpoint_add_internal(struct target *target,
- uint32_t address,
- uint32_t asid,
- uint32_t length,
- enum breakpoint_type type)
-{
- struct breakpoint *breakpoint = target->breakpoints;
- struct breakpoint **breakpoint_p = &target->breakpoints;
- int retval;
- int n;
- n = 0;
- while (breakpoint) {
- n++;
- if ((breakpoint->asid == asid) && (breakpoint->address == address)) {
- /* FIXME don't assume "same address" means "same
- * breakpoint" ... check all the parameters before
- * succeeding.
- */
- LOG_DEBUG("Duplicate Hybrid Breakpoint asid: 0x%08" PRIx32 " (BP %" PRIu32 ")",
- asid, breakpoint->unique_id);
- return -1;
- } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) {
- LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %" PRIu32 ")",
- address, breakpoint->unique_id);
- return -1;
-
- }
- breakpoint_p = &breakpoint->next;
- breakpoint = breakpoint->next;
- }
- (*breakpoint_p) = malloc(sizeof(struct breakpoint));
- (*breakpoint_p)->address = address;
- (*breakpoint_p)->asid = asid;
- (*breakpoint_p)->length = length;
- (*breakpoint_p)->type = type;
- (*breakpoint_p)->set = 0;
- (*breakpoint_p)->orig_instr = malloc(length);
- (*breakpoint_p)->next = NULL;
- (*breakpoint_p)->unique_id = bpwp_unique_id++;
-
-
- retval = target_add_hybrid_breakpoint(target, *breakpoint_p);
- if (retval != ERROR_OK) {
- LOG_ERROR("could not add breakpoint");
- free((*breakpoint_p)->orig_instr);
- free(*breakpoint_p);
- *breakpoint_p = NULL;
- return retval;
- }
- LOG_DEBUG(
- "added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")",
- breakpoint_type_strings[(*breakpoint_p)->type],
- (*breakpoint_p)->address,
- (*breakpoint_p)->length,
- (*breakpoint_p)->unique_id);
-
- return ERROR_OK;
-}
-
-int breakpoint_add(struct target *target,
- uint32_t address,
- uint32_t length,
- enum breakpoint_type type)
-{
- int retval = ERROR_OK;
- if (target->smp) {
- struct target_list *head;
- struct target *curr;
- head = target->head;
- if (type == BKPT_SOFT)
- return breakpoint_add_internal(head->target, address, length, type);
-
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- retval = breakpoint_add_internal(curr, address, length, type);
- if (retval != ERROR_OK)
- return retval;
- head = head->next;
- }
- return retval;
- } else
- return breakpoint_add_internal(target, address, length, type);
-}
-int context_breakpoint_add(struct target *target,
- uint32_t asid,
- uint32_t length,
- enum breakpoint_type type)
-{
- int retval = ERROR_OK;
- if (target->smp) {
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- retval = context_breakpoint_add_internal(curr, asid, length, type);
- if (retval != ERROR_OK)
- return retval;
- head = head->next;
- }
- return retval;
- } else
- return context_breakpoint_add_internal(target, asid, length, type);
-}
-int hybrid_breakpoint_add(struct target *target,
- uint32_t address,
- uint32_t asid,
- uint32_t length,
- enum breakpoint_type type)
-{
- int retval = ERROR_OK;
- if (target->smp) {
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- retval = hybrid_breakpoint_add_internal(curr, address, asid, length, type);
- if (retval != ERROR_OK)
- return retval;
- head = head->next;
- }
- return retval;
- } else
- return hybrid_breakpoint_add_internal(target, address, asid, length, type);
-}
-
-/* free up a breakpoint */
-static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove)
-{
- struct breakpoint *breakpoint = target->breakpoints;
- struct breakpoint **breakpoint_p = &target->breakpoints;
- int retval;
-
- while (breakpoint) {
- if (breakpoint == breakpoint_to_remove)
- break;
- breakpoint_p = &breakpoint->next;
- breakpoint = breakpoint->next;
- }
-
- if (breakpoint == NULL)
- return;
-
- retval = target_remove_breakpoint(target, breakpoint);
-
- LOG_DEBUG("free BPID: %" PRIu32 " --> %d", breakpoint->unique_id, retval);
- (*breakpoint_p) = breakpoint->next;
- free(breakpoint->orig_instr);
- free(breakpoint);
-}
-
-int breakpoint_remove_internal(struct target *target, uint32_t address)
-{
- struct breakpoint *breakpoint = target->breakpoints;
-
- while (breakpoint) {
- if ((breakpoint->address == address) && (breakpoint->asid == 0))
- break;
- else if ((breakpoint->address == 0) && (breakpoint->asid == address))
- break;
- else if ((breakpoint->address == address) && (breakpoint->asid != 0))
- break;
- breakpoint = breakpoint->next;
- }
-
- if (breakpoint) {
- breakpoint_free(target, breakpoint);
- return 1;
- } else {
- if (!target->smp)
- LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
- return 0;
- }
-}
-void breakpoint_remove(struct target *target, uint32_t address)
-{
- int found = 0;
- if (target->smp) {
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- found += breakpoint_remove_internal(curr, address);
- head = head->next;
- }
- if (found == 0)
- LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address);
- } else
- breakpoint_remove_internal(target, address);
-}
-
-void breakpoint_clear_target_internal(struct target *target)
-{
- LOG_DEBUG("Delete all breakpoints for target: %s",
- target_name(target));
- while (target->breakpoints != NULL)
- breakpoint_free(target, target->breakpoints);
-}
-
-void breakpoint_clear_target(struct target *target)
-{
- if (target->smp) {
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- breakpoint_clear_target_internal(curr);
- head = head->next;
- }
- } else
- breakpoint_clear_target_internal(target);
-
-}
-
-struct breakpoint *breakpoint_find(struct target *target, uint32_t address)
-{
- struct breakpoint *breakpoint = target->breakpoints;
-
- while (breakpoint) {
- if (breakpoint->address == address)
- return breakpoint;
- breakpoint = breakpoint->next;
- }
-
- return NULL;
-}
-
-int watchpoint_add(struct target *target, uint32_t address, uint32_t length,
- enum watchpoint_rw rw, uint32_t value, uint32_t mask)
-{
- struct watchpoint *watchpoint = target->watchpoints;
- struct watchpoint **watchpoint_p = &target->watchpoints;
- int retval;
- const char *reason;
-
- while (watchpoint) {
- if (watchpoint->address == address) {
- if (watchpoint->length != length
- || watchpoint->value != value
- || watchpoint->mask != mask
- || watchpoint->rw != rw) {
- LOG_ERROR("address 0x%8.8" PRIx32
- "already has watchpoint %d",
- address, watchpoint->unique_id);
- return ERROR_FAIL;
- }
-
- /* ignore duplicate watchpoint */
- return ERROR_OK;
- }
- watchpoint_p = &watchpoint->next;
- watchpoint = watchpoint->next;
- }
-
- (*watchpoint_p) = calloc(1, sizeof(struct watchpoint));
- (*watchpoint_p)->address = address;
- (*watchpoint_p)->length = length;
- (*watchpoint_p)->value = value;
- (*watchpoint_p)->mask = mask;
- (*watchpoint_p)->rw = rw;
- (*watchpoint_p)->unique_id = bpwp_unique_id++;
-
- retval = target_add_watchpoint(target, *watchpoint_p);
- switch (retval) {
- case ERROR_OK:
- break;
- case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
- reason = "resource not available";
- goto bye;
- case ERROR_TARGET_NOT_HALTED:
- reason = "target running";
- goto bye;
- default:
- reason = "unrecognized error";
-bye:
- LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s",
- watchpoint_rw_strings[(*watchpoint_p)->rw],
- address, reason);
- free(*watchpoint_p);
- *watchpoint_p = NULL;
- return retval;
- }
-
- LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32
- " of length 0x%8.8" PRIx32 " (WPID: %d)",
- watchpoint_rw_strings[(*watchpoint_p)->rw],
- (*watchpoint_p)->address,
- (*watchpoint_p)->length,
- (*watchpoint_p)->unique_id);
-
- return ERROR_OK;
-}
-
-static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
-{
- struct watchpoint *watchpoint = target->watchpoints;
- struct watchpoint **watchpoint_p = &target->watchpoints;
- int retval;
-
- while (watchpoint) {
- if (watchpoint == watchpoint_to_remove)
- break;
- watchpoint_p = &watchpoint->next;
- watchpoint = watchpoint->next;
- }
-
- if (watchpoint == NULL)
- return;
- retval = target_remove_watchpoint(target, watchpoint);
- LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
- (*watchpoint_p) = watchpoint->next;
- free(watchpoint);
-}
-
-void watchpoint_remove(struct target *target, uint32_t address)
-{
- struct watchpoint *watchpoint = target->watchpoints;
-
- while (watchpoint) {
- if (watchpoint->address == address)
- break;
- watchpoint = watchpoint->next;
- }
-
- if (watchpoint)
- watchpoint_free(target, watchpoint);
- else
- LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address);
-}
-
-void watchpoint_clear_target(struct target *target)
-{
- LOG_DEBUG("Delete all watchpoints for target: %s",
- target_name(target));
- while (target->watchpoints != NULL)
- watchpoint_free(target, target->watchpoints);
-}
-
-int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address)
-{
- int retval;
- struct watchpoint *hit_watchpoint;
-
- retval = target_hit_watchpoint(target, &hit_watchpoint);
- if (retval != ERROR_OK)
- return ERROR_FAIL;
-
- *rw = hit_watchpoint->rw;
- *address = hit_watchpoint->address;
-
- LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32 " (WPID: %d)",
- hit_watchpoint->address,
- hit_watchpoint->unique_id);
-
- return ERROR_OK;
-}
diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h
deleted file mode 100644
index 6e260ab..0000000
--- a/src/target/breakpoints.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_BREAKPOINTS_H
-#define OPENOCD_TARGET_BREAKPOINTS_H
-
-struct target;
-
-enum breakpoint_type {
- BKPT_HARD,
- BKPT_SOFT,
-};
-
-enum watchpoint_rw {
- WPT_READ = 0, WPT_WRITE = 1, WPT_ACCESS = 2
-};
-
-struct breakpoint {
- uint32_t address;
- uint32_t asid;
- int length;
- enum breakpoint_type type;
- int set;
- uint8_t *orig_instr;
- struct breakpoint *next;
- uint32_t unique_id;
- int linked_BRP;
-};
-
-struct watchpoint {
- uint32_t address;
- uint32_t length;
- uint32_t mask;
- uint32_t value;
- enum watchpoint_rw rw;
- int set;
- struct watchpoint *next;
- int unique_id;
-};
-
-void breakpoint_clear_target(struct target *target);
-int breakpoint_add(struct target *target,
- uint32_t address, uint32_t length, enum breakpoint_type type);
-int context_breakpoint_add(struct target *target,
- uint32_t asid, uint32_t length, enum breakpoint_type type);
-int hybrid_breakpoint_add(struct target *target,
- uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type);
-void breakpoint_remove(struct target *target, uint32_t address);
-
-struct breakpoint *breakpoint_find(struct target *target, uint32_t address);
-
-void watchpoint_clear_target(struct target *target);
-int watchpoint_add(struct target *target,
- uint32_t address, uint32_t length,
- enum watchpoint_rw rw, uint32_t value, uint32_t mask);
-void watchpoint_remove(struct target *target, uint32_t address);
-
-/* report type and address of just hit watchpoint */
-int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address);
-
-#endif /* OPENOCD_TARGET_BREAKPOINTS_H */
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
deleted file mode 100644
index d1590f6..0000000
--- a/src/target/cortex_a.c
+++ /dev/null
@@ -1,3591 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2009 by Dirk Behme *
- * dirk.behme@gmail.com - copy from cortex_m3 *
- * *
- * Copyright (C) 2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) ST-Ericsson SA 2011 *
- * michel.jaouen@stericsson.com : smp minimum support *
- * *
- * Copyright (C) Broadcom 2012 *
- * ehunter@broadcom.com : Cortex-R4 support *
- * *
- * Copyright (C) 2013 Kamal Dasu *
- * kdasu.kdev@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- * *
- * Cortex-A8(tm) TRM, ARM DDI 0344H *
- * Cortex-A9(tm) TRM, ARM DDI 0407F *
- * Cortex-A4(tm) TRM, ARM DDI 0363E *
- * Cortex-A15(tm)TRM, ARM DDI 0438C *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "cortex_a.h"
-#include "register.h"
-#include "target_request.h"
-#include "target_type.h"
-#include "arm_opcodes.h"
-#include <helper/time_support.h>
-
-static int cortex_a_poll(struct target *target);
-static int cortex_a_debug_entry(struct target *target);
-static int cortex_a_restore_context(struct target *target, bool bpwp);
-static int cortex_a_set_breakpoint(struct target *target,
- struct breakpoint *breakpoint, uint8_t matchmode);
-static int cortex_a_set_context_breakpoint(struct target *target,
- struct breakpoint *breakpoint, uint8_t matchmode);
-static int cortex_a_set_hybrid_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-static int cortex_a_unset_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-static int cortex_a_dap_read_coreregister_u32(struct target *target,
- uint32_t *value, int regnum);
-static int cortex_a_dap_write_coreregister_u32(struct target *target,
- uint32_t value, int regnum);
-static int cortex_a_mmu(struct target *target, int *enabled);
-static int cortex_a_mmu_modify(struct target *target, int enable);
-static int cortex_a_virt2phys(struct target *target,
- uint32_t virt, uint32_t *phys);
-static int cortex_a_read_cpu_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
-
-
-/* restore cp15_control_reg at resume */
-static int cortex_a_restore_cp15_control_reg(struct target *target)
-{
- int retval = ERROR_OK;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (cortex_a->cp15_control_reg != cortex_a->cp15_control_reg_curr) {
- cortex_a->cp15_control_reg_curr = cortex_a->cp15_control_reg;
- /* LOG_INFO("cp15_control_reg: %8.8" PRIx32, cortex_a->cp15_control_reg); */
- retval = armv7a->arm.mcr(target, 15,
- 0, 0, /* op1, op2 */
- 1, 0, /* CRn, CRm */
- cortex_a->cp15_control_reg);
- }
- return retval;
-}
-
-/*
- * Set up ARM core for memory access.
- * If !phys_access, switch to SVC mode and make sure MMU is on
- * If phys_access, switch off mmu
- */
-static int cortex_a_prep_memaccess(struct target *target, int phys_access)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- int mmu_enabled = 0;
-
- if (phys_access == 0) {
- dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
- cortex_a_mmu(target, &mmu_enabled);
- if (mmu_enabled)
- cortex_a_mmu_modify(target, 1);
- if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) {
- /* overwrite DACR to all-manager */
- armv7a->arm.mcr(target, 15,
- 0, 0, 3, 0,
- 0xFFFFFFFF);
- }
- } else {
- cortex_a_mmu(target, &mmu_enabled);
- if (mmu_enabled)
- cortex_a_mmu_modify(target, 0);
- }
- return ERROR_OK;
-}
-
-/*
- * Restore ARM core after memory access.
- * If !phys_access, switch to previous mode
- * If phys_access, restore MMU setting
- */
-static int cortex_a_post_memaccess(struct target *target, int phys_access)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- if (phys_access == 0) {
- if (cortex_a->dacrfixup_mode == CORTEX_A_DACRFIXUP_ON) {
- /* restore */
- armv7a->arm.mcr(target, 15,
- 0, 0, 3, 0,
- cortex_a->cp15_dacr_reg);
- }
- dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
- } else {
- int mmu_enabled = 0;
- cortex_a_mmu(target, &mmu_enabled);
- if (mmu_enabled)
- cortex_a_mmu_modify(target, 1);
- }
- return ERROR_OK;
-}
-
-
-/* modify cp15_control_reg in order to enable or disable mmu for :
- * - virt2phys address conversion
- * - read or write memory in phys or virt address */
-static int cortex_a_mmu_modify(struct target *target, int enable)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval = ERROR_OK;
- int need_write = 0;
-
- if (enable) {
- /* if mmu enabled at target stop and mmu not enable */
- if (!(cortex_a->cp15_control_reg & 0x1U)) {
- LOG_ERROR("trying to enable mmu on target stopped with mmu disable");
- return ERROR_FAIL;
- }
- if ((cortex_a->cp15_control_reg_curr & 0x1U) == 0) {
- cortex_a->cp15_control_reg_curr |= 0x1U;
- need_write = 1;
- }
- } else {
- if ((cortex_a->cp15_control_reg_curr & 0x1U) == 0x1U) {
- cortex_a->cp15_control_reg_curr &= ~0x1U;
- need_write = 1;
- }
- }
-
- if (need_write) {
- LOG_DEBUG("%s, writing cp15 ctrl: %" PRIx32,
- enable ? "enable mmu" : "disable mmu",
- cortex_a->cp15_control_reg_curr);
-
- retval = armv7a->arm.mcr(target, 15,
- 0, 0, /* op1, op2 */
- 1, 0, /* CRn, CRm */
- cortex_a->cp15_control_reg_curr);
- }
- return retval;
-}
-
-/*
- * Cortex-A Basic debug access, very low level assumes state is saved
- */
-static int cortex_a8_init_debug_access(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval;
-
- LOG_DEBUG(" ");
-
- /* Unlocking the debug registers for modification
- * The debugport might be uninitialised so try twice */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
- if (retval != ERROR_OK) {
- /* try again */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
- if (retval == ERROR_OK)
- LOG_USER(
- "Locking debug access failed on first, but succeeded on second try.");
- }
-
- return retval;
-}
-
-/*
- * Cortex-A Basic debug access, very low level assumes state is saved
- */
-static int cortex_a_init_debug_access(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval;
- uint32_t dbg_osreg;
- uint32_t cortex_part_num;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- LOG_DEBUG(" ");
- cortex_part_num = (cortex_a->cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >>
- CORTEX_A_MIDR_PARTNUM_SHIFT;
-
- switch (cortex_part_num) {
- case CORTEX_A7_PARTNUM:
- case CORTEX_A15_PARTNUM:
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLSR,
- &dbg_osreg);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("DBGOSLSR 0x%" PRIx32, dbg_osreg);
-
- if (dbg_osreg & CPUDBG_OSLAR_LK_MASK)
- /* Unlocking the DEBUG OS registers for modification */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLAR,
- 0);
- break;
-
- case CORTEX_A5_PARTNUM:
- case CORTEX_A8_PARTNUM:
- case CORTEX_A9_PARTNUM:
- default:
- retval = cortex_a8_init_debug_access(target);
- }
-
- if (retval != ERROR_OK)
- return retval;
- /* Clear Sticky Power Down status Bit in PRSR to enable access to
- the registers in the Core Power Domain */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
- LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg);
-
- if (retval != ERROR_OK)
- return retval;
-
- /* Disable cacheline fills and force cache write-through in debug state */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCCR, 0);
- if (retval != ERROR_OK)
- return retval;
-
- /* Disable TLB lookup and refill/eviction in debug state */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSMCR, 0);
- if (retval != ERROR_OK)
- return retval;
-
- /* Enabling of instruction execution in debug mode is done in debug_entry code */
-
- /* Resync breakpoint registers */
-
- /* Since this is likely called from init or reset, update target state information*/
- return cortex_a_poll(target);
-}
-
-static int cortex_a_wait_instrcmpl(struct target *target, uint32_t *dscr, bool force)
-{
- /* Waits until InstrCmpl_l becomes 1, indicating instruction is done.
- * Writes final value of DSCR into *dscr. Pass force to force always
- * reading DSCR at least once. */
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int64_t then = timeval_ms();
- while ((*dscr & DSCR_INSTR_COMP) == 0 || force) {
- force = false;
- int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, dscr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read DSCR register");
- return retval;
- }
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for InstrCompl=1");
- return ERROR_FAIL;
- }
- }
- return ERROR_OK;
-}
-
-/* To reduce needless round-trips, pass in a pointer to the current
- * DSCR value. Initialize it to zero if you just need to know the
- * value on return from this function; or DSCR_INSTR_COMP if you
- * happen to know that no instruction is pending.
- */
-static int cortex_a_exec_opcode(struct target *target,
- uint32_t opcode, uint32_t *dscr_p)
-{
- uint32_t dscr;
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- dscr = dscr_p ? *dscr_p : 0;
-
- LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
-
- /* Wait for InstrCompl bit to be set */
- retval = cortex_a_wait_instrcmpl(target, dscr_p, false);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_write_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_ITR, opcode);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- do {
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read DSCR register");
- return retval;
- }
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for cortex_a_exec_opcode");
- return ERROR_FAIL;
- }
- } while ((dscr & DSCR_INSTR_COMP) == 0); /* Wait for InstrCompl bit to be set */
-
- if (dscr_p)
- *dscr_p = dscr;
-
- return retval;
-}
-
-/**************************************************************************
-Read core register with very few exec_opcode, fast but needs work_area.
-This can cause problems with MMU active.
-**************************************************************************/
-static int cortex_a_read_regs_through_mem(struct target *target, uint32_t address,
- uint32_t *regfile)
-{
- int retval = ERROR_OK;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- retval = cortex_a_dap_read_coreregister_u32(target, regfile, 0);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_coreregister_u32(target, address, 0);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_read_buf(armv7a->memory_ap,
- (uint8_t *)(&regfile[1]), 4, 15, address);
-
- return retval;
-}
-
-static int cortex_a_dap_read_coreregister_u32(struct target *target,
- uint32_t *value, int regnum)
-{
- int retval = ERROR_OK;
- uint8_t reg = regnum&0xFF;
- uint32_t dscr = 0;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (reg > 17)
- return retval;
-
- if (reg < 15) {
- /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0" 0xEE00nE15 */
- retval = cortex_a_exec_opcode(target,
- ARMV4_5_MCR(14, 0, reg, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- } else if (reg == 15) {
- /* "MOV r0, r15"; then move r0 to DCCTX */
- retval = cortex_a_exec_opcode(target, 0xE1A0000F, &dscr);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_exec_opcode(target,
- ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- } else {
- /* "MRS r0, CPSR" or "MRS r0, SPSR"
- * then move r0 to DCCTX
- */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_exec_opcode(target,
- ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* Wait for DTRRXfull then read DTRRTX */
- int64_t then = timeval_ms();
- while ((dscr & DSCR_DTR_TX_FULL) == 0) {
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for cortex_a_exec_opcode");
- return ERROR_FAIL;
- }
- }
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRTX, value);
- LOG_DEBUG("read DCC 0x%08" PRIx32, *value);
-
- return retval;
-}
-
-static int cortex_a_dap_write_coreregister_u32(struct target *target,
- uint32_t value, int regnum)
-{
- int retval = ERROR_OK;
- uint8_t Rd = regnum&0xFF;
- uint32_t dscr;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
-
- /* Check that DCCRX is not full */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
- if (dscr & DSCR_DTR_RX_FULL) {
- LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
- /* Clear DCCRX with MRC(p14, 0, Rd, c0, c5, 0), opcode 0xEE100E15 */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (Rd > 17)
- return retval;
-
- /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */
- LOG_DEBUG("write DCC 0x%08" PRIx32, value);
- retval = mem_ap_write_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRRX, value);
- if (retval != ERROR_OK)
- return retval;
-
- if (Rd < 15) {
- /* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0),
- &dscr);
-
- if (retval != ERROR_OK)
- return retval;
- } else if (Rd == 15) {
- /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15
- * then "mov r15, r0"
- */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_exec_opcode(target, 0xE1A0F000, &dscr);
- if (retval != ERROR_OK)
- return retval;
- } else {
- /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15
- * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields)
- */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* "Prefetch flush" after modifying execution status in CPSR */
- if (Rd == 16) {
- retval = cortex_a_exec_opcode(target,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- return retval;
-}
-
-/* Write to memory mapped registers directly with no cache or mmu handling */
-static int cortex_a_dap_write_memap_register_u32(struct target *target,
- uint32_t address,
- uint32_t value)
-{
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap, address, value);
-
- return retval;
-}
-
-/*
- * Cortex-A implementation of Debug Programmer's Model
- *
- * NOTE the invariant: these routines return with DSCR_INSTR_COMP set,
- * so there's no need to poll for it before executing an instruction.
- *
- * NOTE that in several of these cases the "stall" mode might be useful.
- * It'd let us queue a few operations together... prepare/finish might
- * be the places to enable/disable that mode.
- */
-
-static inline struct cortex_a_common *dpm_to_a(struct arm_dpm *dpm)
-{
- return container_of(dpm, struct cortex_a_common, armv7a_common.dpm);
-}
-
-static int cortex_a_write_dcc(struct cortex_a_common *a, uint32_t data)
-{
- LOG_DEBUG("write DCC 0x%08" PRIx32, data);
- return mem_ap_write_u32(a->armv7a_common.debug_ap,
- a->armv7a_common.debug_base + CPUDBG_DTRRX, data);
-}
-
-static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
- uint32_t *dscr_p)
-{
- uint32_t dscr = DSCR_INSTR_COMP;
- int retval;
-
- if (dscr_p)
- dscr = *dscr_p;
-
- /* Wait for DTRRXfull */
- int64_t then = timeval_ms();
- while ((dscr & DSCR_DTR_TX_FULL) == 0) {
- retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
- a->armv7a_common.debug_base + CPUDBG_DSCR,
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for read dcc");
- return ERROR_FAIL;
- }
- }
-
- retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
- a->armv7a_common.debug_base + CPUDBG_DTRTX, data);
- if (retval != ERROR_OK)
- return retval;
- /* LOG_DEBUG("read DCC 0x%08" PRIx32, *data); */
-
- if (dscr_p)
- *dscr_p = dscr;
-
- return retval;
-}
-
-static int cortex_a_dpm_prepare(struct arm_dpm *dpm)
-{
- struct cortex_a_common *a = dpm_to_a(dpm);
- uint32_t dscr;
- int retval;
-
- /* set up invariant: INSTR_COMP is set after ever DPM operation */
- int64_t then = timeval_ms();
- for (;; ) {
- retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
- a->armv7a_common.debug_base + CPUDBG_DSCR,
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- if ((dscr & DSCR_INSTR_COMP) != 0)
- break;
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for dpm prepare");
- return ERROR_FAIL;
- }
- }
-
- /* this "should never happen" ... */
- if (dscr & DSCR_DTR_RX_FULL) {
- LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
- /* Clear DCCRX */
- retval = cortex_a_exec_opcode(
- a->armv7a_common.arm.target,
- ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int cortex_a_dpm_finish(struct arm_dpm *dpm)
-{
- /* REVISIT what could be done here? */
- return ERROR_OK;
-}
-
-static int cortex_a_instr_write_data_dcc(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t data)
-{
- struct cortex_a_common *a = dpm_to_a(dpm);
- int retval;
- uint32_t dscr = DSCR_INSTR_COMP;
-
- retval = cortex_a_write_dcc(a, data);
- if (retval != ERROR_OK)
- return retval;
-
- return cortex_a_exec_opcode(
- a->armv7a_common.arm.target,
- opcode,
- &dscr);
-}
-
-static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t data)
-{
- struct cortex_a_common *a = dpm_to_a(dpm);
- uint32_t dscr = DSCR_INSTR_COMP;
- int retval;
-
- retval = cortex_a_write_dcc(a, data);
- if (retval != ERROR_OK)
- return retval;
-
- /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
- retval = cortex_a_exec_opcode(
- a->armv7a_common.arm.target,
- ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* then the opcode, taking data from R0 */
- retval = cortex_a_exec_opcode(
- a->armv7a_common.arm.target,
- opcode,
- &dscr);
-
- return retval;
-}
-
-static int cortex_a_instr_cpsr_sync(struct arm_dpm *dpm)
-{
- struct target *target = dpm->arm->target;
- uint32_t dscr = DSCR_INSTR_COMP;
-
- /* "Prefetch flush" after modifying execution status in CPSR */
- return cortex_a_exec_opcode(target,
- ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
- &dscr);
-}
-
-static int cortex_a_instr_read_data_dcc(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t *data)
-{
- struct cortex_a_common *a = dpm_to_a(dpm);
- int retval;
- uint32_t dscr = DSCR_INSTR_COMP;
-
- /* the opcode, writing data to DCC */
- retval = cortex_a_exec_opcode(
- a->armv7a_common.arm.target,
- opcode,
- &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- return cortex_a_read_dcc(a, data, &dscr);
-}
-
-
-static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
- uint32_t opcode, uint32_t *data)
-{
- struct cortex_a_common *a = dpm_to_a(dpm);
- uint32_t dscr = DSCR_INSTR_COMP;
- int retval;
-
- /* the opcode, writing data to R0 */
- retval = cortex_a_exec_opcode(
- a->armv7a_common.arm.target,
- opcode,
- &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* write R0 to DCC */
- retval = cortex_a_exec_opcode(
- a->armv7a_common.arm.target,
- ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
- &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- return cortex_a_read_dcc(a, data, &dscr);
-}
-
-static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
- uint32_t addr, uint32_t control)
-{
- struct cortex_a_common *a = dpm_to_a(dpm);
- uint32_t vr = a->armv7a_common.debug_base;
- uint32_t cr = a->armv7a_common.debug_base;
- int retval;
-
- switch (index_t) {
- case 0 ... 15: /* breakpoints */
- vr += CPUDBG_BVR_BASE;
- cr += CPUDBG_BCR_BASE;
- break;
- case 16 ... 31: /* watchpoints */
- vr += CPUDBG_WVR_BASE;
- cr += CPUDBG_WCR_BASE;
- index_t -= 16;
- break;
- default:
- return ERROR_FAIL;
- }
- vr += 4 * index_t;
- cr += 4 * index_t;
-
- LOG_DEBUG("A: bpwp enable, vr %08x cr %08x",
- (unsigned) vr, (unsigned) cr);
-
- retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target,
- vr, addr);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(dpm->arm->target,
- cr, control);
- return retval;
-}
-
-static int cortex_a_bpwp_disable(struct arm_dpm *dpm, unsigned index_t)
-{
- struct cortex_a_common *a = dpm_to_a(dpm);
- uint32_t cr;
-
- switch (index_t) {
- case 0 ... 15:
- cr = a->armv7a_common.debug_base + CPUDBG_BCR_BASE;
- break;
- case 16 ... 31:
- cr = a->armv7a_common.debug_base + CPUDBG_WCR_BASE;
- index_t -= 16;
- break;
- default:
- return ERROR_FAIL;
- }
- cr += 4 * index_t;
-
- LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr);
-
- /* clear control register */
- return cortex_a_dap_write_memap_register_u32(dpm->arm->target, cr, 0);
-}
-
-static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
-{
- struct arm_dpm *dpm = &a->armv7a_common.dpm;
- int retval;
-
- dpm->arm = &a->armv7a_common.arm;
- dpm->didr = didr;
-
- dpm->prepare = cortex_a_dpm_prepare;
- dpm->finish = cortex_a_dpm_finish;
-
- dpm->instr_write_data_dcc = cortex_a_instr_write_data_dcc;
- dpm->instr_write_data_r0 = cortex_a_instr_write_data_r0;
- dpm->instr_cpsr_sync = cortex_a_instr_cpsr_sync;
-
- dpm->instr_read_data_dcc = cortex_a_instr_read_data_dcc;
- dpm->instr_read_data_r0 = cortex_a_instr_read_data_r0;
-
- dpm->bpwp_enable = cortex_a_bpwp_enable;
- dpm->bpwp_disable = cortex_a_bpwp_disable;
-
- retval = arm_dpm_setup(dpm);
- if (retval == ERROR_OK)
- retval = arm_dpm_initialize(dpm);
-
- return retval;
-}
-static struct target *get_cortex_a(struct target *target, int32_t coreid)
-{
- struct target_list *head;
- struct target *curr;
-
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
- return curr;
- head = head->next;
- }
- return target;
-}
-static int cortex_a_halt(struct target *target);
-
-static int cortex_a_halt_smp(struct target *target)
-{
- int retval = 0;
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if ((curr != target) && (curr->state != TARGET_HALTED))
- retval += cortex_a_halt(curr);
- head = head->next;
- }
- return retval;
-}
-
-static int update_halt_gdb(struct target *target)
-{
- int retval = 0;
- if (target->gdb_service && target->gdb_service->core[0] == -1) {
- target->gdb_service->target = target;
- target->gdb_service->core[0] = target->coreid;
- retval += cortex_a_halt_smp(target);
- }
- return retval;
-}
-
-/*
- * Cortex-A Run control
- */
-
-static int cortex_a_poll(struct target *target)
-{
- int retval = ERROR_OK;
- uint32_t dscr;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
- enum target_state prev_target_state = target->state;
- /* toggle to another core is done by gdb as follow */
- /* maint packet J core_id */
- /* continue */
- /* the next polling trigger an halt event sent to gdb */
- if ((target->state == TARGET_HALTED) && (target->smp) &&
- (target->gdb_service) &&
- (target->gdb_service->target == NULL)) {
- target->gdb_service->target =
- get_cortex_a(target, target->gdb_service->core[1]);
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- return retval;
- }
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
- cortex_a->cpudbg_dscr = dscr;
-
- if (DSCR_RUN_MODE(dscr) == (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED)) {
- if (prev_target_state != TARGET_HALTED) {
- /* We have a halting debug event */
- LOG_DEBUG("Target halted");
- target->state = TARGET_HALTED;
- if ((prev_target_state == TARGET_RUNNING)
- || (prev_target_state == TARGET_UNKNOWN)
- || (prev_target_state == TARGET_RESET)) {
- retval = cortex_a_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- if (target->smp) {
- retval = update_halt_gdb(target);
- if (retval != ERROR_OK)
- return retval;
- }
- target_call_event_callbacks(target,
- TARGET_EVENT_HALTED);
- }
- if (prev_target_state == TARGET_DEBUG_RUNNING) {
- LOG_DEBUG(" ");
-
- retval = cortex_a_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- if (target->smp) {
- retval = update_halt_gdb(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- target_call_event_callbacks(target,
- TARGET_EVENT_DEBUG_HALTED);
- }
- }
- } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED)
- target->state = TARGET_RUNNING;
- else {
- LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr);
- target->state = TARGET_UNKNOWN;
- }
-
- return retval;
-}
-
-static int cortex_a_halt(struct target *target)
-{
- int retval = ERROR_OK;
- uint32_t dscr;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- /*
- * Tell the core to be halted by writing DRCR with 0x1
- * and then wait for the core to be halted.
- */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
- if (retval != ERROR_OK)
- return retval;
-
- /*
- * enter halting debug mode
- */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- for (;; ) {
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
- if ((dscr & DSCR_CORE_HALTED) != 0)
- break;
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for halt");
- return ERROR_FAIL;
- }
- }
-
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int cortex_a_internal_restore(struct target *target, int current,
- uint32_t *address, int handle_breakpoints, int debug_execution)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- int retval;
- uint32_t resume_pc;
-
- if (!debug_execution)
- target_free_all_working_areas(target);
-
-#if 0
- if (debug_execution) {
- /* Disable interrupts */
- /* We disable interrupts in the PRIMASK register instead of
- * masking with C_MASKINTS,
- * This is probably the same issue as Cortex-M3 Errata 377493:
- * C_MASKINTS in parallel with disabled interrupts can cause
- * local faults to not be taken. */
- buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
- armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
- armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
-
- /* Make sure we are in Thumb mode */
- buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
- buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0,
- 32) | (1 << 24));
- armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
- armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
- }
-#endif
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- resume_pc = buf_get_u32(arm->pc->value, 0, 32);
- if (!current)
- resume_pc = *address;
- else
- *address = resume_pc;
-
- /* Make sure that the Armv7 gdb thumb fixups does not
- * kill the return address
- */
- switch (arm->core_state) {
- case ARM_STATE_ARM:
- resume_pc &= 0xFFFFFFFC;
- break;
- case ARM_STATE_THUMB:
- case ARM_STATE_THUMB_EE:
- /* When the return address is loaded into PC
- * bit 0 must be 1 to stay in Thumb state
- */
- resume_pc |= 0x1;
- break;
- case ARM_STATE_JAZELLE:
- LOG_ERROR("How do I resume into Jazelle state??");
- return ERROR_FAIL;
- }
- LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
- buf_set_u32(arm->pc->value, 0, 32, resume_pc);
- arm->pc->dirty = 1;
- arm->pc->valid = 1;
-
- /* restore dpm_mode at system halt */
- dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
- /* called it now before restoring context because it uses cpu
- * register r0 for restoring cp15 control register */
- retval = cortex_a_restore_cp15_control_reg(target);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_restore_context(target, handle_breakpoints);
- if (retval != ERROR_OK)
- return retval;
- target->debug_reason = DBG_REASON_NOTHALTED;
- target->state = TARGET_RUNNING;
-
- /* registers are now invalid */
- register_cache_invalidate(arm->core_cache);
-
-#if 0
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- /* Single step past breakpoint at current address */
- breakpoint = breakpoint_find(target, resume_pc);
- if (breakpoint) {
- LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
- cortex_m3_unset_breakpoint(target, breakpoint);
- cortex_m3_single_step_core(target);
- cortex_m3_set_breakpoint(target, breakpoint);
- }
- }
-
-#endif
- return retval;
-}
-
-static int cortex_a_internal_restart(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- int retval;
- uint32_t dscr;
- /*
- * * Restart core and wait for it to be started. Clear ITRen and sticky
- * * exception flags: see ARMv7 ARM, C5.9.
- *
- * REVISIT: for single stepping, we probably want to
- * disable IRQs by default, with optional override...
- */
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- if ((dscr & DSCR_INSTR_COMP) == 0)
- LOG_ERROR("DSCR InstrCompl must be set before leaving debug!");
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, dscr & ~DSCR_ITR_EN);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART |
- DRCR_CLEAR_EXCEPTIONS);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- for (;; ) {
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
- if ((dscr & DSCR_CORE_RESTARTED) != 0)
- break;
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for resume");
- return ERROR_FAIL;
- }
- }
-
- target->debug_reason = DBG_REASON_NOTHALTED;
- target->state = TARGET_RUNNING;
-
- /* registers are now invalid */
- register_cache_invalidate(arm->core_cache);
-
- return ERROR_OK;
-}
-
-static int cortex_a_restore_smp(struct target *target, int handle_breakpoints)
-{
- int retval = 0;
- struct target_list *head;
- struct target *curr;
- uint32_t address;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if ((curr != target) && (curr->state != TARGET_RUNNING)) {
- /* resume current address , not in step mode */
- retval += cortex_a_internal_restore(curr, 1, &address,
- handle_breakpoints, 0);
- retval += cortex_a_internal_restart(curr);
- }
- head = head->next;
-
- }
- return retval;
-}
-
-static int cortex_a_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- int retval = 0;
- /* dummy resume for smp toggle in order to reduce gdb impact */
- if ((target->smp) && (target->gdb_service->core[1] != -1)) {
- /* simulate a start and halt of target */
- target->gdb_service->target = NULL;
- target->gdb_service->core[0] = target->gdb_service->core[1];
- /* fake resume at next poll we play the target core[1], see poll*/
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- return 0;
- }
- cortex_a_internal_restore(target, current, &address, handle_breakpoints, debug_execution);
- if (target->smp) {
- target->gdb_service->core[0] = -1;
- retval = cortex_a_restore_smp(target, handle_breakpoints);
- if (retval != ERROR_OK)
- return retval;
- }
- cortex_a_internal_restart(target);
-
- if (!debug_execution) {
- target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- LOG_DEBUG("target resumed at 0x%" PRIx32, address);
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- LOG_DEBUG("target debug resumed at 0x%" PRIx32, address);
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_debug_entry(struct target *target)
-{
- int i;
- uint32_t regfile[16], cpsr, dscr;
- int retval = ERROR_OK;
- struct working_area *regfile_working_area = NULL;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- struct reg *reg;
-
- LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr);
-
- /* REVISIT surely we should not re-read DSCR !! */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* REVISIT see A TRM 12.11.4 steps 2..3 -- make sure that any
- * imprecise data aborts get discarded by issuing a Data
- * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4).
- */
-
- /* Enable the ITR execution once we are in debug mode */
- dscr |= DSCR_ITR_EN;
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Examine debug reason */
- arm_dpm_report_dscr(&armv7a->dpm, cortex_a->cpudbg_dscr);
-
- /* save address of instruction that triggered the watchpoint? */
- if (target->debug_reason == DBG_REASON_WATCHPOINT) {
- uint32_t wfar;
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_WFAR,
- &wfar);
- if (retval != ERROR_OK)
- return retval;
- arm_dpm_report_wfar(&armv7a->dpm, wfar);
- }
-
- /* REVISIT fast_reg_read is never set ... */
-
- /* Examine target state and mode */
- if (cortex_a->fast_reg_read)
- target_alloc_working_area(target, 64, &regfile_working_area);
-
- /* First load register acessible through core debug port*/
- if (!regfile_working_area)
- retval = arm_dpm_read_current_registers(&armv7a->dpm);
- else {
- retval = cortex_a_read_regs_through_mem(target,
- regfile_working_area->address, regfile);
-
- target_free_working_area(target, regfile_working_area);
- if (retval != ERROR_OK)
- return retval;
-
- /* read Current PSR */
- retval = cortex_a_dap_read_coreregister_u32(target, &cpsr, 16);
- /* store current cpsr */
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
-
- arm_set_cpsr(arm, cpsr);
-
- /* update cache */
- for (i = 0; i <= ARM_PC; i++) {
- reg = arm_reg_current(arm, i);
-
- buf_set_u32(reg->value, 0, 32, regfile[i]);
- reg->valid = 1;
- reg->dirty = 0;
- }
-
- /* Fixup PC Resume Address */
- if (cpsr & (1 << 5)) {
- /* T bit set for Thumb or ThumbEE state */
- regfile[ARM_PC] -= 4;
- } else {
- /* ARM state */
- regfile[ARM_PC] -= 8;
- }
-
- reg = arm->pc;
- buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
- reg->dirty = reg->valid;
- }
-
-#if 0
-/* TODO, Move this */
- uint32_t cp15_control_register, cp15_cacr, cp15_nacr;
- cortex_a_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
- LOG_DEBUG("cp15_control_register = 0x%08x", cp15_control_register);
-
- cortex_a_read_cp(target, &cp15_cacr, 15, 0, 1, 0, 2);
- LOG_DEBUG("cp15 Coprocessor Access Control Register = 0x%08x", cp15_cacr);
-
- cortex_a_read_cp(target, &cp15_nacr, 15, 0, 1, 1, 2);
- LOG_DEBUG("cp15 Nonsecure Access Control Register = 0x%08x", cp15_nacr);
-#endif
-
- /* Are we in an exception handler */
-/* armv4_5->exception_number = 0; */
- if (armv7a->post_debug_entry) {
- retval = armv7a->post_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-static int cortex_a_post_debug_entry(struct target *target)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
- int retval;
-
- /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
- retval = armv7a->arm.mrc(target, 15,
- 0, 0, /* op1, op2 */
- 1, 0, /* CRn, CRm */
- &cortex_a->cp15_control_reg);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a->cp15_control_reg);
- cortex_a->cp15_control_reg_curr = cortex_a->cp15_control_reg;
-
- if (armv7a->armv7a_mmu.armv7a_cache.info == -1)
- armv7a_identify_cache(target);
-
- if (armv7a->is_armv7r) {
- armv7a->armv7a_mmu.mmu_enabled = 0;
- } else {
- armv7a->armv7a_mmu.mmu_enabled =
- (cortex_a->cp15_control_reg & 0x1U) ? 1 : 0;
- }
- armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled =
- (cortex_a->cp15_control_reg & 0x4U) ? 1 : 0;
- armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled =
- (cortex_a->cp15_control_reg & 0x1000U) ? 1 : 0;
- cortex_a->curr_mode = armv7a->arm.core_mode;
-
- /* switch to SVC mode to read DACR */
- dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
- armv7a->arm.mrc(target, 15,
- 0, 0, 3, 0,
- &cortex_a->cp15_dacr_reg);
-
- LOG_DEBUG("cp15_dacr_reg: %8.8" PRIx32,
- cortex_a->cp15_dacr_reg);
-
- dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
- return ERROR_OK;
-}
-
-int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- uint32_t dscr;
-
- /* Read DSCR */
- int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (ERROR_OK != retval)
- return retval;
-
- /* clear bitfield */
- dscr &= ~bit_mask;
- /* put new value */
- dscr |= value & bit_mask;
-
- /* write new DSCR */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, dscr);
- return retval;
-}
-
-static int cortex_a_step(struct target *target, int current, uint32_t address,
- int handle_breakpoints)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- struct breakpoint *breakpoint = NULL;
- struct breakpoint stepbreakpoint;
- struct reg *r;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- r = arm->pc;
- if (!current)
- buf_set_u32(r->value, 0, 32, address);
- else
- address = buf_get_u32(r->value, 0, 32);
-
- /* The front-end may request us not to handle breakpoints.
- * But since Cortex-A uses breakpoint for single step,
- * we MUST handle breakpoints.
- */
- handle_breakpoints = 1;
- if (handle_breakpoints) {
- breakpoint = breakpoint_find(target, address);
- if (breakpoint)
- cortex_a_unset_breakpoint(target, breakpoint);
- }
-
- /* Setup single step breakpoint */
- stepbreakpoint.address = address;
- stepbreakpoint.length = (arm->core_state == ARM_STATE_THUMB)
- ? 2 : 4;
- stepbreakpoint.type = BKPT_HARD;
- stepbreakpoint.set = 0;
-
- /* Disable interrupts during single step if requested */
- if (cortex_a->isrmasking_mode == CORTEX_A_ISRMASK_ON) {
- retval = cortex_a_set_dscr_bits(target, DSCR_INT_DIS, DSCR_INT_DIS);
- if (ERROR_OK != retval)
- return retval;
- }
-
- /* Break on IVA mismatch */
- cortex_a_set_breakpoint(target, &stepbreakpoint, 0x04);
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- retval = cortex_a_resume(target, 1, address, 0, 0);
- if (retval != ERROR_OK)
- return retval;
-
- int64_t then = timeval_ms();
- while (target->state != TARGET_HALTED) {
- retval = cortex_a_poll(target);
- if (retval != ERROR_OK)
- return retval;
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("timeout waiting for target halt");
- return ERROR_FAIL;
- }
- }
-
- cortex_a_unset_breakpoint(target, &stepbreakpoint);
-
- /* Re-enable interrupts if they were disabled */
- if (cortex_a->isrmasking_mode == CORTEX_A_ISRMASK_ON) {
- retval = cortex_a_set_dscr_bits(target, DSCR_INT_DIS, 0);
- if (ERROR_OK != retval)
- return retval;
- }
-
-
- target->debug_reason = DBG_REASON_BREAKPOINT;
-
- if (breakpoint)
- cortex_a_set_breakpoint(target, breakpoint, 0);
-
- if (target->state != TARGET_HALTED)
- LOG_DEBUG("target stepped");
-
- return ERROR_OK;
-}
-
-static int cortex_a_restore_context(struct target *target, bool bpwp)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- LOG_DEBUG(" ");
-
- if (armv7a->pre_restore_context)
- armv7a->pre_restore_context(target);
-
- return arm_dpm_write_dirty_registers(&armv7a->dpm, bpwp);
-}
-
-/*
- * Cortex-A Breakpoint and watchpoint functions
- */
-
-/* Setup hardware Breakpoint Register Pair */
-static int cortex_a_set_breakpoint(struct target *target,
- struct breakpoint *breakpoint, uint8_t matchmode)
-{
- int retval;
- int brp_i = 0;
- uint32_t control;
- uint8_t byte_addr_select = 0x0F;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
- struct cortex_a_brp *brp_list = cortex_a->brp_list;
-
- if (breakpoint->set) {
- LOG_WARNING("breakpoint already set");
- return ERROR_OK;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- while (brp_list[brp_i].used && (brp_i < cortex_a->brp_num))
- brp_i++;
- if (brp_i >= cortex_a->brp_num) {
- LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- breakpoint->set = brp_i + 1;
- if (breakpoint->length == 2)
- byte_addr_select = (3 << (breakpoint->address & 0x02));
- control = ((matchmode & 0x7) << 20)
- | (byte_addr_select << 5)
- | (3 << 1) | 1;
- brp_list[brp_i].used = 1;
- brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
- brp_list[brp_i].control = control;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].value);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].control);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
- brp_list[brp_i].control,
- brp_list[brp_i].value);
- } else if (breakpoint->type == BKPT_SOFT) {
- uint8_t code[4];
- if (breakpoint->length == 2)
- buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
- else
- buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
- retval = target_read_memory(target,
- breakpoint->address & 0xFFFFFFFE,
- breakpoint->length, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
-
- /* make sure data cache is cleaned & invalidated down to PoC */
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) {
- armv7a_cache_flush_virt(target, breakpoint->address,
- breakpoint->length);
- }
-
- retval = target_write_memory(target,
- breakpoint->address & 0xFFFFFFFE,
- breakpoint->length, 1, code);
- if (retval != ERROR_OK)
- return retval;
-
- /* update i-cache at breakpoint location */
- armv7a_l1_d_cache_inval_virt(target, breakpoint->address,
- breakpoint->length);
- armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
- breakpoint->length);
-
- breakpoint->set = 0x11; /* Any nice value but 0 */
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_set_context_breakpoint(struct target *target,
- struct breakpoint *breakpoint, uint8_t matchmode)
-{
- int retval = ERROR_FAIL;
- int brp_i = 0;
- uint32_t control;
- uint8_t byte_addr_select = 0x0F;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
- struct cortex_a_brp *brp_list = cortex_a->brp_list;
-
- if (breakpoint->set) {
- LOG_WARNING("breakpoint already set");
- return retval;
- }
- /*check available context BRPs*/
- while ((brp_list[brp_i].used ||
- (brp_list[brp_i].type != BRP_CONTEXT)) && (brp_i < cortex_a->brp_num))
- brp_i++;
-
- if (brp_i >= cortex_a->brp_num) {
- LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
- return ERROR_FAIL;
- }
-
- breakpoint->set = brp_i + 1;
- control = ((matchmode & 0x7) << 20)
- | (byte_addr_select << 5)
- | (3 << 1) | 1;
- brp_list[brp_i].used = 1;
- brp_list[brp_i].value = (breakpoint->asid);
- brp_list[brp_i].control = control;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].value);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].control);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
- brp_list[brp_i].control,
- brp_list[brp_i].value);
- return ERROR_OK;
-
-}
-
-static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- int retval = ERROR_FAIL;
- int brp_1 = 0; /* holds the contextID pair */
- int brp_2 = 0; /* holds the IVA pair */
- uint32_t control_CTX, control_IVA;
- uint8_t CTX_byte_addr_select = 0x0F;
- uint8_t IVA_byte_addr_select = 0x0F;
- uint8_t CTX_machmode = 0x03;
- uint8_t IVA_machmode = 0x01;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
- struct cortex_a_brp *brp_list = cortex_a->brp_list;
-
- if (breakpoint->set) {
- LOG_WARNING("breakpoint already set");
- return retval;
- }
- /*check available context BRPs*/
- while ((brp_list[brp_1].used ||
- (brp_list[brp_1].type != BRP_CONTEXT)) && (brp_1 < cortex_a->brp_num))
- brp_1++;
-
- printf("brp(CTX) found num: %d\n", brp_1);
- if (brp_1 >= cortex_a->brp_num) {
- LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
- return ERROR_FAIL;
- }
-
- while ((brp_list[brp_2].used ||
- (brp_list[brp_2].type != BRP_NORMAL)) && (brp_2 < cortex_a->brp_num))
- brp_2++;
-
- printf("brp(IVA) found num: %d\n", brp_2);
- if (brp_2 >= cortex_a->brp_num) {
- LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
- return ERROR_FAIL;
- }
-
- breakpoint->set = brp_1 + 1;
- breakpoint->linked_BRP = brp_2;
- control_CTX = ((CTX_machmode & 0x7) << 20)
- | (brp_2 << 16)
- | (0 << 14)
- | (CTX_byte_addr_select << 5)
- | (3 << 1) | 1;
- brp_list[brp_1].used = 1;
- brp_list[brp_1].value = (breakpoint->asid);
- brp_list[brp_1].control = control_CTX;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].BRPn,
- brp_list[brp_1].value);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].BRPn,
- brp_list[brp_1].control);
- if (retval != ERROR_OK)
- return retval;
-
- control_IVA = ((IVA_machmode & 0x7) << 20)
- | (brp_1 << 16)
- | (IVA_byte_addr_select << 5)
- | (3 << 1) | 1;
- brp_list[brp_2].used = 1;
- brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC);
- brp_list[brp_2].control = control_IVA;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].BRPn,
- brp_list[brp_2].value);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].BRPn,
- brp_list[brp_2].control);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- int retval;
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
- struct cortex_a_brp *brp_list = cortex_a->brp_list;
-
- if (!breakpoint->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
- int brp_i = breakpoint->set - 1;
- int brp_j = breakpoint->linked_BRP;
- if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) {
- LOG_DEBUG("Invalid BRP number in breakpoint");
- return ERROR_OK;
- }
- LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
- brp_list[brp_i].control, brp_list[brp_i].value);
- brp_list[brp_i].used = 0;
- brp_list[brp_i].value = 0;
- brp_list[brp_i].control = 0;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].control);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].value);
- if (retval != ERROR_OK)
- return retval;
- if ((brp_j < 0) || (brp_j >= cortex_a->brp_num)) {
- LOG_DEBUG("Invalid BRP number in breakpoint");
- return ERROR_OK;
- }
- LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_j,
- brp_list[brp_j].control, brp_list[brp_j].value);
- brp_list[brp_j].used = 0;
- brp_list[brp_j].value = 0;
- brp_list[brp_j].control = 0;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].BRPn,
- brp_list[brp_j].control);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].BRPn,
- brp_list[brp_j].value);
- if (retval != ERROR_OK)
- return retval;
- breakpoint->linked_BRP = 0;
- breakpoint->set = 0;
- return ERROR_OK;
-
- } else {
- int brp_i = breakpoint->set - 1;
- if ((brp_i < 0) || (brp_i >= cortex_a->brp_num)) {
- LOG_DEBUG("Invalid BRP number in breakpoint");
- return ERROR_OK;
- }
- LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
- brp_list[brp_i].control, brp_list[brp_i].value);
- brp_list[brp_i].used = 0;
- brp_list[brp_i].value = 0;
- brp_list[brp_i].control = 0;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].control);
- if (retval != ERROR_OK)
- return retval;
- retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
- + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
- brp_list[brp_i].value);
- if (retval != ERROR_OK)
- return retval;
- breakpoint->set = 0;
- return ERROR_OK;
- }
- } else {
-
- /* make sure data cache is cleaned & invalidated down to PoC */
- if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) {
- armv7a_cache_flush_virt(target, breakpoint->address,
- breakpoint->length);
- }
-
- /* restore original instruction (kept in target endianness) */
- if (breakpoint->length == 4) {
- retval = target_write_memory(target,
- breakpoint->address & 0xFFFFFFFE,
- 4, 1, breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = target_write_memory(target,
- breakpoint->address & 0xFFFFFFFE,
- 2, 1, breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* update i-cache at breakpoint location */
- armv7a_l1_d_cache_inval_virt(target, breakpoint->address,
- breakpoint->length);
- armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
- breakpoint->length);
- }
- breakpoint->set = 0;
-
- return ERROR_OK;
-}
-
-static int cortex_a_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- if ((breakpoint->type == BKPT_HARD) && (cortex_a->brp_num_available < 1)) {
- LOG_INFO("no hardware breakpoint available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->type == BKPT_HARD)
- cortex_a->brp_num_available--;
-
- return cortex_a_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
-}
-
-static int cortex_a_add_context_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- if ((breakpoint->type == BKPT_HARD) && (cortex_a->brp_num_available < 1)) {
- LOG_INFO("no hardware breakpoint available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->type == BKPT_HARD)
- cortex_a->brp_num_available--;
-
- return cortex_a_set_context_breakpoint(target, breakpoint, 0x02); /* asid match */
-}
-
-static int cortex_a_add_hybrid_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- if ((breakpoint->type == BKPT_HARD) && (cortex_a->brp_num_available < 1)) {
- LOG_INFO("no hardware breakpoint available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->type == BKPT_HARD)
- cortex_a->brp_num_available--;
-
- return cortex_a_set_hybrid_breakpoint(target, breakpoint); /* ??? */
-}
-
-
-static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
-#if 0
-/* It is perfectly possible to remove breakpoints while the target is running */
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-#endif
-
- if (breakpoint->set) {
- cortex_a_unset_breakpoint(target, breakpoint);
- if (breakpoint->type == BKPT_HARD)
- cortex_a->brp_num_available++;
- }
-
-
- return ERROR_OK;
-}
-
-/*
- * Cortex-A Reset functions
- */
-
-static int cortex_a_assert_reset(struct target *target)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- LOG_DEBUG(" ");
-
- /* FIXME when halt is requested, make it work somehow... */
-
- /* This function can be called in "target not examined" state */
-
- /* Issue some kind of warm reset. */
- if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
- target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
- else if (jtag_get_reset_config() & RESET_HAS_SRST) {
- /* REVISIT handle "pulls" cases, if there's
- * hardware that needs them to work.
- */
- if (target->reset_halt)
- if (jtag_get_reset_config() & RESET_SRST_NO_GATING)
- jtag_add_reset(0, 1);
- } else {
- LOG_ERROR("%s: how to reset?", target_name(target));
- return ERROR_FAIL;
- }
-
- /* registers are now invalid */
- register_cache_invalidate(armv7a->arm.core_cache);
-
- target->state = TARGET_RESET;
-
- return ERROR_OK;
-}
-
-static int cortex_a_deassert_reset(struct target *target)
-{
- int retval;
-
- LOG_DEBUG(" ");
-
- /* be certain SRST is off */
- jtag_add_reset(0, 0);
-
- retval = cortex_a_poll(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->reset_halt) {
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("%s: ran after reset and before halt ...",
- target_name(target));
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_set_dcc_mode(struct target *target, uint32_t mode, uint32_t *dscr)
-{
- /* Changes the mode of the DCC between non-blocking, stall, and fast mode.
- * New desired mode must be in mode. Current value of DSCR must be in
- * *dscr, which is updated with new value.
- *
- * This function elides actually sending the mode-change over the debug
- * interface if the mode is already set as desired.
- */
- uint32_t new_dscr = (*dscr & ~DSCR_EXT_DCC_MASK) | mode;
- if (new_dscr != *dscr) {
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, new_dscr);
- if (retval == ERROR_OK)
- *dscr = new_dscr;
- return retval;
- } else {
- return ERROR_OK;
- }
-}
-
-static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask,
- uint32_t value, uint32_t *dscr)
-{
- /* Waits until the specified bit(s) of DSCR take on a specified value. */
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int64_t then = timeval_ms();
- int retval;
-
- while ((*dscr & mask) != value) {
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, dscr);
- if (retval != ERROR_OK)
- return retval;
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("timeout waiting for DSCR bit change");
- return ERROR_FAIL;
- }
- }
- return ERROR_OK;
-}
-
-static int cortex_a_read_copro(struct target *target, uint32_t opcode,
- uint32_t *data, uint32_t *dscr)
-{
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- /* Move from coprocessor to R0. */
- retval = cortex_a_exec_opcode(target, opcode, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Move from R0 to DTRTX. */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0), dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Wait until DTRTX is full (according to ARMv7-A/-R architecture
- * manual section C8.4.3, checking InstrCmpl_l is not sufficient; one
- * must also check TXfull_l). Most of the time this will be free
- * because TXfull_l will be set immediately and cached in dscr. */
- retval = cortex_a_wait_dscr_bits(target, DSCR_DTRTX_FULL_LATCHED,
- DSCR_DTRTX_FULL_LATCHED, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Read the value transferred to DTRTX. */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRTX, data);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int cortex_a_read_dfar_dfsr(struct target *target, uint32_t *dfar,
- uint32_t *dfsr, uint32_t *dscr)
-{
- int retval;
-
- if (dfar) {
- retval = cortex_a_read_copro(target, ARMV4_5_MRC(15, 0, 0, 6, 0, 0), dfar, dscr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (dfsr) {
- retval = cortex_a_read_copro(target, ARMV4_5_MRC(15, 0, 0, 5, 0, 0), dfsr, dscr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_write_copro(struct target *target, uint32_t opcode,
- uint32_t data, uint32_t *dscr)
-{
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- /* Write the value into DTRRX. */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRRX, data);
- if (retval != ERROR_OK)
- return retval;
-
- /* Move from DTRRX to R0. */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Move from R0 to coprocessor. */
- retval = cortex_a_exec_opcode(target, opcode, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture manual
- * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also
- * check RXfull_l). Most of the time this will be free because RXfull_l
- * will be cleared immediately and cached in dscr. */
- retval = cortex_a_wait_dscr_bits(target, DSCR_DTRRX_FULL_LATCHED, 0, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int cortex_a_write_dfar_dfsr(struct target *target, uint32_t dfar,
- uint32_t dfsr, uint32_t *dscr)
-{
- int retval;
-
- retval = cortex_a_write_copro(target, ARMV4_5_MCR(15, 0, 0, 6, 0, 0), dfar, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- retval = cortex_a_write_copro(target, ARMV4_5_MCR(15, 0, 0, 5, 0, 0), dfsr, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int cortex_a_dfsr_to_error_code(uint32_t dfsr)
-{
- uint32_t status, upper4;
-
- if (dfsr & (1 << 9)) {
- /* LPAE format. */
- status = dfsr & 0x3f;
- upper4 = status >> 2;
- if (upper4 == 1 || upper4 == 2 || upper4 == 3 || upper4 == 15)
- return ERROR_TARGET_TRANSLATION_FAULT;
- else if (status == 33)
- return ERROR_TARGET_UNALIGNED_ACCESS;
- else
- return ERROR_TARGET_DATA_ABORT;
- } else {
- /* Normal format. */
- status = ((dfsr >> 6) & 0x10) | (dfsr & 0xf);
- if (status == 1)
- return ERROR_TARGET_UNALIGNED_ACCESS;
- else if (status == 5 || status == 7 || status == 3 || status == 6 ||
- status == 9 || status == 11 || status == 13 || status == 15)
- return ERROR_TARGET_TRANSLATION_FAULT;
- else
- return ERROR_TARGET_DATA_ABORT;
- }
-}
-
-static int cortex_a_write_cpu_memory_slow(struct target *target,
- uint32_t size, uint32_t count, const uint8_t *buffer, uint32_t *dscr)
-{
- /* Writes count objects of size size from *buffer. Old value of DSCR must
- * be in *dscr; updated to new value. This is slow because it works for
- * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and
- * the address is aligned, cortex_a_write_cpu_memory_fast should be
- * preferred.
- * Preconditions:
- * - Address is in R0.
- * - R0 is marked dirty.
- */
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- int retval;
-
- /* Mark register R1 as dirty, to use for transferring data. */
- arm_reg_current(arm, 1)->dirty = true;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Go through the objects. */
- while (count) {
- /* Write the value to store into DTRRX. */
- uint32_t data, opcode;
- if (size == 1)
- data = *buffer;
- else if (size == 2)
- data = target_buffer_get_u16(target, buffer);
- else
- data = target_buffer_get_u32(target, buffer);
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRRX, data);
- if (retval != ERROR_OK)
- return retval;
-
- /* Transfer the value from DTRRX to R1. */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 1, 0, 5, 0), dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Write the value transferred to R1 into memory. */
- if (size == 1)
- opcode = ARMV4_5_STRB_IP(1, 0);
- else if (size == 2)
- opcode = ARMV4_5_STRH_IP(1, 0);
- else
- opcode = ARMV4_5_STRW_IP(1, 0);
- retval = cortex_a_exec_opcode(target, opcode, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Check for faults and return early. */
- if (*dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE))
- return ERROR_OK; /* A data fault is not considered a system failure. */
-
- /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture
- * manual section C8.4.3, checking InstrCmpl_l is not sufficient; one
- * must also check RXfull_l). Most of the time this will be free
- * because RXfull_l will be cleared immediately and cached in dscr. */
- retval = cortex_a_wait_dscr_bits(target, DSCR_DTRRX_FULL_LATCHED, 0, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Advance. */
- buffer += size;
- --count;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_write_cpu_memory_fast(struct target *target,
- uint32_t count, const uint8_t *buffer, uint32_t *dscr)
-{
- /* Writes count objects of size 4 from *buffer. Old value of DSCR must be
- * in *dscr; updated to new value. This is fast but only works for
- * word-sized objects at aligned addresses.
- * Preconditions:
- * - Address is in R0 and must be a multiple of 4.
- * - R0 is marked dirty.
- */
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval;
-
- /* Switch to fast mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_FAST_MODE, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Latch STC instruction. */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_ITR, ARMV4_5_STC(0, 1, 0, 1, 14, 5, 0, 4));
- if (retval != ERROR_OK)
- return retval;
-
- /* Transfer all the data and issue all the instructions. */
- return mem_ap_write_buf_noincr(armv7a->debug_ap, buffer,
- 4, count, armv7a->debug_base + CPUDBG_DTRRX);
-}
-
-static int cortex_a_write_cpu_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- /* Write memory through the CPU. */
- int retval, final_retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr;
-
- LOG_DEBUG("Writing CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32,
- address, size, count);
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!count)
- return ERROR_OK;
-
- /* Clear any abort. */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
- if (retval != ERROR_OK)
- return retval;
-
- /* Read DSCR. */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr);
- if (retval != ERROR_OK)
- goto out;
-
- /* Mark R0 as dirty. */
- arm_reg_current(arm, 0)->dirty = true;
-
- /* Read DFAR and DFSR, as they will be modified in the event of a fault. */
- retval = cortex_a_read_dfar_dfsr(target, &orig_dfar, &orig_dfsr, &dscr);
- if (retval != ERROR_OK)
- goto out;
-
- /* Get the memory address into R0. */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRRX, address);
- if (retval != ERROR_OK)
- goto out;
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr);
- if (retval != ERROR_OK)
- goto out;
-
- if (size == 4 && (address % 4) == 0) {
- /* We are doing a word-aligned transfer, so use fast mode. */
- retval = cortex_a_write_cpu_memory_fast(target, count, buffer, &dscr);
- } else {
- /* Use slow path. */
- retval = cortex_a_write_cpu_memory_slow(target, size, count, buffer, &dscr);
- }
-
-out:
- final_retval = retval;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr);
- if (final_retval == ERROR_OK)
- final_retval = retval;
-
- /* Wait for last issued instruction to complete. */
- retval = cortex_a_wait_instrcmpl(target, &dscr, true);
- if (final_retval == ERROR_OK)
- final_retval = retval;
-
- /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture manual
- * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also
- * check RXfull_l). Most of the time this will be free because RXfull_l
- * will be cleared immediately and cached in dscr. However, don't do this
- * if there is fault, because then the instruction might not have completed
- * successfully. */
- if (!(dscr & DSCR_STICKY_ABORT_PRECISE)) {
- retval = cortex_a_wait_dscr_bits(target, DSCR_DTRRX_FULL_LATCHED, 0, &dscr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* If there were any sticky abort flags, clear them. */
- if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) {
- fault_dscr = dscr;
- mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
- dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE);
- } else {
- fault_dscr = 0;
- }
-
- /* Handle synchronous data faults. */
- if (fault_dscr & DSCR_STICKY_ABORT_PRECISE) {
- if (final_retval == ERROR_OK) {
- /* Final return value will reflect cause of fault. */
- retval = cortex_a_read_dfar_dfsr(target, &fault_dfar, &fault_dfsr, &dscr);
- if (retval == ERROR_OK) {
- LOG_ERROR("data abort at 0x%08" PRIx32 ", dfsr = 0x%08" PRIx32, fault_dfar, fault_dfsr);
- final_retval = cortex_a_dfsr_to_error_code(fault_dfsr);
- } else
- final_retval = retval;
- }
- /* Fault destroyed DFAR/DFSR; restore them. */
- retval = cortex_a_write_dfar_dfsr(target, orig_dfar, orig_dfsr, &dscr);
- if (retval != ERROR_OK)
- LOG_ERROR("error restoring dfar/dfsr - dscr = 0x%08" PRIx32, dscr);
- }
-
- /* Handle asynchronous data faults. */
- if (fault_dscr & DSCR_STICKY_ABORT_IMPRECISE) {
- if (final_retval == ERROR_OK)
- /* No other error has been recorded so far, so keep this one. */
- final_retval = ERROR_TARGET_DATA_ABORT;
- }
-
- /* If the DCC is nonempty, clear it. */
- if (dscr & DSCR_DTRTX_FULL_LATCHED) {
- uint32_t dummy;
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRTX, &dummy);
- if (final_retval == ERROR_OK)
- final_retval = retval;
- }
- if (dscr & DSCR_DTRRX_FULL_LATCHED) {
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 1, 0, 5, 0), &dscr);
- if (final_retval == ERROR_OK)
- final_retval = retval;
- }
-
- /* Done. */
- return final_retval;
-}
-
-static int cortex_a_read_cpu_memory_slow(struct target *target,
- uint32_t size, uint32_t count, uint8_t *buffer, uint32_t *dscr)
-{
- /* Reads count objects of size size into *buffer. Old value of DSCR must be
- * in *dscr; updated to new value. This is slow because it works for
- * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and
- * the address is aligned, cortex_a_read_cpu_memory_fast should be
- * preferred.
- * Preconditions:
- * - Address is in R0.
- * - R0 is marked dirty.
- */
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- int retval;
-
- /* Mark register R1 as dirty, to use for transferring data. */
- arm_reg_current(arm, 1)->dirty = true;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Go through the objects. */
- while (count) {
- /* Issue a load of the appropriate size to R1. */
- uint32_t opcode, data;
- if (size == 1)
- opcode = ARMV4_5_LDRB_IP(1, 0);
- else if (size == 2)
- opcode = ARMV4_5_LDRH_IP(1, 0);
- else
- opcode = ARMV4_5_LDRW_IP(1, 0);
- retval = cortex_a_exec_opcode(target, opcode, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Issue a write of R1 to DTRTX. */
- retval = cortex_a_exec_opcode(target, ARMV4_5_MCR(14, 0, 1, 0, 5, 0), dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Check for faults and return early. */
- if (*dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE))
- return ERROR_OK; /* A data fault is not considered a system failure. */
-
- /* Wait until DTRTX is full (according to ARMv7-A/-R architecture
- * manual section C8.4.3, checking InstrCmpl_l is not sufficient; one
- * must also check TXfull_l). Most of the time this will be free
- * because TXfull_l will be set immediately and cached in dscr. */
- retval = cortex_a_wait_dscr_bits(target, DSCR_DTRTX_FULL_LATCHED,
- DSCR_DTRTX_FULL_LATCHED, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Read the value transferred to DTRTX into the buffer. */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRTX, &data);
- if (retval != ERROR_OK)
- return retval;
- if (size == 1)
- *buffer = (uint8_t) data;
- else if (size == 2)
- target_buffer_set_u16(target, buffer, (uint16_t) data);
- else
- target_buffer_set_u32(target, buffer, data);
-
- /* Advance. */
- buffer += size;
- --count;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_read_cpu_memory_fast(struct target *target,
- uint32_t count, uint8_t *buffer, uint32_t *dscr)
-{
- /* Reads count objects of size 4 into *buffer. Old value of DSCR must be in
- * *dscr; updated to new value. This is fast but only works for word-sized
- * objects at aligned addresses.
- * Preconditions:
- * - Address is in R0 and must be a multiple of 4.
- * - R0 is marked dirty.
- */
- struct armv7a_common *armv7a = target_to_armv7a(target);
- uint32_t u32;
- int retval;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Issue the LDC instruction via a write to ITR. */
- retval = cortex_a_exec_opcode(target, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4), dscr);
- if (retval != ERROR_OK)
- return retval;
-
- count--;
-
- if (count > 0) {
- /* Switch to fast mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_FAST_MODE, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Latch LDC instruction. */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_ITR, ARMV4_5_LDC(0, 1, 0, 1, 14, 5, 0, 4));
- if (retval != ERROR_OK)
- return retval;
-
- /* Read the value transferred to DTRTX into the buffer. Due to fast
- * mode rules, this blocks until the instruction finishes executing and
- * then reissues the read instruction to read the next word from
- * memory. The last read of DTRTX in this call reads the second-to-last
- * word from memory and issues the read instruction for the last word.
- */
- retval = mem_ap_read_buf_noincr(armv7a->debug_ap, buffer,
- 4, count, armv7a->debug_base + CPUDBG_DTRTX);
- if (retval != ERROR_OK)
- return retval;
-
- /* Advance. */
- buffer += count * 4;
- }
-
- /* Wait for last issued instruction to complete. */
- retval = cortex_a_wait_instrcmpl(target, dscr, false);
- if (retval != ERROR_OK)
- return retval;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Check for faults and return early. */
- if (*dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE))
- return ERROR_OK; /* A data fault is not considered a system failure. */
-
- /* Wait until DTRTX is full (according to ARMv7-A/-R architecture manual
- * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also
- * check TXfull_l). Most of the time this will be free because TXfull_l
- * will be set immediately and cached in dscr. */
- retval = cortex_a_wait_dscr_bits(target, DSCR_DTRTX_FULL_LATCHED,
- DSCR_DTRTX_FULL_LATCHED, dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Read the value transferred to DTRTX into the buffer. This is the last
- * word. */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRTX, &u32);
- if (retval != ERROR_OK)
- return retval;
- target_buffer_set_u32(target, buffer, u32);
-
- return ERROR_OK;
-}
-
-static int cortex_a_read_cpu_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- /* Read memory through the CPU. */
- int retval, final_retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm *arm = &armv7a->arm;
- uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr;
-
- LOG_DEBUG("Reading CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32,
- address, size, count);
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!count)
- return ERROR_OK;
-
- /* Clear any abort. */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
- if (retval != ERROR_OK)
- return retval;
-
- /* Read DSCR */
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr);
- if (retval != ERROR_OK)
- goto out;
-
- /* Mark R0 as dirty. */
- arm_reg_current(arm, 0)->dirty = true;
-
- /* Read DFAR and DFSR, as they will be modified in the event of a fault. */
- retval = cortex_a_read_dfar_dfsr(target, &orig_dfar, &orig_dfsr, &dscr);
- if (retval != ERROR_OK)
- goto out;
-
- /* Get the memory address into R0. */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRRX, address);
- if (retval != ERROR_OK)
- goto out;
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr);
- if (retval != ERROR_OK)
- goto out;
-
- if (size == 4 && (address % 4) == 0) {
- /* We are doing a word-aligned transfer, so use fast mode. */
- retval = cortex_a_read_cpu_memory_fast(target, count, buffer, &dscr);
- } else {
- /* Use slow path. */
- retval = cortex_a_read_cpu_memory_slow(target, size, count, buffer, &dscr);
- }
-
-out:
- final_retval = retval;
-
- /* Switch to non-blocking mode if not already in that mode. */
- retval = cortex_a_set_dcc_mode(target, DSCR_EXT_DCC_NON_BLOCKING, &dscr);
- if (final_retval == ERROR_OK)
- final_retval = retval;
-
- /* Wait for last issued instruction to complete. */
- retval = cortex_a_wait_instrcmpl(target, &dscr, true);
- if (final_retval == ERROR_OK)
- final_retval = retval;
-
- /* If there were any sticky abort flags, clear them. */
- if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) {
- fault_dscr = dscr;
- mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DRCR, DRCR_CLEAR_EXCEPTIONS);
- dscr &= ~(DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE);
- } else {
- fault_dscr = 0;
- }
-
- /* Handle synchronous data faults. */
- if (fault_dscr & DSCR_STICKY_ABORT_PRECISE) {
- if (final_retval == ERROR_OK) {
- /* Final return value will reflect cause of fault. */
- retval = cortex_a_read_dfar_dfsr(target, &fault_dfar, &fault_dfsr, &dscr);
- if (retval == ERROR_OK) {
- LOG_ERROR("data abort at 0x%08" PRIx32 ", dfsr = 0x%08" PRIx32, fault_dfar, fault_dfsr);
- final_retval = cortex_a_dfsr_to_error_code(fault_dfsr);
- } else
- final_retval = retval;
- }
- /* Fault destroyed DFAR/DFSR; restore them. */
- retval = cortex_a_write_dfar_dfsr(target, orig_dfar, orig_dfsr, &dscr);
- if (retval != ERROR_OK)
- LOG_ERROR("error restoring dfar/dfsr - dscr = 0x%08" PRIx32, dscr);
- }
-
- /* Handle asynchronous data faults. */
- if (fault_dscr & DSCR_STICKY_ABORT_IMPRECISE) {
- if (final_retval == ERROR_OK)
- /* No other error has been recorded so far, so keep this one. */
- final_retval = ERROR_TARGET_DATA_ABORT;
- }
-
- /* If the DCC is nonempty, clear it. */
- if (dscr & DSCR_DTRTX_FULL_LATCHED) {
- uint32_t dummy;
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRTX, &dummy);
- if (final_retval == ERROR_OK)
- final_retval = retval;
- }
- if (dscr & DSCR_DTRRX_FULL_LATCHED) {
- retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 1, 0, 5, 0), &dscr);
- if (final_retval == ERROR_OK)
- final_retval = retval;
- }
-
- /* Done. */
- return final_retval;
-}
-
-
-/*
- * Cortex-A Memory access
- *
- * This is same Cortex-M3 but we must also use the correct
- * ap number for every access.
- */
-
-static int cortex_a_read_phys_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, uint8_t *buffer)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct adiv5_dap *swjdp = armv7a->arm.dap;
- uint8_t apsel = swjdp->apsel;
- int retval;
-
- if (!count || !buffer)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32,
- address, size, count);
-
- if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num))
- return mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address);
-
- /* read memory through the CPU */
- cortex_a_prep_memaccess(target, 1);
- retval = cortex_a_read_cpu_memory(target, address, size, count, buffer);
- cortex_a_post_memaccess(target, 1);
-
- return retval;
-}
-
-static int cortex_a_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- int retval;
-
- /* cortex_a handles unaligned memory access */
- LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
- size, count);
-
- cortex_a_prep_memaccess(target, 0);
- retval = cortex_a_read_cpu_memory(target, address, size, count, buffer);
- cortex_a_post_memaccess(target, 0);
-
- return retval;
-}
-
-static int cortex_a_read_memory_ahb(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- int mmu_enabled = 0;
- uint32_t virt, phys;
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct adiv5_dap *swjdp = armv7a->arm.dap;
- uint8_t apsel = swjdp->apsel;
-
- if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num))
- return target_read_memory(target, address, size, count, buffer);
-
- /* cortex_a handles unaligned memory access */
- LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
- size, count);
-
- /* determine if MMU was enabled on target stop */
- if (!armv7a->is_armv7r) {
- retval = cortex_a_mmu(target, &mmu_enabled);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (mmu_enabled) {
- virt = address;
- retval = cortex_a_virt2phys(target, virt, &phys);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
- virt, phys);
- address = phys;
- }
-
- if (!count || !buffer)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- retval = mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address);
-
- return retval;
-}
-
-static int cortex_a_write_phys_memory(struct target *target,
- uint32_t address, uint32_t size,
- uint32_t count, const uint8_t *buffer)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct adiv5_dap *swjdp = armv7a->arm.dap;
- uint8_t apsel = swjdp->apsel;
- int retval;
-
- if (!count || !buffer)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
- size, count);
-
- if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num))
- return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address);
-
- /* write memory through the CPU */
- cortex_a_prep_memaccess(target, 1);
- retval = cortex_a_write_cpu_memory(target, address, size, count, buffer);
- cortex_a_post_memaccess(target, 1);
-
- return retval;
-}
-
-static int cortex_a_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- int retval;
-
- /* cortex_a handles unaligned memory access */
- LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
- size, count);
-
- /* memory writes bypass the caches, must flush before writing */
- armv7a_cache_auto_flush_on_write(target, address, size * count);
-
- cortex_a_prep_memaccess(target, 0);
- retval = cortex_a_write_cpu_memory(target, address, size, count, buffer);
- cortex_a_post_memaccess(target, 0);
- return retval;
-}
-
-static int cortex_a_write_memory_ahb(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- int mmu_enabled = 0;
- uint32_t virt, phys;
- int retval;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct adiv5_dap *swjdp = armv7a->arm.dap;
- uint8_t apsel = swjdp->apsel;
-
- if (!armv7a->memory_ap_available || (apsel != armv7a->memory_ap->ap_num))
- return target_write_memory(target, address, size, count, buffer);
-
- /* cortex_a handles unaligned memory access */
- LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address,
- size, count);
-
- /* determine if MMU was enabled on target stop */
- if (!armv7a->is_armv7r) {
- retval = cortex_a_mmu(target, &mmu_enabled);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (mmu_enabled) {
- virt = address;
- retval = cortex_a_virt2phys(target, virt, &phys);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32,
- virt,
- phys);
- address = phys;
- }
-
- if (!count || !buffer)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- retval = mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address);
-
- return retval;
-}
-
-static int cortex_a_read_buffer(struct target *target, uint32_t address,
- uint32_t count, uint8_t *buffer)
-{
- uint32_t size;
-
- /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
- * will have something to do with the size we leave to it. */
- for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
- if (address & size) {
- int retval = cortex_a_read_memory_ahb(target, address, size, 1, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += size;
- count -= size;
- buffer += size;
- }
- }
-
- /* Read the data with as large access size as possible. */
- for (; size > 0; size /= 2) {
- uint32_t aligned = count - count % size;
- if (aligned > 0) {
- int retval = cortex_a_read_memory_ahb(target, address, size, aligned / size, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += aligned;
- count -= aligned;
- buffer += aligned;
- }
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_write_buffer(struct target *target, uint32_t address,
- uint32_t count, const uint8_t *buffer)
-{
- uint32_t size;
-
- /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
- * will have something to do with the size we leave to it. */
- for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
- if (address & size) {
- int retval = cortex_a_write_memory_ahb(target, address, size, 1, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += size;
- count -= size;
- buffer += size;
- }
- }
-
- /* Write the data with as large access size as possible. */
- for (; size > 0; size /= 2) {
- uint32_t aligned = count - count % size;
- if (aligned > 0) {
- int retval = cortex_a_write_memory_ahb(target, address, size, aligned / size, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += aligned;
- count -= aligned;
- buffer += aligned;
- }
- }
-
- return ERROR_OK;
-}
-
-static int cortex_a_handle_target_request(void *priv)
-{
- struct target *target = priv;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- int retval;
-
- if (!target_was_examined(target))
- return ERROR_OK;
- if (!target->dbg_msg_enabled)
- return ERROR_OK;
-
- if (target->state == TARGET_RUNNING) {
- uint32_t request;
- uint32_t dscr;
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
-
- /* check if we have data */
- int64_t then = timeval_ms();
- while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) {
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DTRTX, &request);
- if (retval == ERROR_OK) {
- target_request(target, request);
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DSCR, &dscr);
- }
- if (timeval_ms() > then + 1000) {
- LOG_ERROR("Timeout waiting for dtr tx full");
- return ERROR_FAIL;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-/*
- * Cortex-A target information and configuration
- */
-
-static int cortex_a_examine_first(struct target *target)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
- struct adiv5_dap *swjdp = armv7a->arm.dap;
- int i;
- int retval = ERROR_OK;
- uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg;
-
- retval = dap_dp_init(swjdp);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not initialize the debug port");
- return retval;
- }
-
- /* Search for the APB-AP - it is needed for access to debug registers */
- retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not find APB-AP for debug access");
- return retval;
- }
-
- retval = mem_ap_init(armv7a->debug_ap);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not initialize the APB-AP");
- return retval;
- }
-
- armv7a->debug_ap->memaccess_tck = 80;
-
- /* Search for the AHB-AB.
- * REVISIT: We should search for AXI-AP as well and make sure the AP's MEMTYPE says it
- * can access system memory. */
- armv7a->memory_ap_available = false;
- retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap);
- if (retval == ERROR_OK) {
- retval = mem_ap_init(armv7a->memory_ap);
- if (retval == ERROR_OK)
- armv7a->memory_ap_available = true;
- }
- if (retval != ERROR_OK) {
- /* AHB-AP not found or unavailable - use the CPU */
- LOG_DEBUG("No AHB-AP available for memory access");
- }
-
- if (!target->dbgbase_set) {
- uint32_t dbgbase;
- /* Get ROM Table base */
- uint32_t apid;
- int32_t coreidx = target->coreid;
- LOG_DEBUG("%s's dbgbase is not set, trying to detect using the ROM table",
- target->cmd_name);
- retval = dap_get_debugbase(armv7a->debug_ap, &dbgbase, &apid);
- if (retval != ERROR_OK)
- return retval;
- /* Lookup 0x15 -- Processor DAP */
- retval = dap_lookup_cs_component(armv7a->debug_ap, dbgbase, 0x15,
- &armv7a->debug_base, &coreidx);
- if (retval != ERROR_OK) {
- LOG_ERROR("Can't detect %s's dbgbase from the ROM table; you need to specify it explicitly.",
- target->cmd_name);
- return retval;
- }
- LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32,
- target->coreid, armv7a->debug_base);
- } else
- armv7a->debug_base = target->dbgbase;
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_CPUID, &cpuid);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_CPUID, &cpuid);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "CPUID");
- return retval;
- }
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_CTYPR, &ctypr);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "CTYPR");
- return retval;
- }
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_TTYPR, &ttypr);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "TTYPR");
- return retval;
- }
-
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_DIDR, &didr);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Examine %s failed", "DIDR");
- return retval;
- }
-
- LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
- LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr);
- LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
- LOG_DEBUG("didr = 0x%08" PRIx32, didr);
-
- cortex_a->cpuid = cpuid;
- cortex_a->ctypr = ctypr;
- cortex_a->ttypr = ttypr;
- cortex_a->didr = didr;
-
- /* Unlocking the debug registers */
- if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
- CORTEX_A15_PARTNUM) {
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLAR,
- 0);
-
- if (retval != ERROR_OK)
- return retval;
-
- }
- /* Unlocking the debug registers */
- if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==
- CORTEX_A7_PARTNUM) {
-
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_OSLAR,
- 0);
-
- if (retval != ERROR_OK)
- return retval;
-
- }
- retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
- armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);
-
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg);
-
- armv7a->arm.core_type = ARM_MODE_MON;
-
- /* Avoid recreating the registers cache */
- if (!target_was_examined(target)) {
- retval = cortex_a_dpm_setup(cortex_a, didr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* Setup Breakpoint Register Pairs */
- cortex_a->brp_num = ((didr >> 24) & 0x0F) + 1;
- cortex_a->brp_num_context = ((didr >> 20) & 0x0F) + 1;
- cortex_a->brp_num_available = cortex_a->brp_num;
- free(cortex_a->brp_list);
- cortex_a->brp_list = calloc(cortex_a->brp_num, sizeof(struct cortex_a_brp));
-/* cortex_a->brb_enabled = ????; */
- for (i = 0; i < cortex_a->brp_num; i++) {
- cortex_a->brp_list[i].used = 0;
- if (i < (cortex_a->brp_num-cortex_a->brp_num_context))
- cortex_a->brp_list[i].type = BRP_NORMAL;
- else
- cortex_a->brp_list[i].type = BRP_CONTEXT;
- cortex_a->brp_list[i].value = 0;
- cortex_a->brp_list[i].control = 0;
- cortex_a->brp_list[i].BRPn = i;
- }
-
- LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num);
-
- /* select debug_ap as default */
- swjdp->apsel = armv7a->debug_ap->ap_num;
-
- target_set_examined(target);
- return ERROR_OK;
-}
-
-static int cortex_a_examine(struct target *target)
-{
- int retval = ERROR_OK;
-
- /* Reestablish communication after target reset */
- retval = cortex_a_examine_first(target);
-
- /* Configure core debug access */
- if (retval == ERROR_OK)
- retval = cortex_a_init_debug_access(target);
-
- return retval;
-}
-
-/*
- * Cortex-A target creation and initialization
- */
-
-static int cortex_a_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- /* examine_first() does a bunch of this */
- return ERROR_OK;
-}
-
-static int cortex_a_init_arch_info(struct target *target,
- struct cortex_a_common *cortex_a, struct jtag_tap *tap)
-{
- struct armv7a_common *armv7a = &cortex_a->armv7a_common;
-
- /* Setup struct cortex_a_common */
- cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
-
- /* tap has no dap initialized */
- if (!tap->dap) {
- tap->dap = dap_init();
-
- /* Leave (only) generic DAP stuff for debugport_init() */
- tap->dap->tap = tap;
- }
-
- armv7a->arm.dap = tap->dap;
-
- cortex_a->fast_reg_read = 0;
-
- /* register arch-specific functions */
- armv7a->examine_debug_reason = NULL;
-
- armv7a->post_debug_entry = cortex_a_post_debug_entry;
-
- armv7a->pre_restore_context = NULL;
-
- armv7a->armv7a_mmu.read_physical_memory = cortex_a_read_phys_memory;
-
-
-/* arm7_9->handle_target_request = cortex_a_handle_target_request; */
-
- /* REVISIT v7a setup should be in a v7a-specific routine */
- armv7a_init_arch_info(target, armv7a);
- target_register_timer_callback(cortex_a_handle_target_request, 1, 1, target);
-
- return ERROR_OK;
-}
-
-static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
-{
- struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
-
- cortex_a->armv7a_common.is_armv7r = false;
-
- return cortex_a_init_arch_info(target, cortex_a, target->tap);
-}
-
-static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
-{
- struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
-
- cortex_a->armv7a_common.is_armv7r = true;
-
- return cortex_a_init_arch_info(target, cortex_a, target->tap);
-}
-
-static void cortex_a_deinit_target(struct target *target)
-{
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
- struct arm_dpm *dpm = &cortex_a->armv7a_common.dpm;
-
- free(cortex_a->brp_list);
- free(dpm->dbp);
- free(dpm->dwp);
- free(cortex_a);
-}
-
-static int cortex_a_mmu(struct target *target, int *enabled)
-{
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("%s: target not halted", __func__);
- return ERROR_TARGET_INVALID;
- }
-
- if (armv7a->is_armv7r)
- *enabled = 0;
- else
- *enabled = target_to_cortex_a(target)->armv7a_common.armv7a_mmu.mmu_enabled;
-
- return ERROR_OK;
-}
-
-static int cortex_a_virt2phys(struct target *target,
- uint32_t virt, uint32_t *phys)
-{
- int retval = ERROR_FAIL;
- struct armv7a_common *armv7a = target_to_armv7a(target);
- struct adiv5_dap *swjdp = armv7a->arm.dap;
- uint8_t apsel = swjdp->apsel;
- if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) {
- uint32_t ret;
- retval = armv7a_mmu_translate_va(target,
- virt, &ret);
- if (retval != ERROR_OK)
- goto done;
- *phys = ret;
- } else {/* use this method if armv7a->memory_ap not selected
- * mmu must be enable in order to get a correct translation */
- retval = cortex_a_mmu_modify(target, 1);
- if (retval != ERROR_OK)
- goto done;
- retval = armv7a_mmu_translate_va_pa(target, virt, phys, 1);
- }
-done:
- return retval;
-}
-
-COMMAND_HANDLER(cortex_a_handle_cache_info_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct armv7a_common *armv7a = target_to_armv7a(target);
-
- return armv7a_handle_cache_info_command(CMD_CTX,
- &armv7a->armv7a_mmu.armv7a_cache);
-}
-
-
-COMMAND_HANDLER(cortex_a_handle_dbginit_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- if (!target_was_examined(target)) {
- LOG_ERROR("target not examined yet");
- return ERROR_FAIL;
- }
-
- return cortex_a_init_debug_access(target);
-}
-COMMAND_HANDLER(cortex_a_handle_smp_off_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- /* check target is an smp target */
- struct target_list *head;
- struct target *curr;
- head = target->head;
- target->smp = 0;
- if (head != (struct target_list *)NULL) {
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- curr->smp = 0;
- head = head->next;
- }
- /* fixes the target display to the debugger */
- target->gdb_service->target = target;
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_on_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct target_list *head;
- struct target *curr;
- head = target->head;
- if (head != (struct target_list *)NULL) {
- target->smp = 1;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- curr->smp = 1;
- head = head->next;
- }
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_gdb_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- int retval = ERROR_OK;
- struct target_list *head;
- head = target->head;
- if (head != (struct target_list *)NULL) {
- if (CMD_ARGC == 1) {
- int coreid = 0;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);
- if (ERROR_OK != retval)
- return retval;
- target->gdb_service->core[1] = coreid;
-
- }
- command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
- , target->gdb_service->core[1]);
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- static const Jim_Nvp nvp_maskisr_modes[] = {
- { .name = "off", .value = CORTEX_A_ISRMASK_OFF },
- { .name = "on", .value = CORTEX_A_ISRMASK_ON },
- { .name = NULL, .value = -1 },
- };
- const Jim_Nvp *n;
-
- if (CMD_ARGC > 0) {
- n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
- if (n->name == NULL) {
- LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- cortex_a->isrmasking_mode = n->value;
- }
-
- n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
- command_print(CMD_CTX, "cortex_a interrupt mask %s", n->name);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_cortex_a_dacrfixup_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-
- static const Jim_Nvp nvp_dacrfixup_modes[] = {
- { .name = "off", .value = CORTEX_A_DACRFIXUP_OFF },
- { .name = "on", .value = CORTEX_A_DACRFIXUP_ON },
- { .name = NULL, .value = -1 },
- };
- const Jim_Nvp *n;
-
- if (CMD_ARGC > 0) {
- n = Jim_Nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
- if (n->name == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
- cortex_a->dacrfixup_mode = n->value;
-
- }
-
- n = Jim_Nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
- command_print(CMD_CTX, "cortex_a domain access control fixup %s", n->name);
-
- return ERROR_OK;
-}
-
-static const struct command_registration cortex_a_exec_command_handlers[] = {
- {
- .name = "cache_info",
- .handler = cortex_a_handle_cache_info_command,
- .mode = COMMAND_EXEC,
- .help = "display information about target caches",
- .usage = "",
- },
- {
- .name = "dbginit",
- .handler = cortex_a_handle_dbginit_command,
- .mode = COMMAND_EXEC,
- .help = "Initialize core debug",
- .usage = "",
- },
- { .name = "smp_off",
- .handler = cortex_a_handle_smp_off_command,
- .mode = COMMAND_EXEC,
- .help = "Stop smp handling",
- .usage = "",},
- {
- .name = "smp_on",
- .handler = cortex_a_handle_smp_on_command,
- .mode = COMMAND_EXEC,
- .help = "Restart smp handling",
- .usage = "",
- },
- {
- .name = "smp_gdb",
- .handler = cortex_a_handle_smp_gdb_command,
- .mode = COMMAND_EXEC,
- .help = "display/fix current core played to gdb",
- .usage = "",
- },
- {
- .name = "maskisr",
- .handler = handle_cortex_a_mask_interrupts_command,
- .mode = COMMAND_ANY,
- .help = "mask cortex_a interrupts",
- .usage = "['on'|'off']",
- },
- {
- .name = "dacrfixup",
- .handler = handle_cortex_a_dacrfixup_command,
- .mode = COMMAND_EXEC,
- .help = "set domain access control (DACR) to all-manager "
- "on memory access",
- .usage = "['on'|'off']",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration cortex_a_command_handlers[] = {
- {
- .chain = arm_command_handlers,
- },
- {
- .chain = armv7a_command_handlers,
- },
- {
- .name = "cortex_a",
- .mode = COMMAND_ANY,
- .help = "Cortex-A command group",
- .usage = "",
- .chain = cortex_a_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct target_type cortexa_target = {
- .name = "cortex_a",
- .deprecated_name = "cortex_a8",
-
- .poll = cortex_a_poll,
- .arch_state = armv7a_arch_state,
-
- .halt = cortex_a_halt,
- .resume = cortex_a_resume,
- .step = cortex_a_step,
-
- .assert_reset = cortex_a_assert_reset,
- .deassert_reset = cortex_a_deassert_reset,
-
- /* REVISIT allow exporting VFP3 registers ... */
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = cortex_a_read_memory,
- .write_memory = cortex_a_write_memory,
-
- .read_buffer = cortex_a_read_buffer,
- .write_buffer = cortex_a_write_buffer,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = cortex_a_add_breakpoint,
- .add_context_breakpoint = cortex_a_add_context_breakpoint,
- .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint,
- .remove_breakpoint = cortex_a_remove_breakpoint,
- .add_watchpoint = NULL,
- .remove_watchpoint = NULL,
-
- .commands = cortex_a_command_handlers,
- .target_create = cortex_a_target_create,
- .init_target = cortex_a_init_target,
- .examine = cortex_a_examine,
- .deinit_target = cortex_a_deinit_target,
-
- .read_phys_memory = cortex_a_read_phys_memory,
- .write_phys_memory = cortex_a_write_phys_memory,
- .mmu = cortex_a_mmu,
- .virt2phys = cortex_a_virt2phys,
-};
-
-static const struct command_registration cortex_r4_exec_command_handlers[] = {
- {
- .name = "cache_info",
- .handler = cortex_a_handle_cache_info_command,
- .mode = COMMAND_EXEC,
- .help = "display information about target caches",
- .usage = "",
- },
- {
- .name = "dbginit",
- .handler = cortex_a_handle_dbginit_command,
- .mode = COMMAND_EXEC,
- .help = "Initialize core debug",
- .usage = "",
- },
- {
- .name = "maskisr",
- .handler = handle_cortex_a_mask_interrupts_command,
- .mode = COMMAND_EXEC,
- .help = "mask cortex_r4 interrupts",
- .usage = "['on'|'off']",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration cortex_r4_command_handlers[] = {
- {
- .chain = arm_command_handlers,
- },
- {
- .chain = armv7a_command_handlers,
- },
- {
- .name = "cortex_r4",
- .mode = COMMAND_ANY,
- .help = "Cortex-R4 command group",
- .usage = "",
- .chain = cortex_r4_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct target_type cortexr4_target = {
- .name = "cortex_r4",
-
- .poll = cortex_a_poll,
- .arch_state = armv7a_arch_state,
-
- .halt = cortex_a_halt,
- .resume = cortex_a_resume,
- .step = cortex_a_step,
-
- .assert_reset = cortex_a_assert_reset,
- .deassert_reset = cortex_a_deassert_reset,
-
- /* REVISIT allow exporting VFP3 registers ... */
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = cortex_a_read_memory,
- .write_memory = cortex_a_write_memory,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = cortex_a_add_breakpoint,
- .add_context_breakpoint = cortex_a_add_context_breakpoint,
- .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint,
- .remove_breakpoint = cortex_a_remove_breakpoint,
- .add_watchpoint = NULL,
- .remove_watchpoint = NULL,
-
- .commands = cortex_r4_command_handlers,
- .target_create = cortex_r4_target_create,
- .init_target = cortex_a_init_target,
- .examine = cortex_a_examine,
- .deinit_target = cortex_a_deinit_target,
-};
diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h
deleted file mode 100644
index ea08c67..0000000
--- a/src/target/cortex_a.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2009 by Dirk Behme *
- * dirk.behme@gmail.com - copy from cortex_m3 *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_CORTEX_A_H
-#define OPENOCD_TARGET_CORTEX_A_H
-
-#include "armv7a.h"
-
-#define CORTEX_A_COMMON_MAGIC 0x411fc082
-#define CORTEX_A15_COMMON_MAGIC 0x413fc0f1
-
-#define CORTEX_A5_PARTNUM 0xc05
-#define CORTEX_A7_PARTNUM 0xc07
-#define CORTEX_A8_PARTNUM 0xc08
-#define CORTEX_A9_PARTNUM 0xc09
-#define CORTEX_A15_PARTNUM 0xc0f
-#define CORTEX_A_MIDR_PARTNUM_MASK 0x0000fff0
-#define CORTEX_A_MIDR_PARTNUM_SHIFT 4
-
-#define CPUDBG_CPUID 0xD00
-#define CPUDBG_CTYPR 0xD04
-#define CPUDBG_TTYPR 0xD0C
-#define CPUDBG_LOCKACCESS 0xFB0
-#define CPUDBG_LOCKSTATUS 0xFB4
-#define CPUDBG_OSLAR_LK_MASK (1 << 1)
-
-#define BRP_NORMAL 0
-#define BRP_CONTEXT 1
-
-#define CORTEX_A_PADDRDBG_CPU_SHIFT 13
-
-enum cortex_a_isrmasking_mode {
- CORTEX_A_ISRMASK_OFF,
- CORTEX_A_ISRMASK_ON,
-};
-
-enum cortex_a_dacrfixup_mode {
- CORTEX_A_DACRFIXUP_OFF,
- CORTEX_A_DACRFIXUP_ON
-};
-
-struct cortex_a_brp {
- int used;
- int type;
- uint32_t value;
- uint32_t control;
- uint8_t BRPn;
-};
-
-struct cortex_a_common {
- int common_magic;
-
- /* Context information */
- uint32_t cpudbg_dscr;
-
- /* Saved cp15 registers */
- uint32_t cp15_control_reg;
- /* latest cp15 register value written and cpsr processor mode */
- uint32_t cp15_control_reg_curr;
- /* auxiliary control reg */
- uint32_t cp15_aux_control_reg;
- /* DACR */
- uint32_t cp15_dacr_reg;
- enum arm_mode curr_mode;
-
- /* Breakpoint register pairs */
- int brp_num_context;
- int brp_num;
- int brp_num_available;
- struct cortex_a_brp *brp_list;
-
- /* Use cortex_a_read_regs_through_mem for fast register reads */
- int fast_reg_read;
-
- uint32_t cpuid;
- uint32_t ctypr;
- uint32_t ttypr;
- uint32_t didr;
-
- enum cortex_a_isrmasking_mode isrmasking_mode;
- enum cortex_a_dacrfixup_mode dacrfixup_mode;
-
- struct armv7a_common armv7a_common;
-
-};
-
-static inline struct cortex_a_common *
-target_to_cortex_a(struct target *target)
-{
- return container_of(target->arch_info, struct cortex_a_common, armv7a_common.arm);
-}
-
-#endif /* OPENOCD_TARGET_CORTEX_A_H */
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
deleted file mode 100644
index a6a9309..0000000
--- a/src/target/cortex_m.c
+++ /dev/null
@@ -1,2429 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- * *
- * *
- * Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0) *
- * *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/interface.h"
-#include "breakpoints.h"
-#include "cortex_m.h"
-#include "target_request.h"
-#include "target_type.h"
-#include "arm_disassembler.h"
-#include "register.h"
-#include "arm_opcodes.h"
-#include "arm_semihosting.h"
-#include <helper/time_support.h>
-
-/* NOTE: most of this should work fine for the Cortex-M1 and
- * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
- * Some differences: M0/M1 doesn't have FBP remapping or the
- * DWT tracing/profiling support. (So the cycle counter will
- * not be usable; the other stuff isn't currently used here.)
- *
- * Although there are some workarounds for errata seen only in r0p0
- * silicon, such old parts are hard to find and thus not much tested
- * any longer.
- */
-
-/**
- * Returns the type of a break point required by address location
- */
-#define BKPT_TYPE_BY_ADDR(addr) ((addr) < 0x20000000 ? BKPT_HARD : BKPT_SOFT)
-
-/* forward declarations */
-static int cortex_m_store_core_reg_u32(struct target *target,
- uint32_t num, uint32_t value);
-static void cortex_m_dwt_free(struct target *target);
-
-static int cortexm_dap_read_coreregister_u32(struct target *target,
- uint32_t *value, int regnum)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- int retval;
- uint32_t dcrdr;
-
- /* because the DCB_DCRDR is used for the emulated dcc channel
- * we have to save/restore the DCB_DCRDR when used */
- if (target->dbg_msg_enabled) {
- retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, &dcrdr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regnum);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->dbg_msg_enabled) {
- /* restore DCB_DCRDR - this needs to be in a separate
- * transaction otherwise the emulated DCC channel breaks */
- if (retval == ERROR_OK)
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr);
- }
-
- return retval;
-}
-
-static int cortexm_dap_write_coreregister_u32(struct target *target,
- uint32_t value, int regnum)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- int retval;
- uint32_t dcrdr;
-
- /* because the DCB_DCRDR is used for the emulated dcc channel
- * we have to save/restore the DCB_DCRDR when used */
- if (target->dbg_msg_enabled) {
- retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, &dcrdr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regnum | DCRSR_WnR);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->dbg_msg_enabled) {
- /* restore DCB_DCRDR - this needs to be in a seperate
- * transaction otherwise the emulated DCC channel breaks */
- if (retval == ERROR_OK)
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr);
- }
-
- return retval;
-}
-
-static int cortex_m_write_debug_halt_mask(struct target *target,
- uint32_t mask_on, uint32_t mask_off)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
-
- /* mask off status bits */
- cortex_m->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
- /* create new register mask */
- cortex_m->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on;
-
- return mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR, cortex_m->dcb_dhcsr);
-}
-
-static int cortex_m_clear_halt(struct target *target)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- int retval;
-
- /* clear step if any */
- cortex_m_write_debug_halt_mask(target, C_HALT, C_STEP);
-
- /* Read Debug Fault Status Register */
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_DFSR, &cortex_m->nvic_dfsr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Clear Debug Fault Status */
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_DFSR, cortex_m->nvic_dfsr);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m->nvic_dfsr);
-
- return ERROR_OK;
-}
-
-static int cortex_m_single_step_core(struct target *target)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- uint32_t dhcsr_save;
- int retval;
-
- /* backup dhcsr reg */
- dhcsr_save = cortex_m->dcb_dhcsr;
-
- /* Mask interrupts before clearing halt, if done already. This avoids
- * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
- * HALT can put the core into an unknown state.
- */
- if (!(cortex_m->dcb_dhcsr & C_MASKINTS)) {
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
- DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
- DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG(" ");
-
- /* restore dhcsr reg */
- cortex_m->dcb_dhcsr = dhcsr_save;
- cortex_m_clear_halt(target);
-
- return ERROR_OK;
-}
-
-static int cortex_m_enable_fpb(struct target *target)
-{
- int retval = target_write_u32(target, FP_CTRL, 3);
- if (retval != ERROR_OK)
- return retval;
-
- /* check the fpb is actually enabled */
- uint32_t fpctrl;
- retval = target_read_u32(target, FP_CTRL, &fpctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if (fpctrl & 1)
- return ERROR_OK;
-
- return ERROR_FAIL;
-}
-
-static int cortex_m_endreset_event(struct target *target)
-{
- int i;
- int retval;
- uint32_t dcb_demcr;
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
- struct cortex_m_fp_comparator *fp_list = cortex_m->fp_comparator_list;
- struct cortex_m_dwt_comparator *dwt_list = cortex_m->dwt_comparator_list;
-
- /* REVISIT The four debug monitor bits are currently ignored... */
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &dcb_demcr);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "", dcb_demcr);
-
- /* this register is used for emulated dcc channel */
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0);
- if (retval != ERROR_OK)
- return retval;
-
- /* Enable debug requests */
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
- if (retval != ERROR_OK)
- return retval;
- if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* clear any interrupt masking */
- cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS);
-
- /* Enable features controlled by ITM and DWT blocks, and catch only
- * the vectors we were told to pay attention to.
- *
- * Target firmware is responsible for all fault handling policy
- * choices *EXCEPT* explicitly scripted overrides like "vector_catch"
- * or manual updates to the NVIC SHCSR and CCR registers.
- */
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR, TRCENA | armv7m->demcr);
- if (retval != ERROR_OK)
- return retval;
-
- /* Paranoia: evidently some (early?) chips don't preserve all the
- * debug state (including FBP, DWT, etc) across reset...
- */
-
- /* Enable FPB */
- retval = cortex_m_enable_fpb(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Failed to enable the FPB");
- return retval;
- }
-
- cortex_m->fpb_enabled = 1;
-
- /* Restore FPB registers */
- for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
- retval = target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* Restore DWT registers */
- for (i = 0; i < cortex_m->dwt_num_comp; i++) {
- retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 0,
- dwt_list[i].comp);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 4,
- dwt_list[i].mask);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 8,
- dwt_list[i].function);
- if (retval != ERROR_OK)
- return retval;
- }
- retval = dap_run(swjdp);
- if (retval != ERROR_OK)
- return retval;
-
- register_cache_invalidate(armv7m->arm.core_cache);
-
- /* make sure we have latest dhcsr flags */
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
-
- return retval;
-}
-
-static int cortex_m_examine_debug_reason(struct target *target)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
-
- /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason
- * only check the debug reason if we don't know it already */
-
- if ((target->debug_reason != DBG_REASON_DBGRQ)
- && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
- if (cortex_m->nvic_dfsr & DFSR_BKPT) {
- target->debug_reason = DBG_REASON_BREAKPOINT;
- if (cortex_m->nvic_dfsr & DFSR_DWTTRAP)
- target->debug_reason = DBG_REASON_WPTANDBKPT;
- } else if (cortex_m->nvic_dfsr & DFSR_DWTTRAP)
- target->debug_reason = DBG_REASON_WATCHPOINT;
- else if (cortex_m->nvic_dfsr & DFSR_VCATCH)
- target->debug_reason = DBG_REASON_BREAKPOINT;
- else /* EXTERNAL, HALTED */
- target->debug_reason = DBG_REASON_UNDEFINED;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_examine_exception_reason(struct target *target)
-{
- uint32_t shcsr = 0, except_sr = 0, cfsr = -1, except_ar = -1;
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct adiv5_dap *swjdp = armv7m->arm.dap;
- int retval;
-
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_SHCSR, &shcsr);
- if (retval != ERROR_OK)
- return retval;
- switch (armv7m->exception_number) {
- case 2: /* NMI */
- break;
- case 3: /* Hard Fault */
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_HFSR, &except_sr);
- if (retval != ERROR_OK)
- return retval;
- if (except_sr & 0x40000000) {
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_CFSR, &cfsr);
- if (retval != ERROR_OK)
- return retval;
- }
- break;
- case 4: /* Memory Management */
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_CFSR, &except_sr);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_MMFAR, &except_ar);
- if (retval != ERROR_OK)
- return retval;
- break;
- case 5: /* Bus Fault */
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_CFSR, &except_sr);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_BFAR, &except_ar);
- if (retval != ERROR_OK)
- return retval;
- break;
- case 6: /* Usage Fault */
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_CFSR, &except_sr);
- if (retval != ERROR_OK)
- return retval;
- break;
- case 11: /* SVCall */
- break;
- case 12: /* Debug Monitor */
- retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_DFSR, &except_sr);
- if (retval != ERROR_OK)
- return retval;
- break;
- case 14: /* PendSV */
- break;
- case 15: /* SysTick */
- break;
- default:
- except_sr = 0;
- break;
- }
- retval = dap_run(swjdp);
- if (retval == ERROR_OK)
- LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32
- ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32,
- armv7m_exception_string(armv7m->exception_number),
- shcsr, except_sr, cfsr, except_ar);
- return retval;
-}
-
-static int cortex_m_debug_entry(struct target *target)
-{
- int i;
- uint32_t xPSR;
- int retval;
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- struct arm *arm = &armv7m->arm;
- struct reg *r;
-
- LOG_DEBUG(" ");
-
- cortex_m_clear_halt(target);
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
- if (retval != ERROR_OK)
- return retval;
-
- retval = armv7m->examine_debug_reason(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* Examine target state and mode
- * First load register accessible through core debug port */
- int num_regs = arm->core_cache->num_regs;
-
- for (i = 0; i < num_regs; i++) {
- r = &armv7m->arm.core_cache->reg_list[i];
- if (!r->valid)
- arm->read_core_reg(target, r, i, ARM_MODE_ANY);
- }
-
- r = arm->cpsr;
- xPSR = buf_get_u32(r->value, 0, 32);
-
- /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
- if (xPSR & 0xf00) {
- r->dirty = r->valid;
- cortex_m_store_core_reg_u32(target, 16, xPSR & ~0xff);
- }
-
- /* Are we in an exception handler */
- if (xPSR & 0x1FF) {
- armv7m->exception_number = (xPSR & 0x1FF);
-
- arm->core_mode = ARM_MODE_HANDLER;
- arm->map = armv7m_msp_reg_map;
- } else {
- unsigned control = buf_get_u32(arm->core_cache
- ->reg_list[ARMV7M_CONTROL].value, 0, 2);
-
- /* is this thread privileged? */
- arm->core_mode = control & 1
- ? ARM_MODE_USER_THREAD
- : ARM_MODE_THREAD;
-
- /* which stack is it using? */
- if (control & 2)
- arm->map = armv7m_psp_reg_map;
- else
- arm->map = armv7m_msp_reg_map;
-
- armv7m->exception_number = 0;
- }
-
- if (armv7m->exception_number)
- cortex_m_examine_exception_reason(target);
-
- LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
- arm_mode_name(arm->core_mode),
- buf_get_u32(arm->pc->value, 0, 32),
- target_state_name(target));
-
- if (armv7m->post_debug_entry) {
- retval = armv7m->post_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_poll(struct target *target)
-{
- int detected_failure = ERROR_OK;
- int retval = ERROR_OK;
- enum target_state prev_target_state = target->state;
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
-
- /* Read from Debug Halting Control and Status Register */
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
- if (retval != ERROR_OK) {
- target->state = TARGET_UNKNOWN;
- return retval;
- }
-
- /* Recover from lockup. See ARMv7-M architecture spec,
- * section B1.5.15 "Unrecoverable exception cases".
- */
- if (cortex_m->dcb_dhcsr & S_LOCKUP) {
- LOG_ERROR("%s -- clearing lockup after double fault",
- target_name(target));
- cortex_m_write_debug_halt_mask(target, C_HALT, 0);
- target->debug_reason = DBG_REASON_DBGRQ;
-
- /* We have to execute the rest (the "finally" equivalent, but
- * still throw this exception again).
- */
- detected_failure = ERROR_FAIL;
-
- /* refresh status bits */
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (cortex_m->dcb_dhcsr & S_RESET_ST) {
- target->state = TARGET_RESET;
- return ERROR_OK;
- }
-
- if (target->state == TARGET_RESET) {
- /* Cannot switch context while running so endreset is
- * called with target->state == TARGET_RESET
- */
- LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32,
- cortex_m->dcb_dhcsr);
- retval = cortex_m_endreset_event(target);
- if (retval != ERROR_OK) {
- target->state = TARGET_UNKNOWN;
- return retval;
- }
- target->state = TARGET_RUNNING;
- prev_target_state = TARGET_RUNNING;
- }
-
- if (cortex_m->dcb_dhcsr & S_HALT) {
- target->state = TARGET_HALTED;
-
- if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) {
- retval = cortex_m_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (arm_semihosting(target, &retval) != 0)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- }
- if (prev_target_state == TARGET_DEBUG_RUNNING) {
- LOG_DEBUG(" ");
- retval = cortex_m_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
- }
- }
-
- /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
- * How best to model low power modes?
- */
-
- if (target->state == TARGET_UNKNOWN) {
- /* check if processor is retiring instructions */
- if (cortex_m->dcb_dhcsr & S_RETIRE_ST) {
- target->state = TARGET_RUNNING;
- retval = ERROR_OK;
- }
- }
-
- /* Did we detect a failure condition that we cleared? */
- if (detected_failure != ERROR_OK)
- retval = detected_failure;
- return retval;
-}
-
-static int cortex_m_halt(struct target *target)
-{
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- if (target->state == TARGET_UNKNOWN)
- LOG_WARNING("target was in unknown state when halt was requested");
-
- if (target->state == TARGET_RESET) {
- if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
- LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
- return ERROR_TARGET_FAILURE;
- } else {
- /* we came here in a reset_halt or reset_init sequence
- * debug entry was already prepared in cortex_m3_assert_reset()
- */
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
- }
- }
-
- /* Write to Debug Halting Control and Status Register */
- cortex_m_write_debug_halt_mask(target, C_HALT, 0);
-
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int cortex_m_soft_reset_halt(struct target *target)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- uint32_t dcb_dhcsr = 0;
- int retval, timeout = 0;
-
- /* soft_reset_halt is deprecated on cortex_m as the same functionality
- * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset'
- * As this reset only used VC_CORERESET it would only ever reset the cortex_m
- * core, not the peripherals */
- LOG_WARNING("soft_reset_halt is deprecated, please use 'reset halt' instead.");
-
- /* Enter debug state on reset; restore DEMCR in endreset_event() */
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR,
- TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
- if (retval != ERROR_OK)
- return retval;
-
- /* Request a core-only reset */
- retval = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_AIRCR,
- AIRCR_VECTKEY | AIRCR_VECTRESET);
- if (retval != ERROR_OK)
- return retval;
- target->state = TARGET_RESET;
-
- /* registers are now invalid */
- register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
-
- while (timeout < 100) {
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &dcb_dhcsr);
- if (retval == ERROR_OK) {
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_DFSR,
- &cortex_m->nvic_dfsr);
- if (retval != ERROR_OK)
- return retval;
- if ((dcb_dhcsr & S_HALT)
- && (cortex_m->nvic_dfsr & DFSR_VCATCH)) {
- LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
- "DFSR 0x%08x",
- (unsigned) dcb_dhcsr,
- (unsigned) cortex_m->nvic_dfsr);
- cortex_m_poll(target);
- /* FIXME restore user's vector catch config */
- return ERROR_OK;
- } else
- LOG_DEBUG("waiting for system reset-halt, "
- "DHCSR 0x%08x, %d ms",
- (unsigned) dcb_dhcsr, timeout);
- }
- timeout++;
- alive_sleep(1);
- }
-
- return ERROR_OK;
-}
-
-void cortex_m_enable_breakpoints(struct target *target)
-{
- struct breakpoint *breakpoint = target->breakpoints;
-
- /* set any pending breakpoints */
- while (breakpoint) {
- if (!breakpoint->set)
- cortex_m_set_breakpoint(target, breakpoint);
- breakpoint = breakpoint->next;
- }
-}
-
-static int cortex_m_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct breakpoint *breakpoint = NULL;
- uint32_t resume_pc;
- struct reg *r;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!debug_execution) {
- target_free_all_working_areas(target);
- cortex_m_enable_breakpoints(target);
- cortex_m_enable_watchpoints(target);
- }
-
- if (debug_execution) {
- r = armv7m->arm.core_cache->reg_list + ARMV7M_PRIMASK;
-
- /* Disable interrupts */
- /* We disable interrupts in the PRIMASK register instead of
- * masking with C_MASKINTS. This is probably the same issue
- * as Cortex-M3 Erratum 377493 (fixed in r1p0): C_MASKINTS
- * in parallel with disabled interrupts can cause local faults
- * to not be taken.
- *
- * REVISIT this clearly breaks non-debug execution, since the
- * PRIMASK register state isn't saved/restored... workaround
- * by never resuming app code after debug execution.
- */
- buf_set_u32(r->value, 0, 1, 1);
- r->dirty = true;
- r->valid = true;
-
- /* Make sure we are in Thumb mode */
- r = armv7m->arm.cpsr;
- buf_set_u32(r->value, 24, 1, 1);
- r->dirty = true;
- r->valid = true;
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- r = armv7m->arm.pc;
- if (!current) {
- buf_set_u32(r->value, 0, 32, address);
- r->dirty = true;
- r->valid = true;
- }
-
- /* if we halted last time due to a bkpt instruction
- * then we have to manually step over it, otherwise
- * the core will break again */
-
- if (!breakpoint_find(target, buf_get_u32(r->value, 0, 32))
- && !debug_execution)
- armv7m_maybe_skip_bkpt_inst(target, NULL);
-
- resume_pc = buf_get_u32(r->value, 0, 32);
-
- armv7m_restore_context(target);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- /* Single step past breakpoint at current address */
- breakpoint = breakpoint_find(target, resume_pc);
- if (breakpoint) {
- LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")",
- breakpoint->address,
- breakpoint->unique_id);
- cortex_m_unset_breakpoint(target, breakpoint);
- cortex_m_single_step_core(target);
- cortex_m_set_breakpoint(target, breakpoint);
- }
- }
-
- /* Restart core */
- cortex_m_write_debug_halt_mask(target, 0, C_HALT);
-
- target->debug_reason = DBG_REASON_NOTHALTED;
-
- /* registers are now invalid */
- register_cache_invalidate(armv7m->arm.core_cache);
-
- if (!debug_execution) {
- target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
- }
-
- return ERROR_OK;
-}
-
-/* int irqstepcount = 0; */
-static int cortex_m_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- struct breakpoint *breakpoint = NULL;
- struct reg *pc = armv7m->arm.pc;
- bool bkpt_inst_found = false;
- int retval;
- bool isr_timed_out = false;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current)
- buf_set_u32(pc->value, 0, 32, address);
-
- uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- breakpoint = breakpoint_find(target, pc_value);
- if (breakpoint)
- cortex_m_unset_breakpoint(target, breakpoint);
- }
-
- armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- armv7m_restore_context(target);
-
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-
- /* if no bkpt instruction is found at pc then we can perform
- * a normal step, otherwise we have to manually step over the bkpt
- * instruction - as such simulate a step */
- if (bkpt_inst_found == false) {
- /* Automatic ISR masking mode off: Just step over the next instruction */
- if ((cortex_m->isrmasking_mode != CORTEX_M_ISRMASK_AUTO))
- cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
- else {
- /* Process interrupts during stepping in a way they don't interfere
- * debugging.
- *
- * Principle:
- *
- * Set a temporary break point at the current pc and let the core run
- * with interrupts enabled. Pending interrupts get served and we run
- * into the breakpoint again afterwards. Then we step over the next
- * instruction with interrupts disabled.
- *
- * If the pending interrupts don't complete within time, we leave the
- * core running. This may happen if the interrupts trigger faster
- * than the core can process them or the handler doesn't return.
- *
- * If no more breakpoints are available we simply do a step with
- * interrupts enabled.
- *
- */
-
- /* 2012-09-29 ph
- *
- * If a break point is already set on the lower half word then a break point on
- * the upper half word will not break again when the core is restarted. So we
- * just step over the instruction with interrupts disabled.
- *
- * The documentation has no information about this, it was found by observation
- * on STM32F1 and STM32F2. Proper explanation welcome. STM32F0 dosen't seem to
- * suffer from this problem.
- *
- * To add some confusion: pc_value has bit 0 always set, while the breakpoint
- * address has it always cleared. The former is done to indicate thumb mode
- * to gdb.
- *
- */
- if ((pc_value & 0x02) && breakpoint_find(target, pc_value & ~0x03)) {
- LOG_DEBUG("Stepping over next instruction with interrupts disabled");
- cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0);
- cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
- /* Re-enable interrupts */
- cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
- }
- else {
-
- /* Set a temporary break point */
- if (breakpoint)
- retval = cortex_m_set_breakpoint(target, breakpoint);
- else
- retval = breakpoint_add(target, pc_value, 2, BKPT_TYPE_BY_ADDR(pc_value));
- bool tmp_bp_set = (retval == ERROR_OK);
-
- /* No more breakpoints left, just do a step */
- if (!tmp_bp_set)
- cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
- else {
- /* Start the core */
- LOG_DEBUG("Starting core to serve pending interrupts");
- int64_t t_start = timeval_ms();
- cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP);
-
- /* Wait for pending handlers to complete or timeout */
- do {
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap,
- DCB_DHCSR,
- &cortex_m->dcb_dhcsr);
- if (retval != ERROR_OK) {
- target->state = TARGET_UNKNOWN;
- return retval;
- }
- isr_timed_out = ((timeval_ms() - t_start) > 500);
- } while (!((cortex_m->dcb_dhcsr & S_HALT) || isr_timed_out));
-
- /* only remove breakpoint if we created it */
- if (breakpoint)
- cortex_m_unset_breakpoint(target, breakpoint);
- else {
- /* Remove the temporary breakpoint */
- breakpoint_remove(target, pc_value);
- }
-
- if (isr_timed_out) {
- LOG_DEBUG("Interrupt handlers didn't complete within time, "
- "leaving target running");
- } else {
- /* Step over next instruction with interrupts disabled */
- cortex_m_write_debug_halt_mask(target,
- C_HALT | C_MASKINTS,
- 0);
- cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
- /* Re-enable interrupts */
- cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
- }
- }
- }
- }
- }
-
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
- if (retval != ERROR_OK)
- return retval;
-
- /* registers are now invalid */
- register_cache_invalidate(armv7m->arm.core_cache);
-
- if (breakpoint)
- cortex_m_set_breakpoint(target, breakpoint);
-
- if (isr_timed_out) {
- /* Leave the core running. The user has to stop execution manually. */
- target->debug_reason = DBG_REASON_NOTHALTED;
- target->state = TARGET_RUNNING;
- return ERROR_OK;
- }
-
- LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
- " nvic_icsr = 0x%" PRIx32,
- cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
-
- retval = cortex_m_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
- " nvic_icsr = 0x%" PRIx32,
- cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
-
- return ERROR_OK;
-}
-
-static int cortex_m_assert_reset(struct target *target)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- enum cortex_m_soft_reset_config reset_config = cortex_m->soft_reset_config;
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
- /* allow scripts to override the reset event */
-
- target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
- register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
- target->state = TARGET_RESET;
-
- return ERROR_OK;
- }
-
- /* some cores support connecting while srst is asserted
- * use that mode is it has been configured */
-
- bool srst_asserted = false;
-
- if ((jtag_reset_config & RESET_HAS_SRST) &&
- (jtag_reset_config & RESET_SRST_NO_GATING)) {
- adapter_assert_reset();
- srst_asserted = true;
- }
-
- /* Enable debug requests */
- int retval;
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
- /* Store important errors instead of failing and proceed to reset assert */
-
- if (retval != ERROR_OK || !(cortex_m->dcb_dhcsr & C_DEBUGEN))
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
-
- /* If the processor is sleeping in a WFI or WFE instruction, the
- * C_HALT bit must be asserted to regain control */
- if (retval == ERROR_OK && (cortex_m->dcb_dhcsr & S_SLEEP))
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
-
- mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0);
- /* Ignore less important errors */
-
- if (!target->reset_halt) {
- /* Set/Clear C_MASKINTS in a separate operation */
- if (cortex_m->dcb_dhcsr & C_MASKINTS)
- mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
- DBGKEY | C_DEBUGEN | C_HALT);
-
- /* clear any debug flags before resuming */
- cortex_m_clear_halt(target);
-
- /* clear C_HALT in dhcsr reg */
- cortex_m_write_debug_halt_mask(target, 0, C_HALT);
- } else {
- /* Halt in debug on reset; endreset_event() restores DEMCR.
- *
- * REVISIT catching BUSERR presumably helps to defend against
- * bad vector table entries. Should this include MMERR or
- * other flags too?
- */
- int retval2;
- retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR,
- TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
- if (retval != ERROR_OK || retval2 != ERROR_OK)
- LOG_INFO("AP write error, reset will not halt");
- }
-
- if (jtag_reset_config & RESET_HAS_SRST) {
- /* default to asserting srst */
- if (!srst_asserted)
- adapter_assert_reset();
-
- /* srst is asserted, ignore AP access errors */
- retval = ERROR_OK;
- } else {
- /* Use a standard Cortex-M3 software reset mechanism.
- * We default to using VECRESET as it is supported on all current cores.
- * This has the disadvantage of not resetting the peripherals, so a
- * reset-init event handler is needed to perform any peripheral resets.
- */
- LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ)
- ? "SYSRESETREQ" : "VECTRESET");
-
- if (reset_config == CORTEX_M_RESET_VECTRESET) {
- LOG_WARNING("Only resetting the Cortex-M core, use a reset-init event "
- "handler to reset any peripherals or configure hardware srst support.");
- }
-
- int retval3;
- retval3 = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_AIRCR,
- AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ)
- ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET));
- if (retval3 != ERROR_OK)
- LOG_DEBUG("Ignoring AP write error right after reset");
-
- retval3 = dap_dp_init(armv7m->debug_ap->dap);
- if (retval3 != ERROR_OK)
- LOG_ERROR("DP initialisation failed");
-
- else {
- /* I do not know why this is necessary, but it
- * fixes strange effects (step/resume cause NMI
- * after reset) on LM3S6918 -- Michael Schwingen
- */
- uint32_t tmp;
- mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_AIRCR, &tmp);
- }
- }
-
- target->state = TARGET_RESET;
- jtag_add_sleep(50000);
-
- register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
-
- /* now return stored error code if any */
- if (retval != ERROR_OK)
- return retval;
-
- if (target->reset_halt) {
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_deassert_reset(struct target *target)
-{
- struct armv7m_common *armv7m = &target_to_cm(target)->armv7m;
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- /* deassert reset lines */
- adapter_deassert_reset();
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if ((jtag_reset_config & RESET_HAS_SRST) &&
- !(jtag_reset_config & RESET_SRST_NO_GATING)) {
- int retval = dap_dp_init(armv7m->debug_ap->dap);
- if (retval != ERROR_OK) {
- LOG_ERROR("DP initialisation failed");
- return retval;
- }
- }
-
- return ERROR_OK;
-}
-
-int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- int retval;
- int fp_num = 0;
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
-
- if (breakpoint->set) {
- LOG_WARNING("breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id);
- return ERROR_OK;
- }
-
- if (cortex_m->auto_bp_type)
- breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
-
- if (breakpoint->type == BKPT_HARD) {
- uint32_t fpcr_value;
- while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code))
- fp_num++;
- if (fp_num >= cortex_m->fp_num_code) {
- LOG_ERROR("Can not find free FPB Comparator!");
- return ERROR_FAIL;
- }
- breakpoint->set = fp_num + 1;
- fpcr_value = breakpoint->address | 1;
- if (cortex_m->fp_rev == 0) {
- uint32_t hilo;
- hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
- fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1;
- } else if (cortex_m->fp_rev > 1) {
- LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision");
- return ERROR_FAIL;
- }
- comparator_list[fp_num].used = 1;
- comparator_list[fp_num].fpcr_value = fpcr_value;
- target_write_u32(target, comparator_list[fp_num].fpcr_address,
- comparator_list[fp_num].fpcr_value);
- LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "",
- fp_num,
- comparator_list[fp_num].fpcr_value);
- if (!cortex_m->fpb_enabled) {
- LOG_DEBUG("FPB wasn't enabled, do it now");
- retval = cortex_m_enable_fpb(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Failed to enable the FPB");
- return retval;
- }
-
- cortex_m->fpb_enabled = 1;
- }
- } else if (breakpoint->type == BKPT_SOFT) {
- uint8_t code[4];
-
- /* NOTE: on ARMv6-M and ARMv7-M, BKPT(0xab) is used for
- * semihosting; don't use that. Otherwise the BKPT
- * parameter is arbitrary.
- */
- buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
- retval = target_read_memory(target,
- breakpoint->address & 0xFFFFFFFE,
- breakpoint->length, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_memory(target,
- breakpoint->address & 0xFFFFFFFE,
- breakpoint->length, 1,
- code);
- if (retval != ERROR_OK)
- return retval;
- breakpoint->set = true;
- }
-
- LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
- breakpoint->unique_id,
- (int)(breakpoint->type),
- breakpoint->address,
- breakpoint->length,
- breakpoint->set);
-
- return ERROR_OK;
-}
-
-int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- int retval;
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
-
- if (!breakpoint->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
- breakpoint->unique_id,
- (int)(breakpoint->type),
- breakpoint->address,
- breakpoint->length,
- breakpoint->set);
-
- if (breakpoint->type == BKPT_HARD) {
- int fp_num = breakpoint->set - 1;
- if ((fp_num < 0) || (fp_num >= cortex_m->fp_num_code)) {
- LOG_DEBUG("Invalid FP Comparator number in breakpoint");
- return ERROR_OK;
- }
- comparator_list[fp_num].used = 0;
- comparator_list[fp_num].fpcr_value = 0;
- target_write_u32(target, comparator_list[fp_num].fpcr_address,
- comparator_list[fp_num].fpcr_value);
- } else {
- /* restore original instruction (kept in target endianness) */
- if (breakpoint->length == 4) {
- retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- }
- }
- breakpoint->set = false;
-
- return ERROR_OK;
-}
-
-int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
-
- if (cortex_m->auto_bp_type)
- breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
-
- if (breakpoint->type != BKPT_TYPE_BY_ADDR(breakpoint->address)) {
- if (breakpoint->type == BKPT_HARD) {
- LOG_INFO("flash patch comparator requested outside code memory region");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->type == BKPT_SOFT) {
- LOG_INFO("soft breakpoint requested in code (flash) memory region");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- if ((breakpoint->type == BKPT_HARD) && (cortex_m->fp_code_available < 1)) {
- LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->length == 3) {
- LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request");
- breakpoint->length = 2;
- }
-
- if ((breakpoint->length != 2)) {
- LOG_INFO("only breakpoints of two bytes length supported");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->type == BKPT_HARD)
- cortex_m->fp_code_available--;
-
- return cortex_m_set_breakpoint(target, breakpoint);
-}
-
-int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
-
- /* REVISIT why check? FBP can be updated with core running ... */
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (cortex_m->auto_bp_type)
- breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
-
- if (breakpoint->set)
- cortex_m_unset_breakpoint(target, breakpoint);
-
- if (breakpoint->type == BKPT_HARD)
- cortex_m->fp_code_available++;
-
- return ERROR_OK;
-}
-
-int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- int dwt_num = 0;
- uint32_t mask, temp;
- struct cortex_m_common *cortex_m = target_to_cm(target);
-
- /* watchpoint params were validated earlier */
- mask = 0;
- temp = watchpoint->length;
- while (temp) {
- temp >>= 1;
- mask++;
- }
- mask--;
-
- /* REVISIT Don't fully trust these "not used" records ... users
- * may set up breakpoints by hand, e.g. dual-address data value
- * watchpoint using comparator #1; comparator #0 matching cycle
- * count; send data trace info through ITM and TPIU; etc
- */
- struct cortex_m_dwt_comparator *comparator;
-
- for (comparator = cortex_m->dwt_comparator_list;
- comparator->used && dwt_num < cortex_m->dwt_num_comp;
- comparator++, dwt_num++)
- continue;
- if (dwt_num >= cortex_m->dwt_num_comp) {
- LOG_ERROR("Can not find free DWT Comparator");
- return ERROR_FAIL;
- }
- comparator->used = 1;
- watchpoint->set = dwt_num + 1;
-
- comparator->comp = watchpoint->address;
- target_write_u32(target, comparator->dwt_comparator_address + 0,
- comparator->comp);
-
- comparator->mask = mask;
- target_write_u32(target, comparator->dwt_comparator_address + 4,
- comparator->mask);
-
- switch (watchpoint->rw) {
- case WPT_READ:
- comparator->function = 5;
- break;
- case WPT_WRITE:
- comparator->function = 6;
- break;
- case WPT_ACCESS:
- comparator->function = 7;
- break;
- }
- target_write_u32(target, comparator->dwt_comparator_address + 8,
- comparator->function);
-
- LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
- watchpoint->unique_id, dwt_num,
- (unsigned) comparator->comp,
- (unsigned) comparator->mask,
- (unsigned) comparator->function);
- return ERROR_OK;
-}
-
-int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct cortex_m_dwt_comparator *comparator;
- int dwt_num;
-
- if (!watchpoint->set) {
- LOG_WARNING("watchpoint (wpid: %d) not set",
- watchpoint->unique_id);
- return ERROR_OK;
- }
-
- dwt_num = watchpoint->set - 1;
-
- LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
- watchpoint->unique_id, dwt_num,
- (unsigned) watchpoint->address);
-
- if ((dwt_num < 0) || (dwt_num >= cortex_m->dwt_num_comp)) {
- LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
- return ERROR_OK;
- }
-
- comparator = cortex_m->dwt_comparator_list + dwt_num;
- comparator->used = 0;
- comparator->function = 0;
- target_write_u32(target, comparator->dwt_comparator_address + 8,
- comparator->function);
-
- watchpoint->set = false;
-
- return ERROR_OK;
-}
-
-int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
-
- if (cortex_m->dwt_comp_available < 1) {
- LOG_DEBUG("no comparators?");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* hardware doesn't support data value masking */
- if (watchpoint->mask != ~(uint32_t)0) {
- LOG_DEBUG("watchpoint value masks not supported");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* hardware allows address masks of up to 32K */
- unsigned mask;
-
- for (mask = 0; mask < 16; mask++) {
- if ((1u << mask) == watchpoint->length)
- break;
- }
- if (mask == 16) {
- LOG_DEBUG("unsupported watchpoint length");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- if (watchpoint->address & ((1 << mask) - 1)) {
- LOG_DEBUG("watchpoint address is unaligned");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* Caller doesn't seem to be able to describe watching for data
- * values of zero; that flags "no value".
- *
- * REVISIT This DWT may well be able to watch for specific data
- * values. Requires comparator #1 to set DATAVMATCH and match
- * the data, and another comparator (DATAVADDR0) matching addr.
- */
- if (watchpoint->value) {
- LOG_DEBUG("data value watchpoint not YET supported");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- cortex_m->dwt_comp_available--;
- LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available);
-
- return ERROR_OK;
-}
-
-int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
-
- /* REVISIT why check? DWT can be updated with core running ... */
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (watchpoint->set)
- cortex_m_unset_watchpoint(target, watchpoint);
-
- cortex_m->dwt_comp_available++;
- LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available);
-
- return ERROR_OK;
-}
-
-void cortex_m_enable_watchpoints(struct target *target)
-{
- struct watchpoint *watchpoint = target->watchpoints;
-
- /* set any pending watchpoints */
- while (watchpoint) {
- if (!watchpoint->set)
- cortex_m_set_watchpoint(target, watchpoint);
- watchpoint = watchpoint->next;
- }
-}
-
-static int cortex_m_load_core_reg_u32(struct target *target,
- uint32_t num, uint32_t *value)
-{
- int retval;
-
- /* NOTE: we "know" here that the register identifiers used
- * in the v7m header match the Cortex-M3 Debug Core Register
- * Selector values for R0..R15, xPSR, MSP, and PSP.
- */
- switch (num) {
- case 0 ... 18:
- /* read a normal core register */
- retval = cortexm_dap_read_coreregister_u32(target, value, num);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG failure %i", retval);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value);
- break;
-
- case ARMV7M_FPSCR:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, DCB_DCRSR, 0x21);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, DCB_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value);
- break;
-
- case ARMV7M_S0 ... ARMV7M_S31:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, DCB_DCRSR, num - ARMV7M_S0 + 0x40);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, DCB_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32,
- (int)(num - ARMV7M_S0), *value);
- break;
-
- case ARMV7M_PRIMASK:
- case ARMV7M_BASEPRI:
- case ARMV7M_FAULTMASK:
- case ARMV7M_CONTROL:
- /* Cortex-M3 packages these four registers as bitfields
- * in one Debug Core register. So say r0 and r2 docs;
- * it was removed from r1 docs, but still works.
- */
- cortexm_dap_read_coreregister_u32(target, value, 20);
-
- switch (num) {
- case ARMV7M_PRIMASK:
- *value = buf_get_u32((uint8_t *)value, 0, 1);
- break;
-
- case ARMV7M_BASEPRI:
- *value = buf_get_u32((uint8_t *)value, 8, 8);
- break;
-
- case ARMV7M_FAULTMASK:
- *value = buf_get_u32((uint8_t *)value, 16, 1);
- break;
-
- case ARMV7M_CONTROL:
- *value = buf_get_u32((uint8_t *)value, 24, 2);
- break;
- }
-
- LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value);
- break;
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_store_core_reg_u32(struct target *target,
- uint32_t num, uint32_t value)
-{
- int retval;
- uint32_t reg;
- struct armv7m_common *armv7m = target_to_armv7m(target);
-
- /* NOTE: we "know" here that the register identifiers used
- * in the v7m header match the Cortex-M3 Debug Core Register
- * Selector values for R0..R15, xPSR, MSP, and PSP.
- */
- switch (num) {
- case 0 ... 18:
- retval = cortexm_dap_write_coreregister_u32(target, value, num);
- if (retval != ERROR_OK) {
- struct reg *r;
-
- LOG_ERROR("JTAG failure");
- r = armv7m->arm.core_cache->reg_list + num;
- r->dirty = r->valid;
- return ERROR_JTAG_DEVICE_ERROR;
- }
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
- break;
-
- case ARMV7M_FPSCR:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, DCB_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, DCB_DCRSR, 0x21 | (1<<16));
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("write FPSCR value 0x%" PRIx32, value);
- break;
-
- case ARMV7M_S0 ... ARMV7M_S31:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, DCB_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, DCB_DCRSR, (num - ARMV7M_S0 + 0x40) | (1<<16));
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32,
- (int)(num - ARMV7M_S0), value);
- break;
-
- case ARMV7M_PRIMASK:
- case ARMV7M_BASEPRI:
- case ARMV7M_FAULTMASK:
- case ARMV7M_CONTROL:
- /* Cortex-M3 packages these four registers as bitfields
- * in one Debug Core register. So say r0 and r2 docs;
- * it was removed from r1 docs, but still works.
- */
- cortexm_dap_read_coreregister_u32(target, &reg, 20);
-
- switch (num) {
- case ARMV7M_PRIMASK:
- buf_set_u32((uint8_t *)&reg, 0, 1, value);
- break;
-
- case ARMV7M_BASEPRI:
- buf_set_u32((uint8_t *)&reg, 8, 8, value);
- break;
-
- case ARMV7M_FAULTMASK:
- buf_set_u32((uint8_t *)&reg, 16, 1, value);
- break;
-
- case ARMV7M_CONTROL:
- buf_set_u32((uint8_t *)&reg, 24, 2, value);
- break;
- }
-
- cortexm_dap_write_coreregister_u32(target, reg, 20);
-
- LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
- break;
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
-
- if (armv7m->arm.is_armv6m) {
- /* armv6m does not handle unaligned memory access */
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- return mem_ap_read_buf(armv7m->debug_ap, buffer, size, count, address);
-}
-
-static int cortex_m_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
-
- if (armv7m->arm.is_armv6m) {
- /* armv6m does not handle unaligned memory access */
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- return mem_ap_write_buf(armv7m->debug_ap, buffer, size, count, address);
-}
-
-static int cortex_m_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- armv7m_build_reg_cache(target);
- return ERROR_OK;
-}
-
-void cortex_m_deinit_target(struct target *target)
-{
- struct cortex_m_common *cortex_m = target_to_cm(target);
-
- free(cortex_m->fp_comparator_list);
-
- cortex_m_dwt_free(target);
- armv7m_free_reg_cache(target);
-
- free(cortex_m);
-}
-
-/* REVISIT cache valid/dirty bits are unmaintained. We could set "valid"
- * on r/w if the core is not running, and clear on resume or reset ... or
- * at least, in a post_restore_context() method.
- */
-
-struct dwt_reg_state {
- struct target *target;
- uint32_t addr;
- uint8_t value[4]; /* scratch/cache */
-};
-
-static int cortex_m_dwt_get_reg(struct reg *reg)
-{
- struct dwt_reg_state *state = reg->arch_info;
-
- uint32_t tmp;
- int retval = target_read_u32(state->target, state->addr, &tmp);
- if (retval != ERROR_OK)
- return retval;
-
- buf_set_u32(state->value, 0, 32, tmp);
- return ERROR_OK;
-}
-
-static int cortex_m_dwt_set_reg(struct reg *reg, uint8_t *buf)
-{
- struct dwt_reg_state *state = reg->arch_info;
-
- return target_write_u32(state->target, state->addr,
- buf_get_u32(buf, 0, reg->size));
-}
-
-struct dwt_reg {
- uint32_t addr;
- char *name;
- unsigned size;
-};
-
-static struct dwt_reg dwt_base_regs[] = {
- { DWT_CTRL, "dwt_ctrl", 32, },
- /* NOTE that Erratum 532314 (fixed r2p0) affects CYCCNT: it wrongly
- * increments while the core is asleep.
- */
- { DWT_CYCCNT, "dwt_cyccnt", 32, },
- /* plus some 8 bit counters, useful for profiling with TPIU */
-};
-
-static struct dwt_reg dwt_comp[] = {
-#define DWT_COMPARATOR(i) \
- { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \
- { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \
- { DWT_FUNCTION0 + 0x10 * (i), "dwt_" #i "_function", 32, }
- DWT_COMPARATOR(0),
- DWT_COMPARATOR(1),
- DWT_COMPARATOR(2),
- DWT_COMPARATOR(3),
-#undef DWT_COMPARATOR
-};
-
-static const struct reg_arch_type dwt_reg_type = {
- .get = cortex_m_dwt_get_reg,
- .set = cortex_m_dwt_set_reg,
-};
-
-static void cortex_m_dwt_addreg(struct target *t, struct reg *r, struct dwt_reg *d)
-{
- struct dwt_reg_state *state;
-
- state = calloc(1, sizeof *state);
- if (!state)
- return;
- state->addr = d->addr;
- state->target = t;
-
- r->name = d->name;
- r->size = d->size;
- r->value = state->value;
- r->arch_info = state;
- r->type = &dwt_reg_type;
-}
-
-void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
-{
- uint32_t dwtcr;
- struct reg_cache *cache;
- struct cortex_m_dwt_comparator *comparator;
- int reg, i;
-
- target_read_u32(target, DWT_CTRL, &dwtcr);
- if (!dwtcr) {
- LOG_DEBUG("no DWT");
- return;
- }
-
- cm->dwt_num_comp = (dwtcr >> 28) & 0xF;
- cm->dwt_comp_available = cm->dwt_num_comp;
- cm->dwt_comparator_list = calloc(cm->dwt_num_comp,
- sizeof(struct cortex_m_dwt_comparator));
- if (!cm->dwt_comparator_list) {
-fail0:
- cm->dwt_num_comp = 0;
- LOG_ERROR("out of mem");
- return;
- }
-
- cache = calloc(1, sizeof *cache);
- if (!cache) {
-fail1:
- free(cm->dwt_comparator_list);
- goto fail0;
- }
- cache->name = "Cortex-M DWT registers";
- cache->num_regs = 2 + cm->dwt_num_comp * 3;
- cache->reg_list = calloc(cache->num_regs, sizeof *cache->reg_list);
- if (!cache->reg_list) {
- free(cache);
- goto fail1;
- }
-
- for (reg = 0; reg < 2; reg++)
- cortex_m_dwt_addreg(target, cache->reg_list + reg,
- dwt_base_regs + reg);
-
- comparator = cm->dwt_comparator_list;
- for (i = 0; i < cm->dwt_num_comp; i++, comparator++) {
- int j;
-
- comparator->dwt_comparator_address = DWT_COMP0 + 0x10 * i;
- for (j = 0; j < 3; j++, reg++)
- cortex_m_dwt_addreg(target, cache->reg_list + reg,
- dwt_comp + 3 * i + j);
-
- /* make sure we clear any watchpoints enabled on the target */
- target_write_u32(target, comparator->dwt_comparator_address + 8, 0);
- }
-
- *register_get_last_cache_p(&target->reg_cache) = cache;
- cm->dwt_cache = cache;
-
- LOG_DEBUG("DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s",
- dwtcr, cm->dwt_num_comp,
- (dwtcr & (0xf << 24)) ? " only" : "/trigger");
-
- /* REVISIT: if num_comp > 1, check whether comparator #1 can
- * implement single-address data value watchpoints ... so we
- * won't need to check it later, when asked to set one up.
- */
-}
-
-static void cortex_m_dwt_free(struct target *target)
-{
- struct cortex_m_common *cm = target_to_cm(target);
- struct reg_cache *cache = cm->dwt_cache;
-
- free(cm->dwt_comparator_list);
- cm->dwt_comparator_list = NULL;
- cm->dwt_num_comp = 0;
-
- if (cache) {
- register_unlink_cache(&target->reg_cache, cache);
-
- if (cache->reg_list) {
- for (size_t i = 0; i < cache->num_regs; i++)
- free(cache->reg_list[i].arch_info);
- free(cache->reg_list);
- }
- free(cache);
- }
- cm->dwt_cache = NULL;
-}
-
-#define MVFR0 0xe000ef40
-#define MVFR1 0xe000ef44
-
-#define MVFR0_DEFAULT_M4 0x10110021
-#define MVFR1_DEFAULT_M4 0x11000011
-
-#define MVFR0_DEFAULT_M7_SP 0x10110021
-#define MVFR0_DEFAULT_M7_DP 0x10110221
-#define MVFR1_DEFAULT_M7_SP 0x11000011
-#define MVFR1_DEFAULT_M7_DP 0x12000011
-
-int cortex_m_examine(struct target *target)
-{
- int retval;
- uint32_t cpuid, fpcr, mvfr0, mvfr1;
- int i;
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
- struct armv7m_common *armv7m = target_to_armv7m(target);
-
- /* stlink shares the examine handler but does not support
- * all its calls */
- if (!armv7m->stlink) {
- retval = dap_dp_init(swjdp);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not initialize the debug port");
- return retval;
- }
-
- /* Search for the MEM-AP */
- retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not find MEM-AP to control the core");
- return retval;
- }
-
- /* Leave (only) generic DAP stuff for debugport_init(); */
- armv7m->debug_ap->memaccess_tck = 8;
-
- retval = mem_ap_init(armv7m->debug_ap);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (!target_was_examined(target)) {
- target_set_examined(target);
-
- /* Read from Device Identification Registers */
- retval = target_read_u32(target, CPUID, &cpuid);
- if (retval != ERROR_OK)
- return retval;
-
- /* Get CPU Type */
- i = (cpuid >> 4) & 0xf;
-
- LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected",
- i, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
- if (i == 7) {
- uint8_t rev, patch;
- rev = (cpuid >> 20) & 0xf;
- patch = (cpuid >> 0) & 0xf;
- if ((rev == 0) && (patch < 2))
- LOG_WARNING("Silicon bug: single stepping will enter pending exception handler!");
- }
- LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
-
- if (i == 4) {
- target_read_u32(target, MVFR0, &mvfr0);
- target_read_u32(target, MVFR1, &mvfr1);
-
- /* test for floating point feature on Cortex-M4 */
- if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) {
- LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
- armv7m->fp_feature = FPv4_SP;
- }
- } else if (i == 7) {
- target_read_u32(target, MVFR0, &mvfr0);
- target_read_u32(target, MVFR1, &mvfr1);
-
- /* test for floating point features on Cortex-M7 */
- if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) {
- LOG_DEBUG("Cortex-M%d floating point feature FPv5_SP found", i);
- armv7m->fp_feature = FPv5_SP;
- } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) {
- LOG_DEBUG("Cortex-M%d floating point feature FPv5_DP found", i);
- armv7m->fp_feature = FPv5_DP;
- }
- } else if (i == 0) {
- /* Cortex-M0 does not support unaligned memory access */
- armv7m->arm.is_armv6m = true;
- }
-
- if (armv7m->fp_feature == FP_NONE &&
- armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) {
- /* free unavailable FPU registers */
- size_t idx;
-
- for (idx = ARMV7M_NUM_CORE_REGS_NOFP;
- idx < armv7m->arm.core_cache->num_regs;
- idx++) {
- free(armv7m->arm.core_cache->reg_list[idx].value);
- free(armv7m->arm.core_cache->reg_list[idx].feature);
- free(armv7m->arm.core_cache->reg_list[idx].reg_data_type);
- }
- armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP;
- }
-
- if ((i == 3 || i == 4 || i == 7) && !armv7m->stlink) {
- /* Cortex-M3/M4/M7 have at least 4096 bytes autoincrement range,
- * s. ARM IHI 0031C: MEM-AP 7.2.2 */
- armv7m->debug_ap->tar_autoincr_block = (1 << 12);
- }
-
- /* Configure trace modules */
- retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
- if (retval != ERROR_OK)
- return retval;
-
- if (armv7m->trace_config.config_type != DISABLED) {
- armv7m_trace_tpiu_config(target);
- armv7m_trace_itm_config(target);
- }
-
- /* NOTE: FPB and DWT are both optional. */
-
- /* Setup FPB */
- target_read_u32(target, FP_CTRL, &fpcr);
- cortex_m->auto_bp_type = 1;
- /* bits [14:12] and [7:4] */
- cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF);
- cortex_m->fp_num_lit = (fpcr >> 8) & 0xF;
- cortex_m->fp_code_available = cortex_m->fp_num_code;
- /* Detect flash patch revision, see RM DDI 0403E.b page C1-817.
- Revision is zero base, fp_rev == 1 means Rev.2 ! */
- cortex_m->fp_rev = (fpcr >> 28) & 0xf;
- free(cortex_m->fp_comparator_list);
- cortex_m->fp_comparator_list = calloc(
- cortex_m->fp_num_code + cortex_m->fp_num_lit,
- sizeof(struct cortex_m_fp_comparator));
- cortex_m->fpb_enabled = fpcr & 1;
- for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
- cortex_m->fp_comparator_list[i].type =
- (i < cortex_m->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
- cortex_m->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i;
-
- /* make sure we clear any breakpoints enabled on the target */
- target_write_u32(target, cortex_m->fp_comparator_list[i].fpcr_address, 0);
- }
- LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i",
- fpcr,
- cortex_m->fp_num_code,
- cortex_m->fp_num_lit);
-
- /* Setup DWT */
- cortex_m_dwt_free(target);
- cortex_m_dwt_setup(cortex_m, target);
-
- /* These hardware breakpoints only work for code in flash! */
- LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
- target_name(target),
- cortex_m->fp_num_code,
- cortex_m->dwt_num_comp);
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_dcc_read(struct target *target, uint8_t *value, uint8_t *ctrl)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- uint16_t dcrdr;
- uint8_t buf[2];
- int retval;
-
- retval = mem_ap_read_buf_noincr(armv7m->debug_ap, buf, 2, 1, DCB_DCRDR);
- if (retval != ERROR_OK)
- return retval;
-
- dcrdr = target_buffer_get_u16(target, buf);
- *ctrl = (uint8_t)dcrdr;
- *value = (uint8_t)(dcrdr >> 8);
-
- LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
-
- /* write ack back to software dcc register
- * signify we have read data */
- if (dcrdr & (1 << 0)) {
- target_buffer_set_u16(target, buf, 0);
- retval = mem_ap_write_buf_noincr(armv7m->debug_ap, buf, 2, 1, DCB_DCRDR);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_target_request_data(struct target *target,
- uint32_t size, uint8_t *buffer)
-{
- uint8_t data;
- uint8_t ctrl;
- uint32_t i;
-
- for (i = 0; i < (size * 4); i++) {
- int retval = cortex_m_dcc_read(target, &data, &ctrl);
- if (retval != ERROR_OK)
- return retval;
- buffer[i] = data;
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_handle_target_request(void *priv)
-{
- struct target *target = priv;
- if (!target_was_examined(target))
- return ERROR_OK;
-
- if (!target->dbg_msg_enabled)
- return ERROR_OK;
-
- if (target->state == TARGET_RUNNING) {
- uint8_t data;
- uint8_t ctrl;
- int retval;
-
- retval = cortex_m_dcc_read(target, &data, &ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- /* check if we have data */
- if (ctrl & (1 << 0)) {
- uint32_t request;
-
- /* we assume target is quick enough */
- request = data;
- for (int i = 1; i <= 3; i++) {
- retval = cortex_m_dcc_read(target, &data, &ctrl);
- if (retval != ERROR_OK)
- return retval;
- request |= ((uint32_t)data << (i * 8));
- }
- target_request(target, request);
- }
- }
-
- return ERROR_OK;
-}
-
-static int cortex_m_init_arch_info(struct target *target,
- struct cortex_m_common *cortex_m, struct jtag_tap *tap)
-{
- struct armv7m_common *armv7m = &cortex_m->armv7m;
-
- armv7m_init_arch_info(target, armv7m);
-
- /* tap has no dap initialized */
- if (!tap->dap) {
- tap->dap = dap_init();
-
- /* Leave (only) generic DAP stuff for debugport_init() */
- tap->dap->tap = tap;
- }
-
- /* default reset mode is to use srst if fitted
- * if not it will use CORTEX_M3_RESET_VECTRESET */
- cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
-
- armv7m->arm.dap = tap->dap;
-
- /* register arch-specific functions */
- armv7m->examine_debug_reason = cortex_m_examine_debug_reason;
-
- armv7m->post_debug_entry = NULL;
-
- armv7m->pre_restore_context = NULL;
-
- armv7m->load_core_reg_u32 = cortex_m_load_core_reg_u32;
- armv7m->store_core_reg_u32 = cortex_m_store_core_reg_u32;
-
- target_register_timer_callback(cortex_m_handle_target_request, 1, 1, target);
-
- return ERROR_OK;
-}
-
-static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
-{
- struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
-
- cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
- cortex_m_init_arch_info(target, cortex_m, target->tap);
-
- return ERROR_OK;
-}
-
-/*--------------------------------------------------------------------------*/
-
-static int cortex_m_verify_pointer(struct command_context *cmd_ctx,
- struct cortex_m_common *cm)
-{
- if (cm->common_magic != CORTEX_M_COMMON_MAGIC) {
- command_print(cmd_ctx, "target is not a Cortex-M");
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-/*
- * Only stuff below this line should need to verify that its target
- * is a Cortex-M3. Everything else should have indirected through the
- * cortexm3_target structure, which is only used with CM3 targets.
- */
-
-static const struct {
- char name[10];
- unsigned mask;
-} vec_ids[] = {
- { "hard_err", VC_HARDERR, },
- { "int_err", VC_INTERR, },
- { "bus_err", VC_BUSERR, },
- { "state_err", VC_STATERR, },
- { "chk_err", VC_CHKERR, },
- { "nocp_err", VC_NOCPERR, },
- { "mm_err", VC_MMERR, },
- { "reset", VC_CORERESET, },
-};
-
-COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- struct armv7m_common *armv7m = &cortex_m->armv7m;
- uint32_t demcr = 0;
- int retval;
-
- retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &demcr);
- if (retval != ERROR_OK)
- return retval;
-
- if (CMD_ARGC > 0) {
- unsigned catch = 0;
-
- if (CMD_ARGC == 1) {
- if (strcmp(CMD_ARGV[0], "all") == 0) {
- catch = VC_HARDERR | VC_INTERR | VC_BUSERR
- | VC_STATERR | VC_CHKERR | VC_NOCPERR
- | VC_MMERR | VC_CORERESET;
- goto write;
- } else if (strcmp(CMD_ARGV[0], "none") == 0)
- goto write;
- }
- while (CMD_ARGC-- > 0) {
- unsigned i;
- for (i = 0; i < ARRAY_SIZE(vec_ids); i++) {
- if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name) != 0)
- continue;
- catch |= vec_ids[i].mask;
- break;
- }
- if (i == ARRAY_SIZE(vec_ids)) {
- LOG_ERROR("No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-write:
- /* For now, armv7m->demcr only stores vector catch flags. */
- armv7m->demcr = catch;
-
- demcr &= ~0xffff;
- demcr |= catch;
-
- /* write, but don't assume it stuck (why not??) */
- retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR, demcr);
- if (retval != ERROR_OK)
- return retval;
- retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &demcr);
- if (retval != ERROR_OK)
- return retval;
-
- /* FIXME be sure to clear DEMCR on clean server shutdown.
- * Otherwise the vector catch hardware could fire when there's
- * no debugger hooked up, causing much confusion...
- */
- }
-
- for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) {
- command_print(CMD_CTX, "%9s: %s", vec_ids[i].name,
- (demcr & vec_ids[i].mask) ? "catch" : "ignore");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- int retval;
-
- static const Jim_Nvp nvp_maskisr_modes[] = {
- { .name = "auto", .value = CORTEX_M_ISRMASK_AUTO },
- { .name = "off", .value = CORTEX_M_ISRMASK_OFF },
- { .name = "on", .value = CORTEX_M_ISRMASK_ON },
- { .name = NULL, .value = -1 },
- };
- const Jim_Nvp *n;
-
-
- retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- if (CMD_ARGC > 0) {
- n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
- if (n->name == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
- cortex_m->isrmasking_mode = n->value;
-
-
- if (cortex_m->isrmasking_mode == CORTEX_M_ISRMASK_ON)
- cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0);
- else
- cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
- }
-
- n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_m->isrmasking_mode);
- command_print(CMD_CTX, "cortex_m interrupt mask %s", n->name);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_cortex_m_reset_config_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct cortex_m_common *cortex_m = target_to_cm(target);
- int retval;
- char *reset_config;
-
- retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
- if (retval != ERROR_OK)
- return retval;
-
- if (CMD_ARGC > 0) {
- if (strcmp(*CMD_ARGV, "sysresetreq") == 0)
- cortex_m->soft_reset_config = CORTEX_M_RESET_SYSRESETREQ;
- else if (strcmp(*CMD_ARGV, "vectreset") == 0)
- cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
- }
-
- switch (cortex_m->soft_reset_config) {
- case CORTEX_M_RESET_SYSRESETREQ:
- reset_config = "sysresetreq";
- break;
-
- case CORTEX_M_RESET_VECTRESET:
- reset_config = "vectreset";
- break;
-
- default:
- reset_config = "unknown";
- break;
- }
-
- command_print(CMD_CTX, "cortex_m reset_config %s", reset_config);
-
- return ERROR_OK;
-}
-
-static const struct command_registration cortex_m_exec_command_handlers[] = {
- {
- .name = "maskisr",
- .handler = handle_cortex_m_mask_interrupts_command,
- .mode = COMMAND_EXEC,
- .help = "mask cortex_m interrupts",
- .usage = "['auto'|'on'|'off']",
- },
- {
- .name = "vector_catch",
- .handler = handle_cortex_m_vector_catch_command,
- .mode = COMMAND_EXEC,
- .help = "configure hardware vectors to trigger debug entry",
- .usage = "['all'|'none'|('bus_err'|'chk_err'|...)*]",
- },
- {
- .name = "reset_config",
- .handler = handle_cortex_m_reset_config_command,
- .mode = COMMAND_ANY,
- .help = "configure software reset handling",
- .usage = "['srst'|'sysresetreq'|'vectreset']",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration cortex_m_command_handlers[] = {
- {
- .chain = armv7m_command_handlers,
- },
- {
- .chain = armv7m_trace_command_handlers,
- },
- {
- .name = "cortex_m",
- .mode = COMMAND_EXEC,
- .help = "Cortex-M command group",
- .usage = "",
- .chain = cortex_m_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct target_type cortexm_target = {
- .name = "cortex_m",
- .deprecated_name = "cortex_m3",
-
- .poll = cortex_m_poll,
- .arch_state = armv7m_arch_state,
-
- .target_request_data = cortex_m_target_request_data,
-
- .halt = cortex_m_halt,
- .resume = cortex_m_resume,
- .step = cortex_m_step,
-
- .assert_reset = cortex_m_assert_reset,
- .deassert_reset = cortex_m_deassert_reset,
- .soft_reset_halt = cortex_m_soft_reset_halt,
-
- .get_gdb_reg_list = armv7m_get_gdb_reg_list,
-
- .read_memory = cortex_m_read_memory,
- .write_memory = cortex_m_write_memory,
- .checksum_memory = armv7m_checksum_memory,
- .blank_check_memory = armv7m_blank_check_memory,
-
- .run_algorithm = armv7m_run_algorithm,
- .start_algorithm = armv7m_start_algorithm,
- .wait_algorithm = armv7m_wait_algorithm,
-
- .add_breakpoint = cortex_m_add_breakpoint,
- .remove_breakpoint = cortex_m_remove_breakpoint,
- .add_watchpoint = cortex_m_add_watchpoint,
- .remove_watchpoint = cortex_m_remove_watchpoint,
-
- .commands = cortex_m_command_handlers,
- .target_create = cortex_m_target_create,
- .init_target = cortex_m_init_target,
- .examine = cortex_m_examine,
- .deinit_target = cortex_m_deinit_target,
-};
diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h
deleted file mode 100644
index eabaac4..0000000
--- a/src/target/cortex_m.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2006 by Magnus Lundin *
- * lundin@mlu.mine.nu *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_CORTEX_M_H
-#define OPENOCD_TARGET_CORTEX_M_H
-
-#include "armv7m.h"
-
-#define CORTEX_M_COMMON_MAGIC 0x1A451A45
-
-#define SYSTEM_CONTROL_BASE 0x400FE000
-
-#define ITM_TER0 0xE0000E00
-#define ITM_TPR 0xE0000E40
-#define ITM_TCR 0xE0000E80
-#define ITM_LAR 0xE0000FB0
-#define ITM_LAR_KEY 0xC5ACCE55
-
-#define CPUID 0xE000ED00
-/* Debug Control Block */
-#define DCB_DHCSR 0xE000EDF0
-#define DCB_DCRSR 0xE000EDF4
-#define DCB_DCRDR 0xE000EDF8
-#define DCB_DEMCR 0xE000EDFC
-
-#define DCRSR_WnR (1 << 16)
-
-#define DWT_CTRL 0xE0001000
-#define DWT_CYCCNT 0xE0001004
-#define DWT_COMP0 0xE0001020
-#define DWT_MASK0 0xE0001024
-#define DWT_FUNCTION0 0xE0001028
-
-#define FP_CTRL 0xE0002000
-#define FP_REMAP 0xE0002004
-#define FP_COMP0 0xE0002008
-#define FP_COMP1 0xE000200C
-#define FP_COMP2 0xE0002010
-#define FP_COMP3 0xE0002014
-#define FP_COMP4 0xE0002018
-#define FP_COMP5 0xE000201C
-#define FP_COMP6 0xE0002020
-#define FP_COMP7 0xE0002024
-
-#define FPU_CPACR 0xE000ED88
-#define FPU_FPCCR 0xE000EF34
-#define FPU_FPCAR 0xE000EF38
-#define FPU_FPDSCR 0xE000EF3C
-
-#define TPIU_SSPSR 0xE0040000
-#define TPIU_CSPSR 0xE0040004
-#define TPIU_ACPR 0xE0040010
-#define TPIU_SPPR 0xE00400F0
-#define TPIU_FFSR 0xE0040300
-#define TPIU_FFCR 0xE0040304
-#define TPIU_FSCR 0xE0040308
-
-/* DCB_DHCSR bit and field definitions */
-#define DBGKEY (0xA05F << 16)
-#define C_DEBUGEN (1 << 0)
-#define C_HALT (1 << 1)
-#define C_STEP (1 << 2)
-#define C_MASKINTS (1 << 3)
-#define S_REGRDY (1 << 16)
-#define S_HALT (1 << 17)
-#define S_SLEEP (1 << 18)
-#define S_LOCKUP (1 << 19)
-#define S_RETIRE_ST (1 << 24)
-#define S_RESET_ST (1 << 25)
-
-/* DCB_DEMCR bit and field definitions */
-#define TRCENA (1 << 24)
-#define VC_HARDERR (1 << 10)
-#define VC_INTERR (1 << 9)
-#define VC_BUSERR (1 << 8)
-#define VC_STATERR (1 << 7)
-#define VC_CHKERR (1 << 6)
-#define VC_NOCPERR (1 << 5)
-#define VC_MMERR (1 << 4)
-#define VC_CORERESET (1 << 0)
-
-#define NVIC_ICTR 0xE000E004
-#define NVIC_ISE0 0xE000E100
-#define NVIC_ICSR 0xE000ED04
-#define NVIC_AIRCR 0xE000ED0C
-#define NVIC_SHCSR 0xE000ED24
-#define NVIC_CFSR 0xE000ED28
-#define NVIC_MMFSRb 0xE000ED28
-#define NVIC_BFSRb 0xE000ED29
-#define NVIC_USFSRh 0xE000ED2A
-#define NVIC_HFSR 0xE000ED2C
-#define NVIC_DFSR 0xE000ED30
-#define NVIC_MMFAR 0xE000ED34
-#define NVIC_BFAR 0xE000ED38
-
-/* NVIC_AIRCR bits */
-#define AIRCR_VECTKEY (0x5FA << 16)
-#define AIRCR_SYSRESETREQ (1 << 2)
-#define AIRCR_VECTCLRACTIVE (1 << 1)
-#define AIRCR_VECTRESET (1 << 0)
-/* NVIC_SHCSR bits */
-#define SHCSR_BUSFAULTENA (1 << 17)
-/* NVIC_DFSR bits */
-#define DFSR_HALTED 1
-#define DFSR_BKPT 2
-#define DFSR_DWTTRAP 4
-#define DFSR_VCATCH 8
-
-#define FPCR_CODE 0
-#define FPCR_LITERAL 1
-#define FPCR_REPLACE_REMAP (0 << 30)
-#define FPCR_REPLACE_BKPT_LOW (1 << 30)
-#define FPCR_REPLACE_BKPT_HIGH (2 << 30)
-#define FPCR_REPLACE_BKPT_BOTH (3 << 30)
-
-struct cortex_m_fp_comparator {
- int used;
- int type;
- uint32_t fpcr_value;
- uint32_t fpcr_address;
-};
-
-struct cortex_m_dwt_comparator {
- int used;
- uint32_t comp;
- uint32_t mask;
- uint32_t function;
- uint32_t dwt_comparator_address;
-};
-
-enum cortex_m_soft_reset_config {
- CORTEX_M_RESET_SYSRESETREQ,
- CORTEX_M_RESET_VECTRESET,
-};
-
-enum cortex_m_isrmasking_mode {
- CORTEX_M_ISRMASK_AUTO,
- CORTEX_M_ISRMASK_OFF,
- CORTEX_M_ISRMASK_ON,
-};
-
-struct cortex_m_common {
- int common_magic;
-
- /* Context information */
- uint32_t dcb_dhcsr;
- uint32_t nvic_dfsr; /* Debug Fault Status Register - shows reason for debug halt */
- uint32_t nvic_icsr; /* Interrupt Control State Register - shows active and pending IRQ */
-
- /* Flash Patch and Breakpoint (FPB) */
- int fp_num_lit;
- int fp_num_code;
- int fp_code_available;
- int fp_rev;
- int fpb_enabled;
- int auto_bp_type;
- struct cortex_m_fp_comparator *fp_comparator_list;
-
- /* Data Watchpoint and Trace (DWT) */
- int dwt_num_comp;
- int dwt_comp_available;
- struct cortex_m_dwt_comparator *dwt_comparator_list;
- struct reg_cache *dwt_cache;
-
- enum cortex_m_soft_reset_config soft_reset_config;
-
- enum cortex_m_isrmasking_mode isrmasking_mode;
-
- struct armv7m_common armv7m;
-};
-
-static inline struct cortex_m_common *
-target_to_cm(struct target *target)
-{
- return container_of(target->arch_info,
- struct cortex_m_common, armv7m);
-}
-
-int cortex_m_examine(struct target *target);
-int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint);
-int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint);
-int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint);
-int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint);
-int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint);
-int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint);
-int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint);
-int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpoint);
-void cortex_m_enable_breakpoints(struct target *target);
-void cortex_m_enable_watchpoints(struct target *target);
-void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target);
-void cortex_m_deinit_target(struct target *target);
-
-#endif /* OPENOCD_TARGET_CORTEX_M_H */
diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c
deleted file mode 100644
index 783a019..0000000
--- a/src/target/dsp563xx.c
+++ /dev/null
@@ -1,2339 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2011 by Mathias Kuester *
- * mkdorg@users.sourceforge.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jim.h>
-
-#include "target.h"
-#include "breakpoints.h"
-#include "target_type.h"
-#include "algorithm.h"
-#include "register.h"
-#include "dsp563xx.h"
-#include "dsp563xx_once.h"
-
-#define ASM_REG_W_R0 0x60F400
-#define ASM_REG_W_R1 0x61F400
-#define ASM_REG_W_R2 0x62F400
-#define ASM_REG_W_R3 0x63F400
-#define ASM_REG_W_R4 0x64F400
-#define ASM_REG_W_R5 0x65F400
-#define ASM_REG_W_R6 0x66F400
-#define ASM_REG_W_R7 0x67F400
-
-#define ASM_REG_W_N0 0x70F400
-#define ASM_REG_W_N1 0x71F400
-#define ASM_REG_W_N2 0x72F400
-#define ASM_REG_W_N3 0x73F400
-#define ASM_REG_W_N4 0x74F400
-#define ASM_REG_W_N5 0x75F400
-#define ASM_REG_W_N6 0x76F400
-#define ASM_REG_W_N7 0x77F400
-
-#define ASM_REG_W_M0 0x05F420
-#define ASM_REG_W_M1 0x05F421
-#define ASM_REG_W_M2 0x05F422
-#define ASM_REG_W_M3 0x05F423
-#define ASM_REG_W_M4 0x05F424
-#define ASM_REG_W_M5 0x05F425
-#define ASM_REG_W_M6 0x05F426
-#define ASM_REG_W_M7 0x05F427
-
-#define ASM_REG_W_X0 0x44F400
-#define ASM_REG_W_X1 0x45F400
-
-#define ASM_REG_W_Y0 0x46F400
-#define ASM_REG_W_Y1 0x47F400
-
-#define ASM_REG_W_A0 0x50F400
-#define ASM_REG_W_A1 0x54F400
-#define ASM_REG_W_A2 0x52F400
-
-#define ASM_REG_W_B0 0x51F400
-#define ASM_REG_W_B1 0x55F400
-#define ASM_REG_W_B2 0x53F400
-
-#define ASM_REG_W_VBA 0x05F430
-#define ASM_REG_W_OMR 0x05F43A
-#define ASM_REG_W_EP 0x05F42A
-#define ASM_REG_W_SC 0x05F431
-#define ASM_REG_W_SZ 0x05F438
-#define ASM_REG_W_SR 0x05F439
-#define ASM_REG_W_SP 0x05F43B
-#define ASM_REG_W_SSH 0x05F43C
-#define ASM_REG_W_SSL 0x05F43D
-#define ASM_REG_W_LA 0x05F43E
-#define ASM_REG_W_LC 0x05F43F
-#define ASM_REG_W_PC 0x000000
-#define ASM_REG_W_IPRC 0xFFFFFF
-#define ASM_REG_W_IPRP 0xFFFFFE
-
-#define ASM_REG_W_BCR 0xFFFFFB
-#define ASM_REG_W_DCR 0xFFFFFA
-#define ASM_REG_W_AAR0 0xFFFFF9
-#define ASM_REG_W_AAR1 0xFFFFF8
-#define ASM_REG_W_AAR2 0xFFFFF7
-#define ASM_REG_W_AAR3 0xFFFFF6
-
-/*
- * OBCR Register bit definitions
- */
-#define OBCR_b0_and_b1 ((0x0) << 10)
-#define OBCR_b0_or_b1 ((0x1) << 10)
-#define OBCR_b1_after_b0 ((0x2) << 10)
-#define OBCR_b0_after_b1 ((0x3) << 10)
-
-#define OBCR_BP_DISABLED (0x0)
-#define OBCR_BP_MEM_P (0x1)
-#define OBCR_BP_MEM_X (0x2)
-#define OBCR_BP_MEM_Y (0x3)
-#define OBCR_BP_ON_READ ((0x2) << 0)
-#define OBCR_BP_ON_WRITE ((0x1) << 0)
-#define OBCR_BP_CC_NOT_EQUAL ((0x0) << 2)
-#define OBCR_BP_CC_EQUAL ((0x1) << 2)
-#define OBCR_BP_CC_LESS_THAN ((0x2) << 2)
-#define OBCR_BP_CC_GREATER_THAN ((0x3) << 2)
-
-#define OBCR_BP_0(x) ((x)<<2)
-#define OBCR_BP_1(x) ((x)<<6)
-
-
-enum once_reg_idx {
- ONCE_REG_IDX_OSCR = 0,
- ONCE_REG_IDX_OMBC = 1,
- ONCE_REG_IDX_OBCR = 2,
- ONCE_REG_IDX_OMLR0 = 3,
- ONCE_REG_IDX_OMLR1 = 4,
- ONCE_REG_IDX_OGDBR = 5,
- ONCE_REG_IDX_OPDBR = 6,
- ONCE_REG_IDX_OPILR = 7,
- ONCE_REG_IDX_PDB = 8,
- ONCE_REG_IDX_OTC = 9,
- ONCE_REG_IDX_OPABFR = 10,
- ONCE_REG_IDX_OPABDR = 11,
- ONCE_REG_IDX_OPABEX = 12,
- ONCE_REG_IDX_OPABF0 = 13,
- ONCE_REG_IDX_OPABF1 = 14,
- ONCE_REG_IDX_OPABF2 = 15,
- ONCE_REG_IDX_OPABF3 = 16,
- ONCE_REG_IDX_OPABF4 = 17,
- ONCE_REG_IDX_OPABF5 = 18,
- ONCE_REG_IDX_OPABF6 = 19,
- ONCE_REG_IDX_OPABF7 = 20,
- ONCE_REG_IDX_OPABF8 = 21,
- ONCE_REG_IDX_OPABF9 = 22,
- ONCE_REG_IDX_OPABF10 = 23,
- ONCE_REG_IDX_OPABF11 = 24,
-};
-
-static struct once_reg once_regs[] = {
- {ONCE_REG_IDX_OSCR, DSP563XX_ONCE_OSCR, 24, "OSCR", 0},
- {ONCE_REG_IDX_OMBC, DSP563XX_ONCE_OMBC, 24, "OMBC", 0},
- {ONCE_REG_IDX_OBCR, DSP563XX_ONCE_OBCR, 24, "OBCR", 0},
- {ONCE_REG_IDX_OMLR0, DSP563XX_ONCE_OMLR0, 24, "OMLR0", 0},
- {ONCE_REG_IDX_OMLR1, DSP563XX_ONCE_OMLR1, 24, "OMLR1", 0},
- {ONCE_REG_IDX_OGDBR, DSP563XX_ONCE_OGDBR, 24, "OGDBR", 0},
- {ONCE_REG_IDX_OPDBR, DSP563XX_ONCE_OPDBR, 24, "OPDBR", 0},
- {ONCE_REG_IDX_OPILR, DSP563XX_ONCE_OPILR, 24, "OPILR", 0},
- {ONCE_REG_IDX_PDB, DSP563XX_ONCE_PDBGOTO, 24, "PDB", 0},
- {ONCE_REG_IDX_OTC, DSP563XX_ONCE_OTC, 24, "OTC", 0},
- {ONCE_REG_IDX_OPABFR, DSP563XX_ONCE_OPABFR, 24, "OPABFR", 0},
- {ONCE_REG_IDX_OPABDR, DSP563XX_ONCE_OPABDR, 24, "OPABDR", 0},
- {ONCE_REG_IDX_OPABEX, DSP563XX_ONCE_OPABEX, 24, "OPABEX", 0},
- {ONCE_REG_IDX_OPABF0, DSP563XX_ONCE_OPABF11, 25, "OPABF0", 0},
- {ONCE_REG_IDX_OPABF1, DSP563XX_ONCE_OPABF11, 25, "OPABF1", 0},
- {ONCE_REG_IDX_OPABF2, DSP563XX_ONCE_OPABF11, 25, "OPABF2", 0},
- {ONCE_REG_IDX_OPABF3, DSP563XX_ONCE_OPABF11, 25, "OPABF3", 0},
- {ONCE_REG_IDX_OPABF4, DSP563XX_ONCE_OPABF11, 25, "OPABF4", 0},
- {ONCE_REG_IDX_OPABF5, DSP563XX_ONCE_OPABF11, 25, "OPABF5", 0},
- {ONCE_REG_IDX_OPABF6, DSP563XX_ONCE_OPABF11, 25, "OPABF6", 0},
- {ONCE_REG_IDX_OPABF7, DSP563XX_ONCE_OPABF11, 25, "OPABF7", 0},
- {ONCE_REG_IDX_OPABF8, DSP563XX_ONCE_OPABF11, 25, "OPABF8", 0},
- {ONCE_REG_IDX_OPABF9, DSP563XX_ONCE_OPABF11, 25, "OPABF9", 0},
- {ONCE_REG_IDX_OPABF10, DSP563XX_ONCE_OPABF11, 25, "OPABF10", 0},
- {ONCE_REG_IDX_OPABF11, DSP563XX_ONCE_OPABF11, 25, "OPABF11", 0},
-/* {25,0x1f,24,"NRSEL",0}, */
-};
-
-enum dsp563xx_reg_idx {
- DSP563XX_REG_IDX_R0 = 0,
- DSP563XX_REG_IDX_R1 = 1,
- DSP563XX_REG_IDX_R2 = 2,
- DSP563XX_REG_IDX_R3 = 3,
- DSP563XX_REG_IDX_R4 = 4,
- DSP563XX_REG_IDX_R5 = 5,
- DSP563XX_REG_IDX_R6 = 6,
- DSP563XX_REG_IDX_R7 = 7,
- DSP563XX_REG_IDX_N0 = 8,
- DSP563XX_REG_IDX_N1 = 9,
- DSP563XX_REG_IDX_N2 = 10,
- DSP563XX_REG_IDX_N3 = 11,
- DSP563XX_REG_IDX_N4 = 12,
- DSP563XX_REG_IDX_N5 = 13,
- DSP563XX_REG_IDX_N6 = 14,
- DSP563XX_REG_IDX_N7 = 15,
- DSP563XX_REG_IDX_M0 = 16,
- DSP563XX_REG_IDX_M1 = 17,
- DSP563XX_REG_IDX_M2 = 18,
- DSP563XX_REG_IDX_M3 = 19,
- DSP563XX_REG_IDX_M4 = 20,
- DSP563XX_REG_IDX_M5 = 21,
- DSP563XX_REG_IDX_M6 = 22,
- DSP563XX_REG_IDX_M7 = 23,
- DSP563XX_REG_IDX_X0 = 24,
- DSP563XX_REG_IDX_X1 = 25,
- DSP563XX_REG_IDX_Y0 = 26,
- DSP563XX_REG_IDX_Y1 = 27,
- DSP563XX_REG_IDX_A0 = 28,
- DSP563XX_REG_IDX_A1 = 29,
- DSP563XX_REG_IDX_A2 = 30,
- DSP563XX_REG_IDX_B0 = 31,
- DSP563XX_REG_IDX_B1 = 32,
- DSP563XX_REG_IDX_B2 = 33,
- DSP563XX_REG_IDX_SSH = 34,
- DSP563XX_REG_IDX_SSL = 35,
- DSP563XX_REG_IDX_SP = 36,
- DSP563XX_REG_IDX_EP = 37,
- DSP563XX_REG_IDX_SZ = 38,
- DSP563XX_REG_IDX_SC = 39,
- DSP563XX_REG_IDX_PC = 40,
- DSP563XX_REG_IDX_SR = 41,
- DSP563XX_REG_IDX_OMR = 42,
- DSP563XX_REG_IDX_LA = 43,
- DSP563XX_REG_IDX_LC = 44,
- DSP563XX_REG_IDX_VBA = 45,
- DSP563XX_REG_IDX_IPRC = 46,
- DSP563XX_REG_IDX_IPRP = 47,
- DSP563XX_REG_IDX_BCR = 48,
- DSP563XX_REG_IDX_DCR = 49,
- DSP563XX_REG_IDX_AAR0 = 50,
- DSP563XX_REG_IDX_AAR1 = 51,
- DSP563XX_REG_IDX_AAR2 = 52,
- DSP563XX_REG_IDX_AAR3 = 53,
-};
-
-static const struct {
- unsigned id;
- const char *name;
- unsigned bits;
- /* effective addressing mode encoding */
- uint8_t eame;
- uint32_t instr_mask;
-} dsp563xx_regs[] = {
- /* *INDENT-OFF* */
- /* address registers */
- {DSP563XX_REG_IDX_R0, "r0", 24, 0x10, ASM_REG_W_R0},
- {DSP563XX_REG_IDX_R1, "r1", 24, 0x11, ASM_REG_W_R1},
- {DSP563XX_REG_IDX_R2, "r2", 24, 0x12, ASM_REG_W_R2},
- {DSP563XX_REG_IDX_R3, "r3", 24, 0x13, ASM_REG_W_R3},
- {DSP563XX_REG_IDX_R4, "r4", 24, 0x14, ASM_REG_W_R4},
- {DSP563XX_REG_IDX_R5, "r5", 24, 0x15, ASM_REG_W_R5},
- {DSP563XX_REG_IDX_R6, "r6", 24, 0x16, ASM_REG_W_R6},
- {DSP563XX_REG_IDX_R7, "r7", 24, 0x17, ASM_REG_W_R7},
- /* offset registers */
- {DSP563XX_REG_IDX_N0, "n0", 24, 0x18, ASM_REG_W_N0},
- {DSP563XX_REG_IDX_N1, "n1", 24, 0x19, ASM_REG_W_N1},
- {DSP563XX_REG_IDX_N2, "n2", 24, 0x1a, ASM_REG_W_N2},
- {DSP563XX_REG_IDX_N3, "n3", 24, 0x1b, ASM_REG_W_N3},
- {DSP563XX_REG_IDX_N4, "n4", 24, 0x1c, ASM_REG_W_N4},
- {DSP563XX_REG_IDX_N5, "n5", 24, 0x1d, ASM_REG_W_N5},
- {DSP563XX_REG_IDX_N6, "n6", 24, 0x1e, ASM_REG_W_N6},
- {DSP563XX_REG_IDX_N7, "n7", 24, 0x1f, ASM_REG_W_N7},
- /* modifier registers */
- {DSP563XX_REG_IDX_M0, "m0", 24, 0x20, ASM_REG_W_M0},
- {DSP563XX_REG_IDX_M1, "m1", 24, 0x21, ASM_REG_W_M1},
- {DSP563XX_REG_IDX_M2, "m2", 24, 0x22, ASM_REG_W_M2},
- {DSP563XX_REG_IDX_M3, "m3", 24, 0x23, ASM_REG_W_M3},
- {DSP563XX_REG_IDX_M4, "m4", 24, 0x24, ASM_REG_W_M4},
- {DSP563XX_REG_IDX_M5, "m5", 24, 0x25, ASM_REG_W_M5},
- {DSP563XX_REG_IDX_M6, "m6", 24, 0x26, ASM_REG_W_M6},
- {DSP563XX_REG_IDX_M7, "m7", 24, 0x27, ASM_REG_W_M7},
- /* data alu input register */
- {DSP563XX_REG_IDX_X0, "x0", 24, 0x04, ASM_REG_W_X0},
- {DSP563XX_REG_IDX_X1, "x1", 24, 0x05, ASM_REG_W_X1},
- {DSP563XX_REG_IDX_Y0, "y0", 24, 0x06, ASM_REG_W_Y0},
- {DSP563XX_REG_IDX_Y1, "y1", 24, 0x07, ASM_REG_W_Y1},
- /* data alu accumulator register */
- {DSP563XX_REG_IDX_A0, "a0", 24, 0x08, ASM_REG_W_A0},
- {DSP563XX_REG_IDX_A1, "a1", 24, 0x0c, ASM_REG_W_A1},
- {DSP563XX_REG_IDX_A2, "a2", 8, 0x0a, ASM_REG_W_A2},
- {DSP563XX_REG_IDX_B0, "b0", 24, 0x09, ASM_REG_W_B0},
- {DSP563XX_REG_IDX_B1, "b1", 24, 0x0d, ASM_REG_W_B1},
- {DSP563XX_REG_IDX_B2, "b2", 8, 0x0b, ASM_REG_W_B2},
- /* stack */
- {DSP563XX_REG_IDX_SSH, "ssh", 24, 0x3c, ASM_REG_W_SSH},
- {DSP563XX_REG_IDX_SSL, "ssl", 24, 0x3d, ASM_REG_W_SSL},
- {DSP563XX_REG_IDX_SP, "sp", 24, 0x3b, ASM_REG_W_SP},
- {DSP563XX_REG_IDX_EP, "ep", 24, 0x2a, ASM_REG_W_EP},
- {DSP563XX_REG_IDX_SZ, "sz", 24, 0x38, ASM_REG_W_SZ},
- {DSP563XX_REG_IDX_SC, "sc", 24, 0x31, ASM_REG_W_SC},
- /* system */
- {DSP563XX_REG_IDX_PC, "pc", 24, 0x00, ASM_REG_W_PC},
- {DSP563XX_REG_IDX_SR, "sr", 24, 0x39, ASM_REG_W_SR},
- {DSP563XX_REG_IDX_OMR, "omr", 24, 0x3a, ASM_REG_W_OMR},
- {DSP563XX_REG_IDX_LA, "la", 24, 0x3e, ASM_REG_W_LA},
- {DSP563XX_REG_IDX_LC, "lc", 24, 0x3f, ASM_REG_W_LC},
- /* interrupt */
- {DSP563XX_REG_IDX_VBA, "vba", 24, 0x30, ASM_REG_W_VBA},
- {DSP563XX_REG_IDX_IPRC, "iprc", 24, 0x00, ASM_REG_W_IPRC},
- {DSP563XX_REG_IDX_IPRP, "iprp", 24, 0x00, ASM_REG_W_IPRP},
- /* port a */
- {DSP563XX_REG_IDX_BCR, "bcr", 24, 0x00, ASM_REG_W_BCR},
- {DSP563XX_REG_IDX_DCR, "dcr", 24, 0x00, ASM_REG_W_DCR},
- {DSP563XX_REG_IDX_AAR0, "aar0", 24, 0x00, ASM_REG_W_AAR0},
- {DSP563XX_REG_IDX_AAR1, "aar1", 24, 0x00, ASM_REG_W_AAR1},
- {DSP563XX_REG_IDX_AAR2, "aar2", 24, 0x00, ASM_REG_W_AAR2},
- {DSP563XX_REG_IDX_AAR3, "aar3", 24, 0x00, ASM_REG_W_AAR3},
- /* *INDENT-ON* */
-};
-
-enum memory_type {
- MEM_X = 0,
- MEM_Y = 1,
- MEM_P = 2,
- MEM_L = 3,
-};
-
-enum watchpoint_condition {
- EQUAL,
- NOT_EQUAL,
- GREATER,
- LESS_THAN
-};
-
-#define INSTR_JUMP 0x0AF080
-/* Effective Addressing Mode Encoding */
-#define EAME_R0 0x10
-/* instrcution encoder */
-/* movep
- * s - peripheral space X/Y (X=0,Y=1)
- * w - write/read
- * d - source/destination register
- * p - IO short address
- */
-#define INSTR_MOVEP_REG_HIO(s, w, d, p) (0x084000 | \
- ((s & 1) << 16) | ((w & 1) << 15) | ((d & 0x3f) << 8) | (p & 0x3f))
-
-/* the gdb register list is send in this order */
-static const uint8_t gdb_reg_list_idx[] = {
- DSP563XX_REG_IDX_X1, DSP563XX_REG_IDX_X0, DSP563XX_REG_IDX_Y1, DSP563XX_REG_IDX_Y0,
- DSP563XX_REG_IDX_A2, DSP563XX_REG_IDX_A1, DSP563XX_REG_IDX_A0, DSP563XX_REG_IDX_B2,
- DSP563XX_REG_IDX_B1, DSP563XX_REG_IDX_B0, DSP563XX_REG_IDX_PC, DSP563XX_REG_IDX_SR,
- DSP563XX_REG_IDX_OMR, DSP563XX_REG_IDX_LA, DSP563XX_REG_IDX_LC, DSP563XX_REG_IDX_SSH,
- DSP563XX_REG_IDX_SSL, DSP563XX_REG_IDX_SP, DSP563XX_REG_IDX_EP, DSP563XX_REG_IDX_SZ,
- DSP563XX_REG_IDX_SC, DSP563XX_REG_IDX_VBA, DSP563XX_REG_IDX_IPRC, DSP563XX_REG_IDX_IPRP,
- DSP563XX_REG_IDX_BCR, DSP563XX_REG_IDX_DCR, DSP563XX_REG_IDX_AAR0, DSP563XX_REG_IDX_AAR1,
- DSP563XX_REG_IDX_AAR2, DSP563XX_REG_IDX_AAR3, DSP563XX_REG_IDX_R0, DSP563XX_REG_IDX_R1,
- DSP563XX_REG_IDX_R2, DSP563XX_REG_IDX_R3, DSP563XX_REG_IDX_R4, DSP563XX_REG_IDX_R5,
- DSP563XX_REG_IDX_R6, DSP563XX_REG_IDX_R7, DSP563XX_REG_IDX_N0, DSP563XX_REG_IDX_N1,
- DSP563XX_REG_IDX_N2, DSP563XX_REG_IDX_N3, DSP563XX_REG_IDX_N4, DSP563XX_REG_IDX_N5,
- DSP563XX_REG_IDX_N6, DSP563XX_REG_IDX_N7, DSP563XX_REG_IDX_M0, DSP563XX_REG_IDX_M1,
- DSP563XX_REG_IDX_M2, DSP563XX_REG_IDX_M3, DSP563XX_REG_IDX_M4, DSP563XX_REG_IDX_M5,
- DSP563XX_REG_IDX_M6, DSP563XX_REG_IDX_M7,
-};
-
-static int dsp563xx_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[],
- int *reg_list_size,
- enum target_register_class reg_class)
-{
- int i;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- *reg_list_size = DSP563XX_NUMCOREREGS;
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
-
- if (!*reg_list)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- for (i = 0; i < DSP563XX_NUMCOREREGS; i++)
- (*reg_list)[i] = &dsp563xx->core_cache->reg_list[gdb_reg_list_idx[i]];
-
- return ERROR_OK;
-
-}
-
-static int dsp563xx_read_core_reg(struct target *target, int num)
-{
- uint32_t reg_value;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if ((num < 0) || (num >= DSP563XX_NUMCOREREGS))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- reg_value = dsp563xx->core_regs[num];
- buf_set_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32, reg_value);
- dsp563xx->core_cache->reg_list[num].valid = 1;
- dsp563xx->core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_write_core_reg(struct target *target, int num)
-{
- uint32_t reg_value;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if ((num < 0) || (num >= DSP563XX_NUMCOREREGS))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- reg_value = buf_get_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32);
- dsp563xx->core_regs[num] = reg_value;
- dsp563xx->core_cache->reg_list[num].valid = 1;
- dsp563xx->core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_get_core_reg(struct reg *reg)
-{
- struct dsp563xx_core_reg *dsp563xx_reg = reg->arch_info;
- struct target *target = dsp563xx_reg->target;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- LOG_DEBUG("%s", __func__);
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- return dsp563xx->read_core_reg(target, dsp563xx_reg->num);
-}
-
-static int dsp563xx_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- LOG_DEBUG("%s", __func__);
-
- struct dsp563xx_core_reg *dsp563xx_reg = reg->arch_info;
- struct target *target = dsp563xx_reg->target;
- uint32_t value = buf_get_u32(buf, 0, 32);
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- buf_set_u32(reg->value, 0, reg->size, value);
- reg->dirty = 1;
- reg->valid = 1;
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type dsp563xx_reg_type = {
- .get = dsp563xx_get_core_reg,
- .set = dsp563xx_set_core_reg,
-};
-
-static void dsp563xx_build_reg_cache(struct target *target)
-{
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct reg_cache *cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = calloc(DSP563XX_NUMCOREREGS, sizeof(struct reg));
- struct dsp563xx_core_reg *arch_info = malloc(
- sizeof(struct dsp563xx_core_reg) * DSP563XX_NUMCOREREGS);
- int i;
-
- /* Build the process context cache */
- cache->name = "dsp563xx registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = DSP563XX_NUMCOREREGS;
- (*cache_p) = cache;
- dsp563xx->core_cache = cache;
-
- for (i = 0; i < DSP563XX_NUMCOREREGS; i++) {
- arch_info[i].num = dsp563xx_regs[i].id;
- arch_info[i].name = dsp563xx_regs[i].name;
- arch_info[i].size = dsp563xx_regs[i].bits;
- arch_info[i].eame = dsp563xx_regs[i].eame;
- arch_info[i].instr_mask = dsp563xx_regs[i].instr_mask;
- arch_info[i].target = target;
- arch_info[i].dsp563xx_common = dsp563xx;
- reg_list[i].name = dsp563xx_regs[i].name;
- reg_list[i].size = 32; /* dsp563xx_regs[i].bits; */
- reg_list[i].value = calloc(1, 4);
- reg_list[i].dirty = 0;
- reg_list[i].valid = 0;
- reg_list[i].type = &dsp563xx_reg_type;
- reg_list[i].arch_info = &arch_info[i];
- }
-}
-
-static int dsp563xx_read_register(struct target *target, int num, int force);
-static int dsp563xx_write_register(struct target *target, int num, int force);
-
-static int dsp563xx_reg_read_high_io(struct target *target, uint32_t instr_mask, uint32_t *data)
-{
- int err;
- uint32_t instr;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- /* we use r0 to store temporary data */
- if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
-
- /* move source memory to r0 */
- instr = INSTR_MOVEP_REG_HIO(MEM_X, 0, EAME_R0, instr_mask);
- err = dsp563xx_once_execute_sw_ir(target->tap, 0, instr);
- if (err != ERROR_OK)
- return err;
- /* move r0 to debug register */
- instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, EAME_R0, 0xfffffc);
- err = dsp563xx_once_execute_sw_ir(target->tap, 1, instr);
- if (err != ERROR_OK)
- return err;
- /* read debug register */
- err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OGDBR, data);
- if (err != ERROR_OK)
- return err;
- /* r0 is no longer valid on target */
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_reg_write_high_io(struct target *target, uint32_t instr_mask, uint32_t data)
-{
- int err;
- uint32_t instr;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- /* we use r0 to store temporary data */
- if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
-
- /* move data to r0 */
- err = dsp563xx_once_execute_dw_ir(target->tap, 0, 0x60F400, data);
- if (err != ERROR_OK)
- return err;
- /* move r0 to destination memory */
- instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, EAME_R0, instr_mask);
- err = dsp563xx_once_execute_sw_ir(target->tap, 1, instr);
- if (err != ERROR_OK)
- return err;
-
- /* r0 is no longer valid on target */
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_reg_read(struct target *target, uint32_t eame, uint32_t *data)
-{
- int err;
- uint32_t instr;
-
- instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, eame, 0xfffffc);
- err = dsp563xx_once_execute_sw_ir(target->tap, 0, instr);
- if (err != ERROR_OK)
- return err;
- /* nop */
- err = dsp563xx_once_execute_sw_ir(target->tap, 1, 0x000000);
- if (err != ERROR_OK)
- return err;
- /* read debug register */
- return dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OGDBR, data);
-}
-
-static int dsp563xx_reg_write(struct target *target, uint32_t instr_mask, uint32_t data)
-{
- int err;
-
- err = dsp563xx_once_execute_dw_ir(target->tap, 0, instr_mask, data);
- if (err != ERROR_OK)
- return err;
- /* nop */
- return dsp563xx_once_execute_sw_ir(target->tap, 1, 0x000000);
-}
-
-static int dsp563xx_reg_pc_read(struct target *target)
-{
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- /* pc was changed, nothing todo */
- if (dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty)
- return ERROR_OK;
-
- /* conditional branch check */
- if (once_regs[ONCE_REG_IDX_OPABDR].reg == once_regs[ONCE_REG_IDX_OPABEX].reg) {
- if ((once_regs[ONCE_REG_IDX_OPABF11].reg & 1) == 0) {
- LOG_DEBUG("%s conditional branch not supported yet (0x%" PRIx32 " 0x%" PRIx32 " 0x%" PRIx32 ")",
- __func__,
- (once_regs[ONCE_REG_IDX_OPABF11].reg >> 1),
- once_regs[ONCE_REG_IDX_OPABDR].reg,
- once_regs[ONCE_REG_IDX_OPABEX].reg);
-
- /* TODO: use disassembly to set correct pc offset
- * read 2 words from OPABF11 and disasm the instruction
- */
- dsp563xx->core_regs[DSP563XX_REG_IDX_PC] =
- (once_regs[ONCE_REG_IDX_OPABF11].reg >> 1) & 0x00FFFFFF;
- } else {
- if (once_regs[ONCE_REG_IDX_OPABEX].reg ==
- once_regs[ONCE_REG_IDX_OPABFR].reg)
- dsp563xx->core_regs[DSP563XX_REG_IDX_PC] =
- once_regs[ONCE_REG_IDX_OPABEX].reg;
- else
- dsp563xx->core_regs[DSP563XX_REG_IDX_PC] =
- once_regs[ONCE_REG_IDX_OPABEX].reg - 1;
- }
- } else
- dsp563xx->core_regs[DSP563XX_REG_IDX_PC] = once_regs[ONCE_REG_IDX_OPABEX].reg;
-
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_PC);
-
- return ERROR_OK;
-}
-
-static int dsp563xx_reg_ssh_read(struct target *target)
-{
- int err;
- uint32_t sp;
- struct dsp563xx_core_reg *arch_info;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].arch_info;
-
- /* get a valid stack pointer */
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0);
- if (err != ERROR_OK)
- return err;
- sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP];
- err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 0);
- if (err != ERROR_OK)
- return err;
-
- /* get a valid stack count */
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SC, 0);
- if (err != ERROR_OK)
- return err;
-
- err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SC, 0);
- if (err != ERROR_OK)
- return err;
-
- /* get a valid extended pointer */
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_EP, 0);
- if (err != ERROR_OK)
- return err;
-
- err = dsp563xx_write_register(target, DSP563XX_REG_IDX_EP, 0);
- if (err != ERROR_OK)
- return err;
-
- if (!sp)
- sp = 0x00FFFFFF;
- else {
- err = dsp563xx_reg_read(target, arch_info->eame, &sp);
- if (err != ERROR_OK)
- return err;
-
- err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SC, 1);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 1);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_register(target, DSP563XX_REG_IDX_EP, 1);
- if (err != ERROR_OK)
- return err;
- }
-
- dsp563xx->core_regs[DSP563XX_REG_IDX_SSH] = sp;
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SSH);
-
- return ERROR_OK;
-}
-
-static int dsp563xx_reg_ssh_write(struct target *target)
-{
- int err;
- uint32_t sp;
- struct dsp563xx_core_reg *arch_info;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].arch_info;
-
- /* get a valid stack pointer */
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0);
- if (err != ERROR_OK)
- return err;
- sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP];
-
- if (sp) {
- sp--;
- /* write new stackpointer */
- dsp563xx->core_regs[DSP563XX_REG_IDX_SP] = sp;
- err = dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SP);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 1);
- if (err != ERROR_OK)
- return err;
-
- err = dsp563xx_reg_write(target, arch_info->instr_mask,
- dsp563xx->core_regs[DSP563XX_REG_IDX_SSH]);
- if (err != ERROR_OK)
- return err;
-
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 1);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SSH, 1);
- if (err != ERROR_OK)
- return err;
- }
-
- return ERROR_OK;
-}
-
-static int dsp563xx_reg_ssl_read(struct target *target)
-{
- int err;
- uint32_t sp;
- struct dsp563xx_core_reg *arch_info;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSL].arch_info;
-
- /* get a valid stack pointer */
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0);
- if (err != ERROR_OK)
- return err;
- sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP];
-
- if (!sp)
- sp = 0x00FFFFFF;
- else {
- err = dsp563xx_reg_read(target, arch_info->eame, &sp);
- if (err != ERROR_OK)
- return err;
- }
-
- dsp563xx->core_regs[DSP563XX_REG_IDX_SSL] = sp;
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SSL);
-
- return ERROR_OK;
-}
-
-static int dsp563xx_read_register(struct target *target, int num, int force)
-{
- int err = ERROR_OK;
- uint32_t data = 0;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
- struct dsp563xx_core_reg *arch_info;
-
- if (force)
- dsp563xx->core_cache->reg_list[num].valid = 0;
-
- if (!dsp563xx->core_cache->reg_list[num].valid) {
- arch_info = dsp563xx->core_cache->reg_list[num].arch_info;
-
- switch (arch_info->num) {
- case DSP563XX_REG_IDX_SSH:
- err = dsp563xx_reg_ssh_read(target);
- break;
- case DSP563XX_REG_IDX_SSL:
- err = dsp563xx_reg_ssl_read(target);
- break;
- case DSP563XX_REG_IDX_PC:
- err = dsp563xx_reg_pc_read(target);
- break;
- case DSP563XX_REG_IDX_IPRC:
- case DSP563XX_REG_IDX_IPRP:
- case DSP563XX_REG_IDX_BCR:
- case DSP563XX_REG_IDX_DCR:
- case DSP563XX_REG_IDX_AAR0:
- case DSP563XX_REG_IDX_AAR1:
- case DSP563XX_REG_IDX_AAR2:
- case DSP563XX_REG_IDX_AAR3:
- err = dsp563xx_reg_read_high_io(target,
- arch_info->instr_mask, &data);
- if (err == ERROR_OK) {
- dsp563xx->core_regs[num] = data;
- dsp563xx->read_core_reg(target, num);
- }
- break;
- default:
- err = dsp563xx_reg_read(target, arch_info->eame, &data);
- if (err == ERROR_OK) {
- dsp563xx->core_regs[num] = data;
- dsp563xx->read_core_reg(target, num);
- }
- break;
- }
- }
-
- return err;
-}
-
-static int dsp563xx_write_register(struct target *target, int num, int force)
-{
- int err = ERROR_OK;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
- struct dsp563xx_core_reg *arch_info;
-
- if (force)
- dsp563xx->core_cache->reg_list[num].dirty = 1;
-
- if (dsp563xx->core_cache->reg_list[num].dirty) {
- arch_info = dsp563xx->core_cache->reg_list[num].arch_info;
-
- dsp563xx->write_core_reg(target, num);
-
- switch (arch_info->num) {
- case DSP563XX_REG_IDX_SSH:
- err = dsp563xx_reg_ssh_write(target);
- break;
- case DSP563XX_REG_IDX_PC:
- /* pc is updated on resume, no need to write it here */
- break;
- case DSP563XX_REG_IDX_IPRC:
- case DSP563XX_REG_IDX_IPRP:
- case DSP563XX_REG_IDX_BCR:
- case DSP563XX_REG_IDX_DCR:
- case DSP563XX_REG_IDX_AAR0:
- case DSP563XX_REG_IDX_AAR1:
- case DSP563XX_REG_IDX_AAR2:
- case DSP563XX_REG_IDX_AAR3:
- err = dsp563xx_reg_write_high_io(target,
- arch_info->instr_mask,
- dsp563xx->core_regs[num]);
- break;
- default:
- err = dsp563xx_reg_write(target,
- arch_info->instr_mask,
- dsp563xx->core_regs[num]);
-
- if ((err == ERROR_OK) && (arch_info->num == DSP563XX_REG_IDX_SP)) {
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].valid =
- 0;
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSL].valid =
- 0;
- }
-
- break;
- }
- }
-
- return err;
-}
-
-static int dsp563xx_save_context(struct target *target)
-{
- int i, err = ERROR_OK;
-
- for (i = 0; i < DSP563XX_NUMCOREREGS; i++) {
- err = dsp563xx_read_register(target, i, 0);
- if (err != ERROR_OK)
- break;
- }
-
- return err;
-}
-
-static int dsp563xx_restore_context(struct target *target)
-{
- int i, err = ERROR_OK;
-
- for (i = 0; i < DSP563XX_NUMCOREREGS; i++) {
- err = dsp563xx_write_register(target, i, 0);
- if (err != ERROR_OK)
- break;
- }
-
- return err;
-}
-
-static void dsp563xx_invalidate_x_context(struct target *target,
- uint32_t addr_start,
- uint32_t addr_end)
-{
- int i;
- struct dsp563xx_core_reg *arch_info;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if (addr_start > ASM_REG_W_IPRC)
- return;
- if (addr_start < ASM_REG_W_AAR3)
- return;
-
- for (i = DSP563XX_REG_IDX_IPRC; i < DSP563XX_NUMCOREREGS; i++) {
- arch_info = dsp563xx->core_cache->reg_list[i].arch_info;
-
- if ((arch_info->instr_mask >= addr_start) &&
- (arch_info->instr_mask <= addr_end)) {
- dsp563xx->core_cache->reg_list[i].valid = 0;
- dsp563xx->core_cache->reg_list[i].dirty = 0;
- }
- }
-}
-
-static int dsp563xx_target_create(struct target *target, Jim_Interp *interp)
-{
- struct dsp563xx_common *dsp563xx = calloc(1, sizeof(struct dsp563xx_common));
-
- if (!dsp563xx)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- dsp563xx->jtag_info.tap = target->tap;
- target->arch_info = dsp563xx;
- dsp563xx->read_core_reg = dsp563xx_read_core_reg;
- dsp563xx->write_core_reg = dsp563xx_write_core_reg;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_init_target(struct command_context *cmd_ctx, struct target *target)
-{
- LOG_DEBUG("%s", __func__);
-
- dsp563xx_build_reg_cache(target);
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- dsp563xx->hardware_breakpoints_cleared = 0;
- dsp563xx->hardware_breakpoint[0].used = BPU_NONE;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_examine(struct target *target)
-{
- uint32_t chip;
-
- if (target->tap->hasidcode == false) {
- LOG_ERROR("no IDCODE present on device");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (!target_was_examined(target)) {
- target_set_examined(target);
-
- /* examine core and chip derivate number */
- chip = (target->tap->idcode>>12) & 0x3ff;
- /* core number 0 means DSP563XX */
- if (((chip>>5)&0x1f) == 0)
- chip += 300;
-
- LOG_INFO("DSP56%03" PRId32 " device found", chip);
-
- /* Clear all breakpoints */
- dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0);
- }
-
- return ERROR_OK;
-}
-
-static int dsp563xx_arch_state(struct target *target)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-#define DSP563XX_SR_SA (1<<17)
-#define DSP563XX_SR_SC (1<<13)
-
-static int dsp563xx_debug_once_init(struct target *target)
-{
- return dsp563xx_once_read_register(target->tap, 1, once_regs, DSP563XX_NUMONCEREGS);
-}
-
-static int dsp563xx_debug_init(struct target *target)
-{
- int err;
- uint32_t sr;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
- struct dsp563xx_core_reg *arch_info;
-
- err = dsp563xx_debug_once_init(target);
- if (err != ERROR_OK)
- return err;
-
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].arch_info;
-
- /* check 24bit mode */
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SR, 0);
- if (err != ERROR_OK)
- return err;
-
- sr = dsp563xx->core_regs[DSP563XX_REG_IDX_SR];
-
- if (sr & (DSP563XX_SR_SA | DSP563XX_SR_SC)) {
- sr &= ~(DSP563XX_SR_SA | DSP563XX_SR_SC);
-
- err = dsp563xx_once_execute_dw_ir(target->tap, 1, arch_info->instr_mask, sr);
- if (err != ERROR_OK)
- return err;
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].dirty = 1;
- }
-
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_N0, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_N1, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_M0, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_read_register(target, DSP563XX_REG_IDX_M1, 0);
- if (err != ERROR_OK)
- return err;
-
- if (dsp563xx->core_regs[DSP563XX_REG_IDX_N0] != 0x000000) {
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].arch_info;
- err = dsp563xx_reg_write(target, arch_info->instr_mask, 0x000000);
- if (err != ERROR_OK)
- return err;
- }
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].dirty = 1;
-
- if (dsp563xx->core_regs[DSP563XX_REG_IDX_N1] != 0x000000) {
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].arch_info;
- err = dsp563xx_reg_write(target, arch_info->instr_mask, 0x000000);
- if (err != ERROR_OK)
- return err;
- }
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].dirty = 1;
-
- if (dsp563xx->core_regs[DSP563XX_REG_IDX_M0] != 0xffffff) {
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].arch_info;
- err = dsp563xx_reg_write(target, arch_info->instr_mask, 0xffffff);
- if (err != ERROR_OK)
- return err;
- }
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].dirty = 1;
-
- if (dsp563xx->core_regs[DSP563XX_REG_IDX_M1] != 0xffffff) {
- arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].arch_info;
- err = dsp563xx_reg_write(target, arch_info->instr_mask, 0xffffff);
- if (err != ERROR_OK)
- return err;
- }
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].dirty = 1;
-
- err = dsp563xx_save_context(target);
- if (err != ERROR_OK)
- return err;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_jtag_debug_request(struct target *target)
-{
- return dsp563xx_once_request_debug(target->tap, target->state == TARGET_RESET);
-}
-
-static int dsp563xx_poll(struct target *target)
-{
- int err;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
- uint32_t once_status = 0;
- int state;
-
- state = dsp563xx_once_target_status(target->tap);
-
- if (state == TARGET_UNKNOWN) {
- target->state = state;
- LOG_ERROR("jtag status contains invalid mode value - communication failure");
- return ERROR_TARGET_FAILURE;
- }
-
- err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OSCR, &once_status);
- if (err != ERROR_OK)
- return err;
-
- if ((once_status & DSP563XX_ONCE_OSCR_DEBUG_M) == DSP563XX_ONCE_OSCR_DEBUG_M) {
- if (target->state != TARGET_HALTED) {
- target->state = TARGET_HALTED;
-
- err = dsp563xx_debug_init(target);
- if (err != ERROR_OK)
- return err;
-
- if (once_status & (DSP563XX_ONCE_OSCR_MBO|DSP563XX_ONCE_OSCR_SWO))
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
- else
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- LOG_DEBUG("target->state: %s (%" PRIx32 ")", target_state_name(target), once_status);
- LOG_INFO("halted: PC: 0x%" PRIx32, dsp563xx->core_regs[DSP563XX_REG_IDX_PC]);
- }
- }
-
- if (!dsp563xx->hardware_breakpoints_cleared) {
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0);
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, 0);
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0);
- dsp563xx->hardware_breakpoints_cleared = 1;
- }
-
- return ERROR_OK;
-}
-
-static int dsp563xx_halt(struct target *target)
-{
- int err;
-
- LOG_DEBUG("%s", __func__);
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- if (target->state == TARGET_UNKNOWN)
- LOG_WARNING("target was in unknown state when halt was requested");
-
- err = dsp563xx_jtag_debug_request(target);
- if (err != ERROR_OK)
- return err;
-
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_resume(struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints,
- int debug_execution)
-{
- int err;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- /* check if pc was changed and resume want to execute the next address
- * if pc was changed from gdb or other interface we will
- * jump to this address and don't execute the next address
- * this will not affect the resume command with an address argument
- * because current is set to zero then
- */
- if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) {
- dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC);
- address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC];
- current = 0;
- }
-
- LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address);
-
- err = dsp563xx_restore_context(target);
- if (err != ERROR_OK)
- return err;
- register_cache_invalidate(dsp563xx->core_cache);
-
- if (current) {
- /* restore pipeline registers and go */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR,
- once_regs[ONCE_REG_IDX_OPILR].reg);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR |
- DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO,
- once_regs[ONCE_REG_IDX_OPDBR].reg);
- if (err != ERROR_OK)
- return err;
- } else {
- /* set to go register and jump */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, INSTR_JUMP);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_PDBGOTO |
- DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO, address);
- if (err != ERROR_OK)
- return err;
- }
-
- target->state = TARGET_RUNNING;
-
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
-
- return ERROR_OK;
-}
-
-static int dsp563xx_step_ex(struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints,
- int steps)
-{
- int err;
- uint32_t once_status;
- uint32_t dr_in, cnt;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_DEBUG("target was not halted");
- return ERROR_OK;
- }
-
- /* check if pc was changed and step want to execute the next address
- * if pc was changed from gdb or other interface we will
- * jump to this address and don't execute the next address
- * this will not affect the step command with an address argument
- * because current is set to zero then
- */
- if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) {
- dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC);
- address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC];
- current = 0;
- }
-
- LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address);
-
- err = dsp563xx_jtag_debug_request(target);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_restore_context(target);
- if (err != ERROR_OK)
- return err;
-
- /* reset trace mode */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000);
- if (err != ERROR_OK)
- return err;
- /* enable trace mode */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, DSP563XX_ONCE_OSCR_TME);
- if (err != ERROR_OK)
- return err;
-
- cnt = steps;
-
- /* on JUMP we need one extra cycle */
- if (!current)
- cnt++;
-
- /* load step counter with N-1 */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, cnt);
- if (err != ERROR_OK)
- return err;
-
- if (current) {
- /* restore pipeline registers and go */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR,
- once_regs[ONCE_REG_IDX_OPILR].reg);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR |
- DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO,
- once_regs[ONCE_REG_IDX_OPDBR].reg);
- if (err != ERROR_OK)
- return err;
- } else {
- /* set to go register and jump */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, INSTR_JUMP);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_PDBGOTO |
- DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO,
- address);
- if (err != ERROR_OK)
- return err;
- }
-
- while (1) {
- err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OSCR, &once_status);
- if (err != ERROR_OK)
- return err;
-
- if (once_status & DSP563XX_ONCE_OSCR_TO) {
- err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABFR, &dr_in);
- if (err != ERROR_OK)
- return err;
- LOG_DEBUG("fetch: %08X", (unsigned) dr_in&0x00ffffff);
- err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABDR, &dr_in);
- if (err != ERROR_OK)
- return err;
- LOG_DEBUG("decode: %08X", (unsigned) dr_in&0x00ffffff);
- err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABEX, &dr_in);
- if (err != ERROR_OK)
- return err;
- LOG_DEBUG("execute: %08X", (unsigned) dr_in&0x00ffffff);
-
- /* reset trace mode */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000);
- if (err != ERROR_OK)
- return err;
-
- register_cache_invalidate(dsp563xx->core_cache);
- err = dsp563xx_debug_init(target);
- if (err != ERROR_OK)
- return err;
-
- break;
- }
- }
-
- return ERROR_OK;
-}
-
-static int dsp563xx_step(struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints)
-{
- int err;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- err = dsp563xx_step_ex(target, current, address, handle_breakpoints, 0);
- if (err != ERROR_OK)
- return err;
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- LOG_INFO("halted: PC: 0x%" PRIx32, dsp563xx->core_regs[DSP563XX_REG_IDX_PC]);
-
- return err;
-}
-
-static int dsp563xx_assert_reset(struct target *target)
-{
- int retval = 0;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- if (jtag_reset_config & RESET_HAS_SRST) {
- /* default to asserting srst */
- if (jtag_reset_config & RESET_SRST_PULLS_TRST)
- jtag_add_reset(1, 1);
- else
- jtag_add_reset(0, 1);
- }
-
- target->state = TARGET_RESET;
- jtag_add_sleep(5000);
-
- /* registers are now invalid */
- register_cache_invalidate(dsp563xx->core_cache);
-
- if (target->reset_halt) {
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int dsp563xx_deassert_reset(struct target *target)
-{
- int err;
-
- /* deassert reset lines */
- jtag_add_reset(0, 0);
-
- err = dsp563xx_poll(target);
- if (err != ERROR_OK)
- return err;
-
- if (target->reset_halt) {
- if (target->state == TARGET_HALTED) {
- /* after a reset the cpu jmp to the
- * reset vector and need 2 cycles to fill
- * the cache (fetch,decode,excecute)
- */
- err = dsp563xx_step_ex(target, 1, 0, 1, 1);
- if (err != ERROR_OK)
- return err;
- }
- } else
- target->state = TARGET_RUNNING;
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int dsp563xx_run_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info)
-{
- int i;
- int retval = ERROR_OK;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- for (i = 0; i < num_mem_params; i++) {
- retval = target_write_buffer(target, mem_params[i].address,
- mem_params[i].size, mem_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- for (i = 0; i < num_reg_params; i++) {
- struct reg *reg = register_get_by_name(dsp563xx->core_cache,
- reg_params[i].reg_name,
- 0);
-
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- continue;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- continue;
- }
-
- retval = dsp563xx_set_core_reg(reg, reg_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* exec */
- retval = target_resume(target, 0, entry_point, 1, 1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
- if (retval != ERROR_OK)
- return retval;
-
- for (i = 0; i < num_mem_params; i++) {
- if (mem_params[i].direction != PARAM_OUT)
- retval = target_read_buffer(target,
- mem_params[i].address,
- mem_params[i].size,
- mem_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- for (i = 0; i < num_reg_params; i++) {
- if (reg_params[i].direction != PARAM_OUT) {
-
- struct reg *reg = register_get_by_name(dsp563xx->core_cache,
- reg_params[i].reg_name,
- 0);
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- continue;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR(
- "BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- continue;
- }
-
- buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
- }
- }
-
- return ERROR_OK;
-}
-
-/* global command context from openocd.c */
-extern struct command_context *global_cmd_ctx;
-
-static int dsp563xx_get_default_memory(void)
-{
- Jim_Interp *interp;
- Jim_Obj *memspace;
- char *c;
-
- if (!global_cmd_ctx)
- return MEM_P;
-
- interp = global_cmd_ctx->interp;
-
- if (!interp)
- return MEM_P;
-
- memspace = Jim_GetGlobalVariableStr(interp, "memspace", JIM_NONE);
-
- if (!memspace)
- return MEM_P;
-
- c = (char *)Jim_GetString(memspace, NULL);
-
- if (!c)
- return MEM_P;
-
- switch (c[0]) {
- case '1':
- return MEM_X;
- case '2':
- return MEM_Y;
- case '3':
- return MEM_L;
- default:
- break;
- }
-
- return MEM_P;
-}
-
-static int dsp563xx_read_memory_core(struct target *target,
- int mem_type,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- uint8_t *buffer)
-{
- int err;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
- uint32_t i, x;
- uint32_t data, move_cmd = 0;
- uint8_t *b;
-
- LOG_DEBUG(
- "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
- mem_type,
- address,
- size,
- count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- switch (mem_type) {
- case MEM_X:
- /* TODO: mark effected queued registers */
- move_cmd = 0x61d800;
- break;
- case MEM_Y:
- move_cmd = 0x69d800;
- break;
- case MEM_P:
- move_cmd = 0x07d891;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* we use r0 to store temporary data */
- if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
- /* we use r1 to store temporary data */
- if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid)
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1);
-
- /* r0 is no longer valid on target */
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1;
- /* r1 is no longer valid on target */
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1;
-
- x = count;
- b = buffer;
-
- err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address);
- if (err != ERROR_OK)
- return err;
-
- for (i = 0; i < x; i++) {
- err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_once_execute_sw_ir(target->tap, 0, 0x08D13C);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_once_reg_read(target->tap, 0,
- DSP563XX_ONCE_OGDBR, (uint32_t *)(void *)b);
- if (err != ERROR_OK)
- return err;
- b += 4;
- }
-
- /* flush the jtag queue */
- err = jtag_execute_queue();
- if (err != ERROR_OK)
- return err;
-
- /* walk over the buffer and fix target endianness */
- b = buffer;
-
- for (i = 0; i < x; i++) {
- data = buf_get_u32(b, 0, 32) & 0x00FFFFFF;
-/* LOG_DEBUG("R: %08X", *((uint32_t*)b)); */
- target_buffer_set_u32(target, b, data);
- b += 4;
- }
-
- return ERROR_OK;
-}
-
-static int dsp563xx_read_memory(struct target *target,
- int mem_type,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- uint8_t *buffer)
-{
- int err;
- uint32_t i, i1;
- uint8_t *buffer_y, *buffer_x;
-
- /* if size equals zero we are called from target read memory
- * and have to handle the parameter here */
- if ((size == 0) && (count != 0)) {
- size = count % 4;
-
- if (size)
- LOG_DEBUG("size is not aligned to 4 byte");
-
- count = (count - size) / 4;
- size = 4;
- }
-
- /* we only support 4 byte aligned data */
- if ((size != 4) || (!count))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (mem_type != MEM_L)
- return dsp563xx_read_memory_core(target, mem_type, address, size, count, buffer);
-
- buffer_y = malloc(size * count);
- if (!buffer_y)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- buffer_x = malloc(size * count);
- if (!buffer_x) {
- free(buffer_y);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- err = dsp563xx_read_memory_core(target, MEM_Y, address, size, count / 2, buffer_y);
-
- if (err != ERROR_OK) {
- free(buffer_y);
- free(buffer_x);
- return err;
- }
-
- err = dsp563xx_read_memory_core(target, MEM_X, address, size, count / 2, buffer_x);
-
- if (err != ERROR_OK) {
- free(buffer_y);
- free(buffer_x);
- return err;
- }
-
- for (i = 0, i1 = 0; i < count; i += 2, i1++) {
- buf_set_u32(buffer + i*sizeof(uint32_t), 0, 32,
- buf_get_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32));
- buf_set_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32,
- buf_get_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32));
- }
-
- free(buffer_y);
- free(buffer_x);
-
- return ERROR_OK;
-}
-
-static int dsp563xx_read_memory_default(struct target *target,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- uint8_t *buffer)
-{
-
- return dsp563xx_read_memory(target,
- dsp563xx_get_default_memory(), address, size, count, buffer);
-}
-
-static int dsp563xx_read_buffer_default(struct target *target,
- uint32_t address,
- uint32_t size,
- uint8_t *buffer)
-{
-
- return dsp563xx_read_memory(target, dsp563xx_get_default_memory(), address, size, 0,
- buffer);
-}
-
-static int dsp563xx_write_memory_core(struct target *target,
- int mem_type,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- const uint8_t *buffer)
-{
- int err;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
- uint32_t i, x;
- uint32_t data, move_cmd = 0;
- const uint8_t *b;
-
- LOG_DEBUG(
- "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
- mem_type,
- address,
- size,
- count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- switch (mem_type) {
- case MEM_X:
- /* invalidate affected x registers */
- dsp563xx_invalidate_x_context(target, address, address + count - 1);
- move_cmd = 0x615800;
- break;
- case MEM_Y:
- move_cmd = 0x695800;
- break;
- case MEM_P:
- move_cmd = 0x075891;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /* we use r0 to store temporary data */
- if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
- /* we use r1 to store temporary data */
- if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid)
- dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1);
-
- /* r0 is no longer valid on target */
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1;
- /* r1 is no longer valid on target */
- dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1;
-
- x = count;
- b = buffer;
-
- err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address);
- if (err != ERROR_OK)
- return err;
-
- for (i = 0; i < x; i++) {
- data = target_buffer_get_u32(target, b);
-
-/* LOG_DEBUG("W: %08X", data); */
-
- data &= 0x00ffffff;
-
- err = dsp563xx_once_execute_dw_ir(target->tap, 0, 0x61F400, data);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd);
- if (err != ERROR_OK)
- return err;
- b += 4;
- }
-
- /* flush the jtag queue */
- err = jtag_execute_queue();
- if (err != ERROR_OK)
- return err;
-
- return ERROR_OK;
-}
-
-static int dsp563xx_write_memory(struct target *target,
- int mem_type,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- const uint8_t *buffer)
-{
- int err;
- uint32_t i, i1;
- uint8_t *buffer_y, *buffer_x;
-
- /* if size equals zero we are called from target write memory
- * and have to handle the parameter here */
- if ((size == 0) && (count != 0)) {
- size = count % 4;
-
- if (size)
- LOG_DEBUG("size is not aligned to 4 byte");
-
- count = (count - size) / 4;
- size = 4;
- }
-
- /* we only support 4 byte aligned data */
- if ((size != 4) || (!count))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (mem_type != MEM_L)
- return dsp563xx_write_memory_core(target, mem_type, address, size, count, buffer);
-
- buffer_y = malloc(size * count);
- if (!buffer_y)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- buffer_x = malloc(size * count);
- if (!buffer_x) {
- free(buffer_y);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- for (i = 0, i1 = 0; i < count; i += 2, i1++) {
- buf_set_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32,
- buf_get_u32(buffer + i * sizeof(uint32_t), 0, 32));
- buf_set_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32,
- buf_get_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32));
- }
-
- err = dsp563xx_write_memory_core(target, MEM_Y, address, size, count / 2, buffer_y);
-
- if (err != ERROR_OK) {
- free(buffer_y);
- free(buffer_x);
- return err;
- }
-
- err = dsp563xx_write_memory_core(target, MEM_X, address, size, count / 2, buffer_x);
-
- if (err != ERROR_OK) {
- free(buffer_y);
- free(buffer_x);
- return err;
- }
-
- free(buffer_y);
- free(buffer_x);
-
- return ERROR_OK;
-}
-
-static int dsp563xx_write_memory_default(struct target *target,
- uint32_t address,
- uint32_t size,
- uint32_t count,
- const uint8_t *buffer)
-{
- return dsp563xx_write_memory(target,
- dsp563xx_get_default_memory(), address, size, count, buffer);
-}
-
-static int dsp563xx_write_buffer_default(struct target *target,
- uint32_t address,
- uint32_t size,
- const uint8_t *buffer)
-{
- return dsp563xx_write_memory(target, dsp563xx_get_default_memory(), address, size, 0,
- buffer);
-}
-
-/*
- * Exit with error here, because we support watchpoints over a custom command.
- * This is because the DSP has separate X,Y,P memspace which is not compatible to the
- * traditional watchpoint logic.
- */
-static int dsp563xx_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-}
-
-/*
- * @see dsp563xx_add_watchpoint
- */
-static int dsp563xx_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-}
-
-static void handle_md_output(struct command_context *cmd_ctx,
- struct target *target,
- uint32_t address,
- unsigned size,
- unsigned count,
- const uint8_t *buffer)
-{
- const unsigned line_bytecnt = 32;
- unsigned line_modulo = line_bytecnt / size;
-
- char output[line_bytecnt * 4 + 1];
- unsigned output_len = 0;
-
- const char *value_fmt;
- switch (size) {
- case 4:
- value_fmt = "%8.8x ";
- break;
- case 2:
- value_fmt = "%4.4x ";
- break;
- case 1:
- value_fmt = "%2.2x ";
- break;
- default:
- /* "can't happen", caller checked */
- LOG_ERROR("invalid memory read size: %u", size);
- return;
- }
-
- for (unsigned i = 0; i < count; i++) {
- if (i % line_modulo == 0)
- output_len += snprintf(output + output_len,
- sizeof(output) - output_len,
- "0x%8.8x: ",
- (unsigned) (address + i));
-
- uint32_t value = 0;
- const uint8_t *value_ptr = buffer + i * size;
- switch (size) {
- case 4:
- value = target_buffer_get_u32(target, value_ptr);
- break;
- case 2:
- value = target_buffer_get_u16(target, value_ptr);
- break;
- case 1:
- value = *value_ptr;
- }
- output_len += snprintf(output + output_len,
- sizeof(output) - output_len,
- value_fmt,
- value);
-
- if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) {
- command_print(cmd_ctx, "%s", output);
- output_len = 0;
- }
- }
-}
-
-static int dsp563xx_add_custom_watchpoint(struct target *target, uint32_t address, uint32_t memType,
- enum watchpoint_rw rw, enum watchpoint_condition cond)
-{
- int err = ERROR_OK;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- bool wasRunning = false;
- /* Only set breakpoint when halted */
- if (target->state != TARGET_HALTED) {
- dsp563xx_halt(target);
- wasRunning = true;
- }
-
- if (dsp563xx->hardware_breakpoint[0].used) {
- LOG_ERROR("Cannot add watchpoint. Hardware resource already used.");
- err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- uint32_t obcr_value = 0;
- if (err == ERROR_OK) {
- obcr_value |= OBCR_b0_or_b1;
- switch (memType) {
- case MEM_X:
- obcr_value |= OBCR_BP_MEM_X;
- break;
- case MEM_Y:
- obcr_value |= OBCR_BP_MEM_Y;
- break;
- case MEM_P:
- obcr_value |= OBCR_BP_MEM_P;
- break;
- default:
- LOG_ERROR("Unknown memType parameter (%" PRIu32 ")", memType);
- err = ERROR_TARGET_INVALID;
- }
- }
-
- if (err == ERROR_OK) {
- switch (rw) {
- case WPT_READ:
- obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ);
- break;
- case WPT_WRITE:
- obcr_value |= OBCR_BP_0(OBCR_BP_ON_WRITE);
- break;
- case WPT_ACCESS:
- obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ|OBCR_BP_ON_WRITE);
- break;
- default:
- LOG_ERROR("Unsupported write mode (%d)", rw);
- err = ERROR_TARGET_INVALID;
- }
- }
-
- if (err == ERROR_OK) {
- switch (cond) {
- case EQUAL:
- obcr_value |= OBCR_BP_0(OBCR_BP_CC_EQUAL);
- break;
- case NOT_EQUAL:
- obcr_value |= OBCR_BP_0(OBCR_BP_CC_NOT_EQUAL);
- break;
- case LESS_THAN:
- obcr_value |= OBCR_BP_0(OBCR_BP_CC_LESS_THAN);
- break;
- case GREATER:
- obcr_value |= OBCR_BP_0(OBCR_BP_CC_GREATER_THAN);
- break;
- default:
- LOG_ERROR("Unsupported condition code (%d)", cond);
- err = ERROR_TARGET_INVALID;
- }
- }
-
- if (err == ERROR_OK)
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, address);
-
- if (err == ERROR_OK)
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0x0);
-
- if (err == ERROR_OK)
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, obcr_value);
-
- if (err == ERROR_OK) {
- /* You should write the memory breakpoint counter to 0 */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMBC, 0);
- }
-
- if (err == ERROR_OK) {
- /* You should write the memory breakpoint counter to 0 */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, 0);
- }
-
- if (err == ERROR_OK)
- dsp563xx->hardware_breakpoint[0].used = BPU_WATCHPOINT;
-
- if (err == ERROR_OK && wasRunning) {
- /* Resume from current PC */
- err = dsp563xx_resume(target, 1, 0x0, 0, 0);
- }
-
- return err;
-}
-
-static int dsp563xx_remove_custom_watchpoint(struct target *target)
-{
- int err = ERROR_OK;
- struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
-
- if (dsp563xx->hardware_breakpoint[0].used != BPU_WATCHPOINT) {
- LOG_ERROR("Cannot remove watchpoint, as no watchpoint is currently configured!");
- err = ERROR_TARGET_INVALID;
- }
-
- if (err == ERROR_OK) {
- /* Clear watchpoint by clearing OBCR. */
- err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0);
- }
-
- if (err == ERROR_OK)
- dsp563xx->hardware_breakpoint[0].used = BPU_NONE;
-
- return err;
-}
-
-COMMAND_HANDLER(dsp563xx_add_watchpoint_command)
-{
- int err = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
-
- uint32_t mem_type = 0;
- switch (CMD_NAME[2]) {
- case 'x':
- mem_type = MEM_X;
- break;
- case 'y':
- mem_type = MEM_Y;
- break;
- case 'p':
- mem_type = MEM_P;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t address = 0;
- if (CMD_ARGC > 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
-
- enum watchpoint_condition cond;
- switch (CMD_ARGV[0][0]) {
- case '>':
- cond = GREATER;
- break;
- case '<':
- cond = LESS_THAN;
- break;
- case '=':
- cond = EQUAL;
- break;
- case '!':
- cond = NOT_EQUAL;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- enum watchpoint_rw rw;
- switch (CMD_ARGV[1][0]) {
- case 'r':
- rw = WPT_READ;
- break;
- case 'w':
- rw = WPT_WRITE;
- break;
- case 'a':
- rw = WPT_ACCESS;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- err = dsp563xx_add_custom_watchpoint(target, address, mem_type, rw, cond);
-
- return err;
-}
-
-/* Adding a breakpoint using the once breakpoint logic.
- * Note that this mechanism is a true hw breakpoint and is share between the watchpoint logic.
- * This means, you can only have one breakpoint/watchpoint at any time.
- */
-static int dsp563xx_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- return dsp563xx_add_custom_watchpoint(target, breakpoint->address, MEM_P, WPT_READ, EQUAL);
-}
-
-static int dsp563xx_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- return dsp563xx_remove_custom_watchpoint(target);
-}
-
-COMMAND_HANDLER(dsp563xx_remove_watchpoint_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- return dsp563xx_remove_custom_watchpoint(target);
-}
-
-COMMAND_HANDLER(dsp563xx_mem_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- int err = ERROR_OK;
- int read_mem;
- uint32_t address = 0;
- uint32_t count = 1, i;
- uint32_t pattern = 0;
- uint32_t mem_type;
- uint8_t *buffer, *b;
-
- switch (CMD_NAME[1]) {
- case 'w':
- read_mem = 0;
- break;
- case 'd':
- read_mem = 1;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- switch (CMD_NAME[3]) {
- case 'x':
- mem_type = MEM_X;
- break;
- case 'y':
- mem_type = MEM_Y;
- break;
- case 'p':
- mem_type = MEM_P;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (CMD_ARGC > 0)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
-
- if (read_mem == 0) {
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (CMD_ARGC > 1)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
- if (CMD_ARGC > 2)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
- }
-
- if (read_mem == 1) {
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (CMD_ARGC > 1)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], count);
- }
-
- buffer = calloc(count, sizeof(uint32_t));
-
- if (read_mem == 1) {
- err = dsp563xx_read_memory(target, mem_type, address, sizeof(uint32_t),
- count, buffer);
- if (err == ERROR_OK)
- handle_md_output(CMD_CTX, target, address, sizeof(uint32_t), count, buffer);
-
- } else {
- b = buffer;
-
- for (i = 0; i < count; i++) {
- target_buffer_set_u32(target, b, pattern);
- b += 4;
- }
-
- err = dsp563xx_write_memory(target,
- mem_type,
- address,
- sizeof(uint32_t),
- count,
- buffer);
- }
-
- free(buffer);
-
- return err;
-}
-
-static const struct command_registration dsp563xx_command_handlers[] = {
- {
- .name = "mwwx",
- .handler = dsp563xx_mem_command,
- .mode = COMMAND_EXEC,
- .help = "write x memory words",
- .usage = "address value [count]",
- },
- {
- .name = "mwwy",
- .handler = dsp563xx_mem_command,
- .mode = COMMAND_EXEC,
- .help = "write y memory words",
- .usage = "address value [count]",
- },
- {
- .name = "mwwp",
- .handler = dsp563xx_mem_command,
- .mode = COMMAND_EXEC,
- .help = "write p memory words",
- .usage = "address value [count]",
- },
- {
- .name = "mdwx",
- .handler = dsp563xx_mem_command,
- .mode = COMMAND_EXEC,
- .help = "display x memory words",
- .usage = "address [count]",
- },
- {
- .name = "mdwy",
- .handler = dsp563xx_mem_command,
- .mode = COMMAND_EXEC,
- .help = "display y memory words",
- .usage = "address [count]",
- },
- {
- .name = "mdwp",
- .handler = dsp563xx_mem_command,
- .mode = COMMAND_EXEC,
- .help = "display p memory words",
- .usage = "address [count]",
- },
- /*
- * Watchpoint commands
- */
- {
- .name = "wpp",
- .handler = dsp563xx_add_watchpoint_command,
- .mode = COMMAND_EXEC,
- .help = "Create p memspace watchpoint",
- .usage = "(>|<|=|!) (r|w|a) address",
- },
- {
- .name = "wpx",
- .handler = dsp563xx_add_watchpoint_command,
- .mode = COMMAND_EXEC,
- .help = "Create x memspace watchpoint",
- .usage = "(>|<|=|!) (r|w|a) address",
- },
- {
- .name = "wpy",
- .handler = dsp563xx_add_watchpoint_command,
- .mode = COMMAND_EXEC,
- .help = "Create y memspace watchpoint",
- .usage = "(>|<|=|!) (r|w|a) address",
- },
- {
- .name = "rwpc",
- .handler = dsp563xx_remove_watchpoint_command,
- .mode = COMMAND_EXEC,
- .help = "remove watchpoint custom",
- .usage = " ",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-/** Holds methods for DSP563XX targets. */
-struct target_type dsp563xx_target = {
- .name = "dsp563xx",
-
- .poll = dsp563xx_poll,
- .arch_state = dsp563xx_arch_state,
-
- .get_gdb_reg_list = dsp563xx_get_gdb_reg_list,
-
- .halt = dsp563xx_halt,
- .resume = dsp563xx_resume,
- .step = dsp563xx_step,
-
- .assert_reset = dsp563xx_assert_reset,
- .deassert_reset = dsp563xx_deassert_reset,
-
- .read_memory = dsp563xx_read_memory_default,
- .write_memory = dsp563xx_write_memory_default,
-
- .read_buffer = dsp563xx_read_buffer_default,
- .write_buffer = dsp563xx_write_buffer_default,
-
- .run_algorithm = dsp563xx_run_algorithm,
-
- .add_breakpoint = dsp563xx_add_breakpoint,
- .remove_breakpoint = dsp563xx_remove_breakpoint,
- .add_watchpoint = dsp563xx_add_watchpoint,
- .remove_watchpoint = dsp563xx_remove_watchpoint,
-
- .commands = dsp563xx_command_handlers,
- .target_create = dsp563xx_target_create,
- .init_target = dsp563xx_init_target,
- .examine = dsp563xx_examine,
-};
diff --git a/src/target/dsp563xx.h b/src/target/dsp563xx.h
deleted file mode 100644
index 4bb5ace..0000000
--- a/src/target/dsp563xx.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2011 by Mathias Kuester *
- * mkdorg@users.sourceforge.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_DSP563XX_H
-#define OPENOCD_TARGET_DSP563XX_H
-
-#include <jtag/jtag.h>
-#include <target/dsp563xx_once.h>
-
-#define DSP563XX_NUMCOREREGS 54
-#define DSP563XX_NUMONCEREGS 25
-
-struct mcu_jtag {
- struct jtag_tap *tap;
-};
-
-enum breakpoint_usage {
- BPU_NONE = 0,
- BPU_BREAKPOINT,
- BPU_WATCHPOINT
-};
-
-struct hardware_breakpoint {
- enum breakpoint_usage used;
-};
-
-struct dsp563xx_common {
- struct mcu_jtag jtag_info;
- struct reg_cache *core_cache;
- uint32_t core_regs[DSP563XX_NUMCOREREGS];
- struct once_reg once_regs[DSP563XX_NUMONCEREGS];
-
- /* register cache to processor synchronization */
- int (*read_core_reg) (struct target *target, int num);
- int (*write_core_reg) (struct target *target, int num);
-
- struct hardware_breakpoint hardware_breakpoint[1];
-
- /*Were the hardware breakpoints cleared on startup?*/
- int hardware_breakpoints_cleared;
-};
-
-struct dsp563xx_core_reg {
- uint32_t num;
- const char *name;
- uint32_t size;
- uint8_t eame;
- uint32_t instr_mask;
- struct target *target;
- struct dsp563xx_common *dsp563xx_common;
-};
-
-static inline struct dsp563xx_common *target_to_dsp563xx(struct target *target)
-{
- return target->arch_info;
-}
-
-#endif /* OPENOCD_TARGET_DSP563XX_H */
diff --git a/src/target/dsp563xx_once.c b/src/target/dsp563xx_once.c
deleted file mode 100644
index fe4927b..0000000
--- a/src/target/dsp563xx_once.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Mathias Kuester *
- * mkdorg@users.sourceforge.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jim.h>
-
-#include "target.h"
-#include "target_type.h"
-#include "register.h"
-#include "dsp563xx.h"
-#include "dsp563xx_once.h"
-
-#define JTAG_STATUS_STATIC_MASK 0x03
-#define JTAG_STATUS_STATIC_VALUE 0x01
-
-#define JTAG_STATUS_NORMAL 0x01
-#define JTAG_STATUS_STOPWAIT 0x05
-#define JTAG_STATUS_BUSY 0x09
-#define JTAG_STATUS_DEBUG 0x0d
-
-#define JTAG_INSTR_EXTEST 0x00
-#define JTAG_INSTR_SAMPLE_PRELOAD 0x01
-#define JTAG_INSTR_IDCODE 0x02
-#define JTAG_INSTR_HIZ 0x04
-#define JTAG_INSTR_CLAMP 0x05
-#define JTAG_INSTR_ENABLE_ONCE 0x06
-#define JTAG_INSTR_DEBUG_REQUEST 0x07
-#define JTAG_INSTR_BYPASS 0x0F
-
-/** */
-static inline int dsp563xx_write_dr(struct jtag_tap *tap, uint8_t * dr_in, uint8_t * dr_out, int dr_len, int rti)
-{
- jtag_add_plain_dr_scan(dr_len, dr_out, dr_in, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-/** */
-static inline int dsp563xx_write_dr_u8(struct jtag_tap *tap, uint8_t * dr_in, uint8_t dr_out, int dr_len, int rti)
-{
- return dsp563xx_write_dr(tap, dr_in, &dr_out, dr_len, rti);
-}
-
-/** */
-static inline int dsp563xx_write_dr_u32(struct jtag_tap *tap, uint32_t * dr_in, uint32_t dr_out, int dr_len, int rti)
-{
- return dsp563xx_write_dr(tap, (uint8_t *) dr_in, (uint8_t *) &dr_out, dr_len, rti);
-}
-
-/** single word instruction */
-static inline int dsp563xx_once_ir_exec(struct jtag_tap *tap, int flush, uint8_t instr, uint8_t rw, uint8_t go, uint8_t ex)
-{
- int err;
-
- err = dsp563xx_write_dr_u8(tap, 0, instr | (ex << 5) | (go << 6) | (rw << 7), 8, 0);
- if (err != ERROR_OK)
- return err;
- if (flush)
- err = jtag_execute_queue();
- return err;
-}
-
-/* IR and DR functions */
-static inline int dsp563xx_write_ir(struct jtag_tap *tap, uint8_t * ir_in, uint8_t * ir_out, int ir_len, int rti)
-{
- jtag_add_plain_ir_scan(tap->ir_length, ir_out, ir_in, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-static inline int dsp563xx_write_ir_u8(struct jtag_tap *tap, uint8_t * ir_in, uint8_t ir_out, int ir_len, int rti)
-{
- return dsp563xx_write_ir(tap, ir_in, &ir_out, ir_len, rti);
-}
-
-static inline int dsp563xx_jtag_sendinstr(struct jtag_tap *tap, uint8_t * ir_in, uint8_t ir_out)
-{
- return dsp563xx_write_ir_u8(tap, ir_in, ir_out, tap->ir_length, 1);
-}
-
-/** */
-int dsp563xx_once_target_status(struct jtag_tap *tap)
-{
- int err;
- uint8_t jtag_status;
-
- err = dsp563xx_jtag_sendinstr(tap, &jtag_status, JTAG_INSTR_ENABLE_ONCE);
- if (err != ERROR_OK)
- return TARGET_UNKNOWN;
- err = jtag_execute_queue();
- if (err != ERROR_OK)
- return TARGET_UNKNOWN;
-
- /* verify correct static status pattern */
- if ((jtag_status & JTAG_STATUS_STATIC_MASK) != JTAG_STATUS_STATIC_VALUE)
- return TARGET_UNKNOWN;
-
- if (jtag_status != JTAG_STATUS_DEBUG)
- return TARGET_RUNNING;
-
- return TARGET_HALTED;
-}
-
-/** */
-int dsp563xx_once_request_debug(struct jtag_tap *tap, int reset_state)
-{
- int err;
- uint8_t ir_in = 0, pattern = 0;
- uint32_t retry = 0;
-
- /* in reset state we only get a ACK
- * from the interface */
- if (reset_state)
- pattern = 1;
- else
- pattern = JTAG_STATUS_DEBUG;
-
- /* wait until we get the ack */
- while (ir_in != pattern) {
- err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_DEBUG_REQUEST);
- if (err != ERROR_OK)
- return err;
- err = jtag_execute_queue();
- if (err != ERROR_OK)
- return err;
-
- LOG_DEBUG("debug request: %02X", ir_in);
-
- if (retry++ == 100)
- return ERROR_TARGET_FAILURE;
- }
-
- /* we cant enable the once in reset state */
- if (pattern == 1)
- return ERROR_OK;
-
- /* try to enable once */
- retry = 0;
- ir_in = 0;
- while (ir_in != pattern) {
- err = dsp563xx_jtag_sendinstr(tap, &ir_in, JTAG_INSTR_ENABLE_ONCE);
- if (err != ERROR_OK)
- return err;
- err = jtag_execute_queue();
- if (err != ERROR_OK)
- return err;
-
- LOG_DEBUG("enable once: %02X", ir_in);
-
- if (retry++ == 100) {
- LOG_DEBUG("error");
- return ERROR_TARGET_FAILURE;
- }
- }
-
- if (ir_in != JTAG_STATUS_DEBUG)
- return ERROR_TARGET_FAILURE;
-
- return ERROR_OK;
-}
-
-/** once read registers */
-int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len)
-{
- int i;
- int err = ERROR_OK;
-
- for (i = 0; i < len; i++) {
- err = dsp563xx_once_reg_read_ex(tap, flush, regs[i].addr, regs[i].len, &regs[i].reg);
- if (err != ERROR_OK)
- return err;
- }
-
- if (flush)
- err = jtag_execute_queue();
- return err;
-}
-
-/** once read register with register len */
-int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t * data)
-{
- int err;
-
- err = dsp563xx_once_ir_exec(tap, 1, reg, 1, 0, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_dr_u32(tap, data, 0x00, len, 0);
- if (err != ERROR_OK)
- return err;
- if (flush)
- err = jtag_execute_queue();
-
- return err;
-}
-
-/** once read register */
-int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t * data)
-{
- int err;
-
- err = dsp563xx_once_ir_exec(tap, flush, reg, 1, 0, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_dr_u32(tap, data, 0x00, 24, 0);
- if (err != ERROR_OK)
- return err;
- if (flush)
- err = jtag_execute_queue();
-
- return err;
-}
-
-/** once write register */
-int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t data)
-{
- int err;
-
- err = dsp563xx_once_ir_exec(tap, flush, reg, 0, 0, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_dr_u32(tap, 0x00, data, 24, 0);
- if (err != ERROR_OK)
- return err;
- if (flush)
- err = jtag_execute_queue();
- return err;
-}
-
-/** single word instruction */
-int dsp563xx_once_execute_sw_ir(struct jtag_tap *tap, int flush, uint32_t opcode)
-{
- int err;
-
- err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0);
- if (err != ERROR_OK)
- return err;
- if (flush)
- err = jtag_execute_queue();
- return err;
-}
-
-/** double word instruction */
-int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode, uint32_t operand)
-{
- int err;
-
- err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 0, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_dr_u32(tap, 0, opcode, 24, 0);
- if (err != ERROR_OK)
- return err;
- if (flush) {
- err = jtag_execute_queue();
- if (err != ERROR_OK)
- return err;
- }
-
- err = dsp563xx_once_ir_exec(tap, flush, DSP563XX_ONCE_OPDBR, 0, 1, 0);
- if (err != ERROR_OK)
- return err;
- err = dsp563xx_write_dr_u32(tap, 0, operand, 24, 0);
- if (err != ERROR_OK)
- return err;
- if (flush) {
- err = jtag_execute_queue();
- if (err != ERROR_OK)
- return err;
- }
-
- return ERROR_OK;
-}
diff --git a/src/target/dsp563xx_once.h b/src/target/dsp563xx_once.h
deleted file mode 100644
index da7f5e9..0000000
--- a/src/target/dsp563xx_once.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Mathias Kuester *
- * mkdorg@users.sourceforge.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_DSP563XX_ONCE_H
-#define OPENOCD_TARGET_DSP563XX_ONCE_H
-
-#include <jtag/jtag.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define DSP563XX_ONCE_OCR_EX (1<<5)
-#define DSP563XX_ONCE_OCR_GO (1<<6)
-#define DSP563XX_ONCE_OCR_RW (1<<7)
-
-#define DSP563XX_ONCE_OSCR_OS1 (1<<7)
-#define DSP563XX_ONCE_OSCR_OS0 (1<<6)
-#define DSP563XX_ONCE_OSCR_HIT (1<<5)
-#define DSP563XX_ONCE_OSCR_TO (1<<4)
-#define DSP563XX_ONCE_OSCR_MBO (1<<3)
-#define DSP563XX_ONCE_OSCR_SWO (1<<2)
-#define DSP563XX_ONCE_OSCR_IME (1<<1)
-#define DSP563XX_ONCE_OSCR_TME (1<<0)
-
-#define DSP563XX_ONCE_OSCR_NORMAL_M (0)
-#define DSP563XX_ONCE_OSCR_STOPWAIT_M (DSP563XX_ONCE_OSCR_OS0)
-#define DSP563XX_ONCE_OSCR_BUSY_M (DSP563XX_ONCE_OSCR_OS1)
-#define DSP563XX_ONCE_OSCR_DEBUG_M (DSP563XX_ONCE_OSCR_OS0|DSP563XX_ONCE_OSCR_OS1)
-
-#define DSP563XX_ONCE_OSCR 0x000 /* status/ctrl reg. */
-#define DSP563XX_ONCE_OMBC 0x001 /* memory breakp. reg. */
-#define DSP563XX_ONCE_OBCR 0x002 /* breakp. ctrl reg */
-#define DSP563XX_ONCE_OMLR0 0x005 /* memory limit reg */
-#define DSP563XX_ONCE_OMLR1 0x006 /* memory limit reg */
-#define DSP563XX_ONCE_OGDBR 0x009 /* gdb reg */
-#define DSP563XX_ONCE_OPDBR 0x00A /* pdb reg */
-#define DSP563XX_ONCE_OPILR 0x00B /* pil reg */
-#define DSP563XX_ONCE_PDBGOTO 0x00C /* pdb to go reg */
-#define DSP563XX_ONCE_OTC 0x00D /* trace cnt */
-#define DSP563XX_ONCE_TAGB 0x00E /* tags buffer */
-#define DSP563XX_ONCE_OPABFR 0x00F /* pab fetch reg */
-#define DSP563XX_ONCE_OPABDR 0x010 /* pab decode reg */
-#define DSP563XX_ONCE_OPABEX 0x011 /* pab exec reg */
-#define DSP563XX_ONCE_OPABF11 0x012 /* trace buffer/inc ptr */
-#define DSP563XX_ONCE_NOREG 0x01F /* no register selected */
-
-struct once_reg {
- const uint8_t num;
- const uint8_t addr;
- const uint8_t len;
- const char *name;
- uint32_t reg;
-};
-
-/** */
-int dsp563xx_once_request_debug(struct jtag_tap *tap, int reset_state);
-/** */
-int dsp563xx_once_target_status(struct jtag_tap *tap);
-
-/** once read registers */
-int dsp563xx_once_read_register(struct jtag_tap *tap, int flush, struct once_reg *regs, int len);
-/** once read register */
-int dsp563xx_once_reg_read_ex(struct jtag_tap *tap, int flush, uint8_t reg, uint8_t len, uint32_t * data);
-/** once read register */
-int dsp563xx_once_reg_read(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t * data);
-/** once write register */
-int dsp563xx_once_reg_write(struct jtag_tap *tap, int flush, uint8_t reg, uint32_t data);
-/** single word instruction */
-int dsp563xx_once_execute_sw_ir(struct jtag_tap *tap, int flush, uint32_t opcode);
-/** double word instruction */
-int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode, uint32_t operand);
-
-#endif /* OPENOCD_TARGET_DSP563XX_ONCE_H */
diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c
deleted file mode 100644
index 205d8fe..0000000
--- a/src/target/dsp5680xx.c
+++ /dev/null
@@ -1,2297 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Rodrigo L. Rosa *
- * rodrigorosa.LG@gmail.com *
- * *
- * Based on dsp563xx_once.h written by Mathias Kuester *
- * mkdorg@users.sourceforge.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "target_type.h"
-#include "dsp5680xx.h"
-
-struct dsp5680xx_common dsp5680xx_context;
-
-#define _E "DSP5680XX_ERROR:%d\nAt:%s:%d:%s"
-#define err_check(r, c, m) if (r != ERROR_OK) {LOG_ERROR(_E, c, __func__, __LINE__, m); return r; }
-#define err_check_propagate(retval) if (retval != ERROR_OK) return retval;
-#define DEBUG_MSG "Debug mode be enabled to read mem."
-#define DEBUG_FAIL { err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IN_DEBUG, DEBUG_MSG) }
-#define CHECK_DBG if (!dsp5680xx_context.debug_mode_enabled) DEBUG_FAIL
-#define HALT_MSG "Target must be halted."
-#define HALT_FAIL { err_check(ERROR_FAIL, DSP5680XX_ERROR_TARGET_RUNNING, HALT_MSG) }
-#define CHECK_HALT(target) if (target->state != TARGET_HALTED) HALT_FAIL
-#define check_halt_and_debug(target) { CHECK_HALT(target); CHECK_DBG; }
-
-int dsp5680xx_execute_queue(void)
-{
- int retval;
-
- retval = jtag_execute_queue();
- return retval;
-}
-
-/**
- * Reset state machine
- */
-static int reset_jtag(void)
-{
- int retval;
-
- tap_state_t states[2];
-
- const char *cp = "RESET";
-
- states[0] = tap_state_by_name(cp);
- retval = jtag_add_statemove(states[0]);
- err_check_propagate(retval);
- retval = jtag_execute_queue();
- err_check_propagate(retval);
- jtag_add_pathmove(0, states + 1);
- retval = jtag_execute_queue();
- return retval;
-}
-
-static int dsp5680xx_drscan(struct target *target, uint8_t *d_in,
- uint8_t *d_out, int len)
-{
- /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- *
- *Inputs:
- * - d_in: This is the data that will be shifted into the JTAG DR reg.
- * - d_out: The data that will be shifted out of the JTAG DR reg will stored here
- * - len: Length of the data to be shifted to JTAG DR.
- *
- *Note: If d_out == NULL, discard incoming bits.
- *
- *-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
- */
- int retval = ERROR_OK;
-
- if (NULL == target->tap) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_INVALID_TAP,
- "Invalid tap");
- }
- if (len > 32) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_DR_LEN_OVERFLOW,
- "dr_len overflow, maxium is 32");
- }
- /* TODO what values of len are valid for jtag_add_plain_dr_scan? */
- /* can i send as many bits as i want? */
- /* is the casting necessary? */
- jtag_add_plain_dr_scan(len, d_in, d_out, TAP_IDLE);
- if (dsp5680xx_context.flush) {
- retval = dsp5680xx_execute_queue();
- err_check(retval, DSP5680XX_ERROR_JTAG_DRSCAN,
- "drscan failed!");
- }
- if (d_out != NULL)
- LOG_DEBUG("Data read (%d bits): 0x%04X", len, *d_out);
- else
- LOG_DEBUG("Data read was discarded.");
- return retval;
-}
-
-/**
- * Test func
- *
- * @param target
- * @param d_in This is the data that will be shifted into the JTAG IR reg.
- * @param d_out The data that will be shifted out of the JTAG IR reg will be stored here.
- * @apram ir_len Length of the data to be shifted to JTAG IR.
- *
- */
-static int dsp5680xx_irscan(struct target *target, uint32_t *d_in,
- uint32_t *d_out, uint8_t ir_len)
-{
- int retval = ERROR_OK;
-
- uint16_t tap_ir_len = DSP5680XX_JTAG_MASTER_TAP_IRLEN;
-
- if (NULL == target->tap) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_INVALID_TAP,
- "Invalid tap");
- }
- if (ir_len != target->tap->ir_length) {
- if (target->tap->enabled) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_INVALID_IR_LEN,
- "Invalid irlen");
- } else {
- struct jtag_tap *t =
- jtag_tap_by_string("dsp568013.chp");
- if ((t == NULL)
- || ((t->enabled) && (ir_len != tap_ir_len))) {
- retval = ERROR_FAIL;
- err_check(retval,
- DSP5680XX_ERROR_INVALID_IR_LEN,
- "Invalid irlen");
- }
- }
- }
- jtag_add_plain_ir_scan(ir_len, (uint8_t *) d_in, (uint8_t *) d_out,
- TAP_IDLE);
- if (dsp5680xx_context.flush) {
- retval = dsp5680xx_execute_queue();
- err_check(retval, DSP5680XX_ERROR_JTAG_IRSCAN,
- "irscan failed!");
- }
- return retval;
-}
-
-static int dsp5680xx_jtag_status(struct target *target, uint8_t *status)
-{
- uint32_t read_from_ir;
-
- uint32_t instr;
-
- int retval;
-
- instr = JTAG_INSTR_ENABLE_ONCE;
- retval =
- dsp5680xx_irscan(target, &instr, &read_from_ir,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- if (status != NULL)
- *status = (uint8_t) read_from_ir;
- return ERROR_OK;
-}
-
-static int jtag_data_read(struct target *target, uint8_t *data_read,
- int num_bits)
-{
- uint32_t bogus_instr = 0;
-
- int retval =
- dsp5680xx_drscan(target, (uint8_t *) &bogus_instr, data_read,
- num_bits);
- LOG_DEBUG("Data read (%d bits): 0x%04X", num_bits, *data_read);
- /** TODO remove this or move to jtagio? */
- return retval;
-}
-
-#define jtag_data_read8(target, data_read) jtag_data_read(target, data_read, 8)
-#define jtag_data_read16(target, data_read) jtag_data_read(target, data_read, 16)
-#define jtag_data_read32(target, data_read) jtag_data_read(target, data_read, 32)
-
-static uint32_t data_read_dummy;
-
-static int jtag_data_write(struct target *target, uint32_t instr, int num_bits,
- uint32_t *data_read)
-{
- int retval;
-
- retval =
- dsp5680xx_drscan(target, (uint8_t *) &instr,
- (uint8_t *) &data_read_dummy, num_bits);
- err_check_propagate(retval);
- if (data_read != NULL)
- *data_read = data_read_dummy;
- return retval;
-}
-
-#define jtag_data_write8(target, instr, data_read) jtag_data_write(target, instr, 8, data_read)
-#define jtag_data_write16(target, instr, data_read) jtag_data_write(target, instr, 16, data_read)
-#define jtag_data_write24(target, instr, data_read) jtag_data_write(target, instr, 24, data_read)
-#define jtag_data_write32(target, instr, data_read) jtag_data_write(target, instr, 32, data_read)
-
-/**
- * Executes EOnCE instruction.
- *
- * @param target
- * @param instr Instruction to execute.
- * @param rw
- * @param go
- * @param ex
- * @param eonce_status Value read from the EOnCE status register.
- *
- * @return
- */
-static int eonce_instruction_exec_single(struct target *target, uint8_t instr,
- uint8_t rw, uint8_t go, uint8_t ex,
- uint8_t *eonce_status)
-{
- int retval;
-
- uint32_t dr_out_tmp;
-
- uint8_t instr_with_flags = instr | (rw << 7) | (go << 6) | (ex << 5);
-
- retval = jtag_data_write(target, instr_with_flags, 8, &dr_out_tmp);
- err_check_propagate(retval);
- if (eonce_status != NULL)
- *eonce_status = (uint8_t) dr_out_tmp;
- return retval;
-}
-
-/* wrappers for multi opcode instructions */
-#define dsp5680xx_exe_1(target, oc1, oc2, oc3) dsp5680xx_exe1(target, oc1)
-#define dsp5680xx_exe_2(target, oc1, oc2, oc3) dsp5680xx_exe2(target, oc1, oc2)
-#define dsp5680xx_exe_3(target, oc1, oc2, oc3) dsp5680xx_exe3(target, oc1, oc2, oc3)
-#define dsp5680xx_exe_generic(t, words, oc1, oc2, oc3) dsp5680xx_exe_##words(t, oc1, oc2, oc3)
-
-/* Executes one word DSP instruction */
-static int dsp5680xx_exe1(struct target *target, uint16_t opcode)
-{
- int retval;
-
- retval = eonce_instruction_exec_single(target, 0x04, 0, 1, 0, NULL);
- err_check_propagate(retval);
- retval = jtag_data_write16(target, opcode, NULL);
- err_check_propagate(retval);
- return retval;
-}
-
-/* Executes two word DSP instruction */
-static int dsp5680xx_exe2(struct target *target, uint16_t opcode1,
- uint16_t opcode2)
-{
- int retval;
-
- retval = eonce_instruction_exec_single(target, 0x04, 0, 0, 0, NULL);
- err_check_propagate(retval);
- retval = jtag_data_write16(target, opcode1, NULL);
- err_check_propagate(retval);
- retval = eonce_instruction_exec_single(target, 0x04, 0, 1, 0, NULL);
- err_check_propagate(retval);
- retval = jtag_data_write16(target, opcode2, NULL);
- err_check_propagate(retval);
- return retval;
-}
-
-/* Executes three word DSP instruction */
-static int dsp5680xx_exe3(struct target *target, uint16_t opcode1,
- uint16_t opcode2, uint16_t opcode3)
-{
- int retval;
-
- retval = eonce_instruction_exec_single(target, 0x04, 0, 0, 0, NULL);
- err_check_propagate(retval);
- retval = jtag_data_write16(target, opcode1, NULL);
- err_check_propagate(retval);
- retval = eonce_instruction_exec_single(target, 0x04, 0, 0, 0, NULL);
- err_check_propagate(retval);
- retval = jtag_data_write16(target, opcode2, NULL);
- err_check_propagate(retval);
- retval = eonce_instruction_exec_single(target, 0x04, 0, 1, 0, NULL);
- err_check_propagate(retval);
- retval = jtag_data_write16(target, opcode3, NULL);
- err_check_propagate(retval);
- return retval;
-}
-
-/*
- *--------------- Real-time data exchange ---------------
- * The EOnCE Transmit (OTX) and Receive (ORX) registers are data memory mapped, each with an upper
- * and lower 16 bit word.
- * Transmit and receive directions are defined from the core’s perspective.
- * The core writes to the Transmit register and reads the Receive register, and the host through
- * JTAG writes to the Receive register and reads the Transmit register.
- * Both registers have a combined data memory mapped OTXRXSR which provides indication when
- * each may be accessed.
- * ref: eonce_rev.1.0_0208081.pdf@36
- */
-
-/* writes data into upper ORx register of the target */
-static int core_tx_upper_data(struct target *target, uint16_t data,
- uint32_t *eonce_status_low)
-{
- int retval;
-
- retval =
- eonce_instruction_exec_single(target, DSP5680XX_ONCE_ORX1, 0, 0, 0,
- NULL);
- err_check_propagate(retval);
- retval = jtag_data_write16(target, data, eonce_status_low);
- err_check_propagate(retval);
- return retval;
-}
-
-/* writes data into lower ORx register of the target */
-#define CMD1 eonce_instruction_exec_single(target, DSP5680XX_ONCE_ORX, 0, 0, 0, NULL);
-#define CMD2 jtag_data_write16((t, data)
-#define core_tx_lower_data(t, data) PT1\ PT2
-
-/**
- *
- * @param target
- * @param data_read: Returns the data read from the upper OTX register via JTAG.
- * @return: Returns an error code (see error code documentation)
- */
-static int core_rx_upper_data(struct target *target, uint8_t *data_read)
-{
- int retval;
-
- retval =
- eonce_instruction_exec_single(target, DSP5680XX_ONCE_OTX1, 1, 0, 0,
- NULL);
- err_check_propagate(retval);
- retval = jtag_data_read16(target, data_read);
- err_check_propagate(retval);
- return retval;
-}
-
-/**
- *
- * @param target
- * @param data_read: Returns the data read from the lower OTX register via JTAG.
- * @return: Returns an error code (see error code documentation)
- */
-static int core_rx_lower_data(struct target *target, uint8_t *data_read)
-{
- int retval;
-
- retval =
- eonce_instruction_exec_single(target, DSP5680XX_ONCE_OTX, 1, 0, 0,
- NULL);
- err_check_propagate(retval);
- retval = jtag_data_read16(target, data_read);
- err_check_propagate(retval);
- return retval;
-}
-
-/*
- *-- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- --
- *-- -- -- -- --- -- -- -Core Instructions- -- -- -- --- -- -- -- --- --
- *-- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- -- -- -- --- --
- */
-
-#define exe(a, b, c, d, e) dsp5680xx_exe_generic(a, b, c, d, e)
-
-/* move.l #value, r0 */
-#define core_move_long_to_r0(target, value) exe(target, 3, 0xe418, value&0xffff, value>>16)
-
-/* move.l #value, n */
-#define core_move_long_to_n(target, value) exe(target, 3, 0xe41e, value&0xffff, value>>16)
-
-/* move x:(r0), y0 */
-#define core_move_at_r0_to_y0(target) exe(target, 1, 0xF514, 0, 0)
-
-/* move x:(r0), y1 */
-#define core_move_at_r0_to_y1(target) exe(target, 1, 0xF714, 0, 0)
-
-/* move.l x:(r0), y */
-#define core_move_long_at_r0_y(target) exe(target, 1, 0xF734, 0, 0)
-
-/* move y0, x:(r0) */
-#define core_move_y0_at_r0(target) exe(target, 1, 0xd514, 0, 0)
-
-/* bfclr #value, x:(r0) */
-#define eonce_bfclr_at_r0(target, value) exe(target, 2, 0x8040, value, 0)
-
-/* move #value, y0 */
-#define core_move_value_to_y0(target, value) exe(target, 2, 0x8745, value, 0)
-
-/* move.w y0, x:(r0)+ */
-#define core_move_y0_at_r0_inc(target) exe(target, 1, 0xd500, 0, 0)
-
-/* move.w y0, p:(r0)+ */
-#define core_move_y0_at_pr0_inc(target) exe(target, 1, 0x8560, 0, 0)
-
-/* move.w p:(r0)+, y0 */
-#define core_move_at_pr0_inc_to_y0(target) exe(target, 1, 0x8568, 0, 0)
-
-/* move.w p:(r0)+, y1 */
-#define core_move_at_pr0_inc_to_y1(target) exe(target, 1, 0x8768, 0, 0)
-
-/* move.l #value, r2 */
-#define core_move_long_to_r2(target, value) exe(target, 3, 0xe41A, value&0xffff, value>>16)
-
-/* move y0, x:(r2) */
-#define core_move_y0_at_r2(target) exe(target, 1, 0xd516, 0, 0)
-
-/* move.w #<value>, x:(r2) */
-#define core_move_value_at_r2(target, value) exe(target, 2, 0x8642, value, 0)
-
-/* move.w #<value>, x:(r0) */
-#define core_move_value_at_r0(target, value) exe(target, 2, 0x8640, value, 0)
-
-/* move.w #<value>, x:(R2+<disp>) */
-#define core_move_value_at_r2_disp(target, value, disp) exe(target, 3, 0x8646, value, disp)
-
-/* move.w x:(r2), Y0 */
-#define core_move_at_r2_to_y0(target) exe(target, 1, 0xF516, 0, 0)
-
-/* move.w p:(r2)+, y0 */
-#define core_move_at_pr2_inc_to_y0(target) exe(target, 1, 0x856A, 0, 0)
-
-/* move.l #value, r3 */
-#define core_move_long_to_r1(target, value) exe(target, 3, 0xE419, value&0xffff, value>>16)
-
-/* move.l #value, r3 */
-#define core_move_long_to_r3(target, value) exe(target, 3, 0xE41B, value&0xffff, value>>16)
-
-/* move.w y0, p:(r3)+ */
-#define core_move_y0_at_pr3_inc(target) exe(target, 1, 0x8563, 0, 0)
-
-/* move.w y0, x:(r3) */
-#define core_move_y0_at_r3(target) exe(target, 1, 0xD503, 0, 0)
-
-/* move.l #value, r4 */
-#define core_move_long_to_r4(target, value) exe(target, 3, 0xE41C, value&0xffff, value>>16)
-
-/* move pc, r4 */
-#define core_move_pc_to_r4(target) exe(target, 1, 0xE716, 0, 0)
-
-/* move.l r4, y */
-#define core_move_r4_to_y(target) exe(target, 1, 0xe764, 0, 0)
-
-/* move.w p:(r0)+, y0 */
-#define core_move_at_pr0_inc_to_y0(target) exe(target, 1, 0x8568, 0, 0)
-
-/* move.w x:(r0)+, y0 */
-#define core_move_at_r0_inc_to_y0(target) exe(target, 1, 0xf500, 0, 0)
-
-/* move x:(r0), y0 */
-#define core_move_at_r0_y0(target) exe(target, 1, 0xF514, 0, 0)
-
-/* nop */
-#define eonce_nop(target) exe(target, 1, 0xe700, 0, 0)
-
-/* move.w x:(R2+<disp>), Y0 */
-#define core_move_at_r2_disp_to_y0(target, disp) exe(target, 2, 0xF542, disp, 0)
-
-/* move.w y1, x:(r2) */
-#define core_move_y1_at_r2(target) exe(target, 1, 0xd716, 0, 0)
-
-/* move.w y1, x:(r0) */
-#define core_move_y1_at_r0(target) exe(target, 1, 0xd714, 0, 0)
-
-/* move.bp y0, x:(r0)+ */
-#define core_move_byte_y0_at_r0(target) exe(target, 1, 0xd5a0, 0, 0)
-
-/* move.w y1, p:(r0)+ */
-#define core_move_y1_at_pr0_inc(target) exe(target, 1, 0x8760, 0, 0)
-
-/* move.w y1, x:(r0)+ */
-#define core_move_y1_at_r0_inc(target) exe(target, 1, 0xD700, 0, 0)
-
-/* move.l #value, y */
-#define core_move_long_to_y(target, value) exe(target, 3, 0xe417, value&0xffff, value>>16)
-
-static int core_move_value_to_pc(struct target *target, uint32_t value)
-{
- check_halt_and_debug(target);
- int retval;
-
- retval =
- dsp5680xx_exe_generic(target, 3, 0xE71E, value & 0xffff,
- value >> 16);
- err_check_propagate(retval);
- return retval;
-}
-
-static int eonce_load_TX_RX_to_r0(struct target *target)
-{
- int retval;
-
- retval =
- core_move_long_to_r0(target,
- ((MC568013_EONCE_TX_RX_ADDR) +
- (MC568013_EONCE_OBASE_ADDR << 16)));
- return retval;
-}
-
-static int core_load_TX_RX_high_addr_to_r0(struct target *target)
-{
- int retval = 0;
-
- retval =
- core_move_long_to_r0(target,
- ((MC568013_EONCE_TX1_RX1_HIGH_ADDR) +
- (MC568013_EONCE_OBASE_ADDR << 16)));
- return retval;
-}
-
-static int dsp5680xx_read_core_reg(struct target *target, uint8_t reg_addr,
- uint16_t *data_read)
-{
- /* TODO implement a general version of this which matches what openocd uses. */
- int retval;
-
- uint32_t dummy_data_to_shift_into_dr;
-
- retval = eonce_instruction_exec_single(target, reg_addr, 1, 0, 0, NULL);
- err_check_propagate(retval);
- retval =
- dsp5680xx_drscan(target, (uint8_t *) &dummy_data_to_shift_into_dr,
- (uint8_t *) data_read, 8);
- err_check_propagate(retval);
- LOG_DEBUG("Reg. data: 0x%02X.", *data_read);
- return retval;
-}
-
-static int eonce_read_status_reg(struct target *target, uint16_t *data)
-{
- int retval;
-
- retval = dsp5680xx_read_core_reg(target, DSP5680XX_ONCE_OSR, data);
- err_check_propagate(retval);
- return retval;
-}
-
-/**
- * Takes the core out of debug mode.
- *
- * @param target
- * @param eonce_status Data read from the EOnCE status register.
- *
- * @return
- */
-static int eonce_exit_debug_mode(struct target *target, uint8_t *eonce_status)
-{
- int retval;
-
- retval =
- eonce_instruction_exec_single(target, 0x1F, 0, 0, 1, eonce_status);
- err_check_propagate(retval);
- return retval;
-}
-
-static int switch_tap(struct target *target, struct jtag_tap *master_tap,
- struct jtag_tap *core_tap)
-{
- int retval = ERROR_OK;
-
- uint32_t instr;
-
- uint32_t ir_out; /* not used, just to make jtag happy. */
-
- if (master_tap == NULL) {
- master_tap = jtag_tap_by_string("dsp568013.chp");
- if (master_tap == NULL) {
- retval = ERROR_FAIL;
- const char *msg = "Failed to get master tap.";
-
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER,
- msg);
- }
- }
- if (core_tap == NULL) {
- core_tap = jtag_tap_by_string("dsp568013.cpu");
- if (core_tap == NULL) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_CORE,
- "Failed to get core tap.");
- }
- }
-
- if (!(((int)master_tap->enabled) ^ ((int)core_tap->enabled))) {
- LOG_WARNING
- ("Master:%d\nCore:%d\nOnly 1 should be enabled.\n",
- (int)master_tap->enabled, (int)core_tap->enabled);
- }
-
- if (master_tap->enabled) {
- instr = 0x5;
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_MASTER_TAP_IRLEN);
- err_check_propagate(retval);
- instr = 0x2;
- retval =
- dsp5680xx_drscan(target, (uint8_t *) &instr,
- (uint8_t *) &ir_out, 4);
- err_check_propagate(retval);
- core_tap->enabled = true;
- master_tap->enabled = false;
- } else {
- instr = 0x08;
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- instr = 0x1;
- retval =
- dsp5680xx_drscan(target, (uint8_t *) &instr,
- (uint8_t *) &ir_out, 4);
- err_check_propagate(retval);
- core_tap->enabled = false;
- master_tap->enabled = true;
- }
- return retval;
-}
-
-/**
- * Puts the core into debug mode, enabling the EOnCE module.
- * This will not always work, eonce_enter_debug_mode executes much
- * more complicated routine, which is guaranteed to work, but requires
- * a reset. This will complicate comm with the flash module, since
- * after a reset clock divisors must be set again.
- * This implementation works most of the time, and is not accesible to the
- * user.
- *
- * @param target
- * @param eonce_status Data read from the EOnCE status register.
- *
- * @return
- */
-static int eonce_enter_debug_mode_without_reset(struct target *target,
- uint16_t *eonce_status)
-{
- int retval;
-
- uint32_t instr = JTAG_INSTR_DEBUG_REQUEST;
-
- uint32_t ir_out; /* not used, just to make jtag happy.*/
-
- /* Debug request #1 */
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
-
- /* Enable EOnCE module */
- instr = JTAG_INSTR_ENABLE_ONCE;
- /* Two rounds of jtag 0x6 (enable eonce) to enable EOnCE. */
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- if ((ir_out & JTAG_STATUS_MASK) == JTAG_STATUS_DEBUG)
- target->state = TARGET_HALTED;
- else {
- retval = ERROR_FAIL;
- err_check_propagate(retval);
- }
- /* Verify that debug mode is enabled */
- uint16_t data_read_from_dr;
-
- retval = eonce_read_status_reg(target, &data_read_from_dr);
- err_check_propagate(retval);
- if ((data_read_from_dr & 0x30) == 0x30) {
- LOG_DEBUG("EOnCE successfully entered debug mode.");
- dsp5680xx_context.debug_mode_enabled = true;
- retval = ERROR_OK;
- } else {
- dsp5680xx_context.debug_mode_enabled = false;
- retval = ERROR_TARGET_FAILURE;
- /**
- *No error msg here, since there is still hope with full halting sequence
- */
- err_check_propagate(retval);
- }
- if (eonce_status != NULL)
- *eonce_status = data_read_from_dr;
- return retval;
-}
-
-/**
- * Puts the core into debug mode, enabling the EOnCE module.
- *
- * @param target
- * @param eonce_status Data read from the EOnCE status register.
- *
- * @return
- */
-static int eonce_enter_debug_mode(struct target *target,
- uint16_t *eonce_status)
-{
- int retval = ERROR_OK;
-
- uint32_t instr = JTAG_INSTR_DEBUG_REQUEST;
-
- uint32_t ir_out; /* not used, just to make jtag happy. */
-
- uint16_t instr_16;
-
- uint16_t read_16;
-
- /* First try the easy way */
- retval = eonce_enter_debug_mode_without_reset(target, eonce_status);
- if (retval == ERROR_OK)
- return retval;
-
- struct jtag_tap *tap_chp;
-
- struct jtag_tap *tap_cpu;
-
- tap_chp = jtag_tap_by_string("dsp568013.chp");
- if (tap_chp == NULL) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER,
- "Failed to get master tap.");
- }
- tap_cpu = jtag_tap_by_string("dsp568013.cpu");
- if (tap_cpu == NULL) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_FIND_CORE,
- "Failed to get master tap.");
- }
- /* Enable master tap */
- tap_chp->enabled = true;
- tap_cpu->enabled = false;
-
- instr = MASTER_TAP_CMD_IDCODE;
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_MASTER_TAP_IRLEN);
- err_check_propagate(retval);
- jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000);
-
- /* Enable EOnCE module */
- jtag_add_reset(0, 1);
- jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000);
- instr = 0x0606ffff; /* This was selected experimentally. */
- retval =
- dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out,
- 32);
- err_check_propagate(retval);
- /* ir_out now hold tap idcode */
-
- /* Enable core tap */
- tap_chp->enabled = true;
- retval = switch_tap(target, tap_chp, tap_cpu);
- err_check_propagate(retval);
-
- instr = JTAG_INSTR_ENABLE_ONCE;
- /* Two rounds of jtag 0x6 (enable eonce) to enable EOnCE. */
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- instr = JTAG_INSTR_DEBUG_REQUEST;
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- instr_16 = 0x1;
- retval =
- dsp5680xx_drscan(target, (uint8_t *) &instr_16,
- (uint8_t *) &read_16, 8);
- err_check_propagate(retval);
- instr_16 = 0x20;
- retval =
- dsp5680xx_drscan(target, (uint8_t *) &instr_16,
- (uint8_t *) &read_16, 8);
- err_check_propagate(retval);
- jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000);
- jtag_add_reset(0, 0);
- jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000);
-
- instr = JTAG_INSTR_ENABLE_ONCE;
- /* Two rounds of jtag 0x6 (enable eonce) to enable EOnCE. */
- for (int i = 0; i < 3; i++) {
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- }
- if ((ir_out & JTAG_STATUS_MASK) == JTAG_STATUS_DEBUG)
- target->state = TARGET_HALTED;
- else {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_HALT,
- "Failed to halt target.");
- }
-
- for (int i = 0; i < 3; i++) {
- instr_16 = 0x86;
- dsp5680xx_drscan(target, (uint8_t *) &instr_16,
- (uint8_t *) &read_16, 16);
- instr_16 = 0xff;
- dsp5680xx_drscan(target, (uint8_t *) &instr_16,
- (uint8_t *) &read_16, 16);
- }
-
- /* Verify that debug mode is enabled */
- uint16_t data_read_from_dr;
-
- retval = eonce_read_status_reg(target, &data_read_from_dr);
- err_check_propagate(retval);
- if ((data_read_from_dr & 0x30) == 0x30) {
- LOG_DEBUG("EOnCE successfully entered debug mode.");
- dsp5680xx_context.debug_mode_enabled = true;
- retval = ERROR_OK;
- } else {
- const char *msg = "Failed to set EOnCE module to debug mode";
-
- retval = ERROR_TARGET_FAILURE;
- err_check(retval, DSP5680XX_ERROR_ENTER_DEBUG_MODE, msg);
- }
- if (eonce_status != NULL)
- *eonce_status = data_read_from_dr;
- return retval;
-}
-
-/**
- * Reads the current value of the program counter and stores it.
- *
- * @param target
- *
- * @return
- */
-static int eonce_pc_store(struct target *target)
-{
- uint8_t tmp[2];
-
- int retval;
-
- retval = core_move_pc_to_r4(target);
- err_check_propagate(retval);
- retval = core_move_r4_to_y(target);
- err_check_propagate(retval);
- retval = eonce_load_TX_RX_to_r0(target);
- err_check_propagate(retval);
- retval = core_move_y0_at_r0(target);
- err_check_propagate(retval);
- retval = core_rx_lower_data(target, tmp);
- err_check_propagate(retval);
- LOG_USER("PC value: 0x%X%X\n", tmp[1], tmp[0]);
- dsp5680xx_context.stored_pc = (tmp[0] | (tmp[1] << 8));
- return ERROR_OK;
-}
-
-static int dsp5680xx_target_create(struct target *target, Jim_Interp *interp)
-{
- struct dsp5680xx_common *dsp5680xx =
- calloc(1, sizeof(struct dsp5680xx_common));
- target->arch_info = dsp5680xx;
- return ERROR_OK;
-}
-
-static int dsp5680xx_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- dsp5680xx_context.stored_pc = 0;
- dsp5680xx_context.flush = 1;
- dsp5680xx_context.debug_mode_enabled = false;
- LOG_DEBUG("target initiated!");
- /* TODO core tap must be enabled before running these commands, currently
- * this is done in the .cfg tcl script. */
- return ERROR_OK;
-}
-
-static int dsp5680xx_arch_state(struct target *target)
-{
- LOG_USER("%s not implemented yet.", __func__);
- return ERROR_OK;
-}
-
-int dsp5680xx_target_status(struct target *target, uint8_t *jtag_st,
- uint16_t *eonce_st)
-{
- return target->state;
-}
-
-static int dsp5680xx_assert_reset(struct target *target)
-{
- target->state = TARGET_RESET;
- return ERROR_OK;
-}
-
-static int dsp5680xx_deassert_reset(struct target *target)
-{
- target->state = TARGET_RUNNING;
- return ERROR_OK;
-}
-
-static int dsp5680xx_halt(struct target *target)
-{
- int retval;
-
- uint16_t eonce_status = 0xbeef;
-
- if ((target->state == TARGET_HALTED)
- && (dsp5680xx_context.debug_mode_enabled)) {
- LOG_USER("Target already halted and in debug mode.");
- return ERROR_OK;
- } else {
- if (target->state == TARGET_HALTED)
- LOG_USER
- ("Target already halted, re attempting to enter debug mode.");
- }
- retval = eonce_enter_debug_mode(target, &eonce_status);
- err_check_propagate(retval);
- retval = eonce_pc_store(target);
- err_check_propagate(retval);
- if (dsp5680xx_context.debug_mode_enabled) {
- retval = eonce_pc_store(target);
- err_check_propagate(retval);
- }
- return retval;
-}
-
-static int dsp5680xx_poll(struct target *target)
-{
- int retval;
-
- uint8_t jtag_status;
-
- uint8_t eonce_status;
-
- uint16_t read_tmp;
-
- retval = dsp5680xx_jtag_status(target, &jtag_status);
- err_check_propagate(retval);
- if (jtag_status == JTAG_STATUS_DEBUG)
- if (target->state != TARGET_HALTED) {
- retval = eonce_enter_debug_mode(target, &read_tmp);
- err_check_propagate(retval);
- eonce_status = (uint8_t) read_tmp;
- if ((eonce_status & EONCE_STAT_MASK) !=
- DSP5680XX_ONCE_OSCR_DEBUG_M) {
- const char *msg =
- "%s: Failed to put EOnCE in debug mode.Flash locked?...";
- LOG_WARNING(msg, __func__);
- return ERROR_TARGET_FAILURE;
- } else {
- target->state = TARGET_HALTED;
- return ERROR_OK;
- }
- }
- if (jtag_status == JTAG_STATUS_NORMAL) {
- if (target->state == TARGET_RESET) {
- retval = dsp5680xx_halt(target);
- err_check_propagate(retval);
- retval = eonce_exit_debug_mode(target, &eonce_status);
- err_check_propagate(retval);
- if ((eonce_status & EONCE_STAT_MASK) !=
- DSP5680XX_ONCE_OSCR_NORMAL_M) {
- const char *msg =
- "%s: JTAG running, but EOnCE run failed.Try resetting..";
- LOG_WARNING(msg, __func__);
- return ERROR_TARGET_FAILURE;
- } else {
- target->state = TARGET_RUNNING;
- return ERROR_OK;
- }
- }
- if (target->state != TARGET_RUNNING) {
- retval = eonce_read_status_reg(target, &read_tmp);
- err_check_propagate(retval);
- eonce_status = (uint8_t) read_tmp;
- if ((eonce_status & EONCE_STAT_MASK) !=
- DSP5680XX_ONCE_OSCR_NORMAL_M) {
- LOG_WARNING
- ("Inconsistent target status. Restart!");
- return ERROR_TARGET_FAILURE;
- }
- }
- target->state = TARGET_RUNNING;
- return ERROR_OK;
- }
- if (jtag_status == JTAG_STATUS_DEAD) {
- LOG_ERROR
- ("%s: Cannot communicate with JTAG. Check connection...",
- __func__);
- target->state = TARGET_UNKNOWN;
- return ERROR_TARGET_FAILURE;
- }
- if (target->state == TARGET_UNKNOWN) {
- LOG_ERROR("%s: Target status invalid - communication failure",
- __func__);
- return ERROR_TARGET_FAILURE;
- }
- return ERROR_OK;
-}
-
-static int dsp5680xx_resume(struct target *target, int current,
- uint32_t address, int hb, int d)
-{
- if (target->state == TARGET_RUNNING) {
- LOG_USER("Target already running.");
- return ERROR_OK;
- }
- int retval;
-
- uint8_t eonce_status;
-
- uint8_t jtag_status;
-
- if (dsp5680xx_context.debug_mode_enabled) {
- if (!current) {
- retval = core_move_value_to_pc(target, address);
- err_check_propagate(retval);
- }
-
- int retry = 20;
-
- while (retry-- > 1) {
- retval = eonce_exit_debug_mode(target, &eonce_status);
- err_check_propagate(retval);
- if (eonce_status == DSP5680XX_ONCE_OSCR_NORMAL_M)
- break;
- }
- if (retry == 0) {
- retval = ERROR_TARGET_FAILURE;
- err_check(retval, DSP5680XX_ERROR_EXIT_DEBUG_MODE,
- "Failed to exit debug mode...");
- } else {
- target->state = TARGET_RUNNING;
- dsp5680xx_context.debug_mode_enabled = false;
- }
- LOG_DEBUG("EOnCE status: 0x%02X.", eonce_status);
- } else {
- /*
- * If debug mode was not enabled but target was halted, then it is most likely that
- * access to eonce registers is locked.
- * Reset target to make it run again.
- */
- jtag_add_reset(0, 1);
- jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000);
-
- retval = reset_jtag();
- err_check(retval, DSP5680XX_ERROR_JTAG_RESET,
- "Failed to reset JTAG state machine");
- jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000);
- jtag_add_reset(0, 0);
- jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000);
- retval = dsp5680xx_jtag_status(target, &jtag_status);
- err_check_propagate(retval);
- if ((jtag_status & JTAG_STATUS_MASK) == JTAG_STATUS_NORMAL) {
- target->state = TARGET_RUNNING;
- dsp5680xx_context.debug_mode_enabled = false;
- } else {
- retval = ERROR_TARGET_FAILURE;
- err_check(retval, DSP5680XX_ERROR_RESUME,
- "Failed to resume target");
- }
- }
- return ERROR_OK;
-}
-
-/**
- * The value of @address determines if it corresponds to P: (program) or X: (dat) memory.
- * If the address is over 0x200000 then it is considered X: memory, and @pmem = 0.
- * The special case of 0xFFXXXX is not modified, since it allows to read out the
- * memory mapped EOnCE registers.
- *
- * @param address
- * @param pmem
- *
- * @return
- */
-static int dsp5680xx_convert_address(uint32_t *address, int *pmem)
-{
- /*
- * Distinguish data memory (x) from program memory (p) by the address.
- * Addresses over S_FILE_DATA_OFFSET are considered (x) memory.
- */
- if (*address >= S_FILE_DATA_OFFSET) {
- *pmem = 0;
- if (((*address) & 0xff0000) != 0xff0000)
- *address -= S_FILE_DATA_OFFSET;
- }
- return ERROR_OK;
-}
-
-static int dsp5680xx_read_16_single(struct target *t, uint32_t a,
- uint8_t *data_read, int r_pmem)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- int retval;
-
- retval = core_move_long_to_r0(target, address);
- err_check_propagate(retval);
- if (r_pmem)
- retval = core_move_at_pr0_inc_to_y0(target);
- else
- retval = core_move_at_r0_to_y0(target);
- err_check_propagate(retval);
- retval = eonce_load_TX_RX_to_r0(target);
- err_check_propagate(retval);
- retval = core_move_y0_at_r0(target);
- err_check_propagate(retval);
- /* at this point the data i want is at the reg eonce can read */
- retval = core_rx_lower_data(target, data_read);
- err_check_propagate(retval);
- LOG_DEBUG("%s:Data read from 0x%06" PRIX32 ": 0x%02X%02X", __func__, address,
- data_read[1], data_read[0]);
- return retval;
-}
-
-static int dsp5680xx_read_32_single(struct target *t, uint32_t a,
- uint8_t *data_read, int r_pmem)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- int retval;
-
- address = (address & 0xFFFFF);
- /* Get data to an intermediate register */
- retval = core_move_long_to_r0(target, address);
- err_check_propagate(retval);
- if (r_pmem) {
- retval = core_move_at_pr0_inc_to_y0(target);
- err_check_propagate(retval);
- retval = core_move_at_pr0_inc_to_y1(target);
- err_check_propagate(retval);
- } else {
- retval = core_move_at_r0_inc_to_y0(target);
- err_check_propagate(retval);
- retval = core_move_at_r0_to_y1(target);
- err_check_propagate(retval);
- }
- /* Get lower part of data to TX/RX */
- retval = eonce_load_TX_RX_to_r0(target);
- err_check_propagate(retval);
- retval = core_move_y0_at_r0_inc(target); /* This also load TX/RX high to r0 */
- err_check_propagate(retval);
- /* Get upper part of data to TX/RX */
- retval = core_move_y1_at_r0(target);
- err_check_propagate(retval);
- /* at this point the data i want is at the reg eonce can read */
- retval = core_rx_lower_data(target, data_read);
- err_check_propagate(retval);
- retval = core_rx_upper_data(target, data_read + 2);
- err_check_propagate(retval);
- return retval;
-}
-
-static int dsp5680xx_read(struct target *t, uint32_t a, uint32_t size,
- uint32_t count, uint8_t *buf)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- uint8_t *buffer = buf;
-
- check_halt_and_debug(target);
-
- int retval = ERROR_OK;
-
- int pmem = 1;
-
- retval = dsp5680xx_convert_address(&address, &pmem);
- err_check_propagate(retval);
-
- dsp5680xx_context.flush = 0;
- int counter = FLUSH_COUNT_READ_WRITE;
-
- for (unsigned i = 0; i < count; i++) {
- if (--counter == 0) {
- dsp5680xx_context.flush = 1;
- counter = FLUSH_COUNT_READ_WRITE;
- }
- switch (size) {
- case 1:
- if (!(i % 2))
- retval =
- dsp5680xx_read_16_single(target,
- address + i / 2,
- buffer + i, pmem);
- break;
- case 2:
- retval =
- dsp5680xx_read_16_single(target, address + i,
- buffer + 2 * i, pmem);
- break;
- case 4:
- retval =
- dsp5680xx_read_32_single(target, address + 2 * i,
- buffer + 4 * i, pmem);
- break;
- default:
- LOG_USER("%s: Invalid read size.", __func__);
- break;
- }
- err_check_propagate(retval);
- dsp5680xx_context.flush = 0;
- }
-
- dsp5680xx_context.flush = 1;
- retval = dsp5680xx_execute_queue();
- err_check_propagate(retval);
-
- return retval;
-}
-
-static int dsp5680xx_write_16_single(struct target *t, uint32_t a,
- uint16_t data, uint8_t w_pmem)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- int retval = 0;
-
- retval = core_move_long_to_r0(target, address);
- err_check_propagate(retval);
- if (w_pmem) {
- retval = core_move_value_to_y0(target, data);
- err_check_propagate(retval);
- retval = core_move_y0_at_pr0_inc(target);
- err_check_propagate(retval);
- } else {
- retval = core_move_value_at_r0(target, data);
- err_check_propagate(retval);
- }
- return retval;
-}
-
-static int dsp5680xx_write_32_single(struct target *t, uint32_t a,
- uint32_t data, int w_pmem)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- int retval = ERROR_OK;
-
- retval = core_move_long_to_r0(target, address);
- err_check_propagate(retval);
- retval = core_move_long_to_y(target, data);
- err_check_propagate(retval);
- if (w_pmem)
- retval = core_move_y0_at_pr0_inc(target);
- else
- retval = core_move_y0_at_r0_inc(target);
- err_check_propagate(retval);
- if (w_pmem)
- retval = core_move_y1_at_pr0_inc(target);
- else
- retval = core_move_y1_at_r0_inc(target);
- err_check_propagate(retval);
- return retval;
-}
-
-static int dsp5680xx_write_8(struct target *t, uint32_t a, uint32_t c,
- const uint8_t *d, int pmem)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- uint32_t count = c;
-
- const uint8_t *data = d;
-
- int retval = 0;
-
- uint16_t data_16;
-
- uint32_t iter;
-
- int counter = FLUSH_COUNT_READ_WRITE;
-
- for (iter = 0; iter < count / 2; iter++) {
- if (--counter == 0) {
- dsp5680xx_context.flush = 1;
- counter = FLUSH_COUNT_READ_WRITE;
- }
- data_16 = (data[2 * iter] | (data[2 * iter + 1] << 8));
- retval =
- dsp5680xx_write_16_single(target, address + iter, data_16,
- pmem);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s: Could not write to p:0x%04" PRIX32, __func__,
- address);
- dsp5680xx_context.flush = 1;
- return retval;
- }
- dsp5680xx_context.flush = 0;
- }
- dsp5680xx_context.flush = 1;
-
- /* Only one byte left, let's not overwrite the other byte (mem is 16bit) */
- /* Need to retrieve the part we do not want to overwrite. */
- uint16_t data_old;
-
- if ((count == 1) || (count % 2)) {
- retval =
- dsp5680xx_read(target, address + iter, 1, 1,
- (uint8_t *) &data_old);
- err_check_propagate(retval);
- if (count == 1)
- data_old = (((data_old & 0xff) << 8) | data[0]); /* preserve upper byte */
- else
- data_old =
- (((data_old & 0xff) << 8) | data[2 * iter + 1]);
- retval =
- dsp5680xx_write_16_single(target, address + iter, data_old,
- pmem);
- err_check_propagate(retval);
- }
- return retval;
-}
-
-static int dsp5680xx_write_16(struct target *t, uint32_t a, uint32_t c,
- const uint8_t *d, int pmem)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- uint32_t count = c;
-
- const uint8_t *data = d;
-
- int retval = ERROR_OK;
-
- uint32_t iter;
-
- int counter = FLUSH_COUNT_READ_WRITE;
-
- for (iter = 0; iter < count; iter++) {
- if (--counter == 0) {
- dsp5680xx_context.flush = 1;
- counter = FLUSH_COUNT_READ_WRITE;
- }
- retval =
- dsp5680xx_write_16_single(target, address + iter,
- data[iter], pmem);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s: Could not write to p:0x%04" PRIX32, __func__,
- address);
- dsp5680xx_context.flush = 1;
- return retval;
- }
- dsp5680xx_context.flush = 0;
- }
- dsp5680xx_context.flush = 1;
- return retval;
-}
-
-static int dsp5680xx_write_32(struct target *t, uint32_t a, uint32_t c,
- const uint8_t *d, int pmem)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- uint32_t count = c;
-
- const uint8_t *data = d;
-
- int retval = ERROR_OK;
-
- uint32_t iter;
-
- int counter = FLUSH_COUNT_READ_WRITE;
-
- for (iter = 0; iter < count; iter++) {
- if (--counter == 0) {
- dsp5680xx_context.flush = 1;
- counter = FLUSH_COUNT_READ_WRITE;
- }
- retval =
- dsp5680xx_write_32_single(target, address + (iter << 1),
- data[iter], pmem);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s: Could not write to p:0x%04" PRIX32, __func__,
- address);
- dsp5680xx_context.flush = 1;
- return retval;
- }
- dsp5680xx_context.flush = 0;
- }
- dsp5680xx_context.flush = 1;
- return retval;
-}
-
-/**
- * Writes @buffer to memory.
- * The parameter @address determines whether @buffer should be written to
- * P: (program) memory or X: (dat) memory.
- *
- * @param target
- * @param address
- * @param size Bytes (1), Half words (2), Words (4).
- * @param count In bytes.
- * @param buffer
- *
- * @return
- */
-static int dsp5680xx_write(struct target *t, uint32_t a, uint32_t s, uint32_t c,
- const uint8_t *b)
-{
- /* TODO Cannot write 32bit to odd address, will write 0x12345678 as 0x5678 0x0012 */
- struct target *target = t;
-
- uint32_t address = a;
-
- uint32_t count = c;
-
- uint8_t const *buffer = b;
-
- uint32_t size = s;
-
- check_halt_and_debug(target);
-
- int retval = 0;
-
- int p_mem = 1;
-
- retval = dsp5680xx_convert_address(&address, &p_mem);
- err_check_propagate(retval);
-
- switch (size) {
- case 1:
- retval =
- dsp5680xx_write_8(target, address, count, buffer, p_mem);
- break;
- case 2:
- retval =
- dsp5680xx_write_16(target, address, count, buffer, p_mem);
- break;
- case 4:
- retval =
- dsp5680xx_write_32(target, address, count, buffer, p_mem);
- break;
- default:
- retval = ERROR_TARGET_DATA_ABORT;
- err_check(retval, DSP5680XX_ERROR_INVALID_DATA_SIZE_UNIT,
- "Invalid data size.");
- break;
- }
- return retval;
-}
-
-static int dsp5680xx_write_buffer(struct target *t, uint32_t a, uint32_t size,
- const uint8_t *b)
-{
- check_halt_and_debug(t);
- return dsp5680xx_write(t, a, 1, size, b);
-}
-
-/**
- * This function is called by verify_image, it is used to read data from memory.
- *
- * @param target
- * @param address Word addressing.
- * @param size In bytes.
- * @param buffer
- *
- * @return
- */
-static int dsp5680xx_read_buffer(struct target *t, uint32_t a, uint32_t size,
- uint8_t *buf)
-{
- check_halt_and_debug(t);
- /* The "/2" solves the byte/word addressing issue.*/
- return dsp5680xx_read(t, a, 2, size / 2, buf);
-}
-
-/**
- * This function is not implemented.
- * It returns an error in order to get OpenOCD to do read out the data
- * and calculate the CRC, or try a binary comparison.
- *
- * @param target
- * @param address Start address of the image.
- * @param size In bytes.
- * @param checksum
- *
- * @return
- */
-static int dsp5680xx_checksum_memory(struct target *t, uint32_t a, uint32_t s,
- uint32_t *checksum)
-{
- return ERROR_FAIL;
-}
-
-/**
- * Calculates a signature over @word_count words in the data from @buff16.
- * The algorithm used is the same the FM uses, so the @return may be used to compare
- * with the one generated by the FM module, and check if flashing was successful.
- * This algorithm is based on the perl script available from the Freescale website at FAQ 25630.
- *
- * @param buff16
- * @param word_count
- *
- * @return
- */
-static int perl_crc(const uint8_t *buff8, uint32_t word_count)
-{
- uint16_t checksum = 0xffff;
-
- uint16_t data, fbmisr;
-
- uint32_t i;
-
- for (i = 0; i < word_count; i++) {
- data = (buff8[2 * i] | (buff8[2 * i + 1] << 8));
- fbmisr =
- (checksum & 2) >> 1 ^ (checksum & 4) >> 2 ^ (checksum & 16)
- >> 4 ^ (checksum & 0x8000) >> 15;
- checksum = (data ^ ((checksum << 1) | fbmisr));
- }
- i--;
- for (; !(i & 0x80000000); i--) {
- data = (buff8[2 * i] | (buff8[2 * i + 1] << 8));
- fbmisr =
- (checksum & 2) >> 1 ^ (checksum & 4) >> 2 ^ (checksum & 16)
- >> 4 ^ (checksum & 0x8000) >> 15;
- checksum = (data ^ ((checksum << 1) | fbmisr));
- }
- return checksum;
-}
-
-/**
- * Resets the SIM. (System Integration Modul).
- *
- * @param target
- *
- * @return
- */
-int dsp5680xx_f_SIM_reset(struct target *target)
-{
- int retval = ERROR_OK;
-
- uint16_t sim_cmd = SIM_CMD_RESET;
-
- uint32_t sim_addr;
-
- if (strcmp(target->tap->chip, "dsp568013") == 0) {
- sim_addr = MC568013_SIM_BASE_ADDR + S_FILE_DATA_OFFSET;
- retval =
- dsp5680xx_write(target, sim_addr, 1, 2,
- (const uint8_t *)&sim_cmd);
- err_check_propagate(retval);
- }
- return retval;
-}
-
-/**
- * Halts the core and resets the SIM. (System Integration Modul).
- *
- * @param target
- *
- * @return
- */
-static int dsp5680xx_soft_reset_halt(struct target *target)
-{
- /* TODO is this what this function is expected to do...? */
- int retval;
-
- retval = dsp5680xx_halt(target);
- err_check_propagate(retval);
- retval = dsp5680xx_f_SIM_reset(target);
- err_check_propagate(retval);
- return retval;
-}
-
-int dsp5680xx_f_protect_check(struct target *target, uint16_t *protected)
-{
- int retval;
-
- check_halt_and_debug(target);
- if (protected == NULL) {
- const char *msg = "NULL pointer not valid.";
-
- err_check(ERROR_FAIL,
- DSP5680XX_ERROR_PROTECT_CHECK_INVALID_ARGS, msg);
- }
- retval =
- dsp5680xx_read_16_single(target, HFM_BASE_ADDR | HFM_PROT,
- (uint8_t *) protected, 0);
- err_check_propagate(retval);
- return retval;
-}
-
-/**
- * Executes a command on the FM module.
- * Some commands use the parameters @address and @data, others ignore them.
- *
- * @param target
- * @param command Command to execute.
- * @param address Command parameter.
- * @param data Command parameter.
- * @param hfm_ustat FM status register.
- * @param pmem Address is P: (program) memory (@pmem == 1) or X: (dat) memory (@pmem == 0)
- *
- * @return
- */
-static int dsp5680xx_f_ex(struct target *t, uint16_t c, uint32_t a, uint32_t d,
- uint16_t *h, int p)
-{
- struct target *target = t;
-
- uint32_t command = c;
-
- uint32_t address = a;
-
- uint32_t data = d;
-
- uint16_t *hfm_ustat = h;
-
- int pmem = p;
-
- int retval;
-
- retval = core_load_TX_RX_high_addr_to_r0(target);
- err_check_propagate(retval);
- retval = core_move_long_to_r2(target, HFM_BASE_ADDR);
- err_check_propagate(retval);
- uint8_t i[2];
-
- int watchdog = 100;
-
- do {
- retval = core_move_at_r2_disp_to_y0(target, HFM_USTAT); /* read HMF_USTAT */
- err_check_propagate(retval);
- retval = core_move_y0_at_r0(target);
- err_check_propagate(retval);
- retval = core_rx_upper_data(target, i);
- err_check_propagate(retval);
- if ((watchdog--) == 1) {
- retval = ERROR_TARGET_FAILURE;
- const char *msg =
- "Timed out waiting for FM to finish old command.";
- err_check(retval, DSP5680XX_ERROR_FM_BUSY, msg);
- }
- } while (!(i[0] & 0x40)); /* wait until current command is complete */
-
- dsp5680xx_context.flush = 0;
-
- /* write to HFM_CNFG (lock=0,select bank) - flash_desc.bank&0x03, 0x01 == 0x00, 0x01 ??? */
- retval = core_move_value_at_r2_disp(target, 0x00, HFM_CNFG);
- err_check_propagate(retval);
- /* write to HMF_USTAT, clear PVIOL, ACCERR &BLANK bits */
- retval = core_move_value_at_r2_disp(target, 0x04, HFM_USTAT);
- err_check_propagate(retval);
- /* clear only one bit at a time */
- retval = core_move_value_at_r2_disp(target, 0x10, HFM_USTAT);
- err_check_propagate(retval);
- retval = core_move_value_at_r2_disp(target, 0x20, HFM_USTAT);
- err_check_propagate(retval);
- /* write to HMF_PROT, clear protection */
- retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROT);
- err_check_propagate(retval);
- /* write to HMF_PROTB, clear protection */
- retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROTB);
- err_check_propagate(retval);
- retval = core_move_value_to_y0(target, data);
- err_check_propagate(retval);
- /* write to the flash block */
- retval = core_move_long_to_r3(target, address);
- err_check_propagate(retval);
- if (pmem) {
- retval = core_move_y0_at_pr3_inc(target);
- err_check_propagate(retval);
- } else {
- retval = core_move_y0_at_r3(target);
- err_check_propagate(retval);
- }
- /* write command to the HFM_CMD reg */
- retval = core_move_value_at_r2_disp(target, command, HFM_CMD);
- err_check_propagate(retval);
- /* start the command */
- retval = core_move_value_at_r2_disp(target, 0x80, HFM_USTAT);
- err_check_propagate(retval);
-
- dsp5680xx_context.flush = 1;
- retval = dsp5680xx_execute_queue();
- err_check_propagate(retval);
-
- watchdog = 100;
- do {
- /* read HMF_USTAT */
- retval = core_move_at_r2_disp_to_y0(target, HFM_USTAT);
- err_check_propagate(retval);
- retval = core_move_y0_at_r0(target);
- err_check_propagate(retval);
- retval = core_rx_upper_data(target, i);
- err_check_propagate(retval);
- if ((watchdog--) == 1) {
- retval = ERROR_TARGET_FAILURE;
- err_check(retval, DSP5680XX_ERROR_FM_CMD_TIMED_OUT,
- "FM execution did not finish.");
- }
- } while (!(i[0] & 0x40)); /* wait until the command is complete */
- *hfm_ustat = ((i[0] << 8) | (i[1]));
- if (i[0] & HFM_USTAT_MASK_PVIOL_ACCER) {
- retval = ERROR_TARGET_FAILURE;
- const char *msg =
- "pviol and/or accer bits set. HFM command execution error";
- err_check(retval, DSP5680XX_ERROR_FM_EXEC, msg);
- }
- return ERROR_OK;
-}
-
-/**
- * Prior to the execution of any Flash module command, the Flash module Clock Divider (CLKDIV) register must be initialized. The values of this register determine the speed of the internal Flash Clock (FCLK). FCLK must be in the range of 150kHz ≤ FCLK ≤ 200kHz for proper operation of the Flash module. (Running FCLK too slowly wears out the module, while running it too fast under programs Flash leading to bit errors.)
- *
- * @param target
- *
- * @return
- */
-static int set_fm_ck_div(struct target *target)
-{
- uint8_t i[2];
-
- int retval;
-
- retval = core_move_long_to_r2(target, HFM_BASE_ADDR);
- err_check_propagate(retval);
- retval = core_load_TX_RX_high_addr_to_r0(target);
- err_check_propagate(retval);
- /* read HFM_CLKD */
- retval = core_move_at_r2_to_y0(target);
- err_check_propagate(retval);
- retval = core_move_y0_at_r0(target);
- err_check_propagate(retval);
- retval = core_rx_upper_data(target, i);
- err_check_propagate(retval);
- unsigned int hfm_at_wrong_value = 0;
-
- if ((i[0] & 0x7f) != HFM_CLK_DEFAULT) {
- LOG_DEBUG("HFM CLK divisor contained incorrect value (0x%02X).",
- i[0] & 0x7f);
- hfm_at_wrong_value = 1;
- } else {
- LOG_DEBUG
- ("HFM CLK divisor was already set to correct value (0x%02X).",
- i[0] & 0x7f);
- return ERROR_OK;
- }
- /* write HFM_CLKD */
- retval = core_move_value_at_r2(target, HFM_CLK_DEFAULT);
- err_check_propagate(retval);
- /* verify HFM_CLKD */
- retval = core_move_at_r2_to_y0(target);
- err_check_propagate(retval);
- retval = core_move_y0_at_r0(target);
- err_check_propagate(retval);
- retval = core_rx_upper_data(target, i);
- err_check_propagate(retval);
- if (i[0] != (0x80 | (HFM_CLK_DEFAULT & 0x7f))) {
- retval = ERROR_TARGET_FAILURE;
- err_check(retval, DSP5680XX_ERROR_FM_SET_CLK,
- "Unable to set HFM CLK divisor.");
- }
- if (hfm_at_wrong_value)
- LOG_DEBUG("HFM CLK divisor set to 0x%02x.", i[0] & 0x7f);
- return ERROR_OK;
-}
-
-/**
- * Executes the FM calculate signature command. The FM will calculate over the data from @address to @address + @words -1. The result is written to a register, then read out by this function and returned in @signature. The value @signature may be compared to the the one returned by perl_crc to verify the flash was written correctly.
- *
- * @param target
- * @param address Start of flash array where the signature should be calculated.
- * @param words Number of words over which the signature should be calculated.
- * @param signature Value calculated by the FM.
- *
- * @return
- */
-static int dsp5680xx_f_signature(struct target *t, uint32_t a, uint32_t words,
- uint16_t *signature)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- int retval;
-
- uint16_t hfm_ustat;
-
- if (!dsp5680xx_context.debug_mode_enabled) {
- retval = eonce_enter_debug_mode_without_reset(target, NULL);
- /*
- * Generate error here, since it is not done in eonce_enter_debug_mode_without_reset
- */
- err_check(retval, DSP5680XX_ERROR_HALT,
- "Failed to halt target.");
- }
- retval =
- dsp5680xx_f_ex(target, HFM_CALCULATE_DATA_SIGNATURE, address, words,
- &hfm_ustat, 1);
- err_check_propagate(retval);
- retval =
- dsp5680xx_read_16_single(target, HFM_BASE_ADDR | HFM_DATA,
- (uint8_t *) signature, 0);
- return retval;
-}
-
-int dsp5680xx_f_erase_check(struct target *target, uint8_t *erased,
- uint32_t sector)
-{
- int retval;
-
- uint16_t hfm_ustat;
-
- uint32_t tmp;
-
- if (!dsp5680xx_context.debug_mode_enabled) {
- retval = dsp5680xx_halt(target);
- err_check_propagate(retval);
- }
- retval = set_fm_ck_div(target);
- err_check_propagate(retval);
- /*
- * Check if chip is already erased.
- */
- tmp = HFM_FLASH_BASE_ADDR + sector * HFM_SECTOR_SIZE / 2;
- retval =
- dsp5680xx_f_ex(target, HFM_ERASE_VERIFY, tmp, 0, &hfm_ustat, 1);
- err_check_propagate(retval);
- if (erased != NULL)
- *erased = (uint8_t) (hfm_ustat & HFM_USTAT_MASK_BLANK);
- return retval;
-}
-
-/**
- * Executes the FM page erase command.
- *
- * @param target
- * @param sector Page to erase.
- * @param hfm_ustat FM module status register.
- *
- * @return
- */
-static int erase_sector(struct target *target, int sector, uint16_t *hfm_ustat)
-{
- int retval;
-
- uint32_t tmp = HFM_FLASH_BASE_ADDR + sector * HFM_SECTOR_SIZE / 2;
-
- retval = dsp5680xx_f_ex(target, HFM_PAGE_ERASE, tmp, 0, hfm_ustat, 1);
- err_check_propagate(retval);
- return retval;
-}
-
-/**
- * Executes the FM mass erase command. Erases the flash array completely.
- *
- * @param target
- * @param hfm_ustat FM module status register.
- *
- * @return
- */
-static int mass_erase(struct target *target, uint16_t *hfm_ustat)
-{
- int retval;
-
- retval = dsp5680xx_f_ex(target, HFM_MASS_ERASE, 0, 0, hfm_ustat, 1);
- return retval;
-}
-
-int dsp5680xx_f_erase(struct target *target, int first, int last)
-{
- int retval;
-
- if (!dsp5680xx_context.debug_mode_enabled) {
- retval = dsp5680xx_halt(target);
- err_check_propagate(retval);
- }
- /*
- * Reset SIM
- *
- */
- retval = dsp5680xx_f_SIM_reset(target);
- err_check_propagate(retval);
- /*
- * Set hfmdiv
- *
- */
- retval = set_fm_ck_div(target);
- err_check_propagate(retval);
-
- uint16_t hfm_ustat;
-
- int do_mass_erase = ((!(first | last))
- || ((first == 0)
- && (last == (HFM_SECTOR_COUNT - 1))));
- if (do_mass_erase) {
- /* Mass erase */
- retval = mass_erase(target, &hfm_ustat);
- err_check_propagate(retval);
- } else {
- for (int i = first; i <= last; i++) {
- retval = erase_sector(target, i, &hfm_ustat);
- err_check_propagate(retval);
- }
- }
- return ERROR_OK;
-}
-
-/*
- * Algorithm for programming normal p: flash
- * Follow state machine from "56F801x Peripheral Reference Manual"@163.
- * Registers to set up before calling:
- * r0: TX/RX high address.
- * r2: FM module base address.
- * r3: Destination address in flash.
- *
- * hfm_wait: // wait for buffer empty
- * brclr #0x80, x:(r2+0x13), hfm_wait
- * rx_check: // wait for input buffer full
- * brclr #0x01, x:(r0-2), rx_check
- * move.w x:(r0), y0 // read from Rx buffer
- * move.w y0, p:(r3)+
- * move.w #0x20, x:(r2+0x14) // write PGM command
- * move.w #0x80, x:(r2+0x13) // start the command
- * move.w X:(R2+0x13), A // Read USTAT register
- * brclr #0x20, A, accerr_check // protection violation check
- * bfset #0x20, X:(R2+0x13) // clear pviol
- * bra hfm_wait
- * accerr_check:
- * brclr #0x10, A, hfm_wait // access error check
- * bfset #0x10, X:(R2+0x13) // clear accerr
- * bra hfm_wait // loop
- * 0x00000000 0x8A460013807D brclr #0x80, X:(R2+0x13),*+0
- * 0x00000003 0xE700 nop
- * 0x00000004 0xE700 nop
- * 0x00000005 0x8A44FFFE017B brclr #1, X:(R0-2),*-2
- * 0x00000008 0xE700 nop
- * 0x00000009 0xF514 move.w X:(R0), Y0
- * 0x0000000A 0x8563 move.w Y0, P:(R3)+
- * 0x0000000B 0x864600200014 move.w #32, X:(R2+0x14)
- * 0x0000000E 0x864600800013 move.w #128, X:(R2+0x13)
- * 0x00000011 0xF0420013 move.w X:(R2+0x13), A
- * 0x00000013 0x8B402004 brclr #0x20, A,*+6
- * 0x00000015 0x824600130020 bfset #0x20, X:(R2+0x13)
- * 0x00000018 0xA967 bra *-24
- * 0x00000019 0x8B401065 brclr #0x10, A,*-25
- * 0x0000001B 0x824600130010 bfset #0x10, X:(R2+0x13)
- * 0x0000001E 0xA961 bra *-30
- */
-
-const uint16_t pgm_write_pflash[] = { 0x8A46, 0x0013, 0x807D, 0xE700,
- 0xE700, 0x8A44, 0xFFFE, 0x017B,
- 0xE700, 0xF514, 0x8563, 0x8646,
- 0x0020, 0x0014, 0x8646, 0x0080,
- 0x0013, 0xF042, 0x0013, 0x8B40,
- 0x2004, 0x8246, 0x0013, 0x0020,
- 0xA967, 0x8B40, 0x1065, 0x8246,
- 0x0013, 0x0010, 0xA961
-};
-
-const uint32_t pgm_write_pflash_length = 31;
-
-int dsp5680xx_f_wr(struct target *t, const uint8_t *b, uint32_t a, uint32_t count,
- int is_flash_lock)
-{
- struct target *target = t;
-
- uint32_t address = a;
-
- const uint8_t *buffer = b;
-
- int retval = ERROR_OK;
-
- if (!dsp5680xx_context.debug_mode_enabled) {
- retval = eonce_enter_debug_mode(target, NULL);
- err_check_propagate(retval);
- }
- /*
- * Download the pgm that flashes.
- *
- */
- const uint32_t len = pgm_write_pflash_length;
-
- uint32_t ram_addr = 0x8700;
-
- /*
- * This seems to be a safe address.
- * This one is the one used by codewarrior in 56801x_flash.cfg
- */
- if (!is_flash_lock) {
- retval =
- dsp5680xx_write(target, ram_addr, 1, len * 2,
- (uint8_t *) pgm_write_pflash);
- err_check_propagate(retval);
- retval = dsp5680xx_execute_queue();
- err_check_propagate(retval);
- }
- /*
- * Set hfmdiv
- *
- */
- retval = set_fm_ck_div(target);
- err_check_propagate(retval);
- /*
- * Setup registers needed by pgm_write_pflash
- *
- */
-
- dsp5680xx_context.flush = 0;
-
- retval = core_move_long_to_r3(target, address); /* Destination address to r3 */
- err_check_propagate(retval);
- core_load_TX_RX_high_addr_to_r0(target); /* TX/RX reg address to r0 */
- err_check_propagate(retval);
- retval = core_move_long_to_r2(target, HFM_BASE_ADDR); /* FM base address to r2 */
- err_check_propagate(retval);
- /*
- * Run flashing program.
- *
- */
- /* write to HFM_CNFG (lock=0, select bank) */
- retval = core_move_value_at_r2_disp(target, 0x00, HFM_CNFG);
- err_check_propagate(retval);
- /* write to HMF_USTAT, clear PVIOL, ACCERR &BLANK bits */
- retval = core_move_value_at_r2_disp(target, 0x04, HFM_USTAT);
- err_check_propagate(retval);
- /* clear only one bit at a time */
- retval = core_move_value_at_r2_disp(target, 0x10, HFM_USTAT);
- err_check_propagate(retval);
- retval = core_move_value_at_r2_disp(target, 0x20, HFM_USTAT);
- err_check_propagate(retval);
- /* write to HMF_PROT, clear protection */
- retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROT);
- err_check_propagate(retval);
- /* write to HMF_PROTB, clear protection */
- retval = core_move_value_at_r2_disp(target, 0x00, HFM_PROTB);
- err_check_propagate(retval);
- if (count % 2) {
- /* TODO implement handling of odd number of words. */
- retval = ERROR_FAIL;
- const char *msg = "Cannot handle odd number of words.";
-
- err_check(retval, DSP5680XX_ERROR_FLASHING_INVALID_WORD_COUNT,
- msg);
- }
-
- dsp5680xx_context.flush = 1;
- retval = dsp5680xx_execute_queue();
- err_check_propagate(retval);
-
- uint32_t drscan_data;
-
- uint16_t tmp = (buffer[0] | (buffer[1] << 8));
-
- retval = core_tx_upper_data(target, tmp, &drscan_data);
- err_check_propagate(retval);
-
- retval = dsp5680xx_resume(target, 0, ram_addr, 0, 0);
- err_check_propagate(retval);
-
- int counter = FLUSH_COUNT_FLASH;
-
- dsp5680xx_context.flush = 0;
- uint32_t i;
-
- for (i = 1; (i < count / 2) && (i < HFM_SIZE_WORDS); i++) {
- if (--counter == 0) {
- dsp5680xx_context.flush = 1;
- counter = FLUSH_COUNT_FLASH;
- }
- tmp = (buffer[2 * i] | (buffer[2 * i + 1] << 8));
- retval = core_tx_upper_data(target, tmp, &drscan_data);
- if (retval != ERROR_OK) {
- dsp5680xx_context.flush = 1;
- err_check_propagate(retval);
- }
- dsp5680xx_context.flush = 0;
- }
- dsp5680xx_context.flush = 1;
- if (!is_flash_lock) {
- /*
- *Verify flash (skip when exec lock sequence)
- *
- */
- uint16_t signature;
-
- uint16_t pc_crc;
-
- retval = dsp5680xx_f_signature(target, address, i, &signature);
- err_check_propagate(retval);
- pc_crc = perl_crc(buffer, i);
- if (pc_crc != signature) {
- retval = ERROR_FAIL;
- const char *msg =
- "Flashed data failed CRC check, flash again!";
- err_check(retval, DSP5680XX_ERROR_FLASHING_CRC, msg);
- }
- }
- return retval;
-}
-
-int dsp5680xx_f_unlock(struct target *target)
-{
- int retval = ERROR_OK;
-
- uint16_t eonce_status;
-
- uint32_t instr;
-
- uint32_t ir_out;
-
- struct jtag_tap *tap_chp;
-
- struct jtag_tap *tap_cpu;
-
- tap_chp = jtag_tap_by_string("dsp568013.chp");
- if (tap_chp == NULL) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_MASTER,
- "Failed to get master tap.");
- }
- tap_cpu = jtag_tap_by_string("dsp568013.cpu");
- if (tap_cpu == NULL) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_CORE,
- "Failed to get master tap.");
- }
-
- retval = eonce_enter_debug_mode_without_reset(target, &eonce_status);
- if (retval == ERROR_OK)
- LOG_WARNING("Memory was not locked.");
-
- jtag_add_reset(0, 1);
- jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000);
-
- retval = reset_jtag();
- err_check(retval, DSP5680XX_ERROR_JTAG_RESET,
- "Failed to reset JTAG state machine");
- jtag_add_sleep(150);
-
- /* Enable core tap */
- tap_chp->enabled = true;
- retval = switch_tap(target, tap_chp, tap_cpu);
- err_check_propagate(retval);
-
- instr = JTAG_INSTR_DEBUG_REQUEST;
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_CORE_TAP_IRLEN);
- err_check_propagate(retval);
- jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000);
- jtag_add_reset(0, 0);
- jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000);
-
- /* Enable master tap */
- tap_chp->enabled = false;
- retval = switch_tap(target, tap_chp, tap_cpu);
- err_check_propagate(retval);
-
- /* Execute mass erase to unlock */
- instr = MASTER_TAP_CMD_FLASH_ERASE;
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_MASTER_TAP_IRLEN);
- err_check_propagate(retval);
-
- instr = HFM_CLK_DEFAULT;
- retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out, 16);
- err_check_propagate(retval);
-
- jtag_add_sleep(TIME_DIV_FREESCALE * 150 * 1000);
- jtag_add_reset(0, 1);
- jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000);
-
- retval = reset_jtag();
- err_check(retval, DSP5680XX_ERROR_JTAG_RESET,
- "Failed to reset JTAG state machine");
- jtag_add_sleep(150);
-
- instr = 0x0606ffff;
- retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out,
- 32);
- err_check_propagate(retval);
-
- /* enable core tap */
- instr = 0x5;
- retval =
- dsp5680xx_irscan(target, &instr, &ir_out,
- DSP5680XX_JTAG_MASTER_TAP_IRLEN);
- err_check_propagate(retval);
- instr = 0x2;
- retval = dsp5680xx_drscan(target, (uint8_t *) &instr, (uint8_t *) &ir_out,
- 4);
- err_check_propagate(retval);
-
- tap_cpu->enabled = true;
- tap_chp->enabled = false;
- target->state = TARGET_RUNNING;
- dsp5680xx_context.debug_mode_enabled = false;
- return retval;
-}
-
-int dsp5680xx_f_lock(struct target *target)
-{
- int retval;
-
- struct jtag_tap *tap_chp;
-
- struct jtag_tap *tap_cpu;
- uint16_t lock_word[] = { HFM_LOCK_FLASH };
- retval = dsp5680xx_f_wr(target, (uint8_t *) (lock_word), HFM_LOCK_ADDR_L, 2, 1);
- err_check_propagate(retval);
-
- jtag_add_reset(0, 1);
- jtag_add_sleep(TIME_DIV_FREESCALE * 200 * 1000);
-
- retval = reset_jtag();
- err_check(retval, DSP5680XX_ERROR_JTAG_RESET,
- "Failed to reset JTAG state machine");
- jtag_add_sleep(TIME_DIV_FREESCALE * 100 * 1000);
- jtag_add_reset(0, 0);
- jtag_add_sleep(TIME_DIV_FREESCALE * 300 * 1000);
-
- tap_chp = jtag_tap_by_string("dsp568013.chp");
- if (tap_chp == NULL) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_MASTER,
- "Failed to get master tap.");
- }
- tap_cpu = jtag_tap_by_string("dsp568013.cpu");
- if (tap_cpu == NULL) {
- retval = ERROR_FAIL;
- err_check(retval, DSP5680XX_ERROR_JTAG_TAP_ENABLE_CORE,
- "Failed to get master tap.");
- }
- target->state = TARGET_RUNNING;
- dsp5680xx_context.debug_mode_enabled = false;
- tap_cpu->enabled = false;
- tap_chp->enabled = true;
- retval = switch_tap(target, tap_chp, tap_cpu);
- return retval;
-}
-
-static int dsp5680xx_step(struct target *target, int current, uint32_t address,
- int handle_breakpoints)
-{
- err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP,
- "Not implemented yet.");
-}
-
-/** Holds methods for dsp5680xx targets. */
-struct target_type dsp5680xx_target = {
- .name = "dsp5680xx",
-
- .poll = dsp5680xx_poll,
- .arch_state = dsp5680xx_arch_state,
-
- .halt = dsp5680xx_halt,
- .resume = dsp5680xx_resume,
- .step = dsp5680xx_step,
-
- .write_buffer = dsp5680xx_write_buffer,
- .read_buffer = dsp5680xx_read_buffer,
-
- .assert_reset = dsp5680xx_assert_reset,
- .deassert_reset = dsp5680xx_deassert_reset,
- .soft_reset_halt = dsp5680xx_soft_reset_halt,
-
- .read_memory = dsp5680xx_read,
- .write_memory = dsp5680xx_write,
-
- .checksum_memory = dsp5680xx_checksum_memory,
-
- .target_create = dsp5680xx_target_create,
- .init_target = dsp5680xx_init_target,
-};
diff --git a/src/target/dsp5680xx.h b/src/target/dsp5680xx.h
deleted file mode 100644
index 842796b..0000000
--- a/src/target/dsp5680xx.h
+++ /dev/null
@@ -1,382 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Rodrigo L. Rosa *
- * rodrigorosa.LG@gmail.com *
- * *
- * Based on dsp563xx_once.h written by Mathias Kuester *
- * mkdorg@users.sourceforge.net *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_DSP5680XX_H
-#define OPENOCD_TARGET_DSP5680XX_H
-
-#include <jtag/jtag.h>
-
-/**
- * @file dsp5680xx.h
- * @author Rodrigo Rosa <rodrigorosa.LG@gmail.com>
- * @date Thu Jun 9 18:54:38 2011
- *
- * @brief Basic support for the 5680xx DSP from Freescale.
- * The chip has two taps in the JTAG chain, the Master tap and the Core tap.
- * In this code the Master tap is only used to unlock the flash memory by executing a JTAG instruction.
- *
- */
-
-#define S_FILE_DATA_OFFSET 0x200000
-#define TIME_DIV_FREESCALE 0.3
-
-/** ----------------------------------------------------------------
- * JTAG
- *----------------------------------------------------------------
- */
-#define DSP5680XX_JTAG_CORE_TAP_IRLEN 4
-#define DSP5680XX_JTAG_MASTER_TAP_IRLEN 8
-
-#define JTAG_STATUS_MASK 0x0F
-
-#define JTAG_STATUS_NORMAL 0x01
-#define JTAG_STATUS_STOPWAIT 0x05
-#define JTAG_STATUS_BUSY 0x09
-#define JTAG_STATUS_DEBUG 0x0D
-#define JTAG_STATUS_DEAD 0x0f
-
-#define JTAG_INSTR_EXTEST 0x0
-#define JTAG_INSTR_SAMPLE_PRELOAD 0x1
-#define JTAG_INSTR_IDCODE 0x2
-#define JTAG_INSTR_EXTEST_PULLUP 0x3
-#define JTAG_INSTR_HIGHZ 0x4
-#define JTAG_INSTR_CLAMP 0x5
-#define JTAG_INSTR_ENABLE_ONCE 0x6
-#define JTAG_INSTR_DEBUG_REQUEST 0x7
-#define JTAG_INSTR_BYPASS 0xF
- /**
- * ----------------------------------------------------------------
- */
-
-/** ----------------------------------------------------------------
- * Master TAP instructions from MC56F8000RM.pdf
- * ----------------------------------------------------------------
- */
-#define MASTER_TAP_CMD_BYPASS 0xF
-#define MASTER_TAP_CMD_IDCODE 0x2
-#define MASTER_TAP_CMD_TLM_SEL 0x5
-#define MASTER_TAP_CMD_FLASH_ERASE 0x8
- /**
- * ----------------------------------------------------------------
- */
-
- /** ----------------------------------------------------------------
- * EOnCE control register info
- * ----------------------------------------------------------------
- */
-#define DSP5680XX_ONCE_OCR_EX (1<<5)
-/* EX Bit Definition
- 0 Remain in the Debug Processing State
- 1 Leave the Debug Processing State */
-#define DSP5680XX_ONCE_OCR_GO (1<<6)
-/* GO Bit Definition
- 0 Inactive—No Action Taken
- 1 Execute Controller Instruction */
-#define DSP5680XX_ONCE_OCR_RW (1<<7)
-/** RW Bit Definition
- * 0 Write To the Register Specified by the RS[4:0] Bits
- * 1 ReadFrom the Register Specified by the RS[4:0] Bits
- * ----------------------------------------------------------------
- */
-
- /** ----------------------------------------------------------------
- * EOnCE Status Register
- * ----------------------------------------------------------------
- */
-#define DSP5680XX_ONCE_OSCR_OS1 (1<<5)
-#define DSP5680XX_ONCE_OSCR_OS0 (1<<4)
- /**
- * ----------------------------------------------------------------
- */
-
- /** ----------------------------------------------------------------
- * EOnCE Core Status - Describes the operating status of the core controller
- * ----------------------------------------------------------------
- */
-#define DSP5680XX_ONCE_OSCR_NORMAL_M (0)
-/* 00 - Normal - Controller Core Executing Instructions or in Reset */
-#define DSP5680XX_ONCE_OSCR_STOPWAIT_M (DSP5680XX_ONCE_OSCR_OS0)
-/* 01 - Stop/Wait - Controller Core in Stop or Wait Mode */
-#define DSP5680XX_ONCE_OSCR_BUSY_M (DSP5680XX_ONCE_OSCR_OS1)
-/* 10 - Busy - Controller is Performing External or Peripheral Access (Wait States) */
-#define DSP5680XX_ONCE_OSCR_DEBUG_M (DSP5680XX_ONCE_OSCR_OS0|DSP5680XX_ONCE_OSCR_OS1)
-/* 11 - Debug - Controller Core Halted and in Debug Mode */
-#define EONCE_STAT_MASK 0x30
- /**
- * ----------------------------------------------------------------
- */
-
- /** ----------------------------------------------------------------
- * Register Select Encoding (eonce_rev.1.0_0208081.pdf:14)
- * ----------------------------------------------------------------
- */
-#define DSP5680XX_ONCE_NOREG 0x00 /* No register selected */
-#define DSP5680XX_ONCE_OCR 0x01 /* OnCE Debug Control Register */
-#define DSP5680XX_ONCE_OCNTR 0x02 /* OnCE Breakpoint and Trace Counter */
-#define DSP5680XX_ONCE_OSR 0x03 /* EOnCE status register */
-#define DSP5680XX_ONCE_OBAR 0x04 /* OnCE Breakpoint Address Register */
-#define DSP5680XX_ONCE_OBASE 0x05 /* EOnCE Peripheral Base Address register */
-#define DSP5680XX_ONCE_OTXRXSR 0x06 /* EOnCE TXRX Status and Control Register (OTXRXSR) */
-#define DSP5680XX_ONCE_OTX 0x07 /* EOnCE Transmit register (OTX) */
-#define DSP5680XX_ONCE_OPDBR 0x08 /* EOnCE Program Data Bus Register (OPDBR) */
-#define DSP5680XX_ONCE_OTX1 0x09 /* EOnCE Upper Transmit register (OTX1) */
-#define DSP5680XX_ONCE_OPABFR 0x0A /* OnCE Program Address Register—Fetch cycle */
-#define DSP5680XX_ONCE_ORX 0x0B /* EOnCE Receive register (ORX) */
-#define DSP5680XX_ONCE_OCNTR_C 0x0C /* Clear OCNTR */
-#define DSP5680XX_ONCE_ORX1 0x0D /* EOnCE Upper Receive register (ORX1) */
-#define DSP5680XX_ONCE_OTBCR 0x0E /* EOnCE Trace Buffer Control Reg (OTBCR) */
-#define DSP5680XX_ONCE_OPABER 0x10 /* OnCE Program Address Register—Execute cycle */
-#define DSP5680XX_ONCE_OPFIFO 0x11 /* OnCE Program address FIFO */
-#define DSP5680XX_ONCE_OBAR1 0x12 /* EOnCE Breakpoint 1 Unit 0 Address Reg.(OBAR1) */
-#define DSP5680XX_ONCE_OPABDR 0x13 /* OnCE Program Address Register—Decode cycle (OPABDR) */
- /**
- * ----------------------------------------------------------------
- */
-
-#define FLUSH_COUNT_READ_WRITE 8192 /* This value works, higher values (and lower...) may work as well. */
-#define FLUSH_COUNT_FLASH 8192
-/** ----------------------------------------------------------------
- * HFM (flash module) Commands (ref:MC56F801xRM.pdf:159)
- * ----------------------------------------------------------------
- */
-#define HFM_ERASE_VERIFY 0x05
-#define HFM_CALCULATE_DATA_SIGNATURE 0x06
-#define HFM_WORD_PROGRAM 0x20
-#define HFM_PAGE_ERASE 0x40
-#define HFM_MASS_ERASE 0x41
-#define HFM_CALCULATE_IFR_BLOCK_SIGNATURE 0x66
- /**
- * ----------------------------------------------------------------
- */
-
-/** ----------------------------------------------------------------
- * Flashing (ref:MC56F801xRM.pdf:159)
- * ----------------------------------------------------------------
- */
-#define HFM_BASE_ADDR 0x0F400 /** In x: mem. (write to S_FILE_DATA_OFFSET+HFM_BASE_ADDR
- * to get data into x: mem.)
- */
-/**
- * The following are register addresses, not memory
- * addresses (though all registers are memory mapped)
- */
-#define HFM_CLK_DIV 0x00 /* r/w */
-#define HFM_CNFG 0x01 /* r/w */
-#define HFM_SECHI 0x03 /* r */
-#define HFM_SECLO 0x04 /* r */
-#define HFM_PROT 0x10 /* r/w */
-#define HFM_PROTB 0x11 /* r/w */
-#define HFM_USTAT 0x13 /* r/w */
-#define HFM_CMD 0x14 /* r/w */
-#define HFM_DATA 0x18 /* r */
-#define HFM_OPT1 0x1B /* r */
-#define HFM_TSTSIG 0x1D /* r */
-
-#define HFM_EXEC_COMPLETE 0x40
-
-/* User status register (USTAT) masks (MC56F80XXRM.pdf:6.7.5) */
-#define HFM_USTAT_MASK_BLANK 0x4
-#define HFM_USTAT_MASK_PVIOL_ACCER 0x30
-
-/**
- * The value used on for the FM clock is important to prevent flashing errors and to prevent deterioration of the FM.
- * This value was calculated using a spreadsheet tool available on the Freescale website under FAQ 25464.
- *
- */
-#define HFM_CLK_DEFAULT 0x27
-/* 0x27 according to freescale cfg, but 0x40 according to freescale spreadsheet... */
-#define HFM_FLASH_BASE_ADDR 0x0
-#define HFM_SIZE_BYTES 0x4000 /* bytes */
-#define HFM_SIZE_WORDS 0x2000 /* words */
-#define HFM_SECTOR_SIZE 0x200 /* Size in bytes */
-#define HFM_SECTOR_COUNT 0x20
-/* A 16K block in pages of 256 words. */
-
-/**
- * Writing HFM_LOCK_FLASH to HFM_LOCK_ADDR_L and HFM_LOCK_ADDR_H will enable security on flash after the next reset.
- */
-#define HFM_LOCK_FLASH 0xE70A
-#define HFM_LOCK_ADDR_L 0x1FF7
-#define HFM_LOCK_ADDR_H 0x1FF8
- /**
- * ----------------------------------------------------------------
- */
-
-/** ----------------------------------------------------------------
- * Register Memory Map (eonce_rev.1.0_0208081.pdf:16)
- * ----------------------------------------------------------------
- */
-#define MC568013_EONCE_OBASE_ADDR 0xFF
-/* The following are relative to EONCE_OBASE_ADDR (EONCE_OBASE_ADDR<<16 + ...) */
-#define MC568013_EONCE_TX_RX_ADDR 0xFFFE
-#define MC568013_EONCE_TX1_RX1_HIGH_ADDR 0xFFFF /* Relative to EONCE_OBASE_ADDR */
-#define MC568013_EONCE_OCR 0xFFA0 /* Relative to EONCE_OBASE_ADDR */
- /**
- * ----------------------------------------------------------------
- */
-
-/** ----------------------------------------------------------------
- * SIM addresses & commands (MC56F80xx.h from freescale)
- * ----------------------------------------------------------------
- */
-#define MC568013_SIM_BASE_ADDR 0xF140
-#define MC56803x_2x_SIM_BASE_ADDR 0xF100
-
-#define SIM_CMD_RESET 0x10
- /**
- * ----------------------------------------------------------------
- */
-
-/**
- * ----------------------------------------------------------------
- * ERROR codes - enable automatic parsing of output
- * ----------------------------------------------------------------
- */
-#define DSP5680XX_ERROR_UNKNOWN_OR_ERROR_OPENOCD -100
-#define DSP5680XX_ERROR_JTAG_COMM -1
-#define DSP5680XX_ERROR_JTAG_RESET -2
-#define DSP5680XX_ERROR_JTAG_INVALID_TAP -3
-#define DSP5680XX_ERROR_JTAG_DR_LEN_OVERFLOW -4
-#define DSP5680XX_ERROR_INVALID_IR_LEN -5
-#define DSP5680XX_ERROR_JTAG_TAP_ENABLE_MASTER -6
-#define DSP5680XX_ERROR_JTAG_TAP_ENABLE_CORE -7
-#define DSP5680XX_ERROR_JTAG_TAP_FIND_MASTER -8
-#define DSP5680XX_ERROR_JTAG_TAP_FIND_CORE -9
-#define DSP5680XX_ERROR_JTAG_DRSCAN -10
-#define DSP5680XX_ERROR_JTAG_IRSCAN -11
-#define DSP5680XX_ERROR_ENTER_DEBUG_MODE -12
-#define DSP5680XX_ERROR_RESUME -13
-#define DSP5680XX_ERROR_WRITE_WITH_TARGET_RUNNING -14
-#define DSP5680XX_ERROR_INVALID_DATA_SIZE_UNIT -15
-#define DSP5680XX_ERROR_PROTECT_CHECK_INVALID_ARGS -16
-#define DSP5680XX_ERROR_FM_BUSY -17
-#define DSP5680XX_ERROR_FM_CMD_TIMED_OUT -18
-#define DSP5680XX_ERROR_FM_EXEC -19
-#define DSP5680XX_ERROR_FM_SET_CLK -20
-#define DSP5680XX_ERROR_FLASHING_INVALID_WORD_COUNT -21
-#define DSP5680XX_ERROR_FLASHING_CRC -22
-#define DSP5680XX_ERROR_FLASHING -23
-#define DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP -24
-#define DSP5680XX_ERROR_HALT -25
-#define DSP5680XX_ERROR_EXIT_DEBUG_MODE -26
-#define DSP5680XX_ERROR_TARGET_RUNNING -27
-#define DSP5680XX_ERROR_NOT_IN_DEBUG -28
-/**
- * ----------------------------------------------------------------
- */
-
-struct dsp5680xx_common {
- uint32_t stored_pc;
- int flush;
- bool debug_mode_enabled;
-};
-
-extern struct dsp5680xx_common dsp5680xx_context;
-
-static inline struct dsp5680xx_common *target_to_dsp5680xx(struct target
- *target)
-{
- return target->arch_info;
-}
-
-/**
- * Writes to flash memory.
- * Does not check if flash is erased, it's up to the user to erase the flash before running
- * this function.
- * The flashing algorithm runs from RAM, reading from a register to which this function
- * writes to. The algorithm is open loop, there is no control to verify that the FM read
- * the register before writing the next data. A closed loop approach was much slower,
- * and the current implementation does not fail, and if it did the crc check would detect it,
- * allowing to flash again.
- *
- * @param target
- * @param buffer
- * @param address Word addressing.
- * @param count In bytes.
- * @param is_flash_lock
- *
- * @return
- */
-int dsp5680xx_f_wr(struct target *target, const uint8_t * buffer, uint32_t address,
- uint32_t count, int is_flash_lock);
-
-/**
- * The FM has the functionality of checking if the flash array is erased. This function
- * executes it. It does not support individual sector analysis.
- *
- * @param target
- * @param erased
- * @param sector This parameter is ignored because the FM does not support checking if
- * individual sectors are erased.
- *
- * @return
- */
-int dsp5680xx_f_erase_check(struct target *target, uint8_t * erased,
- uint32_t sector);
-
-/**
- * Erases either a sector or the complete flash array. If either the range first-last covers
- * the complete array or if first == 0 and last == 0 then a mass erase command is executed
- * on the FM. If not, then individual sectors are erased.
- *
- * @param target
- * @param first
- * @param last
- *
- * @return
- */
-int dsp5680xx_f_erase(struct target *target, int first, int last);
-
-/**
- * Reads the memory mapped protection register. A 1 implies the sector is protected,
- * a 0 implies the sector is not protected.
- *
- * @param target
- * @param protected Data read from the protection register.
- *
- * @return
- */
-int dsp5680xx_f_protect_check(struct target *target, uint16_t * protected);
-
-/**
- * Writes the flash security words with a specific value. The chip's security will be
- * enabled after the first reset following the execution of this function.
- *
- * @param target
- *
- * @return
- */
-int dsp5680xx_f_lock(struct target *target);
-
-/**
- * Executes a mass erase command. The must be done from the Master tap.
- * It is up to the user to select the master tap (jtag tapenable dsp5680xx.chp)
- * before running this function.
- * The flash array will be unsecured (and erased) after the first reset following
- * the execution of this function.
- *
- * @param target
- *
- * @return
- */
-int dsp5680xx_f_unlock(struct target *target);
-
-#endif /* OPENOCD_TARGET_DSP5680XX_H */
diff --git a/src/target/embeddedice.c b/src/target/embeddedice.c
deleted file mode 100644
index 09d6fc8..0000000
--- a/src/target/embeddedice.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "embeddedice.h"
-#include "register.h"
-
-/**
- * @file
- *
- * This provides lowlevel glue to the EmbeddedICE (or EmbeddedICE-RT)
- * module found on scan chain 2 in ARM7, ARM9, and some other families
- * of ARM cores. The module is called "EmbeddedICE-RT" if it has
- * monitor mode support.
- *
- * EmbeddedICE provides basic watchpoint/breakpoint hardware and a Debug
- * Communications Channel (DCC) used to read or write 32-bit words to
- * OpenOCD-aware code running on the target CPU.
- * Newer modules also include vector catch hardware. Some versions
- * support hardware single-stepping, "monitor mode" debug (which is not
- * currently supported by OpenOCD), or extended reporting on why the
- * core entered debug mode.
- */
-
-static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf);
-
-/*
- * From: ARM9E-S TRM, DDI 0165, table C-4 (and similar, for other cores)
- */
-static const struct {
- const char *name;
- unsigned short addr;
- unsigned short width;
-} eice_regs[] = {
- [EICE_DBG_CTRL] = {
- .name = "debug_ctrl",
- .addr = 0,
- /* width is assigned based on EICE version */
- },
- [EICE_DBG_STAT] = {
- .name = "debug_status",
- .addr = 1,
- /* width is assigned based on EICE version */
- },
- [EICE_COMMS_CTRL] = {
- .name = "comms_ctrl",
- .addr = 4,
- .width = 6,
- },
- [EICE_COMMS_DATA] = {
- .name = "comms_data",
- .addr = 5,
- .width = 32,
- },
- [EICE_W0_ADDR_VALUE] = {
- .name = "watch_0_addr_value",
- .addr = 8,
- .width = 32,
- },
- [EICE_W0_ADDR_MASK] = {
- .name = "watch_0_addr_mask",
- .addr = 9,
- .width = 32,
- },
- [EICE_W0_DATA_VALUE] = {
- .name = "watch_0_data_value",
- .addr = 10,
- .width = 32,
- },
- [EICE_W0_DATA_MASK] = {
- .name = "watch_0_data_mask",
- .addr = 11,
- .width = 32,
- },
- [EICE_W0_CONTROL_VALUE] = {
- .name = "watch_0_control_value",
- .addr = 12,
- .width = 9,
- },
- [EICE_W0_CONTROL_MASK] = {
- .name = "watch_0_control_mask",
- .addr = 13,
- .width = 8,
- },
- [EICE_W1_ADDR_VALUE] = {
- .name = "watch_1_addr_value",
- .addr = 16,
- .width = 32,
- },
- [EICE_W1_ADDR_MASK] = {
- .name = "watch_1_addr_mask",
- .addr = 17,
- .width = 32,
- },
- [EICE_W1_DATA_VALUE] = {
- .name = "watch_1_data_value",
- .addr = 18,
- .width = 32,
- },
- [EICE_W1_DATA_MASK] = {
- .name = "watch_1_data_mask",
- .addr = 19,
- .width = 32,
- },
- [EICE_W1_CONTROL_VALUE] = {
- .name = "watch_1_control_value",
- .addr = 20,
- .width = 9,
- },
- [EICE_W1_CONTROL_MASK] = {
- .name = "watch_1_control_mask",
- .addr = 21,
- .width = 8,
- },
- /* vector_catch isn't always present */
- [EICE_VEC_CATCH] = {
- .name = "vector_catch",
- .addr = 2,
- .width = 8,
- },
-};
-
-static int embeddedice_get_reg(struct reg *reg)
-{
- int retval = embeddedice_read_reg(reg);
- if (retval != ERROR_OK) {
- LOG_ERROR("error queueing EmbeddedICE register read");
- return retval;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- LOG_ERROR("EmbeddedICE register read failed");
-
- return retval;
-}
-
-static const struct reg_arch_type eice_reg_type = {
- .get = embeddedice_get_reg,
- .set = embeddedice_set_reg_w_exec,
-};
-
-/**
- * Probe EmbeddedICE module and set up local records of its registers.
- * Different versions of the modules have different capabilities, such as
- * hardware support for vector_catch, single stepping, and monitor mode.
- */
-struct reg_cache *embeddedice_build_reg_cache(struct target *target,
- struct arm7_9_common *arm7_9)
-{
- int retval;
- struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = NULL;
- struct embeddedice_reg *arch_info = NULL;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- int num_regs = ARRAY_SIZE(eice_regs);
- int i;
- int eice_version = 0;
-
- /* vector_catch isn't always present */
- if (!arm7_9->has_vector_catch)
- num_regs--;
-
- /* the actual registers are kept in two arrays */
- reg_list = calloc(num_regs, sizeof(struct reg));
- arch_info = calloc(num_regs, sizeof(struct embeddedice_reg));
-
- /* fill in values for the reg cache */
- reg_cache->name = "EmbeddedICE registers";
- reg_cache->next = NULL;
- reg_cache->reg_list = reg_list;
- reg_cache->num_regs = num_regs;
-
- /* FIXME the second watchpoint unit on Feroceon and Dragonite
- * seems not to work ... we should have a way to not set up
- * its four registers here!
- */
-
- /* set up registers */
- for (i = 0; i < num_regs; i++) {
- reg_list[i].name = eice_regs[i].name;
- reg_list[i].size = eice_regs[i].width;
- reg_list[i].dirty = 0;
- reg_list[i].valid = 0;
- reg_list[i].value = calloc(1, 4);
- reg_list[i].arch_info = &arch_info[i];
- reg_list[i].type = &eice_reg_type;
- arch_info[i].addr = eice_regs[i].addr;
- arch_info[i].jtag_info = jtag_info;
- }
-
- /* identify EmbeddedICE version by reading DCC control register */
- embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- for (i = 0; i < num_regs; i++)
- free(reg_list[i].value);
- free(reg_list);
- free(reg_cache);
- free(arch_info);
- return NULL;
- }
-
- eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
- LOG_INFO("Embedded ICE version %d", eice_version);
-
- switch (eice_version) {
- case 1:
- /* ARM7TDMI r3, ARM7TDMI-S r3
- *
- * REVISIT docs say ARM7TDMI-S r4 uses version 1 but
- * that it has 6-bit CTRL and 5-bit STAT... doc bug?
- * ARM7TDMI r4 docs say EICE v4.
- */
- reg_list[EICE_DBG_CTRL].size = 3;
- reg_list[EICE_DBG_STAT].size = 5;
- break;
- case 2:
- /* ARM9TDMI */
- reg_list[EICE_DBG_CTRL].size = 4;
- reg_list[EICE_DBG_STAT].size = 5;
- arm7_9->has_single_step = 1;
- break;
- case 3:
- LOG_ERROR("EmbeddedICE v%d handling might be broken",
- eice_version);
- reg_list[EICE_DBG_CTRL].size = 6;
- reg_list[EICE_DBG_STAT].size = 5;
- arm7_9->has_single_step = 1;
- arm7_9->has_monitor_mode = 1;
- break;
- case 4:
- /* ARM7TDMI r4 */
- reg_list[EICE_DBG_CTRL].size = 6;
- reg_list[EICE_DBG_STAT].size = 5;
- arm7_9->has_monitor_mode = 1;
- break;
- case 5:
- /* ARM9E-S rev 1 */
- reg_list[EICE_DBG_CTRL].size = 6;
- reg_list[EICE_DBG_STAT].size = 5;
- arm7_9->has_single_step = 1;
- arm7_9->has_monitor_mode = 1;
- break;
- case 6:
- /* ARM7EJ-S, ARM9E-S rev 2, ARM9EJ-S */
- reg_list[EICE_DBG_CTRL].size = 6;
- reg_list[EICE_DBG_STAT].size = 10;
- /* DBG_STAT has MOE bits */
- arm7_9->has_monitor_mode = 1;
- break;
- case 7:
- LOG_ERROR("EmbeddedICE v%d handling might be broken",
- eice_version);
- reg_list[EICE_DBG_CTRL].size = 6;
- reg_list[EICE_DBG_STAT].size = 5;
- arm7_9->has_monitor_mode = 1;
- break;
- default:
- /*
- * The Feroceon implementation has the version number
- * in some unusual bits. Let feroceon.c validate it
- * and do the appropriate setup itself.
- */
- if (strcmp(target_type_name(target), "feroceon") == 0 ||
- strcmp(target_type_name(target), "dragonite") == 0)
- break;
- LOG_ERROR("unknown EmbeddedICE version "
- "(comms ctrl: 0x%8.8" PRIx32 ")",
- buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
- }
-
- /* On Feroceon and Dragonite the second unit is seemingly missing. */
- LOG_INFO("%s: hardware has %d breakpoint/watchpoint unit%s",
- target_name(target), arm7_9->wp_available_max,
- (arm7_9->wp_available_max != 1) ? "s" : "");
-
- return reg_cache;
-}
-
-/**
- * Initialize EmbeddedICE module, if needed.
- */
-int embeddedice_setup(struct target *target)
-{
- int retval;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
-
- /* Explicitly disable monitor mode. For now we only support halting
- * debug ... we don't know how to talk with a resident debug monitor
- * that manages break requests. ARM's "Angel Debug Monitor" is one
- * common example of such code.
- */
- if (arm7_9->has_monitor_mode) {
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-
- embeddedice_read_reg(dbg_ctrl);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- buf_set_u32(dbg_ctrl->value, 4, 1, 0);
- embeddedice_set_reg_w_exec(dbg_ctrl, dbg_ctrl->value);
- }
- return jtag_execute_queue();
-}
-
-/**
- * Queue a read for an EmbeddedICE register into the register cache,
- * optionally checking the value read.
- * Note that at this level, all registers are 32 bits wide.
- */
-int embeddedice_read_reg_w_check(struct reg *reg,
- uint8_t *check_value, uint8_t *check_mask)
-{
- struct embeddedice_reg *ice_reg = reg->arch_info;
- uint8_t reg_addr = ice_reg->addr & 0x1f;
- struct scan_field fields[3];
- uint8_t field1_out[1];
- uint8_t field2_out[1];
- int retval;
-
- retval = arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm_jtag_set_instr(ice_reg->jtag_info->tap,
- ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- /* bits 31:0 -- data (ignored here) */
- fields[0].num_bits = 32;
- fields[0].out_value = reg->value;
- fields[0].in_value = NULL;
- fields[0].check_value = NULL;
- fields[0].check_mask = NULL;
-
- /* bits 36:32 -- register */
- fields[1].num_bits = 5;
- fields[1].out_value = field1_out;
- field1_out[0] = reg_addr;
- fields[1].in_value = NULL;
- fields[1].check_value = NULL;
- fields[1].check_mask = NULL;
-
- /* bit 37 -- 0/read */
- fields[2].num_bits = 1;
- fields[2].out_value = field2_out;
- field2_out[0] = 0;
- fields[2].in_value = NULL;
- fields[2].check_value = NULL;
- fields[2].check_mask = NULL;
-
- /* traverse Update-DR, setting address for the next read */
- jtag_add_dr_scan(ice_reg->jtag_info->tap, 3, fields, TAP_IDLE);
-
- /* bits 31:0 -- the data we're reading (and maybe checking) */
- fields[0].in_value = reg->value;
- fields[0].check_value = check_value;
- fields[0].check_mask = check_mask;
-
- /* when reading the DCC data register, leaving the address field set to
- * EICE_COMMS_DATA would read the register twice
- * reading the control register is safe
- */
- field1_out[0] = eice_regs[EICE_COMMS_CTRL].addr;
-
- /* traverse Update-DR, reading but with no other side effects */
- jtag_add_dr_scan_check(ice_reg->jtag_info->tap, 3, fields, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-/**
- * Receive a block of size 32-bit words from the DCC.
- * We assume the target is always going to be fast enough (relative to
- * the JTAG clock) that the debugger won't need to poll the handshake
- * bit. The JTAG clock is usually at least six times slower than the
- * functional clock, so the 50+ JTAG clocks needed to receive the word
- * allow hundreds of instruction cycles (per word) in the target.
- */
-int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
-{
- struct scan_field fields[3];
- uint8_t field1_out[1];
- uint8_t field2_out[1];
- int retval;
-
- retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 5;
- fields[1].out_value = field1_out;
- field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- fields[2].out_value = field2_out;
- field2_out[0] = 0;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
- while (size > 0) {
- /* when reading the last item, set the register address to the DCC control reg,
- * to avoid reading additional data from the DCC data reg
- */
- if (size == 1)
- field1_out[0] = eice_regs[EICE_COMMS_CTRL].addr;
-
- fields[0].in_value = (uint8_t *)data;
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
- jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)data);
-
- data++;
- size--;
- }
-
- return jtag_execute_queue();
-}
-
-/**
- * Queue a read for an EmbeddedICE register into the register cache,
- * not checking the value read.
- */
-int embeddedice_read_reg(struct reg *reg)
-{
- return embeddedice_read_reg_w_check(reg, NULL, NULL);
-}
-
-/**
- * Queue a write for an EmbeddedICE register, updating the register cache.
- * Uses embeddedice_write_reg().
- */
-void embeddedice_set_reg(struct reg *reg, uint32_t value)
-{
- embeddedice_write_reg(reg, value);
-
- buf_set_u32(reg->value, 0, reg->size, value);
- reg->valid = 1;
- reg->dirty = 0;
-
-}
-
-/**
- * Write an EmbeddedICE register, updating the register cache.
- * Uses embeddedice_set_reg(); not queued.
- */
-static int embeddedice_set_reg_w_exec(struct reg *reg, uint8_t *buf)
-{
- int retval;
-
- embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- LOG_ERROR("register write failed");
- return retval;
-}
-
-/**
- * Queue a write for an EmbeddedICE register, bypassing the register cache.
- */
-void embeddedice_write_reg(struct reg *reg, uint32_t value)
-{
- struct embeddedice_reg *ice_reg = reg->arch_info;
-
- LOG_DEBUG("%i: 0x%8.8" PRIx32 "", ice_reg->addr, value);
-
- arm_jtag_scann(ice_reg->jtag_info, 0x2, TAP_IDLE);
-
- arm_jtag_set_instr(ice_reg->jtag_info->tap, ice_reg->jtag_info->intest_instr, NULL, TAP_IDLE);
-
- uint8_t reg_addr = ice_reg->addr & 0x1f;
- embeddedice_write_reg_inner(ice_reg->jtag_info->tap, reg_addr, value);
-}
-
-/**
- * Queue a write for an EmbeddedICE register, using cached value.
- * Uses embeddedice_write_reg().
- */
-void embeddedice_store_reg(struct reg *reg)
-{
- embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
-}
-
-/**
- * Send a block of size 32-bit words to the DCC.
- * We assume the target is always going to be fast enough (relative to
- * the JTAG clock) that the debugger won't need to poll the handshake
- * bit. The JTAG clock is usually at least six times slower than the
- * functional clock, so the 50+ JTAG clocks needed to receive the word
- * allow hundreds of instruction cycles (per word) in the target.
- */
-int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size)
-{
- struct scan_field fields[3];
- uint8_t field0_out[4];
- uint8_t field1_out[1];
- uint8_t field2_out[1];
- int retval;
-
- retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = field0_out;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 5;
- fields[1].out_value = field1_out;
- field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- fields[2].out_value = field2_out;
- field2_out[0] = 1;
-
- fields[2].in_value = NULL;
-
- while (size > 0) {
- buf_set_u32(field0_out, 0, 32, *data);
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
-
- data++;
- size--;
- }
-
- /* call to jtag_execute_queue() intentionally omitted */
- return ERROR_OK;
-}
-
-/**
- * Poll DCC control register until read or write handshake completes.
- */
-int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout)
-{
- struct scan_field fields[3];
- uint8_t field0_in[4];
- uint8_t field1_out[1];
- uint8_t field2_out[1];
- int retval;
- uint32_t hsact;
- struct timeval lap;
- struct timeval now;
-
- if (hsbit == EICE_COMM_CTRL_WBIT)
- hsact = 1;
- else if (hsbit == EICE_COMM_CTRL_RBIT)
- hsact = 0;
- else {
- LOG_ERROR("Invalid arguments");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- retval = arm_jtag_scann(jtag_info, 0x2, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = field0_in;
-
- fields[1].num_bits = 5;
- fields[1].out_value = field1_out;
- field1_out[0] = eice_regs[EICE_COMMS_DATA].addr;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- fields[2].out_value = field2_out;
- field2_out[0] = 0;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
- gettimeofday(&lap, NULL);
- do {
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (buf_get_u32(field0_in, hsbit, 1) == hsact)
- return ERROR_OK;
-
- gettimeofday(&now, NULL);
- } while ((uint32_t)((now.tv_sec - lap.tv_sec) * 1000
- + (now.tv_usec - lap.tv_usec) / 1000) <= timeout);
-
- LOG_ERROR("embeddedice handshake timeout");
- return ERROR_TARGET_TIMEOUT;
-}
-
-#ifndef HAVE_JTAG_MINIDRIVER_H
-/**
- * This is an inner loop of the open loop DCC write of data to target
- */
-void embeddedice_write_dcc(struct jtag_tap *tap,
- int reg_addr, const uint8_t *buffer, int little, int count)
-{
- int i;
-
- for (i = 0; i < count; i++) {
- embeddedice_write_reg_inner(tap, reg_addr,
- fast_target_buffer_get_u32(buffer, little));
- buffer += 4;
- }
-}
-#else
-/* provided by minidriver */
-#endif
diff --git a/src/target/embeddedice.h b/src/target/embeddedice.h
deleted file mode 100644
index 39902fb..0000000
--- a/src/target/embeddedice.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005, 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_EMBEDDEDICE_H
-#define OPENOCD_TARGET_EMBEDDEDICE_H
-
-#include "arm7_9_common.h"
-
-enum {
- EICE_DBG_CTRL = 0,
- EICE_DBG_STAT = 1,
- EICE_COMMS_CTRL = 2,
- EICE_COMMS_DATA = 3,
- EICE_W0_ADDR_VALUE = 4,
- EICE_W0_ADDR_MASK = 5,
- EICE_W0_DATA_VALUE = 6,
- EICE_W0_DATA_MASK = 7,
- EICE_W0_CONTROL_VALUE = 8,
- EICE_W0_CONTROL_MASK = 9,
- EICE_W1_ADDR_VALUE = 10,
- EICE_W1_ADDR_MASK = 11,
- EICE_W1_DATA_VALUE = 12,
- EICE_W1_DATA_MASK = 13,
- EICE_W1_CONTROL_VALUE = 14,
- EICE_W1_CONTROL_MASK = 15,
- EICE_VEC_CATCH = 16
-};
-
-enum {
- EICE_DBG_CONTROL_ICEDIS = 5,
- EICE_DBG_CONTROL_MONEN = 4,
- EICE_DBG_CONTROL_INTDIS = 2,
- EICE_DBG_CONTROL_DBGRQ = 1,
- EICE_DBG_CONTROL_DBGACK = 0,
-};
-
-enum {
- EICE_DBG_STATUS_IJBIT = 5,
- EICE_DBG_STATUS_ITBIT = 4,
- EICE_DBG_STATUS_SYSCOMP = 3,
- EICE_DBG_STATUS_IFEN = 2,
- EICE_DBG_STATUS_DBGRQ = 1,
- EICE_DBG_STATUS_DBGACK = 0
-};
-
-enum {
- EICE_W_CTRL_ENABLE = 0x100,
- EICE_W_CTRL_RANGE = 0x80,
- EICE_W_CTRL_CHAIN = 0x40,
- EICE_W_CTRL_EXTERN = 0x20,
- EICE_W_CTRL_nTRANS = 0x10,
- EICE_W_CTRL_nOPC = 0x8,
- EICE_W_CTRL_MAS = 0x6,
- EICE_W_CTRL_ITBIT = 0x2,
- EICE_W_CTRL_nRW = 0x1
-};
-
-enum {
- EICE_COMM_CTRL_WBIT = 1,
- EICE_COMM_CTRL_RBIT = 0
-};
-
-struct embeddedice_reg {
- int addr;
- struct arm_jtag *jtag_info;
-};
-
-struct reg_cache *embeddedice_build_reg_cache(struct target *target,
- struct arm7_9_common *arm7_9);
-
-int embeddedice_setup(struct target *target);
-
-int embeddedice_read_reg(struct reg *reg);
-int embeddedice_read_reg_w_check(struct reg *reg,
- uint8_t *check_value, uint8_t *check_mask);
-
-void embeddedice_write_reg(struct reg *reg, uint32_t value);
-void embeddedice_store_reg(struct reg *reg);
-
-void embeddedice_set_reg(struct reg *reg, uint32_t value);
-
-int embeddedice_receive(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size);
-int embeddedice_send(struct arm_jtag *jtag_info, uint32_t *data, uint32_t size);
-
-int embeddedice_handshake(struct arm_jtag *jtag_info, int hsbit, uint32_t timeout);
-
-/* If many embeddedice_write_reg() follow eachother, then the >1 invocations can be
- * this faster version of embeddedice_write_reg
- */
-static inline void embeddedice_write_reg_inner(struct jtag_tap *tap, int reg_addr, uint32_t value)
-{
- uint8_t out_reg_addr = (1 << 5) | reg_addr;
- uint8_t out_value[4];
- buf_set_u32(out_value, 0, 32, value);
-
- struct scan_field fields[2] = {
- { .num_bits = 32, .out_value = out_value },
- { .num_bits = 6, .out_value = &out_reg_addr },
- };
-
- jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
-}
-
-void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer,
- int little, int count);
-
-#endif /* OPENOCD_TARGET_EMBEDDEDICE_H */
diff --git a/src/target/etb.c b/src/target/etb.c
deleted file mode 100644
index dc25844..0000000
--- a/src/target/etb.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "etm.h"
-#include "etb.h"
-#include "register.h"
-
-static const char * const etb_reg_list[] = {
- "ETB_identification",
- "ETB_ram_depth",
- "ETB_ram_width",
- "ETB_status",
- "ETB_ram_data",
- "ETB_ram_read_pointer",
- "ETB_ram_write_pointer",
- "ETB_trigger_counter",
- "ETB_control",
-};
-
-static int etb_get_reg(struct reg *reg);
-
-static int etb_set_instr(struct etb *etb, uint32_t new_instr)
-{
- struct jtag_tap *tap;
-
- tap = etb->tap;
- if (tap == NULL)
- return ERROR_FAIL;
-
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
- struct scan_field field;
-
- field.num_bits = tap->ir_length;
- void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_instr);
-
- field.in_value = NULL;
-
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- free(t);
- }
-
- return ERROR_OK;
-}
-
-static int etb_scann(struct etb *etb, uint32_t new_scan_chain)
-{
- if (etb->cur_scan_chain != new_scan_chain) {
- struct scan_field field;
-
- field.num_bits = 5;
- void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_scan_chain);
-
- field.in_value = NULL;
-
- /* select INTEST instruction */
- etb_set_instr(etb, 0x2);
- jtag_add_dr_scan(etb->tap, 1, &field, TAP_IDLE);
-
- etb->cur_scan_chain = new_scan_chain;
-
- free(t);
- }
-
- return ERROR_OK;
-}
-
-static int etb_read_reg_w_check(struct reg *, uint8_t *, uint8_t *);
-static int etb_set_reg_w_exec(struct reg *, uint8_t *);
-
-static int etb_read_reg(struct reg *reg)
-{
- return etb_read_reg_w_check(reg, NULL, NULL);
-}
-
-static int etb_get_reg(struct reg *reg)
-{
- int retval;
-
- retval = etb_read_reg(reg);
- if (retval != ERROR_OK) {
- LOG_ERROR("BUG: error scheduling ETB register read");
- return retval;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("ETB register read failed");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type etb_reg_type = {
- .get = etb_get_reg,
- .set = etb_set_reg_w_exec,
-};
-
-struct reg_cache *etb_build_reg_cache(struct etb *etb)
-{
- struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = NULL;
- struct etb_reg *arch_info = NULL;
- int num_regs = 9;
- int i;
-
- /* the actual registers are kept in two arrays */
- reg_list = calloc(num_regs, sizeof(struct reg));
- arch_info = calloc(num_regs, sizeof(struct etb_reg));
-
- /* fill in values for the reg cache */
- reg_cache->name = "etb registers";
- reg_cache->next = NULL;
- reg_cache->reg_list = reg_list;
- reg_cache->num_regs = num_regs;
-
- /* set up registers */
- for (i = 0; i < num_regs; i++) {
- reg_list[i].name = etb_reg_list[i];
- reg_list[i].size = 32;
- reg_list[i].dirty = 0;
- reg_list[i].valid = 0;
- reg_list[i].value = calloc(1, 4);
- reg_list[i].arch_info = &arch_info[i];
- reg_list[i].type = &etb_reg_type;
- reg_list[i].size = 32;
- arch_info[i].addr = i;
- arch_info[i].etb = etb;
- }
-
- return reg_cache;
-}
-
-static void etb_getbuf(jtag_callback_data_t arg)
-{
- uint8_t *in = (uint8_t *)arg;
-
- *((uint32_t *)arg) = buf_get_u32(in, 0, 32);
-}
-
-static int etb_read_ram(struct etb *etb, uint32_t *data, int num_frames)
-{
- struct scan_field fields[3];
- int i;
-
- etb_scann(etb, 0x0);
- etb_set_instr(etb, 0xc);
-
- fields[0].num_bits = 32;
- fields[0].out_value = NULL;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 7;
- uint8_t temp1;
- fields[1].out_value = &temp1;
- buf_set_u32(&temp1, 0, 7, 4);
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- uint8_t temp2;
- fields[2].out_value = &temp2;
- buf_set_u32(&temp2, 0, 1, 0);
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(etb->tap, 3, fields, TAP_IDLE);
-
- for (i = 0; i < num_frames; i++) {
- /* ensure nR/W remains set to read */
- buf_set_u32(&temp2, 0, 1, 0);
-
- /* address remains set to 0x4 (RAM data) until we read the last frame */
- if (i < num_frames - 1)
- buf_set_u32(&temp1, 0, 7, 4);
- else
- buf_set_u32(&temp1, 0, 7, 0);
-
- fields[0].in_value = (uint8_t *)(data + i);
- jtag_add_dr_scan(etb->tap, 3, fields, TAP_IDLE);
-
- jtag_add_callback(etb_getbuf, (jtag_callback_data_t)(data + i));
- }
-
- jtag_execute_queue();
-
- return ERROR_OK;
-}
-
-static int etb_read_reg_w_check(struct reg *reg,
- uint8_t *check_value, uint8_t *check_mask)
-{
- struct etb_reg *etb_reg = reg->arch_info;
- uint8_t reg_addr = etb_reg->addr & 0x7f;
- struct scan_field fields[3];
-
- LOG_DEBUG("%i", (int)(etb_reg->addr));
-
- etb_scann(etb_reg->etb, 0x0);
- etb_set_instr(etb_reg->etb, 0xc);
-
- fields[0].num_bits = 32;
- fields[0].out_value = reg->value;
- fields[0].in_value = NULL;
- fields[0].check_value = NULL;
- fields[0].check_mask = NULL;
-
- fields[1].num_bits = 7;
- uint8_t temp1;
- fields[1].out_value = &temp1;
- buf_set_u32(&temp1, 0, 7, reg_addr);
- fields[1].in_value = NULL;
- fields[1].check_value = NULL;
- fields[1].check_mask = NULL;
-
- fields[2].num_bits = 1;
- uint8_t temp2;
- fields[2].out_value = &temp2;
- buf_set_u32(&temp2, 0, 1, 0);
- fields[2].in_value = NULL;
- fields[2].check_value = NULL;
- fields[2].check_mask = NULL;
-
- jtag_add_dr_scan(etb_reg->etb->tap, 3, fields, TAP_IDLE);
-
- /* read the identification register in the second run, to make sure we
- * don't read the ETB data register twice, skipping every second entry
- */
- buf_set_u32(&temp1, 0, 7, 0x0);
- fields[0].in_value = reg->value;
- fields[0].check_value = check_value;
- fields[0].check_mask = check_mask;
-
- jtag_add_dr_scan_check(etb_reg->etb->tap, 3, fields, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-static int etb_write_reg(struct reg *, uint32_t);
-
-static int etb_set_reg(struct reg *reg, uint32_t value)
-{
- int retval;
-
- retval = etb_write_reg(reg, value);
- if (retval != ERROR_OK) {
- LOG_ERROR("BUG: error scheduling ETB register write");
- return retval;
- }
-
- buf_set_u32(reg->value, 0, reg->size, value);
- reg->valid = 1;
- reg->dirty = 0;
-
- return ERROR_OK;
-}
-
-static int etb_set_reg_w_exec(struct reg *reg, uint8_t *buf)
-{
- int retval;
-
- etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("ETB: register write failed");
- return retval;
- }
- return ERROR_OK;
-}
-
-static int etb_write_reg(struct reg *reg, uint32_t value)
-{
- struct etb_reg *etb_reg = reg->arch_info;
- uint8_t reg_addr = etb_reg->addr & 0x7f;
- struct scan_field fields[3];
-
- LOG_DEBUG("%i: 0x%8.8" PRIx32 "", (int)(etb_reg->addr), value);
-
- etb_scann(etb_reg->etb, 0x0);
- etb_set_instr(etb_reg->etb, 0xc);
-
- fields[0].num_bits = 32;
- uint8_t temp0[4];
- fields[0].out_value = temp0;
- buf_set_u32(temp0, 0, 32, value);
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 7;
- uint8_t temp1;
- fields[1].out_value = &temp1;
- buf_set_u32(&temp1, 0, 7, reg_addr);
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- uint8_t temp2;
- fields[2].out_value = &temp2;
- buf_set_u32(&temp2, 0, 1, 1);
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(etb_reg->etb->tap, 3, fields, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etb_config_command)
-{
- struct target *target;
- struct jtag_tap *tap;
- struct arm *arm;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_target(CMD_ARGV[0]);
-
- if (!target) {
- LOG_ERROR("ETB: target '%s' not defined", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETB: '%s' isn't an ARM", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- tap = jtag_tap_by_string(CMD_ARGV[1]);
- if (tap == NULL) {
- command_print(CMD_CTX, "ETB: TAP %s does not exist", CMD_ARGV[1]);
- return ERROR_FAIL;
- }
-
- if (arm->etm) {
- struct etb *etb = malloc(sizeof(struct etb));
-
- arm->etm->capture_driver_priv = etb;
-
- etb->tap = tap;
- etb->cur_scan_chain = 0xffffffff;
- etb->reg_cache = NULL;
- etb->ram_width = 0;
- etb->ram_depth = 0;
- } else {
- LOG_ERROR("ETM: target has no ETM defined, ETB left unconfigured");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etb_trigger_percent_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm;
- struct etb *etb;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETB: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm = arm->etm;
- if (!etm) {
- command_print(CMD_CTX, "ETB: target has no ETM configured");
- return ERROR_FAIL;
- }
- if (etm->capture_driver != &etb_capture_driver) {
- command_print(CMD_CTX, "ETB: target not using ETB");
- return ERROR_FAIL;
- }
- etb = arm->etm->capture_driver_priv;
-
- if (CMD_ARGC > 0) {
- uint32_t new_value;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], new_value);
- if ((new_value < 2) || (new_value > 100))
- command_print(CMD_CTX,
- "valid percentages are 2%% to 100%%");
- else
- etb->trigger_percent = (unsigned) new_value;
- }
-
- command_print(CMD_CTX, "%d percent of tracebuffer fills after trigger",
- etb->trigger_percent);
-
- return ERROR_OK;
-}
-
-static const struct command_registration etb_config_command_handlers[] = {
- {
- /* NOTE: with ADIv5, ETBs are accessed using DAP operations,
- * possibly over SWD, not through separate TAPs...
- */
- .name = "config",
- .handler = handle_etb_config_command,
- .mode = COMMAND_CONFIG,
- .help = "Associate ETB with target and JTAG TAP.",
- .usage = "target tap",
- },
- {
- .name = "trigger_percent",
- .handler = handle_etb_trigger_percent_command,
- .mode = COMMAND_EXEC,
- .help = "Set percent of trace buffer to be filled "
- "after the trigger occurs (2..100).",
- .usage = "[percent]",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration etb_command_handlers[] = {
- {
- .name = "etb",
- .mode = COMMAND_ANY,
- .help = "Embedded Trace Buffer command group",
- .chain = etb_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int etb_init(struct etm_context *etm_ctx)
-{
- struct etb *etb = etm_ctx->capture_driver_priv;
-
- etb->etm_ctx = etm_ctx;
-
- /* identify ETB RAM depth and width */
- etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_DEPTH]);
- etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WIDTH]);
- jtag_execute_queue();
-
- etb->ram_depth = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_DEPTH].value, 0, 32);
- etb->ram_width = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32);
-
- etb->trigger_percent = 50;
-
- return ERROR_OK;
-}
-
-static trace_status_t etb_status(struct etm_context *etm_ctx)
-{
- struct etb *etb = etm_ctx->capture_driver_priv;
- struct reg *control = &etb->reg_cache->reg_list[ETB_CTRL];
- struct reg *status = &etb->reg_cache->reg_list[ETB_STATUS];
- trace_status_t retval = 0;
- int etb_timeout = 100;
-
- etb->etm_ctx = etm_ctx;
-
- /* read control and status registers */
- etb_read_reg(control);
- etb_read_reg(status);
- jtag_execute_queue();
-
- /* See if it's (still) active */
- retval = buf_get_u32(control->value, 0, 1) ? TRACE_RUNNING : TRACE_IDLE;
-
- /* check Full bit to identify wraparound/overflow */
- if (buf_get_u32(status->value, 0, 1) == 1)
- retval |= TRACE_OVERFLOWED;
-
- /* check Triggered bit to identify trigger condition */
- if (buf_get_u32(status->value, 1, 1) == 1)
- retval |= TRACE_TRIGGERED;
-
- /* check AcqComp to see if trigger counter dropped to zero */
- if (buf_get_u32(status->value, 2, 1) == 1) {
- /* wait for DFEmpty */
- while (etb_timeout-- && buf_get_u32(status->value, 3, 1) == 0)
- etb_get_reg(status);
-
- if (etb_timeout == 0)
- LOG_ERROR("ETB: DFEmpty won't go high, status 0x%02x",
- (unsigned) buf_get_u32(status->value, 0, 4));
-
- if (!(etm_ctx->capture_status & TRACE_TRIGGERED))
- LOG_WARNING("ETB: trace complete without triggering?");
-
- retval |= TRACE_COMPLETED;
- }
-
- /* NOTE: using a trigger is optional; and at least ETB11 has a mode
- * where it can ignore the trigger counter.
- */
-
- /* update recorded state */
- etm_ctx->capture_status = retval;
-
- return retval;
-}
-
-static int etb_read_trace(struct etm_context *etm_ctx)
-{
- struct etb *etb = etm_ctx->capture_driver_priv;
- int first_frame = 0;
- int num_frames = etb->ram_depth;
- uint32_t *trace_data = NULL;
- int i, j;
-
- etb_read_reg(&etb->reg_cache->reg_list[ETB_STATUS]);
- etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER]);
- jtag_execute_queue();
-
- /* check if we overflowed, and adjust first frame of the trace accordingly
- * if we didn't overflow, read only up to the frame that would be written next,
- * i.e. don't read invalid entries
- */
- if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1))
- first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value,
- 0,
- 32);
- else
- num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value,
- 0,
- 32);
-
- etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);
-
- /* read data into temporary array for unpacking */
- trace_data = malloc(sizeof(uint32_t) * num_frames);
- etb_read_ram(etb, trace_data, num_frames);
-
- if (etm_ctx->trace_depth > 0)
- free(etm_ctx->trace_data);
-
- if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
- etm_ctx->trace_depth = num_frames * 3;
- else if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
- etm_ctx->trace_depth = num_frames * 2;
- else
- etm_ctx->trace_depth = num_frames;
-
- etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
-
- for (i = 0, j = 0; i < num_frames; i++) {
- if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT) {
- /* trace word j */
- etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
- etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3;
- etm_ctx->trace_data[j].flags = 0;
- if ((trace_data[i] & 0x80) >> 7)
- etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
- if (etm_ctx->trace_data[j].pipestat == STAT_TR) {
- etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet &
- 0x7;
- etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
- }
-
- /* trace word j + 1 */
- etm_ctx->trace_data[j + 1].pipestat = (trace_data[i] & 0x100) >> 8;
- etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7800) >> 11;
- etm_ctx->trace_data[j + 1].flags = 0;
- if ((trace_data[i] & 0x8000) >> 15)
- etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE;
- if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR) {
- etm_ctx->trace_data[j +
- 1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7;
- etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE;
- }
-
- /* trace word j + 2 */
- etm_ctx->trace_data[j + 2].pipestat = (trace_data[i] & 0x10000) >> 16;
- etm_ctx->trace_data[j + 2].packet = (trace_data[i] & 0x780000) >> 19;
- etm_ctx->trace_data[j + 2].flags = 0;
- if ((trace_data[i] & 0x800000) >> 23)
- etm_ctx->trace_data[j + 2].flags |= ETMV1_TRACESYNC_CYCLE;
- if (etm_ctx->trace_data[j + 2].pipestat == STAT_TR) {
- etm_ctx->trace_data[j +
- 2].pipestat = etm_ctx->trace_data[j + 2].packet & 0x7;
- etm_ctx->trace_data[j + 2].flags |= ETMV1_TRIGGER_CYCLE;
- }
-
- j += 3;
- } else if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) {
- /* trace word j */
- etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
- etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
- etm_ctx->trace_data[j].flags = 0;
- if ((trace_data[i] & 0x800) >> 11)
- etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
- if (etm_ctx->trace_data[j].pipestat == STAT_TR) {
- etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet &
- 0x7;
- etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
- }
-
- /* trace word j + 1 */
- etm_ctx->trace_data[j + 1].pipestat = (trace_data[i] & 0x7000) >> 12;
- etm_ctx->trace_data[j + 1].packet = (trace_data[i] & 0x7f8000) >> 15;
- etm_ctx->trace_data[j + 1].flags = 0;
- if ((trace_data[i] & 0x800000) >> 23)
- etm_ctx->trace_data[j + 1].flags |= ETMV1_TRACESYNC_CYCLE;
- if (etm_ctx->trace_data[j + 1].pipestat == STAT_TR) {
- etm_ctx->trace_data[j +
- 1].pipestat = etm_ctx->trace_data[j + 1].packet & 0x7;
- etm_ctx->trace_data[j + 1].flags |= ETMV1_TRIGGER_CYCLE;
- }
-
- j += 2;
- } else {
- /* trace word j */
- etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
- etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
- etm_ctx->trace_data[j].flags = 0;
- if ((trace_data[i] & 0x80000) >> 19)
- etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
- if (etm_ctx->trace_data[j].pipestat == STAT_TR) {
- etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet &
- 0x7;
- etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
- }
-
- j += 1;
- }
- }
-
- free(trace_data);
-
- return ERROR_OK;
-}
-
-static int etb_start_capture(struct etm_context *etm_ctx)
-{
- struct etb *etb = etm_ctx->capture_driver_priv;
- uint32_t etb_ctrl_value = 0x1;
- uint32_t trigger_count;
-
- if ((etm_ctx->control & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED) {
- if ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT) {
- LOG_ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port");
- return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
- }
- etb_ctrl_value |= 0x2;
- }
-
- if ((etm_ctx->control & ETM_PORT_MODE_MASK) == ETM_PORT_MUXED) {
- LOG_ERROR("ETB: can't run in multiplexed mode");
- return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
- }
-
- trigger_count = (etb->ram_depth * etb->trigger_percent) / 100;
-
- etb_write_reg(&etb->reg_cache->reg_list[ETB_TRIGGER_COUNTER], trigger_count);
- etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER], 0x0);
- etb_write_reg(&etb->reg_cache->reg_list[ETB_CTRL], etb_ctrl_value);
- jtag_execute_queue();
-
- /* we're starting a new trace, initialize capture status */
- etm_ctx->capture_status = TRACE_RUNNING;
-
- return ERROR_OK;
-}
-
-static int etb_stop_capture(struct etm_context *etm_ctx)
-{
- struct etb *etb = etm_ctx->capture_driver_priv;
- struct reg *etb_ctrl_reg = &etb->reg_cache->reg_list[ETB_CTRL];
-
- etb_write_reg(etb_ctrl_reg, 0x0);
- jtag_execute_queue();
-
- /* trace stopped, just clear running flag, but preserve others */
- etm_ctx->capture_status &= ~TRACE_RUNNING;
-
- return ERROR_OK;
-}
-
-struct etm_capture_driver etb_capture_driver = {
- .name = "etb",
- .commands = etb_command_handlers,
- .init = etb_init,
- .status = etb_status,
- .start_capture = etb_start_capture,
- .stop_capture = etb_stop_capture,
- .read_trace = etb_read_trace,
-};
diff --git a/src/target/etb.h b/src/target/etb.h
deleted file mode 100644
index 680c8a1..0000000
--- a/src/target/etb.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ETB_H
-#define OPENOCD_TARGET_ETB_H
-
-/* ETB registers */
-enum {
- ETB_ID = 0x00,
- ETB_RAM_DEPTH = 0x01,
- ETB_RAM_WIDTH = 0x02,
- ETB_STATUS = 0x03,
- ETB_RAM_DATA = 0x04,
- ETB_RAM_READ_POINTER = 0x05,
- ETB_RAM_WRITE_POINTER = 0x06,
- ETB_TRIGGER_COUNTER = 0x07,
- ETB_CTRL = 0x08,
-};
-
-struct etb {
- struct etm_context *etm_ctx;
- struct jtag_tap *tap;
- uint32_t cur_scan_chain;
- struct reg_cache *reg_cache;
-
- /* ETB parameters */
- uint32_t ram_depth;
- uint32_t ram_width;
-
- /** how much trace buffer to fill after trigger */
- unsigned trigger_percent;
-};
-
-struct etb_reg {
- uint32_t addr;
- struct etb *etb;
-};
-
-extern struct etm_capture_driver etb_capture_driver;
-
-struct reg_cache *etb_build_reg_cache(struct etb *etb);
-
-#endif /* OPENOCD_TARGET_ETB_H */
diff --git a/src/target/etm.c b/src/target/etm.c
deleted file mode 100644
index 6a00c23..0000000
--- a/src/target/etm.c
+++ /dev/null
@@ -1,2115 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "etm.h"
-#include "etb.h"
-#include "image.h"
-#include "arm_disassembler.h"
-#include "register.h"
-#include "etm_dummy.h"
-
-#if BUILD_OOCD_TRACE == 1
-#include "oocd_trace.h"
-#endif
-
-
-/*
- * ARM "Embedded Trace Macrocell" (ETM) support -- direct JTAG access.
- *
- * ETM modules collect instruction and/or data trace information, compress
- * it, and transfer it to a debugging host through either a (buffered) trace
- * port (often a 38-pin Mictor connector) or an Embedded Trace Buffer (ETB).
- *
- * There are several generations of these modules. Original versions have
- * JTAG access through a dedicated scan chain. Recent versions have added
- * access via coprocessor instructions, memory addressing, and the ARM Debug
- * Interface v5 (ADIv5); and phased out direct JTAG access.
- *
- * This code supports up to the ETMv1.3 architecture, as seen in ETM9 and
- * most common ARM9 systems. Note: "CoreSight ETM9" implements ETMv3.2,
- * implying non-JTAG connectivity options.
- *
- * Relevant documentation includes:
- * ARM DDI 0157G ... ETM9 (r2p2) Technical Reference Manual
- * ARM DDI 0315B ... CoreSight ETM9 (r0p1) Technical Reference Manual
- * ARM IHI 0014O ... Embedded Trace Macrocell, Architecture Specification
- */
-
-enum {
- RO, /* read/only */
- WO, /* write/only */
- RW, /* read/write */
-};
-
-struct etm_reg_info {
- uint8_t addr;
- uint8_t size; /* low-N of 32 bits */
- uint8_t mode; /* RO, WO, RW */
- uint8_t bcd_vers; /* 1.0, 2.0, etc */
- const char *name;
-};
-
-/*
- * Registers 0..0x7f are JTAG-addressable using scanchain 6.
- * (Or on some processors, through coprocessor operations.)
- * Newer versions of ETM make some W/O registers R/W, and
- * provide definitions for some previously-unused bits.
- */
-
-/* core registers used to version/configure the ETM */
-static const struct etm_reg_info etm_core[] = {
- /* NOTE: we "know" the order here ... */
- { ETM_CONFIG, 32, RO, 0x10, "ETM_config", },
- { ETM_ID, 32, RO, 0x20, "ETM_id", },
-};
-
-/* basic registers that are always there given the right ETM version */
-static const struct etm_reg_info etm_basic[] = {
- /* ETM Trace Registers */
- { ETM_CTRL, 32, RW, 0x10, "ETM_ctrl", },
- { ETM_TRIG_EVENT, 17, WO, 0x10, "ETM_trig_event", },
- { ETM_ASIC_CTRL, 8, WO, 0x10, "ETM_asic_ctrl", },
- { ETM_STATUS, 3, RO, 0x11, "ETM_status", },
- { ETM_SYS_CONFIG, 9, RO, 0x12, "ETM_sys_config", },
-
- /* TraceEnable configuration */
- { ETM_TRACE_RESOURCE_CTRL, 32, WO, 0x12, "ETM_trace_resource_ctrl", },
- { ETM_TRACE_EN_CTRL2, 16, WO, 0x12, "ETM_trace_en_ctrl2", },
- { ETM_TRACE_EN_EVENT, 17, WO, 0x10, "ETM_trace_en_event", },
- { ETM_TRACE_EN_CTRL1, 26, WO, 0x10, "ETM_trace_en_ctrl1", },
-
- /* ViewData configuration (data trace) */
- { ETM_VIEWDATA_EVENT, 17, WO, 0x10, "ETM_viewdata_event", },
- { ETM_VIEWDATA_CTRL1, 32, WO, 0x10, "ETM_viewdata_ctrl1", },
- { ETM_VIEWDATA_CTRL2, 32, WO, 0x10, "ETM_viewdata_ctrl2", },
- { ETM_VIEWDATA_CTRL3, 17, WO, 0x10, "ETM_viewdata_ctrl3", },
-
- /* REVISIT exclude VIEWDATA_CTRL2 when it's not there */
-
- { 0x78, 12, WO, 0x20, "ETM_sync_freq", },
- { 0x7a, 22, RO, 0x31, "ETM_config_code_ext", },
- { 0x7b, 32, WO, 0x31, "ETM_ext_input_select", },
- { 0x7c, 32, WO, 0x34, "ETM_trace_start_stop", },
- { 0x7d, 8, WO, 0x34, "ETM_behavior_control", },
-};
-
-static const struct etm_reg_info etm_fifofull[] = {
- /* FIFOFULL configuration */
- { ETM_FIFOFULL_REGION, 25, WO, 0x10, "ETM_fifofull_region", },
- { ETM_FIFOFULL_LEVEL, 8, WO, 0x10, "ETM_fifofull_level", },
-};
-
-static const struct etm_reg_info etm_addr_comp[] = {
- /* Address comparator register pairs */
-#define ADDR_COMPARATOR(i) \
- { ETM_ADDR_COMPARATOR_VALUE + (i) - 1, 32, WO, 0x10, \
- "ETM_addr_" #i "_comparator_value", }, \
- { ETM_ADDR_ACCESS_TYPE + (i) - 1, 7, WO, 0x10, \
- "ETM_addr_" #i "_access_type", }
- ADDR_COMPARATOR(1),
- ADDR_COMPARATOR(2),
- ADDR_COMPARATOR(3),
- ADDR_COMPARATOR(4),
- ADDR_COMPARATOR(5),
- ADDR_COMPARATOR(6),
- ADDR_COMPARATOR(7),
- ADDR_COMPARATOR(8),
-
- ADDR_COMPARATOR(9),
- ADDR_COMPARATOR(10),
- ADDR_COMPARATOR(11),
- ADDR_COMPARATOR(12),
- ADDR_COMPARATOR(13),
- ADDR_COMPARATOR(14),
- ADDR_COMPARATOR(15),
- ADDR_COMPARATOR(16),
- { 0, 0, 0, 0, NULL }
-#undef ADDR_COMPARATOR
-};
-
-static const struct etm_reg_info etm_data_comp[] = {
- /* Data Value Comparators (NOTE: odd addresses are reserved) */
-#define DATA_COMPARATOR(i) \
- { ETM_DATA_COMPARATOR_VALUE + 2*(i) - 1, 32, WO, 0x10, \
- "ETM_data_" #i "_comparator_value", }, \
- { ETM_DATA_COMPARATOR_MASK + 2*(i) - 1, 32, WO, 0x10, \
- "ETM_data_" #i "_comparator_mask", }
- DATA_COMPARATOR(1),
- DATA_COMPARATOR(2),
- DATA_COMPARATOR(3),
- DATA_COMPARATOR(4),
- DATA_COMPARATOR(5),
- DATA_COMPARATOR(6),
- DATA_COMPARATOR(7),
- DATA_COMPARATOR(8),
- { 0, 0, 0, 0, NULL }
-#undef DATA_COMPARATOR
-};
-
-static const struct etm_reg_info etm_counters[] = {
-#define ETM_COUNTER(i) \
- { ETM_COUNTER_RELOAD_VALUE + (i) - 1, 16, WO, 0x10, \
- "ETM_counter_" #i "_reload_value", }, \
- { ETM_COUNTER_ENABLE + (i) - 1, 18, WO, 0x10, \
- "ETM_counter_" #i "_enable", }, \
- { ETM_COUNTER_RELOAD_EVENT + (i) - 1, 17, WO, 0x10, \
- "ETM_counter_" #i "_reload_event", }, \
- { ETM_COUNTER_VALUE + (i) - 1, 16, RO, 0x10, \
- "ETM_counter_" #i "_value", }
- ETM_COUNTER(1),
- ETM_COUNTER(2),
- ETM_COUNTER(3),
- ETM_COUNTER(4),
- { 0, 0, 0, 0, NULL }
-#undef ETM_COUNTER
-};
-
-static const struct etm_reg_info etm_sequencer[] = {
-#define ETM_SEQ(i) \
- { ETM_SEQUENCER_EVENT + (i), 17, WO, 0x10, \
- "ETM_sequencer_event" #i, }
- ETM_SEQ(0), /* 1->2 */
- ETM_SEQ(1), /* 2->1 */
- ETM_SEQ(2), /* 2->3 */
- ETM_SEQ(3), /* 3->1 */
- ETM_SEQ(4), /* 3->2 */
- ETM_SEQ(5), /* 1->3 */
-#undef ETM_SEQ
- /* 0x66 reserved */
- { ETM_SEQUENCER_STATE, 2, RO, 0x10, "ETM_sequencer_state", },
-};
-
-static const struct etm_reg_info etm_outputs[] = {
-#define ETM_OUTPUT(i) \
- { ETM_EXTERNAL_OUTPUT + (i) - 1, 17, WO, 0x10, \
- "ETM_external_output" #i, }
-
- ETM_OUTPUT(1),
- ETM_OUTPUT(2),
- ETM_OUTPUT(3),
- ETM_OUTPUT(4),
- { 0, 0, 0, 0, NULL }
-#undef ETM_OUTPUT
-};
-
-#if 0
- /* registers from 0x6c..0x7f were added after ETMv1.3 */
-
- /* Context ID Comparators */
- { 0x6c, 32, RO, 0x20, "ETM_contextid_comparator_value1", }
- { 0x6d, 32, RO, 0x20, "ETM_contextid_comparator_value2", }
- { 0x6e, 32, RO, 0x20, "ETM_contextid_comparator_value3", }
- { 0x6f, 32, RO, 0x20, "ETM_contextid_comparator_mask", }
-#endif
-
-static int etm_get_reg(struct reg *reg);
-static int etm_read_reg_w_check(struct reg *reg,
- uint8_t *check_value, uint8_t *check_mask);
-static int etm_register_user_commands(struct command_context *cmd_ctx);
-static int etm_set_reg_w_exec(struct reg *reg, uint8_t *buf);
-static int etm_write_reg(struct reg *reg, uint32_t value);
-
-static const struct reg_arch_type etm_scan6_type = {
- .get = etm_get_reg,
- .set = etm_set_reg_w_exec,
-};
-
-/* Look up register by ID ... most ETM instances only
- * support a subset of the possible registers.
- */
-static struct reg *etm_reg_lookup(struct etm_context *etm_ctx, unsigned id)
-{
- struct reg_cache *cache = etm_ctx->reg_cache;
- unsigned i;
-
- for (i = 0; i < cache->num_regs; i++) {
- struct etm_reg *reg = cache->reg_list[i].arch_info;
-
- if (reg->reg_info->addr == id)
- return &cache->reg_list[i];
- }
-
- /* caller asking for nonexistent register is a bug!
- * REVISIT say which of the N targets was involved */
- LOG_ERROR("ETM: register 0x%02x not available", id);
- return NULL;
-}
-
-static void etm_reg_add(unsigned bcd_vers, struct arm_jtag *jtag_info,
- struct reg_cache *cache, struct etm_reg *ereg,
- const struct etm_reg_info *r, unsigned nreg)
-{
- struct reg *reg = cache->reg_list;
-
- reg += cache->num_regs;
- ereg += cache->num_regs;
-
- /* add up to "nreg" registers from "r", if supported by this
- * version of the ETM, to the specified cache.
- */
- for (; nreg--; r++) {
- /* No more registers to add */
- if (!r->size) {
- LOG_ERROR("etm_reg_add is requested to add non-existing registers, ETM config might be bogus");
- return;
- }
-
- /* this ETM may be too old to have some registers */
- if (r->bcd_vers > bcd_vers)
- continue;
-
- reg->name = r->name;
- reg->size = r->size;
- reg->value = &ereg->value;
- reg->arch_info = ereg;
- reg->type = &etm_scan6_type;
- reg++;
- cache->num_regs++;
-
- ereg->reg_info = r;
- ereg->jtag_info = jtag_info;
- ereg++;
- }
-}
-
-struct reg_cache *etm_build_reg_cache(struct target *target,
- struct arm_jtag *jtag_info, struct etm_context *etm_ctx)
-{
- struct reg_cache *reg_cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = NULL;
- struct etm_reg *arch_info = NULL;
- unsigned bcd_vers, config;
-
- /* the actual registers are kept in two arrays */
- reg_list = calloc(128, sizeof(struct reg));
- arch_info = calloc(128, sizeof(struct etm_reg));
-
- /* fill in values for the reg cache */
- reg_cache->name = "etm registers";
- reg_cache->next = NULL;
- reg_cache->reg_list = reg_list;
- reg_cache->num_regs = 0;
-
- /* add ETM_CONFIG, then parse its values to see
- * which other registers exist in this ETM
- */
- etm_reg_add(0x10, jtag_info, reg_cache, arch_info,
- etm_core, 1);
-
- etm_get_reg(reg_list);
- etm_ctx->config = buf_get_u32(arch_info->value, 0, 32);
- config = etm_ctx->config;
-
- /* figure ETM version then add base registers */
- if (config & (1 << 31)) {
- LOG_WARNING("ETMv2+ support is incomplete");
-
- /* REVISIT more registers may exist; they may now be
- * readable; more register bits have defined meanings;
- * don't presume trace start/stop support is present;
- * and include any context ID comparator registers.
- */
- etm_reg_add(0x20, jtag_info, reg_cache, arch_info,
- etm_core + 1, 1);
- etm_get_reg(reg_list + 1);
- etm_ctx->id = buf_get_u32(
- arch_info[1].value, 0, 32);
- LOG_DEBUG("ETM ID: %08x", (unsigned) etm_ctx->id);
- bcd_vers = 0x10 + (((etm_ctx->id) >> 4) & 0xff);
-
- } else {
- switch (config >> 28) {
- case 7:
- case 5:
- case 3:
- bcd_vers = 0x13;
- break;
- case 4:
- case 2:
- bcd_vers = 0x12;
- break;
- case 1:
- bcd_vers = 0x11;
- break;
- case 0:
- bcd_vers = 0x10;
- break;
- default:
- LOG_WARNING("Bad ETMv1 protocol %d", config >> 28);
- goto fail;
- }
- }
- etm_ctx->bcd_vers = bcd_vers;
- LOG_INFO("ETM v%d.%d", bcd_vers >> 4, bcd_vers & 0xf);
-
- etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info,
- etm_basic, ARRAY_SIZE(etm_basic));
-
- /* address and data comparators; counters; outputs */
- etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info,
- etm_addr_comp, 4 * (0x0f & (config >> 0)));
- etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info,
- etm_data_comp, 2 * (0x0f & (config >> 4)));
- etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info,
- etm_counters, 4 * (0x07 & (config >> 13)));
- etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info,
- etm_outputs, (0x07 & (config >> 20)));
-
- /* FIFOFULL presence is optional
- * REVISIT for ETMv1.2 and later, don't bother adding this
- * unless ETM_SYS_CONFIG says it's also *supported* ...
- */
- if (config & (1 << 23))
- etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info,
- etm_fifofull, ARRAY_SIZE(etm_fifofull));
-
- /* sequencer is optional (for state-dependant triggering) */
- if (config & (1 << 16))
- etm_reg_add(bcd_vers, jtag_info, reg_cache, arch_info,
- etm_sequencer, ARRAY_SIZE(etm_sequencer));
-
- /* REVISIT could realloc and likely save half the memory
- * in the two chunks we allocated...
- */
-
- /* the ETM might have an ETB connected */
- if (strcmp(etm_ctx->capture_driver->name, "etb") == 0) {
- struct etb *etb = etm_ctx->capture_driver_priv;
-
- if (!etb) {
- LOG_ERROR("etb selected as etm capture driver, but no ETB configured");
- goto fail;
- }
-
- reg_cache->next = etb_build_reg_cache(etb);
-
- etb->reg_cache = reg_cache->next;
- }
-
- etm_ctx->reg_cache = reg_cache;
- return reg_cache;
-
-fail:
- free(reg_cache);
- free(reg_list);
- free(arch_info);
- return NULL;
-}
-
-static int etm_read_reg(struct reg *reg)
-{
- return etm_read_reg_w_check(reg, NULL, NULL);
-}
-
-static int etm_store_reg(struct reg *reg)
-{
- return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
-}
-
-int etm_setup(struct target *target)
-{
- int retval;
- uint32_t etm_ctrl_value;
- struct arm *arm = target_to_arm(target);
- struct etm_context *etm_ctx = arm->etm;
- struct reg *etm_ctrl_reg;
-
- etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
- if (!etm_ctrl_reg)
- return ERROR_OK;
-
- /* initialize some ETM control register settings */
- etm_get_reg(etm_ctrl_reg);
- etm_ctrl_value = buf_get_u32(etm_ctrl_reg->value, 0, 32);
-
- /* clear the ETM powerdown bit (0) */
- etm_ctrl_value &= ~ETM_CTRL_POWERDOWN;
-
- /* configure port width (21,6:4), mode (13,17:16) and
- * for older modules clocking (13)
- */
- etm_ctrl_value = (etm_ctrl_value
- & ~ETM_PORT_WIDTH_MASK
- & ~ETM_PORT_MODE_MASK
- & ~ETM_CTRL_DBGRQ
- & ~ETM_PORT_CLOCK_MASK)
- | etm_ctx->control;
-
- buf_set_u32(etm_ctrl_reg->value, 0, 32, etm_ctrl_value);
- etm_store_reg(etm_ctrl_reg);
-
- etm_ctx->control = etm_ctrl_value;
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* REVISIT for ETMv3.0 and later, read ETM_sys_config to
- * verify that those width and mode settings are OK ...
- */
-
- retval = etm_ctx->capture_driver->init(etm_ctx);
- if (retval != ERROR_OK) {
- LOG_ERROR("ETM capture driver initialization failed");
- return retval;
- }
- return ERROR_OK;
-}
-
-static int etm_get_reg(struct reg *reg)
-{
- int retval;
-
- retval = etm_read_reg(reg);
- if (retval != ERROR_OK) {
- LOG_ERROR("BUG: error scheduling etm register read");
- return retval;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("register read failed");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int etm_read_reg_w_check(struct reg *reg,
- uint8_t *check_value, uint8_t *check_mask)
-{
- struct etm_reg *etm_reg = reg->arch_info;
- const struct etm_reg_info *r = etm_reg->reg_info;
- uint8_t reg_addr = r->addr & 0x7f;
- struct scan_field fields[3];
- int retval;
-
- if (etm_reg->reg_info->mode == WO) {
- LOG_ERROR("BUG: can't read write-only register %s", r->name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- LOG_DEBUG("%s (%u)", r->name, reg_addr);
-
- retval = arm_jtag_scann(etm_reg->jtag_info, 0x6, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(etm_reg->jtag_info->tap,
- etm_reg->jtag_info->intest_instr,
- NULL,
- TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = reg->value;
- fields[0].in_value = NULL;
- fields[0].check_value = NULL;
- fields[0].check_mask = NULL;
-
- fields[1].num_bits = 7;
- uint8_t temp1;
- fields[1].out_value = &temp1;
- buf_set_u32(&temp1, 0, 7, reg_addr);
- fields[1].in_value = NULL;
- fields[1].check_value = NULL;
- fields[1].check_mask = NULL;
-
- fields[2].num_bits = 1;
- uint8_t temp2;
- fields[2].out_value = &temp2;
- buf_set_u32(&temp2, 0, 1, 0);
- fields[2].in_value = NULL;
- fields[2].check_value = NULL;
- fields[2].check_mask = NULL;
-
- jtag_add_dr_scan(etm_reg->jtag_info->tap, 3, fields, TAP_IDLE);
-
- fields[0].in_value = reg->value;
- fields[0].check_value = check_value;
- fields[0].check_mask = check_mask;
-
- jtag_add_dr_scan_check(etm_reg->jtag_info->tap, 3, fields, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-static int etm_set_reg(struct reg *reg, uint32_t value)
-{
- int retval = etm_write_reg(reg, value);
- if (retval != ERROR_OK) {
- LOG_ERROR("BUG: error scheduling etm register write");
- return retval;
- }
-
- buf_set_u32(reg->value, 0, reg->size, value);
- reg->valid = 1;
- reg->dirty = 0;
-
- return ERROR_OK;
-}
-
-static int etm_set_reg_w_exec(struct reg *reg, uint8_t *buf)
-{
- int retval;
-
- etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("register write failed");
- return retval;
- }
- return ERROR_OK;
-}
-
-static int etm_write_reg(struct reg *reg, uint32_t value)
-{
- struct etm_reg *etm_reg = reg->arch_info;
- const struct etm_reg_info *r = etm_reg->reg_info;
- uint8_t reg_addr = r->addr & 0x7f;
- struct scan_field fields[3];
- int retval;
-
- if (etm_reg->reg_info->mode == RO) {
- LOG_ERROR("BUG: can't write read--only register %s", r->name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- LOG_DEBUG("%s (%u): 0x%8.8" PRIx32 "", r->name, reg_addr, value);
-
- retval = arm_jtag_scann(etm_reg->jtag_info, 0x6, TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
- retval = arm_jtag_set_instr(etm_reg->jtag_info->tap,
- etm_reg->jtag_info->intest_instr,
- NULL,
- TAP_IDLE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- uint8_t tmp1[4];
- fields[0].out_value = tmp1;
- buf_set_u32(tmp1, 0, 32, value);
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 7;
- uint8_t tmp2;
- fields[1].out_value = &tmp2;
- buf_set_u32(&tmp2, 0, 7, reg_addr);
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 1;
- uint8_t tmp3;
- fields[2].out_value = &tmp3;
- buf_set_u32(&tmp3, 0, 1, 1);
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(etm_reg->jtag_info->tap, 3, fields, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-
-/* ETM trace analysis functionality */
-
-static struct etm_capture_driver *etm_capture_drivers[] = {
- &etb_capture_driver,
- &etm_dummy_capture_driver,
-#if BUILD_OOCD_TRACE == 1
- &oocd_trace_capture_driver,
-#endif
- NULL
-};
-
-static int etm_read_instruction(struct etm_context *ctx, struct arm_instruction *instruction)
-{
- int i;
- int section = -1;
- size_t size_read;
- uint32_t opcode;
- int retval;
-
- if (!ctx->image)
- return ERROR_TRACE_IMAGE_UNAVAILABLE;
-
- /* search for the section the current instruction belongs to */
- for (i = 0; i < ctx->image->num_sections; i++) {
- if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&
- (ctx->image->sections[i].base_address + ctx->image->sections[i].size >
- ctx->current_pc)) {
- section = i;
- break;
- }
- }
-
- if (section == -1) {
- /* current instruction couldn't be found in the image */
- return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
- }
-
- if (ctx->core_state == ARM_STATE_ARM) {
- uint8_t buf[4];
- retval = image_read_section(ctx->image, section,
- ctx->current_pc -
- ctx->image->sections[section].base_address,
- 4, buf, &size_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("error while reading instruction");
- return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
- }
- opcode = target_buffer_get_u32(ctx->target, buf);
- arm_evaluate_opcode(opcode, ctx->current_pc, instruction);
- } else if (ctx->core_state == ARM_STATE_THUMB) {
- uint8_t buf[2];
- retval = image_read_section(ctx->image, section,
- ctx->current_pc -
- ctx->image->sections[section].base_address,
- 2, buf, &size_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("error while reading instruction");
- return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
- }
- opcode = target_buffer_get_u16(ctx->target, buf);
- thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);
- } else if (ctx->core_state == ARM_STATE_JAZELLE) {
- LOG_ERROR("BUG: tracing of jazelle code not supported");
- return ERROR_FAIL;
- } else {
- LOG_ERROR("BUG: unknown core state encountered");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int etmv1_next_packet(struct etm_context *ctx, uint8_t *packet, int apo)
-{
- while (ctx->data_index < ctx->trace_depth) {
- /* if the caller specified an address packet offset, skip until the
- * we reach the n-th cycle marked with tracesync */
- if (apo > 0) {
- if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)
- apo--;
-
- if (apo > 0) {
- ctx->data_index++;
- ctx->data_half = 0;
- }
- continue;
- }
-
- /* no tracedata output during a TD cycle
- * or in a trigger cycle */
- if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)
- || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE)) {
- ctx->data_index++;
- ctx->data_half = 0;
- continue;
- }
-
- /* FIXME there are more port widths than these... */
- if ((ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT) {
- if (ctx->data_half == 0) {
- *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
- ctx->data_half = 1;
- } else {
- *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;
- ctx->data_half = 0;
- ctx->data_index++;
- }
- } else if ((ctx->control & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT) {
- *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
- ctx->data_index++;
- } else {
- /* on a 4-bit port, a packet will be output during two consecutive cycles */
- if (ctx->data_index > (ctx->trace_depth - 2))
- return -1;
-
- *packet = ctx->trace_data[ctx->data_index].packet & 0xf;
- *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;
- ctx->data_index += 2;
- }
-
- return 0;
- }
-
- return -1;
-}
-
-static int etmv1_branch_address(struct etm_context *ctx)
-{
- int retval;
- uint8_t packet;
- int shift = 0;
- int apo;
- uint32_t i;
-
- /* quit analysis if less than two cycles are left in the trace
- * because we can't extract the APO */
- if (ctx->data_index > (ctx->trace_depth - 2))
- return -1;
-
- /* a BE could be output during an APO cycle, skip the current
- * and continue with the new one */
- if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)
- return 1;
- if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)
- return 2;
-
- /* address packet offset encoded in the next two cycles' pipestat bits */
- apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;
- apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;
-
- /* count number of tracesync cycles between current pipe_index and data_index
- * i.e. the number of tracesyncs that data_index already passed by
- * to subtract them from the APO */
- for (i = ctx->pipe_index; i < ctx->data_index; i++) {
- if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)
- apo--;
- }
-
- /* extract up to four 7-bit packets */
- do {
- retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0);
- if (retval != 0)
- return -1;
- ctx->last_branch &= ~(0x7f << shift);
- ctx->last_branch |= (packet & 0x7f) << shift;
- shift += 7;
- } while ((packet & 0x80) && (shift < 28));
-
- /* one last packet holding 4 bits of the address, plus the branch reason code */
- if ((shift == 28) && (packet & 0x80)) {
- retval = etmv1_next_packet(ctx, &packet, 0);
- if (retval != 0)
- return -1;
- ctx->last_branch &= 0x0fffffff;
- ctx->last_branch |= (packet & 0x0f) << 28;
- ctx->last_branch_reason = (packet & 0x70) >> 4;
- shift += 4;
- } else
- ctx->last_branch_reason = 0;
-
- if (shift == 32)
- ctx->pc_ok = 1;
-
- /* if a full address was output, we might have branched into Jazelle state */
- if ((shift == 32) && (packet & 0x80))
- ctx->core_state = ARM_STATE_JAZELLE;
- else {
- /* if we didn't branch into Jazelle state, the current processor state is
- * encoded in bit 0 of the branch target address */
- if (ctx->last_branch & 0x1) {
- ctx->core_state = ARM_STATE_THUMB;
- ctx->last_branch &= ~0x1;
- } else {
- ctx->core_state = ARM_STATE_ARM;
- ctx->last_branch &= ~0x3;
- }
- }
-
- return 0;
-}
-
-static int etmv1_data(struct etm_context *ctx, int size, uint32_t *data)
-{
- int j;
- uint8_t buf[4];
- int retval;
-
- for (j = 0; j < size; j++) {
- retval = etmv1_next_packet(ctx, &buf[j], 0);
- if (retval != 0)
- return -1;
- }
-
- if (size == 8) {
- LOG_ERROR("TODO: add support for 64-bit values");
- return -1;
- } else if (size == 4)
- *data = target_buffer_get_u32(ctx->target, buf);
- else if (size == 2)
- *data = target_buffer_get_u16(ctx->target, buf);
- else if (size == 1)
- *data = buf[0];
- else
- return -1;
-
- return 0;
-}
-
-static int etmv1_analyze_trace(struct etm_context *ctx, struct command_context *cmd_ctx)
-{
- int retval;
- struct arm_instruction instruction;
-
- /* read the trace data if it wasn't read already */
- if (ctx->trace_depth == 0)
- ctx->capture_driver->read_trace(ctx);
-
- if (ctx->trace_depth == 0) {
- command_print(cmd_ctx, "Trace is empty.");
- return ERROR_OK;
- }
-
- /* start at the beginning of the captured trace */
- ctx->pipe_index = 0;
- ctx->data_index = 0;
- ctx->data_half = 0;
-
- /* neither the PC nor the data pointer are valid */
- ctx->pc_ok = 0;
- ctx->ptr_ok = 0;
-
- while (ctx->pipe_index < ctx->trace_depth) {
- uint8_t pipestat = ctx->trace_data[ctx->pipe_index].pipestat;
- uint32_t next_pc = ctx->current_pc;
- uint32_t old_data_index = ctx->data_index;
- uint32_t old_data_half = ctx->data_half;
- uint32_t old_index = ctx->pipe_index;
- uint32_t last_instruction = ctx->last_instruction;
- uint32_t cycles = 0;
- int current_pc_ok = ctx->pc_ok;
-
- if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)
- command_print(cmd_ctx, "--- trigger ---");
-
- /* instructions execute in IE/D or BE/D cycles */
- if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
- ctx->last_instruction = ctx->pipe_index;
-
- /* if we don't have a valid pc skip until we reach an indirect branch */
- if ((!ctx->pc_ok) && (pipestat != STAT_BE)) {
- ctx->pipe_index++;
- continue;
- }
-
- /* any indirect branch could have interrupted instruction flow
- * - the branch reason code could indicate a trace discontinuity
- * - a branch to the exception vectors indicates an exception
- */
- if ((pipestat == STAT_BE) || (pipestat == STAT_BD)) {
- /* backup current data index, to be able to consume the branch address
- * before examining data address and values
- */
- old_data_index = ctx->data_index;
- old_data_half = ctx->data_half;
-
- ctx->last_instruction = ctx->pipe_index;
-
- retval = etmv1_branch_address(ctx);
- if (retval != 0) {
- /* negative return value from etmv1_branch_address means we ran out of packets,
- * quit analysing the trace */
- if (retval < 0)
- break;
-
- /* a positive return values means the current branch was abandoned,
- * and a new branch was encountered in cycle ctx->pipe_index + retval;
- */
- LOG_WARNING(
- "abandoned branch encountered, correctness of analysis uncertain");
- ctx->pipe_index += retval;
- continue;
- }
-
- /* skip over APO cycles */
- ctx->pipe_index += 2;
-
- switch (ctx->last_branch_reason) {
- case 0x0: /* normal PC change */
- next_pc = ctx->last_branch;
- break;
- case 0x1: /* tracing enabled */
- command_print(cmd_ctx,
- "--- tracing enabled at 0x%8.8" PRIx32 " ---",
- ctx->last_branch);
- ctx->current_pc = ctx->last_branch;
- ctx->pipe_index++;
- continue;
- break;
- case 0x2: /* trace restarted after FIFO overflow */
- command_print(cmd_ctx,
- "--- trace restarted after FIFO overflow at 0x%8.8" PRIx32 " ---",
- ctx->last_branch);
- ctx->current_pc = ctx->last_branch;
- ctx->pipe_index++;
- continue;
- break;
- case 0x3: /* exit from debug state */
- command_print(cmd_ctx,
- "--- exit from debug state at 0x%8.8" PRIx32 " ---",
- ctx->last_branch);
- ctx->current_pc = ctx->last_branch;
- ctx->pipe_index++;
- continue;
- break;
- case 0x4: /* periodic synchronization point */
- next_pc = ctx->last_branch;
- /* if we had no valid PC prior to this synchronization point,
- * we have to move on with the next trace cycle
- */
- if (!current_pc_ok) {
- command_print(cmd_ctx,
- "--- periodic synchronization point at 0x%8.8" PRIx32 " ---",
- next_pc);
- ctx->current_pc = next_pc;
- ctx->pipe_index++;
- continue;
- }
- break;
- default: /* reserved */
- LOG_ERROR(
- "BUG: branch reason code 0x%" PRIx32 " is reserved",
- ctx->last_branch_reason);
- return ERROR_FAIL;
- }
-
- /* if we got here the branch was a normal PC change
- * (or a periodic synchronization point, which means the same for that matter)
- * if we didn't acquire a complete PC continue with the next cycle
- */
- if (!ctx->pc_ok)
- continue;
-
- /* indirect branch to the exception vector means an exception occurred */
- if ((ctx->last_branch <= 0x20)
- || ((ctx->last_branch >= 0xffff0000) &&
- (ctx->last_branch <= 0xffff0020))) {
- if ((ctx->last_branch & 0xff) == 0x10)
- command_print(cmd_ctx, "data abort");
- else {
- command_print(cmd_ctx,
- "exception vector 0x%2.2" PRIx32 "",
- ctx->last_branch);
- ctx->current_pc = ctx->last_branch;
- ctx->pipe_index++;
- continue;
- }
- }
- }
-
- /* an instruction was executed (or not, depending on the condition flags)
- * retrieve it from the image for displaying */
- if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&
- !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&
- ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4)))) {
- retval = etm_read_instruction(ctx, &instruction);
- if (retval != ERROR_OK) {
- /* can't continue tracing with no image available */
- if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
- return retval;
- else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE) {
- /* TODO: handle incomplete images
- * for now we just quit the analysis*/
- return retval;
- }
- }
-
- cycles = old_index - last_instruction;
- }
-
- if ((pipestat == STAT_ID) || (pipestat == STAT_BD)) {
- uint32_t new_data_index = ctx->data_index;
- uint32_t new_data_half = ctx->data_half;
-
- /* in case of a branch with data, the branch target address was consumed before
- * we temporarily go back to the saved data index */
- if (pipestat == STAT_BD) {
- ctx->data_index = old_data_index;
- ctx->data_half = old_data_half;
- }
-
- if (ctx->control & ETM_CTRL_TRACE_ADDR) {
- uint8_t packet;
- int shift = 0;
-
- do {
- retval = etmv1_next_packet(ctx, &packet, 0);
- if (retval != 0)
- return ERROR_ETM_ANALYSIS_FAILED;
- ctx->last_ptr &= ~(0x7f << shift);
- ctx->last_ptr |= (packet & 0x7f) << shift;
- shift += 7;
- } while ((packet & 0x80) && (shift < 32));
-
- if (shift >= 32)
- ctx->ptr_ok = 1;
-
- if (ctx->ptr_ok)
- command_print(cmd_ctx,
- "address: 0x%8.8" PRIx32 "",
- ctx->last_ptr);
- }
-
- if (ctx->control & ETM_CTRL_TRACE_DATA) {
- if ((instruction.type == ARM_LDM) ||
- (instruction.type == ARM_STM)) {
- int i;
- for (i = 0; i < 16; i++) {
- if (instruction.info.load_store_multiple.
- register_list & (1 << i)) {
- uint32_t data;
- if (etmv1_data(ctx, 4, &data) != 0)
- return ERROR_ETM_ANALYSIS_FAILED;
- command_print(cmd_ctx,
- "data: 0x%8.8" PRIx32 "",
- data);
- }
- }
- } else if ((instruction.type >= ARM_LDR) &&
- (instruction.type <= ARM_STRH)) {
- uint32_t data;
- if (etmv1_data(ctx, arm_access_size(&instruction),
- &data) != 0)
- return ERROR_ETM_ANALYSIS_FAILED;
- command_print(cmd_ctx, "data: 0x%8.8" PRIx32 "", data);
- }
- }
-
- /* restore data index after consuming BD address and data */
- if (pipestat == STAT_BD) {
- ctx->data_index = new_data_index;
- ctx->data_half = new_data_half;
- }
- }
-
- /* adjust PC */
- if ((pipestat == STAT_IE) || (pipestat == STAT_ID)) {
- if (((instruction.type == ARM_B) ||
- (instruction.type == ARM_BL) ||
- (instruction.type == ARM_BLX)) &&
- (instruction.info.b_bl_bx_blx.target_address != 0xffffffff))
- next_pc = instruction.info.b_bl_bx_blx.target_address;
- else
- next_pc += (ctx->core_state == ARM_STATE_ARM) ? 4 : 2;
- } else if (pipestat == STAT_IN)
- next_pc += (ctx->core_state == ARM_STATE_ARM) ? 4 : 2;
-
- if ((pipestat != STAT_TD) && (pipestat != STAT_WT)) {
- char cycles_text[32] = "";
-
- /* if the trace was captured with cycle accurate tracing enabled,
- * output the number of cycles since the last executed instruction
- */
- if (ctx->control & ETM_CTRL_CYCLE_ACCURATE) {
- snprintf(cycles_text, 32, " (%i %s)",
- (int)cycles,
- (cycles == 1) ? "cycle" : "cycles");
- }
-
- command_print(cmd_ctx, "%s%s%s",
- instruction.text,
- (pipestat == STAT_IN) ? " (not executed)" : "",
- cycles_text);
-
- ctx->current_pc = next_pc;
-
- /* packets for an instruction don't start on or before the preceding
- * functional pipestat (i.e. other than WT or TD)
- */
- if (ctx->data_index <= ctx->pipe_index) {
- ctx->data_index = ctx->pipe_index + 1;
- ctx->data_half = 0;
- }
- }
-
- ctx->pipe_index += 1;
- }
-
- return ERROR_OK;
-}
-
-static COMMAND_HELPER(handle_etm_tracemode_command_update,
- uint32_t *mode)
-{
- uint32_t tracemode;
-
- /* what parts of data access are traced? */
- if (strcmp(CMD_ARGV[0], "none") == 0)
- tracemode = 0;
- else if (strcmp(CMD_ARGV[0], "data") == 0)
- tracemode = ETM_CTRL_TRACE_DATA;
- else if (strcmp(CMD_ARGV[0], "address") == 0)
- tracemode = ETM_CTRL_TRACE_ADDR;
- else if (strcmp(CMD_ARGV[0], "all") == 0)
- tracemode = ETM_CTRL_TRACE_DATA | ETM_CTRL_TRACE_ADDR;
- else {
- command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- uint8_t context_id;
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], context_id);
- switch (context_id) {
- case 0:
- tracemode |= ETM_CTRL_CONTEXTID_NONE;
- break;
- case 8:
- tracemode |= ETM_CTRL_CONTEXTID_8;
- break;
- case 16:
- tracemode |= ETM_CTRL_CONTEXTID_16;
- break;
- case 32:
- tracemode |= ETM_CTRL_CONTEXTID_32;
- break;
- default:
- command_print(CMD_CTX, "invalid option '%s'", CMD_ARGV[1]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- bool etmv1_cycle_accurate;
- COMMAND_PARSE_ENABLE(CMD_ARGV[2], etmv1_cycle_accurate);
- if (etmv1_cycle_accurate)
- tracemode |= ETM_CTRL_CYCLE_ACCURATE;
-
- bool etmv1_branch_output;
- COMMAND_PARSE_ENABLE(CMD_ARGV[3], etmv1_branch_output);
- if (etmv1_branch_output)
- tracemode |= ETM_CTRL_BRANCH_OUTPUT;
-
- /* IGNORED:
- * - CPRT tracing (coprocessor register transfers)
- * - debug request (causes debug entry on trigger)
- * - stall on FIFOFULL (preventing tracedata loss)
- */
- *mode = tracemode;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_tracemode_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct etm_context *etm;
-
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm = arm->etm;
- if (!etm) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- uint32_t tracemode = etm->control;
-
- switch (CMD_ARGC) {
- case 0:
- break;
- case 4:
- CALL_COMMAND_HANDLER(handle_etm_tracemode_command_update,
- &tracemode);
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- /**
- * todo: fail if parameters were invalid for this hardware,
- * or couldn't be written; display actual hardware state...
- */
-
- command_print(CMD_CTX, "current tracemode configuration:");
-
- switch (tracemode & ETM_CTRL_TRACE_MASK) {
- default:
- command_print(CMD_CTX, "data tracing: none");
- break;
- case ETM_CTRL_TRACE_DATA:
- command_print(CMD_CTX, "data tracing: data only");
- break;
- case ETM_CTRL_TRACE_ADDR:
- command_print(CMD_CTX, "data tracing: address only");
- break;
- case ETM_CTRL_TRACE_DATA | ETM_CTRL_TRACE_ADDR:
- command_print(CMD_CTX, "data tracing: address and data");
- break;
- }
-
- switch (tracemode & ETM_CTRL_CONTEXTID_MASK) {
- case ETM_CTRL_CONTEXTID_NONE:
- command_print(CMD_CTX, "contextid tracing: none");
- break;
- case ETM_CTRL_CONTEXTID_8:
- command_print(CMD_CTX, "contextid tracing: 8 bit");
- break;
- case ETM_CTRL_CONTEXTID_16:
- command_print(CMD_CTX, "contextid tracing: 16 bit");
- break;
- case ETM_CTRL_CONTEXTID_32:
- command_print(CMD_CTX, "contextid tracing: 32 bit");
- break;
- }
-
- if (tracemode & ETM_CTRL_CYCLE_ACCURATE)
- command_print(CMD_CTX, "cycle-accurate tracing enabled");
- else
- command_print(CMD_CTX, "cycle-accurate tracing disabled");
-
- if (tracemode & ETM_CTRL_BRANCH_OUTPUT)
- command_print(CMD_CTX, "full branch address output enabled");
- else
- command_print(CMD_CTX, "full branch address output disabled");
-
-#define TRACEMODE_MASK ( \
- ETM_CTRL_CONTEXTID_MASK \
- | ETM_CTRL_BRANCH_OUTPUT \
- | ETM_CTRL_CYCLE_ACCURATE \
- | ETM_CTRL_TRACE_MASK \
- )
-
- /* only update ETM_CTRL register if tracemode changed */
- if ((etm->control & TRACEMODE_MASK) != tracemode) {
- struct reg *etm_ctrl_reg;
-
- etm_ctrl_reg = etm_reg_lookup(etm, ETM_CTRL);
- if (!etm_ctrl_reg)
- return ERROR_FAIL;
-
- etm->control &= ~TRACEMODE_MASK;
- etm->control |= tracemode & TRACEMODE_MASK;
-
- buf_set_u32(etm_ctrl_reg->value, 0, 32, etm->control);
- etm_store_reg(etm_ctrl_reg);
-
- /* invalidate old trace data */
- etm->capture_status = TRACE_IDLE;
- if (etm->trace_depth > 0) {
- free(etm->trace_data);
- etm->trace_data = NULL;
- }
- etm->trace_depth = 0;
- }
-
-#undef TRACEMODE_MASK
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_config_command)
-{
- struct target *target;
- struct arm *arm;
- uint32_t portmode = 0x0;
- struct etm_context *etm_ctx;
- int i;
-
- if (CMD_ARGC != 5)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_target(CMD_ARGV[0]);
- if (!target) {
- LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "target '%s' is '%s'; not an ARM",
- target_name(target),
- target_type_name(target));
- return ERROR_FAIL;
- }
-
- /* FIXME for ETMv3.0 and above -- and we don't yet know what ETM
- * version we'll be using!! -- so we can't know how to validate
- * params yet. "etm config" should likely be *AFTER* hookup...
- *
- * - Many more widths might be supported ... and we can easily
- * check whether our setting "took".
- *
- * - The "clock" and "mode" bits are interpreted differently.
- * See ARM IHI 0014O table 2-17 for the old behaviour, and
- * table 2-18 for the new. With ETB it's best to specify
- * "normal full" ...
- */
- uint8_t port_width;
- COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], port_width);
- switch (port_width) {
- /* before ETMv3.0 */
- case 4:
- portmode |= ETM_PORT_4BIT;
- break;
- case 8:
- portmode |= ETM_PORT_8BIT;
- break;
- case 16:
- portmode |= ETM_PORT_16BIT;
- break;
- /* ETMv3.0 and later*/
- case 24:
- portmode |= ETM_PORT_24BIT;
- break;
- case 32:
- portmode |= ETM_PORT_32BIT;
- break;
- case 48:
- portmode |= ETM_PORT_48BIT;
- break;
- case 64:
- portmode |= ETM_PORT_64BIT;
- break;
- case 1:
- portmode |= ETM_PORT_1BIT;
- break;
- case 2:
- portmode |= ETM_PORT_2BIT;
- break;
- default:
- command_print(CMD_CTX,
- "unsupported ETM port width '%s'", CMD_ARGV[1]);
- return ERROR_FAIL;
- }
-
- if (strcmp("normal", CMD_ARGV[2]) == 0)
- portmode |= ETM_PORT_NORMAL;
- else if (strcmp("multiplexed", CMD_ARGV[2]) == 0)
- portmode |= ETM_PORT_MUXED;
- else if (strcmp("demultiplexed", CMD_ARGV[2]) == 0)
- portmode |= ETM_PORT_DEMUXED;
- else {
- command_print(CMD_CTX,
- "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'",
- CMD_ARGV[2]);
- return ERROR_FAIL;
- }
-
- if (strcmp("half", CMD_ARGV[3]) == 0)
- portmode |= ETM_PORT_HALF_CLOCK;
- else if (strcmp("full", CMD_ARGV[3]) == 0)
- portmode |= ETM_PORT_FULL_CLOCK;
- else {
- command_print(CMD_CTX,
- "unsupported ETM port clocking '%s', must be 'full' or 'half'",
- CMD_ARGV[3]);
- return ERROR_FAIL;
- }
-
- etm_ctx = calloc(1, sizeof(struct etm_context));
- if (!etm_ctx) {
- LOG_DEBUG("out of memory");
- return ERROR_FAIL;
- }
-
- for (i = 0; etm_capture_drivers[i]; i++) {
- if (strcmp(CMD_ARGV[4], etm_capture_drivers[i]->name) == 0) {
- int retval = register_commands(CMD_CTX, NULL,
- etm_capture_drivers[i]->commands);
- if (ERROR_OK != retval) {
- free(etm_ctx);
- return retval;
- }
-
- etm_ctx->capture_driver = etm_capture_drivers[i];
-
- break;
- }
- }
-
- if (!etm_capture_drivers[i]) {
- /* no supported capture driver found, don't register an ETM */
- free(etm_ctx);
- LOG_ERROR("trace capture driver '%s' not found", CMD_ARGV[4]);
- return ERROR_FAIL;
- }
-
- etm_ctx->target = target;
- etm_ctx->trace_data = NULL;
- etm_ctx->control = portmode;
- etm_ctx->core_state = ARM_STATE_ARM;
-
- arm->etm = etm_ctx;
-
- return etm_register_user_commands(CMD_CTX);
-}
-
-COMMAND_HANDLER(handle_etm_info_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm;
- struct reg *etm_sys_config_reg;
- int max_port_size;
- uint32_t config;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm = arm->etm;
- if (!etm) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- command_print(CMD_CTX, "ETM v%d.%d",
- etm->bcd_vers >> 4, etm->bcd_vers & 0xf);
- command_print(CMD_CTX, "pairs of address comparators: %i",
- (int) (etm->config >> 0) & 0x0f);
- command_print(CMD_CTX, "data comparators: %i",
- (int) (etm->config >> 4) & 0x0f);
- command_print(CMD_CTX, "memory map decoders: %i",
- (int) (etm->config >> 8) & 0x1f);
- command_print(CMD_CTX, "number of counters: %i",
- (int) (etm->config >> 13) & 0x07);
- command_print(CMD_CTX, "sequencer %spresent",
- (int) (etm->config & (1 << 16)) ? "" : "not ");
- command_print(CMD_CTX, "number of ext. inputs: %i",
- (int) (etm->config >> 17) & 0x07);
- command_print(CMD_CTX, "number of ext. outputs: %i",
- (int) (etm->config >> 20) & 0x07);
- command_print(CMD_CTX, "FIFO full %spresent",
- (int) (etm->config & (1 << 23)) ? "" : "not ");
- if (etm->bcd_vers < 0x20)
- command_print(CMD_CTX, "protocol version: %i",
- (int) (etm->config >> 28) & 0x07);
- else {
- command_print(CMD_CTX,
- "coprocessor and memory access %ssupported",
- (etm->config & (1 << 26)) ? "" : "not ");
- command_print(CMD_CTX, "trace start/stop %spresent",
- (etm->config & (1 << 26)) ? "" : "not ");
- command_print(CMD_CTX, "number of context comparators: %i",
- (int) (etm->config >> 24) & 0x03);
- }
-
- /* SYS_CONFIG isn't present before ETMv1.2 */
- etm_sys_config_reg = etm_reg_lookup(etm, ETM_SYS_CONFIG);
- if (!etm_sys_config_reg)
- return ERROR_OK;
-
- etm_get_reg(etm_sys_config_reg);
- config = buf_get_u32(etm_sys_config_reg->value, 0, 32);
-
- LOG_DEBUG("ETM SYS CONFIG %08x", (unsigned) config);
-
- max_port_size = config & 0x7;
- if (etm->bcd_vers >= 0x30)
- max_port_size |= (config >> 6) & 0x08;
- switch (max_port_size) {
- /* before ETMv3.0 */
- case 0:
- max_port_size = 4;
- break;
- case 1:
- max_port_size = 8;
- break;
- case 2:
- max_port_size = 16;
- break;
- /* ETMv3.0 and later*/
- case 3:
- max_port_size = 24;
- break;
- case 4:
- max_port_size = 32;
- break;
- case 5:
- max_port_size = 48;
- break;
- case 6:
- max_port_size = 64;
- break;
- case 8:
- max_port_size = 1;
- break;
- case 9:
- max_port_size = 2;
- break;
- default:
- LOG_ERROR("Illegal max_port_size");
- return ERROR_FAIL;
- }
- command_print(CMD_CTX, "max. port size: %i", max_port_size);
-
- if (etm->bcd_vers < 0x30) {
- command_print(CMD_CTX, "half-rate clocking %ssupported",
- (config & (1 << 3)) ? "" : "not ");
- command_print(CMD_CTX, "full-rate clocking %ssupported",
- (config & (1 << 4)) ? "" : "not ");
- command_print(CMD_CTX, "normal trace format %ssupported",
- (config & (1 << 5)) ? "" : "not ");
- command_print(CMD_CTX, "multiplex trace format %ssupported",
- (config & (1 << 6)) ? "" : "not ");
- command_print(CMD_CTX, "demultiplex trace format %ssupported",
- (config & (1 << 7)) ? "" : "not ");
- } else {
- /* REVISIT show which size and format are selected ... */
- command_print(CMD_CTX, "current port size %ssupported",
- (config & (1 << 10)) ? "" : "not ");
- command_print(CMD_CTX, "current trace format %ssupported",
- (config & (1 << 11)) ? "" : "not ");
- }
- if (etm->bcd_vers >= 0x21)
- command_print(CMD_CTX, "fetch comparisons %ssupported",
- (config & (1 << 17)) ? "not " : "");
- command_print(CMD_CTX, "FIFO full %ssupported",
- (config & (1 << 8)) ? "" : "not ");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_status_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm;
- trace_status_t trace_status;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm = arm->etm;
- if (!etm) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- /* ETM status */
- if (etm->bcd_vers >= 0x11) {
- struct reg *reg;
-
- reg = etm_reg_lookup(etm, ETM_STATUS);
- if (!reg)
- return ERROR_FAIL;
- if (etm_get_reg(reg) == ERROR_OK) {
- unsigned s = buf_get_u32(reg->value, 0, reg->size);
-
- command_print(CMD_CTX, "etm: %s%s%s%s",
- /* bit(1) == progbit */
- (etm->bcd_vers >= 0x12)
- ? ((s & (1 << 1))
- ? "disabled" : "enabled")
- : "?",
- ((s & (1 << 3)) && etm->bcd_vers >= 0x31)
- ? " triggered" : "",
- ((s & (1 << 2)) && etm->bcd_vers >= 0x12)
- ? " start/stop" : "",
- ((s & (1 << 0)) && etm->bcd_vers >= 0x11)
- ? " untraced-overflow" : "");
- } /* else ignore and try showing trace port status */
- }
-
- /* Trace Port Driver status */
- trace_status = etm->capture_driver->status(etm);
- if (trace_status == TRACE_IDLE)
- command_print(CMD_CTX, "%s: idle", etm->capture_driver->name);
- else {
- static char *completed = " completed";
- static char *running = " is running";
- static char *overflowed = ", overflowed";
- static char *triggered = ", triggered";
-
- command_print(CMD_CTX, "%s: trace collection%s%s%s",
- etm->capture_driver->name,
- (trace_status & TRACE_RUNNING) ? running : completed,
- (trace_status & TRACE_OVERFLOWED) ? overflowed : "",
- (trace_status & TRACE_TRIGGERED) ? triggered : "");
-
- if (etm->trace_depth > 0) {
- command_print(CMD_CTX, "%i frames of trace data read",
- (int)(etm->trace_depth));
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_image_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm_ctx;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm_ctx = arm->etm;
- if (!etm_ctx) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- if (etm_ctx->image) {
- image_close(etm_ctx->image);
- free(etm_ctx->image);
- command_print(CMD_CTX, "previously loaded image found and closed");
- }
-
- etm_ctx->image = malloc(sizeof(struct image));
- etm_ctx->image->base_address_set = 0;
- etm_ctx->image->start_address_set = 0;
-
- /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
- if (CMD_ARGC >= 2) {
- etm_ctx->image->base_address_set = 1;
- COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], etm_ctx->image->base_address);
- } else
- etm_ctx->image->base_address_set = 0;
-
- if (image_open(etm_ctx->image, CMD_ARGV[0],
- (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) {
- free(etm_ctx->image);
- etm_ctx->image = NULL;
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_dump_command)
-{
- struct fileio *file;
- struct target *target;
- struct arm *arm;
- struct etm_context *etm_ctx;
- uint32_t i;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm_ctx = arm->etm;
- if (!etm_ctx) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- if (etm_ctx->capture_driver->status == TRACE_IDLE) {
- command_print(CMD_CTX, "trace capture wasn't enabled, no trace data captured");
- return ERROR_OK;
- }
-
- if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING) {
- /* TODO: if on-the-fly capture is to be supported, this needs to be changed */
- command_print(CMD_CTX, "trace capture not completed");
- return ERROR_FAIL;
- }
-
- /* read the trace data if it wasn't read already */
- if (etm_ctx->trace_depth == 0)
- etm_ctx->capture_driver->read_trace(etm_ctx);
-
- if (fileio_open(&file, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
- return ERROR_FAIL;
-
- fileio_write_u32(file, etm_ctx->capture_status);
- fileio_write_u32(file, etm_ctx->control);
- fileio_write_u32(file, etm_ctx->trace_depth);
-
- for (i = 0; i < etm_ctx->trace_depth; i++) {
- fileio_write_u32(file, etm_ctx->trace_data[i].pipestat);
- fileio_write_u32(file, etm_ctx->trace_data[i].packet);
- fileio_write_u32(file, etm_ctx->trace_data[i].flags);
- }
-
- fileio_close(file);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_load_command)
-{
- struct fileio *file;
- struct target *target;
- struct arm *arm;
- struct etm_context *etm_ctx;
- uint32_t i;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm_ctx = arm->etm;
- if (!etm_ctx) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING) {
- command_print(CMD_CTX, "trace capture running, stop first");
- return ERROR_FAIL;
- }
-
- if (fileio_open(&file, CMD_ARGV[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
- return ERROR_FAIL;
-
- size_t filesize;
- int retval = fileio_size(file, &filesize);
- if (retval != ERROR_OK) {
- fileio_close(file);
- return retval;
- }
-
- if (filesize % 4) {
- command_print(CMD_CTX, "size isn't a multiple of 4, no valid trace data");
- fileio_close(file);
- return ERROR_FAIL;
- }
-
- if (etm_ctx->trace_depth > 0) {
- free(etm_ctx->trace_data);
- etm_ctx->trace_data = NULL;
- }
-
- {
- uint32_t tmp;
- fileio_read_u32(file, &tmp); etm_ctx->capture_status = tmp;
- fileio_read_u32(file, &tmp); etm_ctx->control = tmp;
- fileio_read_u32(file, &etm_ctx->trace_depth);
- }
- etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
- if (etm_ctx->trace_data == NULL) {
- command_print(CMD_CTX, "not enough memory to perform operation");
- fileio_close(file);
- return ERROR_FAIL;
- }
-
- for (i = 0; i < etm_ctx->trace_depth; i++) {
- uint32_t pipestat, packet, flags;
- fileio_read_u32(file, &pipestat);
- fileio_read_u32(file, &packet);
- fileio_read_u32(file, &flags);
- etm_ctx->trace_data[i].pipestat = pipestat & 0xff;
- etm_ctx->trace_data[i].packet = packet & 0xffff;
- etm_ctx->trace_data[i].flags = flags;
- }
-
- fileio_close(file);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_start_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm_ctx;
- struct reg *etm_ctrl_reg;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm_ctx = arm->etm;
- if (!etm_ctx) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- /* invalidate old tracing data */
- etm_ctx->capture_status = TRACE_IDLE;
- if (etm_ctx->trace_depth > 0) {
- free(etm_ctx->trace_data);
- etm_ctx->trace_data = NULL;
- }
- etm_ctx->trace_depth = 0;
-
- etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
- if (!etm_ctrl_reg)
- return ERROR_FAIL;
-
- etm_get_reg(etm_ctrl_reg);
-
- /* Clear programming bit (10), set port selection bit (11) */
- buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);
-
- etm_store_reg(etm_ctrl_reg);
- jtag_execute_queue();
-
- etm_ctx->capture_driver->start_capture(etm_ctx);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_stop_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm_ctx;
- struct reg *etm_ctrl_reg;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm_ctx = arm->etm;
- if (!etm_ctx) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- etm_ctrl_reg = etm_reg_lookup(etm_ctx, ETM_CTRL);
- if (!etm_ctrl_reg)
- return ERROR_FAIL;
-
- etm_get_reg(etm_ctrl_reg);
-
- /* Set programming bit (10), clear port selection bit (11) */
- buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);
-
- etm_store_reg(etm_ctrl_reg);
- jtag_execute_queue();
-
- etm_ctx->capture_driver->stop_capture(etm_ctx);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_trigger_debug_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: %s isn't an ARM",
- target_name(target));
- return ERROR_FAIL;
- }
-
- etm = arm->etm;
- if (!etm) {
- command_print(CMD_CTX, "ETM: no ETM configured for %s",
- target_name(target));
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC == 1) {
- struct reg *etm_ctrl_reg;
- bool dbgrq;
-
- etm_ctrl_reg = etm_reg_lookup(etm, ETM_CTRL);
- if (!etm_ctrl_reg)
- return ERROR_FAIL;
-
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], dbgrq);
- if (dbgrq)
- etm->control |= ETM_CTRL_DBGRQ;
- else
- etm->control &= ~ETM_CTRL_DBGRQ;
-
- /* etm->control will be written to hardware
- * the next time an "etm start" is issued.
- */
- buf_set_u32(etm_ctrl_reg->value, 0, 32, etm->control);
- }
-
- command_print(CMD_CTX, "ETM: %s debug halt",
- (etm->control & ETM_CTRL_DBGRQ)
- ? "triggers"
- : "does not trigger");
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_etm_analyze_command)
-{
- struct target *target;
- struct arm *arm;
- struct etm_context *etm_ctx;
- int retval;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "ETM: current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- etm_ctx = arm->etm;
- if (!etm_ctx) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- retval = etmv1_analyze_trace(etm_ctx, CMD_CTX);
- if (retval != ERROR_OK) {
- /* FIX! error should be reported inside etmv1_analyze_trace() */
- switch (retval) {
- case ERROR_ETM_ANALYSIS_FAILED:
- command_print(CMD_CTX,
- "further analysis failed (corrupted trace data or just end of data");
- break;
- case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:
- command_print(CMD_CTX,
- "no instruction for current address available, analysis aborted");
- break;
- case ERROR_TRACE_IMAGE_UNAVAILABLE:
- command_print(CMD_CTX, "no image available for trace analysis");
- break;
- default:
- command_print(CMD_CTX, "unknown error");
- }
- }
-
- return retval;
-}
-
-static const struct command_registration etm_config_command_handlers[] = {
- {
- /* NOTE: with ADIv5, ETMs are accessed by DAP operations,
- * possibly over SWD, not JTAG scanchain 6 of 'target'.
- *
- * Also, these parameters don't match ETM v3+ modules...
- */
- .name = "config",
- .handler = handle_etm_config_command,
- .mode = COMMAND_CONFIG,
- .help = "Set up ETM output port.",
- .usage = "target port_width port_mode clocking capture_driver",
- },
- COMMAND_REGISTRATION_DONE
-};
-const struct command_registration etm_command_handlers[] = {
- {
- .name = "etm",
- .mode = COMMAND_ANY,
- .help = "Embedded Trace Macrocell command group",
- .usage = "",
- .chain = etm_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration etm_exec_command_handlers[] = {
- {
- .name = "tracemode",
- .handler = handle_etm_tracemode_command,
- .mode = COMMAND_EXEC,
- .help = "configure/display trace mode",
- .usage = "('none'|'data'|'address'|'all') "
- "context_id_bits "
- "['enable'|'disable'] "
- "['enable'|'disable']",
- },
- {
- .name = "info",
- .handler = handle_etm_info_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "display info about the current target's ETM",
- },
- {
- .name = "status",
- .handler = handle_etm_status_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "display current target's ETM status",
- },
- {
- .name = "start",
- .handler = handle_etm_start_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "start ETM trace collection",
- },
- {
- .name = "stop",
- .handler = handle_etm_stop_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "stop ETM trace collection",
- },
- {
- .name = "trigger_debug",
- .handler = handle_etm_trigger_debug_command,
- .mode = COMMAND_EXEC,
- .help = "enable/disable debug entry on trigger",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "analyze",
- .handler = handle_etm_analyze_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "analyze collected ETM trace",
- },
- {
- .name = "image",
- .handler = handle_etm_image_command,
- .mode = COMMAND_EXEC,
- .help = "load image from file with optional offset",
- .usage = "<file> [base address] [type]",
- },
- {
- .name = "dump",
- .handler = handle_etm_dump_command,
- .mode = COMMAND_EXEC,
- .help = "dump captured trace data to file",
- .usage = "filename",
- },
- {
- .name = "load",
- .handler = handle_etm_load_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "load trace data for analysis <file>",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int etm_register_user_commands(struct command_context *cmd_ctx)
-{
- struct command *etm_cmd = command_find_in_context(cmd_ctx, "etm");
- return register_commands(cmd_ctx, etm_cmd, etm_exec_command_handlers);
-}
diff --git a/src/target/etm.h b/src/target/etm.h
deleted file mode 100644
index 6a78b75..0000000
--- a/src/target/etm.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005, 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007 by Vincent Palatin *
- * vincent.palatin_openocd@m4x.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ETM_H
-#define OPENOCD_TARGET_ETM_H
-
-#include "trace.h"
-#include "arm_jtag.h"
-
-struct image;
-
-/* ETM registers (JTAG protocol) */
-enum {
- ETM_CTRL = 0x00,
- ETM_CONFIG = 0x01,
- ETM_TRIG_EVENT = 0x02,
- ETM_ASIC_CTRL = 0x03,
- ETM_STATUS = 0x04,
- ETM_SYS_CONFIG = 0x05,
- ETM_TRACE_RESOURCE_CTRL = 0x06,
- ETM_TRACE_EN_CTRL2 = 0x07,
- ETM_TRACE_EN_EVENT = 0x08,
- ETM_TRACE_EN_CTRL1 = 0x09,
- /* optional FIFOFULL */
- ETM_FIFOFULL_REGION = 0x0a,
- ETM_FIFOFULL_LEVEL = 0x0b,
- /* viewdata support */
- ETM_VIEWDATA_EVENT = 0x0c,
- ETM_VIEWDATA_CTRL1 = 0x0d,
- ETM_VIEWDATA_CTRL2 = 0x0e, /* optional */
- ETM_VIEWDATA_CTRL3 = 0x0f,
- /* N pairs of ADDR_{COMPARATOR,ACCESS} registers */
- ETM_ADDR_COMPARATOR_VALUE = 0x10,
- ETM_ADDR_ACCESS_TYPE = 0x20,
- /* N pairs of DATA_COMPARATOR_{VALUE,MASK} registers */
- ETM_DATA_COMPARATOR_VALUE = 0x30,
- ETM_DATA_COMPARATOR_MASK = 0x40,
- /* N quads of COUNTER_{RELOAD_{VALUE,EVENT},ENABLE,VALUE} registers */
- ETM_COUNTER_RELOAD_VALUE = 0x50,
- ETM_COUNTER_ENABLE = 0x54,
- ETM_COUNTER_RELOAD_EVENT = 0x58,
- ETM_COUNTER_VALUE = 0x5c,
- /* 6 sequencer event transitions */
- ETM_SEQUENCER_EVENT = 0x60,
- ETM_SEQUENCER_STATE = 0x67,
- /* N triggered outputs */
- ETM_EXTERNAL_OUTPUT = 0x68,
- /* N task contexts */
- ETM_CONTEXTID_COMPARATOR_VALUE = 0x6c,
- ETM_CONTEXTID_COMPARATOR_MASK = 0x6f,
- ETM_ID = 0x79,
-};
-
-struct etm_reg {
- uint8_t value[4];
- const struct etm_reg_info *reg_info;
- struct arm_jtag *jtag_info;
-};
-
-/* Subset of ETM_CTRL bit assignments. Many of these
- * control the configuration of trace output, which
- * hooks up either to ETB or to an external device.
- *
- * NOTE that these have evolved since the ~v1.3 defns ...
- */
-enum {
- ETM_CTRL_POWERDOWN = (1 << 0),
- ETM_CTRL_MONITOR_CPRT = (1 << 1),
-
- /* bits 3:2 == trace type */
- ETM_CTRL_TRACE_DATA = (1 << 2),
- ETM_CTRL_TRACE_ADDR = (2 << 2),
- ETM_CTRL_TRACE_MASK = (3 << 2),
-
- /* Port width (bits 21 and 6:4) */
- ETM_PORT_4BIT = 0x00,
- ETM_PORT_8BIT = 0x10,
- ETM_PORT_16BIT = 0x20,
- ETM_PORT_24BIT = 0x30,
- ETM_PORT_32BIT = 0x40,
- ETM_PORT_48BIT = 0x50,
- ETM_PORT_64BIT = 0x60,
- ETM_PORT_1BIT = 0x00 | (1 << 21),
- ETM_PORT_2BIT = 0x10 | (1 << 21),
- ETM_PORT_WIDTH_MASK = 0x70 | (1 << 21),
-
- ETM_CTRL_FIFOFULL_STALL = (1 << 7),
- ETM_CTRL_BRANCH_OUTPUT = (1 << 8),
- ETM_CTRL_DBGRQ = (1 << 9),
- ETM_CTRL_ETM_PROG = (1 << 10),
- ETM_CTRL_ETMEN = (1 << 11),
- ETM_CTRL_CYCLE_ACCURATE = (1 << 12),
-
- /* Clocking modes -- up to v2.1, bit 13 */
- ETM_PORT_FULL_CLOCK = (0 << 13),
- ETM_PORT_HALF_CLOCK = (1 << 13),
- ETM_PORT_CLOCK_MASK = (1 << 13),
-
- /* bits 15:14 == context ID size used in tracing */
- ETM_CTRL_CONTEXTID_NONE = (0 << 14),
- ETM_CTRL_CONTEXTID_8 = (1 << 14),
- ETM_CTRL_CONTEXTID_16 = (2 << 14),
- ETM_CTRL_CONTEXTID_32 = (3 << 14),
- ETM_CTRL_CONTEXTID_MASK = (3 << 14),
-
- /* Port modes -- bits 17:16, tied to clocking mode */
- ETM_PORT_NORMAL = (0 << 16),
- ETM_PORT_MUXED = (1 << 16),
- ETM_PORT_DEMUXED = (2 << 16),
- ETM_PORT_MODE_MASK = (3 << 16),
-
- /* bits 31:18 defined in v3.0 and later (e.g. ARM11+) */
-};
-
-/* forward-declare ETM context */
-struct etm_context;
-
-struct etm_capture_driver {
- const char *name;
- const struct command_registration *commands;
- int (*init)(struct etm_context *etm_ctx);
- trace_status_t (*status)(struct etm_context *etm_ctx);
- int (*read_trace)(struct etm_context *etm_ctx);
- int (*start_capture)(struct etm_context *etm_ctx);
- int (*stop_capture)(struct etm_context *etm_ctx);
-};
-
-enum {
- ETMV1_TRACESYNC_CYCLE = 0x1,
- ETMV1_TRIGGER_CYCLE = 0x2,
-};
-
-struct etmv1_trace_data {
- uint8_t pipestat; /* bits 0-2 pipeline status */
- uint16_t packet; /* packet data (4, 8 or 16 bit) */
- int flags; /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */
-};
-
-/* describe a trace context
- * if support for ETMv2 or ETMv3 is to be implemented,
- * this will have to be split into version independent elements
- * and a version specific part
- */
-struct etm_context {
- struct target *target; /* target this ETM is connected to */
- struct reg_cache *reg_cache; /* ETM register cache */
- struct etm_capture_driver *capture_driver; /* driver used to access ETM data */
- void *capture_driver_priv; /* capture driver private data */
- trace_status_t capture_status; /* current state of capture run */
- struct etmv1_trace_data *trace_data; /* trace data */
- uint32_t trace_depth; /* number of cycles to be analyzed, 0 if no data available */
- uint32_t control; /* shadow of ETM_CTRL */
- int /*arm_state*/ core_state; /* current core state */
- struct image *image; /* source for target opcodes */
- uint32_t pipe_index; /* current trace cycle */
- uint32_t data_index; /* cycle holding next data packet */
- bool data_half; /* port half on a 16 bit port */
- bool pc_ok; /* full PC has been acquired */
- bool ptr_ok; /* whether last_ptr is valid */
- uint8_t bcd_vers; /* e.g. 0x13 == ETMv1.3 */
- uint32_t config; /* cache of ETM_CONFIG value */
- uint32_t id; /* cache of ETM_ID value, or 0 */
- uint32_t current_pc; /* current program counter */
- uint32_t last_branch; /* last branch address output */
- uint32_t last_branch_reason; /* type of last branch encountered */
- uint32_t last_ptr; /* address of the last data access */
- uint32_t last_instruction; /* index of last executed (to calc timings) */
-};
-
-/* PIPESTAT values */
-typedef enum {
- STAT_IE = 0x0,
- STAT_ID = 0x1,
- STAT_IN = 0x2,
- STAT_WT = 0x3,
- STAT_BE = 0x4,
- STAT_BD = 0x5,
- STAT_TR = 0x6,
- STAT_TD = 0x7
-} etmv1_pipestat_t;
-
-/* branch reason values */
-typedef enum {
- BR_NORMAL = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */
- BR_ENABLE = 0x1, /* Trace has been enabled */
- BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */
- BR_NODEBUG = 0x3, /* ARM has exited for debug state */
- BR_PERIOD = 0x4, /* Peridioc synchronization point (ETM >= v1.2)*/
- BR_RSVD5 = 0x5, /* reserved */
- BR_RSVD6 = 0x6, /* reserved */
- BR_RSVD7 = 0x7, /* reserved */
-} etmv1_branch_reason_t;
-
-struct reg_cache *etm_build_reg_cache(struct target *target,
- struct arm_jtag *jtag_info, struct etm_context *etm_ctx);
-
-int etm_setup(struct target *target);
-
-extern const struct command_registration etm_command_handlers[];
-
-#define ERROR_ETM_INVALID_DRIVER (-1300)
-#define ERROR_ETM_PORTMODE_NOT_SUPPORTED (-1301)
-#define ERROR_ETM_CAPTURE_INIT_FAILED (-1302)
-#define ERROR_ETM_ANALYSIS_FAILED (-1303)
-
-#endif /* OPENOCD_TARGET_ETM_H */
diff --git a/src/target/etm_dummy.c b/src/target/etm_dummy.c
deleted file mode 100644
index b18ce17..0000000
--- a/src/target/etm_dummy.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "etm_dummy.h"
-
-COMMAND_HANDLER(handle_etm_dummy_config_command)
-{
- struct target *target;
- struct arm *arm;
-
- target = get_target(CMD_ARGV[0]);
-
- if (!target) {
- LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "target '%s' isn't an ARM", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- if (arm->etm)
- arm->etm->capture_driver_priv = NULL;
- else {
- LOG_ERROR("target has no ETM defined, ETM dummy left unconfigured");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration etm_dummy_config_command_handlers[] = {
- {
- .name = "config",
- .handler = handle_etm_dummy_config_command,
- .mode = COMMAND_CONFIG,
- .usage = "target",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration etm_dummy_command_handlers[] = {
- {
- .name = "etm_dummy",
- .mode = COMMAND_ANY,
- .help = "Dummy ETM capture driver command group",
- .chain = etm_dummy_config_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int etm_dummy_init(struct etm_context *etm_ctx)
-{
- return ERROR_OK;
-}
-
-static trace_status_t etm_dummy_status(struct etm_context *etm_ctx)
-{
- return TRACE_IDLE;
-}
-
-static int etm_dummy_read_trace(struct etm_context *etm_ctx)
-{
- return ERROR_OK;
-}
-
-static int etm_dummy_start_capture(struct etm_context *etm_ctx)
-{
- return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
-}
-
-static int etm_dummy_stop_capture(struct etm_context *etm_ctx)
-{
- return ERROR_OK;
-}
-
-struct etm_capture_driver etm_dummy_capture_driver = {
- .name = "dummy",
- .commands = etm_dummy_command_handlers,
- .init = etm_dummy_init,
- .status = etm_dummy_status,
- .start_capture = etm_dummy_start_capture,
- .stop_capture = etm_dummy_stop_capture,
- .read_trace = etm_dummy_read_trace,
-};
diff --git a/src/target/etm_dummy.h b/src/target/etm_dummy.h
deleted file mode 100644
index 5a1955f..0000000
--- a/src/target/etm_dummy.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_ETM_DUMMY_H
-#define OPENOCD_TARGET_ETM_DUMMY_H
-
-#include "etm.h"
-
-extern struct etm_capture_driver etm_dummy_capture_driver;
-
-#endif /* OPENOCD_TARGET_ETM_DUMMY_H */
diff --git a/src/target/fa526.c b/src/target/fa526.c
deleted file mode 100644
index 9f6b805..0000000
--- a/src/target/fa526.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 by Paulius Zaleckas *
- * paulius.zaleckas@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * FA526 is very similar to ARM920T with following differences:
- *
- * - execution pipeline is 6 steps
- * - Unified TLB
- * - has Branch Target Buffer
- * - does not support reading of I/D cache contents
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm920t.h"
-#include "target_type.h"
-#include "arm_opcodes.h"
-
-static void fa526_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc)
-{
- LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
-}
-
-static void fa526_read_core_regs(struct target *target,
- uint32_t mask, uint32_t *core_regs[16])
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* STMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, STM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STM in SHIFT stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, STM in MEMORY (i'th cycle) */
- arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
- }
-}
-
-static void fa526_read_core_regs_target_buffer(struct target *target,
- uint32_t mask, void *buffer, int size)
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
- uint32_t *buf_u32 = buffer;
- uint16_t *buf_u16 = buffer;
- uint8_t *buf_u8 = buffer;
-
- /* STMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, STM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STM in SHIFT stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, STM in MEMORY (i'th cycle) */
- switch (size) {
- case 4:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
- break;
- case 2:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
- break;
- case 1:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
- break;
- }
- }
-}
-
-static void fa526_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* MRS r0, cpsr */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- /* STR r0, [r15] */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
- /* fetch NOP, STR in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STR in SHIFT stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, STR in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, STR in MEMORY */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
-}
-
-static void fa526_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
-
- /* MSR1 fetched */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
- /* MSR2 fetched, MSR1 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
- /* MSR3 fetched, MSR1 in SHIFT, MSR2 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
- /* MSR4 fetched, MSR1 in EXECUTE (1), MSR2 in SHIFT, MSR3 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
- /* nothing fetched, MSR1 in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR1 in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR2 in EXECUTE (1), MSR3 in SHIFT, MSR4 in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR2 in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR2 in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in SHIFT */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR3 in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR3 in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* NOP fetched, MSR4 in EXECUTE (1) */
- /* last MSR writes flags, which takes only one cycle */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void fa526_write_xpsr_im8(struct target *target,
- uint8_t xpsr_im, int rot, int spsr)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
-
- /* MSR fetched */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
- /* NOP fetched, MSR in DECODE */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* NOP fetched, MSR in SHIFT */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* NOP fetched, MSR in EXECUTE (1) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- /* rot == 4 writes flags, which takes only one cycle */
- if (rot != 4) {
- /* nothing fetched, MSR in EXECUTE (2) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, MSR in EXECUTE (3) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- }
-}
-
-static void fa526_write_core_regs(struct target *target,
- uint32_t mask, uint32_t core_regs[16])
-{
- int i;
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* LDMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, LDM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in SHIFT stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i))
- /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
- }
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void fa526_write_pc(struct target *target, uint32_t pc)
-{
- struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /* LDMIA r0-15, [r0] at debug speed
- * register values will start to appear on 4th DCLK
- */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
-
- /* fetch NOP, LDM in DECODE stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in SHIFT stage */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
- /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void fa526_branch_resume_thumb(struct target *target)
-{
- LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
-}
-
-static int fa526_init_arch_info_2(struct target *target,
- struct arm7_9_common *arm7_9, struct jtag_tap *tap)
-{
- /* prepare JTAG information for the new target */
- arm7_9->jtag_info.tap = tap;
- arm7_9->jtag_info.scann_size = 5;
-
- /* register arch-specific functions */
- arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
- arm7_9->change_to_arm = fa526_change_to_arm;
- arm7_9->read_core_regs = fa526_read_core_regs;
- arm7_9->read_core_regs_target_buffer = fa526_read_core_regs_target_buffer;
- arm7_9->read_xpsr = fa526_read_xpsr;
-
- arm7_9->write_xpsr = fa526_write_xpsr;
- arm7_9->write_xpsr_im8 = fa526_write_xpsr_im8;
- arm7_9->write_core_regs = fa526_write_core_regs;
-
- arm7_9->load_word_regs = arm9tdmi_load_word_regs;
- arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
- arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
-
- arm7_9->store_word_regs = arm9tdmi_store_word_regs;
- arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
- arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
-
- arm7_9->write_pc = fa526_write_pc;
- arm7_9->branch_resume = arm9tdmi_branch_resume;
- arm7_9->branch_resume_thumb = fa526_branch_resume_thumb;
-
- arm7_9->enable_single_step = arm9tdmi_enable_single_step;
- arm7_9->disable_single_step = arm9tdmi_disable_single_step;
-
- arm7_9->write_memory = arm920t_write_memory;
- arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
-
- arm7_9->post_debug_entry = NULL;
-
- arm7_9->pre_restore_context = NULL;
-
- /* initialize arch-specific breakpoint handling */
- arm7_9->arm_bkpt = 0xdeeedeee;
- arm7_9->thumb_bkpt = 0xdeee;
-
- arm7_9->dbgreq_adjust_pc = 3;
-
- arm7_9_init_arch_info(target, arm7_9);
-
- /* override use of DBGRQ, this is safe on ARM9TDMI */
- arm7_9->use_dbgrq = 1;
-
- /* all ARM9s have the vector catch register */
- arm7_9->has_vector_catch = 1;
-
- return ERROR_OK;
-}
-
-static int fa526_init_arch_info(struct target *target,
- struct arm920t_common *arm920t, struct jtag_tap *tap)
-{
- struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
-
- /* initialize arm7/arm9 specific info (including armv4_5) */
- fa526_init_arch_info_2(target, arm7_9, tap);
-
- arm920t->common_magic = ARM920T_COMMON_MAGIC;
-
- arm7_9->post_debug_entry = arm920t_post_debug_entry;
- arm7_9->pre_restore_context = arm920t_pre_restore_context;
-
- arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
- arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
- arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
- arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
- arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
- arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
- arm920t->armv4_5_mmu.has_tiny_pages = 1;
- arm920t->armv4_5_mmu.mmu_enabled = 0;
-
- /* disabling linefills leads to lockups, so keep them enabled for now
- * this doesn't affect correctness, but might affect timing issues, if
- * important data is evicted from the cache during the debug session
- * */
- arm920t->preserve_cache = 0;
-
- /* override hw single-step capability from ARM9TDMI */
- arm7_9->has_single_step = 1;
-
- return ERROR_OK;
-}
-
-static int fa526_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm920t_common *arm920t = calloc(1, sizeof(struct arm920t_common));
-
- return fa526_init_arch_info(target, arm920t, target->tap);
-}
-
-/** Holds methods for FA526 targets. */
-struct target_type fa526_target = {
- .name = "fa526",
-
- .poll = arm7_9_poll,
- .arch_state = arm920t_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = arm7_9_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm920t_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm920t_read_memory,
- .write_memory = arm7_9_write_memory_opt,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm920t_command_handlers,
- .target_create = fa526_target_create,
- .init_target = arm9tdmi_init_target,
- .examine = arm7_9_examine,
- .check_reset = arm7_9_check_reset,
-};
diff --git a/src/target/feroceon.c b/src/target/feroceon.c
deleted file mode 100644
index f12e4e4..0000000
--- a/src/target/feroceon.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. *
- * Written by Nicolas Pitre <nico@marvell.com> *
- * *
- * Copyright (C) 2008 by Hongtao Zheng *
- * hontor@126.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * Marvell Feroceon/Dragonite support.
- *
- * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
- * mimics the ARM926 ICE interface with the following differences:
- *
- * - the MOE (method of entry) reporting is not implemented
- *
- * - breakpoint/watchpoint comparator #1 is seemingly not implemented
- *
- * - due to a different pipeline implementation, some injected debug
- * instruction sequences have to be somewhat different
- *
- * Other issues:
- *
- * - asserting DBGRQ doesn't work if target is looping on the undef vector
- *
- * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
- * not at the top, and rather meaningless due to existing discrepencies
- *
- * - the DCC channel is half duplex (only one FIFO for both directions) with
- * seemingly no proper flow control.
- *
- * The Dragonite core is the non-mmu version based on the ARM966 model, and
- * it shares the above issues as well.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm926ejs.h"
-#include "arm966e.h"
-#include "target_type.h"
-#include "register.h"
-#include "arm_opcodes.h"
-
-static int feroceon_assert_reset(struct target *target)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- int ud = arm7_9->use_dbgrq;
-
- /* TODO: apply hw reset signal in not examined state */
- if (!(target_was_examined(target))) {
- LOG_WARNING("Reset is not asserted because the target is not examined.");
- LOG_WARNING("Use a reset button or power cycle the target.");
- return ERROR_TARGET_NOT_EXAMINED;
- }
-
- arm7_9->use_dbgrq = 0;
- if (target->reset_halt)
- arm7_9_halt(target);
- arm7_9->use_dbgrq = ud;
- return arm7_9_assert_reset(target);
-}
-
-static int feroceon_dummy_clock_out(struct arm_jtag *jtag_info, uint32_t instr)
-{
- struct scan_field fields[3];
- uint8_t out_buf[4];
- uint8_t instr_buf[4];
- uint8_t sysspeed_buf = 0x0;
- int retval;
-
- /* prepare buffer */
- buf_set_u32(out_buf, 0, 32, 0);
-
- buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
-
- retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
- if (retval != ERROR_OK)
- return retval;
-
- fields[0].num_bits = 32;
- fields[0].out_value = out_buf;
- fields[0].in_value = NULL;
-
- fields[1].num_bits = 3;
- fields[1].out_value = &sysspeed_buf;
- fields[1].in_value = NULL;
-
- fields[2].num_bits = 32;
- fields[2].out_value = instr_buf;
- fields[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
-
- /* no jtag_add_runtest(0, TAP_DRPAUSE) here */
-
- return ERROR_OK;
-}
-
-static void feroceon_change_to_arm(struct target *target, uint32_t *r0,
- uint32_t *pc)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- /*
- * save r0 before using it and put system in ARM state
- * to allow common handling of ARM and THUMB debugging
- */
-
- feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
- feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
- feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- jtag_execute_queue();
-
- /*
- * fix program counter:
- * MOV R0, PC was the 7th instruction (+12)
- * reading PC in Thumb state gives address of instruction + 4
- */
- *pc -= (12 + 4);
-}
-
-static void feroceon_read_core_regs(struct target *target,
- uint32_t mask, uint32_t *core_regs[16])
-{
- int i;
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++)
- if (mask & (1 << i))
- arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void feroceon_read_core_regs_target_buffer(struct target *target,
- uint32_t mask, void *buffer, int size)
-{
- int i;
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
- uint32_t *buf_u32 = buffer;
- uint16_t *buf_u16 = buffer;
- uint8_t *buf_u8 = buffer;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++) {
- if (mask & (1 << i)) {
- switch (size) {
- case 4:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
- break;
- case 2:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
- break;
- case 1:
- arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
- break;
- }
- }
- }
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void feroceon_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void feroceon_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void feroceon_write_xpsr_im8(struct target *target,
- uint8_t xpsr_im, int rot, int spsr)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void feroceon_write_core_regs(struct target *target,
- uint32_t mask, uint32_t core_regs[16])
-{
- int i;
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- for (i = 0; i <= 15; i++)
- if (mask & (1 << i))
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-static void feroceon_branch_resume(struct target *target)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-
- arm7_9->need_bypass_before_restart = 1;
-}
-
-static void feroceon_branch_resume_thumb(struct target *target)
-{
- LOG_DEBUG("-");
-
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
- uint32_t pc = buf_get_u32(arm->pc->value, 0, 32);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); /* add r0,pc,#1 */
- arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
- pc = (pc & 2) >> 1;
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
-
- arm7_9->need_bypass_before_restart = 1;
-}
-
-static int feroceon_read_cp15(struct target *target, uint32_t op1,
- uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
- int err;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
- err = arm7_9_execute_sys_speed(target);
- if (err != ERROR_OK)
- return err;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- return jtag_execute_queue();
-}
-
-static int feroceon_write_cp15(struct target *target, uint32_t op1,
- uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct arm_jtag *jtag_info = &arm7_9->jtag_info;
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
- arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
- arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
- return arm7_9_execute_sys_speed(target);
-}
-
-static void feroceon_set_dbgrq(struct target *target)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
-
- buf_set_u32(dbg_ctrl->value, 0, 8, 2);
- embeddedice_store_reg(dbg_ctrl);
-}
-
-static void feroceon_enable_single_step(struct target *target, uint32_t next_pc)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
-
- /* set a breakpoint there */
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
-}
-
-static void feroceon_disable_single_step(struct target *target)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
-
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
-}
-
-static int feroceon_examine_debug_reason(struct target *target)
-{
- /* the MOE is not implemented */
- if (target->debug_reason != DBG_REASON_SINGLESTEP)
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int feroceon_bulk_write_memory(struct target *target,
- uint32_t address, uint32_t count, const uint8_t *buffer)
-{
- int retval;
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- enum arm_state core_state = arm->core_state;
- uint32_t x, flip, shift, save[7];
- uint32_t i;
-
- /*
- * We can't use the dcc flow control bits, so let's transfer data
- * with 31 bits and flip the MSB each time a new data word is sent.
- */
- static uint32_t dcc_code[] = {
- 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
- 0xe3a0301e, /* 1: mov r3, #30 */
- 0xe3a04002, /* mov r4, #2 */
- 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
- 0xe1310005, /* teq r1, r5 */
- 0x0afffffc, /* beq 1b */
- 0xe1a05001, /* mov r5, r1 */
- 0xe1a01081, /* mov r1, r1, lsl #1 */
- 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
- 0xe1320005, /* teq r2, r5 */
- 0x0afffffc, /* beq 3b */
- 0xe1a05002, /* mov r5, r2 */
- 0xe3c22102, /* bic r2, r2, #0x80000000 */
- 0xe1811332, /* orr r1, r1, r2, lsr r3 */
- 0xe2533001, /* subs r3, r3, #1 */
- 0xe4801004, /* str r1, [r0], #4 */
- 0xe1a01412, /* mov r1, r2, lsl r4 */
- 0xe2844001, /* add r4, r4, #1 */
- 0x4affffed, /* bmi 1b */
- 0xeafffff3, /* b 3b */
- };
-
- uint32_t dcc_size = sizeof(dcc_code);
-
- if (address % 4 != 0)
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- if (!arm7_9->dcc_downloads)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- /* regrab previously allocated working_area, or allocate a new one */
- if (!arm7_9->dcc_working_area) {
- uint8_t dcc_code_buf[dcc_size];
-
- /* make sure we have a working area */
- if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) {
- LOG_INFO("no working area available, falling back to memory writes");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* copy target instructions to target endianness */
- target_buffer_set_u32_array(target, dcc_code_buf, ARRAY_SIZE(dcc_code), dcc_code);
-
- /* write DCC code to working area, using the non-optimized
- * memory write to avoid ending up here again */
- retval = arm7_9_write_memory_no_opt(target,
- arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* backup clobbered processor state */
- for (i = 0; i <= 5; i++)
- save[i] = buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32);
- save[i] = buf_get_u32(arm->pc->value, 0, 32);
-
- /* set up target address in r0 */
- buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, address);
- arm->core_cache->reg_list[0].valid = 1;
- arm->core_cache->reg_list[0].dirty = 1;
- arm->core_state = ARM_STATE_ARM;
-
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
- arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
-
- /* send data over */
- x = 0;
- flip = 0;
- shift = 1;
- for (i = 0; i < count; i++) {
- uint32_t y = target_buffer_get_u32(target, buffer);
- uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
- x = y << (32 - shift);
- if (++shift >= 32 || i + 1 >= count) {
- z = (x >> 1) | (flip ^= 0x80000000);
- embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
- x = 0;
- shift = 1;
- }
- buffer += 4;
- }
-
- retval = target_halt(target);
- if (retval == ERROR_OK)
- retval = target_wait_state(target, TARGET_HALTED, 500);
- if (retval == ERROR_OK) {
- uint32_t endaddress =
- buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
- if (endaddress != address + count*4) {
- LOG_ERROR("DCC write failed,"
- " expected end address 0x%08" PRIx32
- " got 0x%0" PRIx32 "",
- address + count*4, endaddress);
- retval = ERROR_FAIL;
- }
- }
-
- /* restore target state */
- for (i = 0; i <= 5; i++) {
- buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, save[i]);
- arm->core_cache->reg_list[i].valid = 1;
- arm->core_cache->reg_list[i].dirty = 1;
- }
- buf_set_u32(arm->pc->value, 0, 32, save[i]);
- arm->pc->valid = 1;
- arm->pc->dirty = 1;
- arm->core_state = core_state;
-
- return retval;
-}
-
-static int feroceon_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- arm9tdmi_init_target(cmd_ctx, target);
- return ERROR_OK;
-}
-
-static void feroceon_common_setup(struct target *target)
-{
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
-
- /* override some insn sequence functions */
- arm7_9->change_to_arm = feroceon_change_to_arm;
- arm7_9->read_core_regs = feroceon_read_core_regs;
- arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
- arm7_9->read_xpsr = feroceon_read_xpsr;
- arm7_9->write_xpsr = feroceon_write_xpsr;
- arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
- arm7_9->write_core_regs = feroceon_write_core_regs;
- arm7_9->branch_resume = feroceon_branch_resume;
- arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
-
- /* must be implemented with only one comparator */
- arm7_9->enable_single_step = feroceon_enable_single_step;
- arm7_9->disable_single_step = feroceon_disable_single_step;
-
- arm7_9->bulk_write_memory = feroceon_bulk_write_memory;
-
- /* MOE is not implemented */
- arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
-
- /* Note: asserting DBGRQ might not win over the undef exception.
- If that happens then just use "arm7_9 dbgrq disable". */
- arm7_9->use_dbgrq = 1;
- arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
-
- /* only one working comparator */
- arm7_9->wp_available_max = 1;
- arm7_9->wp1_used_default = -1;
-}
-
-static int feroceon_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
-
- arm926ejs_init_arch_info(target, arm926ejs, target->tap);
- feroceon_common_setup(target);
-
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- arm7_9->write_memory = arm926ejs_write_memory;
-
- /* the standard ARM926 methods don't always work (don't ask...) */
- arm926ejs->read_cp15 = feroceon_read_cp15;
- arm926ejs->write_cp15 = feroceon_write_cp15;
-
- return ERROR_OK;
-}
-
-static int dragonite_target_create(struct target *target, Jim_Interp *interp)
-{
- struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
-
- arm966e_init_arch_info(target, arm966e, target->tap);
- feroceon_common_setup(target);
-
- struct arm *arm = target->arch_info;
- struct arm7_9_common *arm7_9 = arm->arch_info;
- arm7_9->write_memory = arm7_9_write_memory;
-
- return ERROR_OK;
-}
-
-static int feroceon_examine(struct target *target)
-{
- struct arm *arm;
- struct arm7_9_common *arm7_9;
- int retval;
-
- retval = arm7_9_examine(target);
- if (retval != ERROR_OK)
- return retval;
-
- arm = target->arch_info;
- arm7_9 = arm->arch_info;
-
- /* the COMMS_CTRL bits are all contiguous */
- if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
- LOG_ERROR("unexpected Feroceon EICE version signature");
-
- arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
- arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
- arm7_9->has_monitor_mode = 1;
-
- /* vector catch reg is not initialized on reset */
- embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
-
- /* clear monitor mode, enable comparators */
- embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
- jtag_execute_queue();
- buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
- buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
- embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
-
- return ERROR_OK;
-}
-
-struct target_type feroceon_target = {
- .name = "feroceon",
-
- .poll = arm7_9_poll,
- .arch_state = arm926ejs_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = feroceon_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm926ejs_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm7_9_read_memory,
- .write_memory = arm7_9_write_memory_opt,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm926ejs_command_handlers,
- .target_create = feroceon_target_create,
- .init_target = feroceon_init_target,
- .examine = feroceon_examine,
-};
-
-struct target_type dragonite_target = {
- .name = "dragonite",
-
- .poll = arm7_9_poll,
- .arch_state = arm_arch_state,
-
- .target_request_data = arm7_9_target_request_data,
-
- .halt = arm7_9_halt,
- .resume = arm7_9_resume,
- .step = arm7_9_step,
-
- .assert_reset = feroceon_assert_reset,
- .deassert_reset = arm7_9_deassert_reset,
- .soft_reset_halt = arm7_9_soft_reset_halt,
-
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = arm7_9_read_memory,
- .write_memory = arm7_9_write_memory_opt,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = arm7_9_add_breakpoint,
- .remove_breakpoint = arm7_9_remove_breakpoint,
- .add_watchpoint = arm7_9_add_watchpoint,
- .remove_watchpoint = arm7_9_remove_watchpoint,
-
- .commands = arm966e_command_handlers,
- .target_create = dragonite_target_create,
- .init_target = feroceon_init_target,
- .examine = feroceon_examine,
-};
diff --git a/src/target/hla_target.c b/src/target/hla_target.c
deleted file mode 100644
index e02abc4..0000000
--- a/src/target/hla_target.c
+++ /dev/null
@@ -1,815 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Mathias Kuester *
- * Mathias Kuester <kesmtp@freenet.de> *
- * *
- * Copyright (C) 2011 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * revised: 4/25/13 by brent@mbari.org [DCC target request support] *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "jtag/jtag.h"
-#include "jtag/hla/hla_transport.h"
-#include "jtag/hla/hla_interface.h"
-#include "jtag/hla/hla_layout.h"
-#include "register.h"
-#include "algorithm.h"
-#include "target.h"
-#include "breakpoints.h"
-#include "target_type.h"
-#include "armv7m.h"
-#include "cortex_m.h"
-#include "arm_semihosting.h"
-#include "target_request.h"
-
-#define savedDCRDR dbgbase /* FIXME: using target->dbgbase to preserve DCRDR */
-
-#define ARMV7M_SCS_DCRSR DCB_DCRSR
-#define ARMV7M_SCS_DCRDR DCB_DCRDR
-
-static inline struct hl_interface_s *target_to_adapter(struct target *target)
-{
- return target->tap->priv;
-}
-
-static int adapter_load_core_reg_u32(struct target *target,
- uint32_t num, uint32_t *value)
-{
- int retval;
- struct hl_interface_s *adapter = target_to_adapter(target);
-
- LOG_DEBUG("%s", __func__);
-
- /* NOTE: we "know" here that the register identifiers used
- * in the v7m header match the Cortex-M3 Debug Core Register
- * Selector values for R0..R15, xPSR, MSP, and PSP.
- */
- switch (num) {
- case 0 ... 18:
- /* read a normal core register */
- retval = adapter->layout->api->read_reg(adapter->handle, num, value);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG failure %i", retval);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value);
- break;
-
- case ARMV7M_FPSCR:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value);
- break;
-
- case ARMV7M_S0 ... ARMV7M_S31:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, ARMV7M_SCS_DCRSR, num-ARMV7M_S0+64);
- if (retval != ERROR_OK)
- return retval;
- retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32,
- (int)(num - ARMV7M_S0), *value);
- break;
-
- case ARMV7M_PRIMASK:
- case ARMV7M_BASEPRI:
- case ARMV7M_FAULTMASK:
- case ARMV7M_CONTROL:
- /* Cortex-M3 packages these four registers as bitfields
- * in one Debug Core register. So say r0 and r2 docs;
- * it was removed from r1 docs, but still works.
- */
- retval = adapter->layout->api->read_reg(adapter->handle, 20, value);
- if (retval != ERROR_OK)
- return retval;
-
- switch (num) {
- case ARMV7M_PRIMASK:
- *value = buf_get_u32((uint8_t *) value, 0, 1);
- break;
-
- case ARMV7M_BASEPRI:
- *value = buf_get_u32((uint8_t *) value, 8, 8);
- break;
-
- case ARMV7M_FAULTMASK:
- *value = buf_get_u32((uint8_t *) value, 16, 1);
- break;
-
- case ARMV7M_CONTROL:
- *value = buf_get_u32((uint8_t *) value, 24, 2);
- break;
- }
-
- LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "",
- (int)num, *value);
- break;
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int adapter_store_core_reg_u32(struct target *target,
- uint32_t num, uint32_t value)
-{
- int retval;
- uint32_t reg;
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct hl_interface_s *adapter = target_to_adapter(target);
-
- LOG_DEBUG("%s", __func__);
-
- /* NOTE: we "know" here that the register identifiers used
- * in the v7m header match the Cortex-M3 Debug Core Register
- * Selector values for R0..R15, xPSR, MSP, and PSP.
- */
- switch (num) {
- case 0 ... 18:
- retval = adapter->layout->api->write_reg(adapter->handle, num, value);
-
- if (retval != ERROR_OK) {
- struct reg *r;
-
- LOG_ERROR("JTAG failure");
- r = armv7m->arm.core_cache->reg_list + num;
- r->dirty = r->valid;
- return ERROR_JTAG_DEVICE_ERROR;
- }
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
- break;
-
- case ARMV7M_FPSCR:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33 | (1<<16));
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("write FPSCR value 0x%" PRIx32, value);
- break;
-
- case ARMV7M_S0 ... ARMV7M_S31:
- /* Floating-point Status and Registers */
- retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, ARMV7M_SCS_DCRSR, (num-ARMV7M_S0+64) | (1<<16));
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32,
- (int)(num - ARMV7M_S0), value);
- break;
-
- case ARMV7M_PRIMASK:
- case ARMV7M_BASEPRI:
- case ARMV7M_FAULTMASK:
- case ARMV7M_CONTROL:
- /* Cortex-M3 packages these four registers as bitfields
- * in one Debug Core register. So say r0 and r2 docs;
- * it was removed from r1 docs, but still works.
- */
-
- adapter->layout->api->read_reg(adapter->handle, 20, &reg);
-
- switch (num) {
- case ARMV7M_PRIMASK:
- buf_set_u32((uint8_t *) &reg, 0, 1, value);
- break;
-
- case ARMV7M_BASEPRI:
- buf_set_u32((uint8_t *) &reg, 8, 8, value);
- break;
-
- case ARMV7M_FAULTMASK:
- buf_set_u32((uint8_t *) &reg, 16, 1, value);
- break;
-
- case ARMV7M_CONTROL:
- buf_set_u32((uint8_t *) &reg, 24, 2, value);
- break;
- }
-
- adapter->layout->api->write_reg(adapter->handle, 20, reg);
-
- LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
- break;
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int adapter_examine_debug_reason(struct target *target)
-{
- if ((target->debug_reason != DBG_REASON_DBGRQ)
- && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
- target->debug_reason = DBG_REASON_BREAKPOINT;
- }
-
- return ERROR_OK;
-}
-
-static int hl_dcc_read(struct hl_interface_s *hl_if, uint8_t *value, uint8_t *ctrl)
-{
- uint16_t dcrdr;
- int retval = hl_if->layout->api->read_mem(hl_if->handle,
- DCB_DCRDR, 1, sizeof(dcrdr), (uint8_t *)&dcrdr);
- if (retval == ERROR_OK) {
- *ctrl = (uint8_t)dcrdr;
- *value = (uint8_t)(dcrdr >> 8);
-
- LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
-
- if (dcrdr & 1) {
- /* write ack back to software dcc register
- * to signify we have read data */
- /* atomically clear just the byte containing the busy bit */
- static const uint8_t zero;
- retval = hl_if->layout->api->write_mem(hl_if->handle, DCB_DCRDR, 1, 1, &zero);
- }
- }
- return retval;
-}
-
-static int hl_target_request_data(struct target *target,
- uint32_t size, uint8_t *buffer)
-{
- struct hl_interface_s *hl_if = target_to_adapter(target);
- uint8_t data;
- uint8_t ctrl;
- uint32_t i;
-
- for (i = 0; i < (size * 4); i++) {
- hl_dcc_read(hl_if, &data, &ctrl);
- buffer[i] = data;
- }
-
- return ERROR_OK;
-}
-
-static int hl_handle_target_request(void *priv)
-{
- struct target *target = priv;
- if (!target_was_examined(target))
- return ERROR_OK;
- struct hl_interface_s *hl_if = target_to_adapter(target);
-
- if (!target->dbg_msg_enabled)
- return ERROR_OK;
-
- if (target->state == TARGET_RUNNING) {
- uint8_t data;
- uint8_t ctrl;
-
- hl_dcc_read(hl_if, &data, &ctrl);
-
- /* check if we have data */
- if (ctrl & (1 << 0)) {
- uint32_t request;
-
- /* we assume target is quick enough */
- request = data;
- hl_dcc_read(hl_if, &data, &ctrl);
- request |= (data << 8);
- hl_dcc_read(hl_if, &data, &ctrl);
- request |= (data << 16);
- hl_dcc_read(hl_if, &data, &ctrl);
- request |= (data << 24);
- target_request(target, request);
- }
- }
-
- return ERROR_OK;
-}
-
-static int adapter_init_arch_info(struct target *target,
- struct cortex_m_common *cortex_m,
- struct jtag_tap *tap)
-{
- struct armv7m_common *armv7m;
-
- LOG_DEBUG("%s", __func__);
-
- armv7m = &cortex_m->armv7m;
- armv7m_init_arch_info(target, armv7m);
-
- armv7m->load_core_reg_u32 = adapter_load_core_reg_u32;
- armv7m->store_core_reg_u32 = adapter_store_core_reg_u32;
-
- armv7m->examine_debug_reason = adapter_examine_debug_reason;
- armv7m->stlink = true;
-
- target_register_timer_callback(hl_handle_target_request, 1, 1, target);
-
- return ERROR_OK;
-}
-
-static int adapter_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- LOG_DEBUG("%s", __func__);
-
- armv7m_build_reg_cache(target);
-
- return ERROR_OK;
-}
-
-static int adapter_target_create(struct target *target,
- Jim_Interp *interp)
-{
- LOG_DEBUG("%s", __func__);
-
- struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
-
- if (!cortex_m)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- adapter_init_arch_info(target, cortex_m, target->tap);
-
- return ERROR_OK;
-}
-
-static int adapter_load_context(struct target *target)
-{
- struct armv7m_common *armv7m = target_to_armv7m(target);
- int num_regs = armv7m->arm.core_cache->num_regs;
-
- for (int i = 0; i < num_regs; i++) {
-
- struct reg *r = &armv7m->arm.core_cache->reg_list[i];
- if (!r->valid)
- armv7m->arm.read_core_reg(target, r, i, ARM_MODE_ANY);
- }
-
- return ERROR_OK;
-}
-
-static int adapter_debug_entry(struct target *target)
-{
- struct hl_interface_s *adapter = target_to_adapter(target);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct arm *arm = &armv7m->arm;
- struct reg *r;
- uint32_t xPSR;
- int retval;
-
- /* preserve the DCRDR across halts */
- retval = target_read_u32(target, DCB_DCRDR, &target->savedDCRDR);
- if (retval != ERROR_OK)
- return retval;
-
- retval = armv7m->examine_debug_reason(target);
- if (retval != ERROR_OK)
- return retval;
-
- adapter_load_context(target);
-
- /* make sure we clear the vector catch bit */
- adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA);
-
- r = arm->cpsr;
- xPSR = buf_get_u32(r->value, 0, 32);
-
- /* Are we in an exception handler */
- if (xPSR & 0x1FF) {
- armv7m->exception_number = (xPSR & 0x1FF);
-
- arm->core_mode = ARM_MODE_HANDLER;
- arm->map = armv7m_msp_reg_map;
- } else {
- unsigned control = buf_get_u32(arm->core_cache
- ->reg_list[ARMV7M_CONTROL].value, 0, 2);
-
- /* is this thread privileged? */
- arm->core_mode = control & 1
- ? ARM_MODE_USER_THREAD
- : ARM_MODE_THREAD;
-
- /* which stack is it using? */
- if (control & 2)
- arm->map = armv7m_psp_reg_map;
- else
- arm->map = armv7m_msp_reg_map;
-
- armv7m->exception_number = 0;
- }
-
- LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32 ", target->state: %s",
- arm_mode_name(arm->core_mode),
- buf_get_u32(arm->pc->value, 0, 32),
- target_state_name(target));
-
- return retval;
-}
-
-static int adapter_poll(struct target *target)
-{
- enum target_state state;
- struct hl_interface_s *adapter = target_to_adapter(target);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- enum target_state prev_target_state = target->state;
-
- state = adapter->layout->api->state(adapter->handle);
-
- if (state == TARGET_UNKNOWN) {
- LOG_ERROR("jtag status contains invalid mode value - communication failure");
- return ERROR_TARGET_FAILURE;
- }
-
- if (prev_target_state == state)
- return ERROR_OK;
-
- target->state = state;
-
- if (state == TARGET_HALTED) {
-
- int retval = adapter_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (prev_target_state == TARGET_DEBUG_RUNNING) {
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
- } else {
- if (arm_semihosting(target, &retval) != 0)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- }
-
- LOG_DEBUG("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32));
- }
-
- return ERROR_OK;
-}
-
-static int adapter_assert_reset(struct target *target)
-{
- int res = ERROR_OK;
- struct hl_interface_s *adapter = target_to_adapter(target);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- bool use_srst_fallback = true;
-
- LOG_DEBUG("%s", __func__);
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- bool srst_asserted = false;
-
- if ((jtag_reset_config & RESET_HAS_SRST) &&
- (jtag_reset_config & RESET_SRST_NO_GATING)) {
- jtag_add_reset(0, 1);
- res = adapter->layout->api->assert_srst(adapter->handle, 0);
- srst_asserted = true;
- }
-
- adapter->layout->api->write_debug_reg(adapter->handle, DCB_DHCSR, DBGKEY|C_DEBUGEN);
-
- /* only set vector catch if halt is requested */
- if (target->reset_halt)
- adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA|VC_CORERESET);
- else
- adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA);
-
- if (jtag_reset_config & RESET_HAS_SRST) {
- if (!srst_asserted) {
- jtag_add_reset(0, 1);
- res = adapter->layout->api->assert_srst(adapter->handle, 0);
- }
- if (res == ERROR_COMMAND_NOTFOUND)
- LOG_ERROR("Hardware srst not supported, falling back to software reset");
- else if (res == ERROR_OK) {
- /* hardware srst supported */
- use_srst_fallback = false;
- }
- }
-
- if (use_srst_fallback) {
- /* stlink v1 api does not support hardware srst, so we use a software reset fallback */
- adapter->layout->api->write_debug_reg(adapter->handle, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
- }
-
- res = adapter->layout->api->reset(adapter->handle);
-
- if (res != ERROR_OK)
- return res;
-
- /* registers are now invalid */
- register_cache_invalidate(armv7m->arm.core_cache);
-
- if (target->reset_halt) {
- target->state = TARGET_RESET;
- target->debug_reason = DBG_REASON_DBGRQ;
- } else {
- target->state = TARGET_HALTED;
- }
-
- return ERROR_OK;
-}
-
-static int adapter_deassert_reset(struct target *target)
-{
- struct hl_interface_s *adapter = target_to_adapter(target);
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- LOG_DEBUG("%s", __func__);
-
- if (jtag_reset_config & RESET_HAS_SRST)
- adapter->layout->api->assert_srst(adapter->handle, 1);
-
- /* virtual deassert reset, we need it for the internal
- * jtag state machine
- */
- jtag_add_reset(0, 0);
-
- target->savedDCRDR = 0; /* clear both DCC busy bits on initial resume */
-
- return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0);
-}
-
-static int adapter_halt(struct target *target)
-{
- int res;
- struct hl_interface_s *adapter = target_to_adapter(target);
-
- LOG_DEBUG("%s", __func__);
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- if (target->state == TARGET_UNKNOWN)
- LOG_WARNING("target was in unknown state when halt was requested");
-
- res = adapter->layout->api->halt(adapter->handle);
-
- if (res != ERROR_OK)
- return res;
-
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int adapter_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints,
- int debug_execution)
-{
- int res;
- struct hl_interface_s *adapter = target_to_adapter(target);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- uint32_t resume_pc;
- struct breakpoint *breakpoint = NULL;
- struct reg *pc;
-
- LOG_DEBUG("%s %d 0x%08" PRIx32 " %d %d", __func__, current, address,
- handle_breakpoints, debug_execution);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!debug_execution) {
- target_free_all_working_areas(target);
- cortex_m_enable_breakpoints(target);
- cortex_m_enable_watchpoints(target);
- }
-
- pc = armv7m->arm.pc;
- if (!current) {
- buf_set_u32(pc->value, 0, 32, address);
- pc->dirty = true;
- pc->valid = true;
- }
-
- if (!breakpoint_find(target, buf_get_u32(pc->value, 0, 32))
- && !debug_execution) {
- armv7m_maybe_skip_bkpt_inst(target, NULL);
- }
-
- resume_pc = buf_get_u32(pc->value, 0, 32);
-
- /* write any user vector flags */
- res = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
- if (res != ERROR_OK)
- return res;
-
- armv7m_restore_context(target);
-
- /* restore savedDCRDR */
- res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR);
- if (res != ERROR_OK)
- return res;
-
- /* registers are now invalid */
- register_cache_invalidate(armv7m->arm.core_cache);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- /* Single step past breakpoint at current address */
- breakpoint = breakpoint_find(target, resume_pc);
- if (breakpoint) {
- LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")",
- breakpoint->address,
- breakpoint->unique_id);
- cortex_m_unset_breakpoint(target, breakpoint);
-
- res = adapter->layout->api->step(adapter->handle);
-
- if (res != ERROR_OK)
- return res;
-
- cortex_m_set_breakpoint(target, breakpoint);
- }
- }
-
- res = adapter->layout->api->run(adapter->handle);
-
- if (res != ERROR_OK)
- return res;
-
- target->debug_reason = DBG_REASON_NOTHALTED;
-
- if (!debug_execution) {
- target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- }
-
- return ERROR_OK;
-}
-
-static int adapter_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- int res;
- struct hl_interface_s *adapter = target_to_adapter(target);
- struct armv7m_common *armv7m = target_to_armv7m(target);
- struct breakpoint *breakpoint = NULL;
- struct reg *pc = armv7m->arm.pc;
- bool bkpt_inst_found = false;
-
- LOG_DEBUG("%s", __func__);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!current) {
- buf_set_u32(pc->value, 0, 32, address);
- pc->dirty = true;
- pc->valid = true;
- }
-
- uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- breakpoint = breakpoint_find(target, pc_value);
- if (breakpoint)
- cortex_m_unset_breakpoint(target, breakpoint);
- }
-
- armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- armv7m_restore_context(target);
-
- /* restore savedDCRDR */
- res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR);
- if (res != ERROR_OK)
- return res;
-
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-
- res = adapter->layout->api->step(adapter->handle);
-
- if (res != ERROR_OK)
- return res;
-
- /* registers are now invalid */
- register_cache_invalidate(armv7m->arm.core_cache);
-
- if (breakpoint)
- cortex_m_set_breakpoint(target, breakpoint);
-
- adapter_debug_entry(target);
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- LOG_INFO("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32));
-
- return ERROR_OK;
-}
-
-static int adapter_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count,
- uint8_t *buffer)
-{
- struct hl_interface_s *adapter = target_to_adapter(target);
-
- if (!count || !buffer)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count);
-
- return adapter->layout->api->read_mem(adapter->handle, address, size, count, buffer);
-}
-
-static int adapter_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count,
- const uint8_t *buffer)
-{
- struct hl_interface_s *adapter = target_to_adapter(target);
-
- if (!count || !buffer)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count);
-
- return adapter->layout->api->write_mem(adapter->handle, address, size, count, buffer);
-}
-
-static const struct command_registration adapter_command_handlers[] = {
- {
- .chain = arm_command_handlers,
- },
- {
- .chain = armv7m_trace_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct target_type hla_target = {
- .name = "hla_target",
- .deprecated_name = "stm32_stlink",
-
- .init_target = adapter_init_target,
- .deinit_target = cortex_m_deinit_target,
- .target_create = adapter_target_create,
- .examine = cortex_m_examine,
- .commands = adapter_command_handlers,
-
- .poll = adapter_poll,
- .arch_state = armv7m_arch_state,
-
- .target_request_data = hl_target_request_data,
- .assert_reset = adapter_assert_reset,
- .deassert_reset = adapter_deassert_reset,
-
- .halt = adapter_halt,
- .resume = adapter_resume,
- .step = adapter_step,
-
- .get_gdb_reg_list = armv7m_get_gdb_reg_list,
-
- .read_memory = adapter_read_memory,
- .write_memory = adapter_write_memory,
- .checksum_memory = armv7m_checksum_memory,
- .blank_check_memory = armv7m_blank_check_memory,
-
- .run_algorithm = armv7m_run_algorithm,
- .start_algorithm = armv7m_start_algorithm,
- .wait_algorithm = armv7m_wait_algorithm,
-
- .add_breakpoint = cortex_m_add_breakpoint,
- .remove_breakpoint = cortex_m_remove_breakpoint,
- .add_watchpoint = cortex_m_add_watchpoint,
- .remove_watchpoint = cortex_m_remove_watchpoint,
-};
diff --git a/src/target/image.c b/src/target/image.c
deleted file mode 100644
index 0612ea7..0000000
--- a/src/target/image.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2009 by Franck Hereson *
- * franck.hereson@secad.fr *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "image.h"
-#include "target.h"
-#include <helper/log.h>
-
-/* convert ELF header field to host endianness */
-#define field16(elf, field) \
- ((elf->endianness == ELFDATA2LSB) ? \
- le_to_h_u16((uint8_t *)&field) : be_to_h_u16((uint8_t *)&field))
-
-#define field32(elf, field) \
- ((elf->endianness == ELFDATA2LSB) ? \
- le_to_h_u32((uint8_t *)&field) : be_to_h_u32((uint8_t *)&field))
-
-static int autodetect_image_type(struct image *image, const char *url)
-{
- int retval;
- struct fileio *fileio;
- size_t read_bytes;
- uint8_t buffer[9];
-
- /* read the first 4 bytes of image */
- retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY);
- if (retval != ERROR_OK)
- return retval;
- retval = fileio_read(fileio, 9, buffer, &read_bytes);
-
- if (retval == ERROR_OK) {
- if (read_bytes != 9)
- retval = ERROR_FILEIO_OPERATION_FAILED;
- }
- fileio_close(fileio);
-
- if (retval != ERROR_OK)
- return retval;
-
- /* check header against known signatures */
- if (strncmp((char *)buffer, ELFMAG, SELFMAG) == 0) {
- LOG_DEBUG("ELF image detected.");
- image->type = IMAGE_ELF;
- } else if ((buffer[0] == ':') /* record start byte */
- && (isxdigit(buffer[1]))
- && (isxdigit(buffer[2]))
- && (isxdigit(buffer[3]))
- && (isxdigit(buffer[4]))
- && (isxdigit(buffer[5]))
- && (isxdigit(buffer[6]))
- && (buffer[7] == '0') /* record type : 00 -> 05 */
- && (buffer[8] >= '0') && (buffer[8] < '6')) {
- LOG_DEBUG("IHEX image detected.");
- image->type = IMAGE_IHEX;
- } else if ((buffer[0] == 'S') /* record start byte */
- && (isxdigit(buffer[1]))
- && (isxdigit(buffer[2]))
- && (isxdigit(buffer[3]))
- && (buffer[1] >= '0') && (buffer[1] < '9')) {
- LOG_DEBUG("S19 image detected.");
- image->type = IMAGE_SRECORD;
- } else
- image->type = IMAGE_BINARY;
-
- return ERROR_OK;
-}
-
-static int identify_image_type(struct image *image, const char *type_string, const char *url)
-{
- if (type_string) {
- if (!strcmp(type_string, "bin"))
- image->type = IMAGE_BINARY;
- else if (!strcmp(type_string, "ihex"))
- image->type = IMAGE_IHEX;
- else if (!strcmp(type_string, "elf"))
- image->type = IMAGE_ELF;
- else if (!strcmp(type_string, "mem"))
- image->type = IMAGE_MEMORY;
- else if (!strcmp(type_string, "s19"))
- image->type = IMAGE_SRECORD;
- else if (!strcmp(type_string, "build"))
- image->type = IMAGE_BUILDER;
- else
- return ERROR_IMAGE_TYPE_UNKNOWN;
- } else
- return autodetect_image_type(image, url);
-
- return ERROR_OK;
-}
-
-static int image_ihex_buffer_complete_inner(struct image *image,
- char *lpszLine,
- struct imagesection *section)
-{
- struct image_ihex *ihex = image->type_private;
- struct fileio *fileio = ihex->fileio;
- uint32_t full_address = 0x0;
- uint32_t cooked_bytes;
- int i;
-
- /* we can't determine the number of sections that we'll have to create ahead of time,
- * so we locally hold them until parsing is finished */
-
- size_t filesize;
- int retval;
- retval = fileio_size(fileio, &filesize);
- if (retval != ERROR_OK)
- return retval;
-
- ihex->buffer = malloc(filesize >> 1);
- cooked_bytes = 0x0;
- image->num_sections = 0;
- section[image->num_sections].private = &ihex->buffer[cooked_bytes];
- section[image->num_sections].base_address = 0x0;
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
-
- while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
- uint32_t count;
- uint32_t address;
- uint32_t record_type;
- uint32_t checksum;
- uint8_t cal_checksum = 0;
- size_t bytes_read = 0;
-
- if (lpszLine[0] == '#')
- continue;
-
- if (sscanf(&lpszLine[bytes_read], ":%2" SCNx32 "%4" SCNx32 "%2" SCNx32, &count,
- &address, &record_type) != 3)
- return ERROR_IMAGE_FORMAT_ERROR;
- bytes_read += 9;
-
- cal_checksum += (uint8_t)count;
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- cal_checksum += (uint8_t)record_type;
-
- if (record_type == 0) { /* Data Record */
- if ((full_address & 0xffff) != address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- if (image->num_sections >= IMAGE_MAX_SECTIONS) {
- /* too many sections */
- LOG_ERROR("Too many sections found in IHEX file");
- return ERROR_IMAGE_FORMAT_ERROR;
- }
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &ihex->buffer[cooked_bytes];
- }
- section[image->num_sections].base_address =
- (full_address & 0xffff0000) | address;
- full_address = (full_address & 0xffff0000) | address;
- }
-
- while (count-- > 0) {
- unsigned value;
- sscanf(&lpszLine[bytes_read], "%2x", &value);
- ihex->buffer[cooked_bytes] = (uint8_t)value;
- cal_checksum += (uint8_t)ihex->buffer[cooked_bytes];
- bytes_read += 2;
- cooked_bytes += 1;
- section[image->num_sections].size += 1;
- full_address++;
- }
- } else if (record_type == 1) { /* End of File Record */
- /* finish the current section */
- image->num_sections++;
-
- /* copy section information */
- image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
- for (i = 0; i < image->num_sections; i++) {
- image->sections[i].private = section[i].private;
- image->sections[i].base_address = section[i].base_address;
- image->sections[i].size = section[i].size;
- image->sections[i].flags = section[i].flags;
- }
-
- return ERROR_OK;
- } else if (record_type == 2) { /* Linear Address Record */
- uint16_t upper_address;
-
- sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
- cal_checksum += (uint8_t)(upper_address >> 8);
- cal_checksum += (uint8_t)upper_address;
- bytes_read += 4;
-
- if ((full_address >> 4) != upper_address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- if (image->num_sections >= IMAGE_MAX_SECTIONS) {
- /* too many sections */
- LOG_ERROR("Too many sections found in IHEX file");
- return ERROR_IMAGE_FORMAT_ERROR;
- }
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &ihex->buffer[cooked_bytes];
- }
- section[image->num_sections].base_address =
- (full_address & 0xffff) | (upper_address << 4);
- full_address = (full_address & 0xffff) | (upper_address << 4);
- }
- } else if (record_type == 3) { /* Start Segment Address Record */
- uint32_t dummy;
-
- /* "Start Segment Address Record" will not be supported
- * but we must consume it, and do not create an error. */
- while (count-- > 0) {
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
- cal_checksum += (uint8_t)dummy;
- bytes_read += 2;
- }
- } else if (record_type == 4) { /* Extended Linear Address Record */
- uint16_t upper_address;
-
- sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
- cal_checksum += (uint8_t)(upper_address >> 8);
- cal_checksum += (uint8_t)upper_address;
- bytes_read += 4;
-
- if ((full_address >> 16) != upper_address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- if (image->num_sections >= IMAGE_MAX_SECTIONS) {
- /* too many sections */
- LOG_ERROR("Too many sections found in IHEX file");
- return ERROR_IMAGE_FORMAT_ERROR;
- }
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &ihex->buffer[cooked_bytes];
- }
- section[image->num_sections].base_address =
- (full_address & 0xffff) | (upper_address << 16);
- full_address = (full_address & 0xffff) | (upper_address << 16);
- }
- } else if (record_type == 5) { /* Start Linear Address Record */
- uint32_t start_address;
-
- sscanf(&lpszLine[bytes_read], "%8" SCNx32, &start_address);
- cal_checksum += (uint8_t)(start_address >> 24);
- cal_checksum += (uint8_t)(start_address >> 16);
- cal_checksum += (uint8_t)(start_address >> 8);
- cal_checksum += (uint8_t)start_address;
- bytes_read += 8;
-
- image->start_address_set = 1;
- image->start_address = be_to_h_u32((uint8_t *)&start_address);
- } else {
- LOG_ERROR("unhandled IHEX record type: %i", (int)record_type);
- return ERROR_IMAGE_FORMAT_ERROR;
- }
-
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
-
- if ((uint8_t)checksum != (uint8_t)(~cal_checksum + 1)) {
- /* checksum failed */
- LOG_ERROR("incorrect record checksum found in IHEX file");
- return ERROR_IMAGE_CHECKSUM;
- }
- }
-
- LOG_ERROR("premature end of IHEX file, no end-of-file record found");
- return ERROR_IMAGE_FORMAT_ERROR;
-}
-
-/**
- * Allocate memory dynamically instead of on the stack. This
- * is important w/embedded hosts.
- */
-static int image_ihex_buffer_complete(struct image *image)
-{
- char *lpszLine = malloc(1023);
- if (lpszLine == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS);
- if (section == NULL) {
- free(lpszLine);
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- int retval;
-
- retval = image_ihex_buffer_complete_inner(image, lpszLine, section);
-
- free(section);
- free(lpszLine);
-
- return retval;
-}
-
-static int image_elf_read_headers(struct image *image)
-{
- struct image_elf *elf = image->type_private;
- size_t read_bytes;
- uint32_t i, j;
- int retval;
- uint32_t nload, load_to_vaddr = 0;
-
- elf->header = malloc(sizeof(Elf32_Ehdr));
-
- if (elf->header == NULL) {
- LOG_ERROR("insufficient memory to perform operation ");
- return ERROR_FILEIO_OPERATION_FAILED;
- }
-
- retval = fileio_read(elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes);
- if (retval != ERROR_OK) {
- LOG_ERROR("cannot read ELF file header, read failed");
- return ERROR_FILEIO_OPERATION_FAILED;
- }
- if (read_bytes != sizeof(Elf32_Ehdr)) {
- LOG_ERROR("cannot read ELF file header, only partially read");
- return ERROR_FILEIO_OPERATION_FAILED;
- }
-
- if (strncmp((char *)elf->header->e_ident, ELFMAG, SELFMAG) != 0) {
- LOG_ERROR("invalid ELF file, bad magic number");
- return ERROR_IMAGE_FORMAT_ERROR;
- }
- if (elf->header->e_ident[EI_CLASS] != ELFCLASS32) {
- LOG_ERROR("invalid ELF file, only 32bits files are supported");
- return ERROR_IMAGE_FORMAT_ERROR;
- }
-
- elf->endianness = elf->header->e_ident[EI_DATA];
- if ((elf->endianness != ELFDATA2LSB)
- && (elf->endianness != ELFDATA2MSB)) {
- LOG_ERROR("invalid ELF file, unknown endianness setting");
- return ERROR_IMAGE_FORMAT_ERROR;
- }
-
- elf->segment_count = field16(elf, elf->header->e_phnum);
- if (elf->segment_count == 0) {
- LOG_ERROR("invalid ELF file, no program headers");
- return ERROR_IMAGE_FORMAT_ERROR;
- }
-
- retval = fileio_seek(elf->fileio, field32(elf, elf->header->e_phoff));
- if (retval != ERROR_OK) {
- LOG_ERROR("cannot seek to ELF program header table, read failed");
- return retval;
- }
-
- elf->segments = malloc(elf->segment_count*sizeof(Elf32_Phdr));
- if (elf->segments == NULL) {
- LOG_ERROR("insufficient memory to perform operation ");
- return ERROR_FILEIO_OPERATION_FAILED;
- }
-
- retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf32_Phdr),
- (uint8_t *)elf->segments, &read_bytes);
- if (retval != ERROR_OK) {
- LOG_ERROR("cannot read ELF segment headers, read failed");
- return retval;
- }
- if (read_bytes != elf->segment_count*sizeof(Elf32_Phdr)) {
- LOG_ERROR("cannot read ELF segment headers, only partially read");
- return ERROR_FILEIO_OPERATION_FAILED;
- }
-
- /* count useful segments (loadable), ignore BSS section */
- image->num_sections = 0;
- for (i = 0; i < elf->segment_count; i++)
- if ((field32(elf,
- elf->segments[i].p_type) == PT_LOAD) &&
- (field32(elf, elf->segments[i].p_filesz) != 0))
- image->num_sections++;
-
- assert(image->num_sections > 0);
-
- /**
- * some ELF linkers produce binaries with *all* the program header
- * p_paddr fields zero (there can be however one loadable segment
- * that has valid physical address 0x0).
- * If we have such a binary with more than
- * one PT_LOAD header, then use p_vaddr instead of p_paddr
- * (ARM ELF standard demands p_paddr = 0 anyway, and BFD
- * library uses this approach to workaround zero-initialized p_paddrs
- * when obtaining lma - look at elf.c of BDF)
- */
- for (nload = 0, i = 0; i < elf->segment_count; i++)
- if (elf->segments[i].p_paddr != 0)
- break;
- else if ((field32(elf,
- elf->segments[i].p_type) == PT_LOAD) &&
- (field32(elf, elf->segments[i].p_memsz) != 0))
- ++nload;
-
- if (i >= elf->segment_count && nload > 1)
- load_to_vaddr = 1;
-
- /* alloc and fill sections array with loadable segments */
- image->sections = malloc(image->num_sections * sizeof(struct imagesection));
- for (i = 0, j = 0; i < elf->segment_count; i++) {
- if ((field32(elf,
- elf->segments[i].p_type) == PT_LOAD) &&
- (field32(elf, elf->segments[i].p_filesz) != 0)) {
- image->sections[j].size = field32(elf, elf->segments[i].p_filesz);
- if (load_to_vaddr)
- image->sections[j].base_address = field32(elf,
- elf->segments[i].p_vaddr);
- else
- image->sections[j].base_address = field32(elf,
- elf->segments[i].p_paddr);
- image->sections[j].private = &elf->segments[i];
- image->sections[j].flags = field32(elf, elf->segments[i].p_flags);
- j++;
- }
- }
-
- image->start_address_set = 1;
- image->start_address = field32(elf, elf->header->e_entry);
-
- return ERROR_OK;
-}
-
-static int image_elf_read_section(struct image *image,
- int section,
- uint32_t offset,
- uint32_t size,
- uint8_t *buffer,
- size_t *size_read)
-{
- struct image_elf *elf = image->type_private;
- Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private;
- size_t read_size, really_read;
- int retval;
-
- *size_read = 0;
-
- LOG_DEBUG("load segment %d at 0x%" PRIx32 " (sz = 0x%" PRIx32 ")", section, offset, size);
-
- /* read initialized data in current segment if any */
- if (offset < field32(elf, segment->p_filesz)) {
- /* maximal size present in file for the current segment */
- read_size = MIN(size, field32(elf, segment->p_filesz) - offset);
- LOG_DEBUG("read elf: size = 0x%zu at 0x%" PRIx32 "", read_size,
- field32(elf, segment->p_offset) + offset);
- /* read initialized area of the segment */
- retval = fileio_seek(elf->fileio, field32(elf, segment->p_offset) + offset);
- if (retval != ERROR_OK) {
- LOG_ERROR("cannot find ELF segment content, seek failed");
- return retval;
- }
- retval = fileio_read(elf->fileio, read_size, buffer, &really_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("cannot read ELF segment content, read failed");
- return retval;
- }
- size -= read_size;
- *size_read += read_size;
- /* need more data ? */
- if (!size)
- return ERROR_OK;
- }
-
- return ERROR_OK;
-}
-
-static int image_mot_buffer_complete_inner(struct image *image,
- char *lpszLine,
- struct imagesection *section)
-{
- struct image_mot *mot = image->type_private;
- struct fileio *fileio = mot->fileio;
- uint32_t full_address = 0x0;
- uint32_t cooked_bytes;
- int i;
-
- /* we can't determine the number of sections that we'll have to create ahead of time,
- * so we locally hold them until parsing is finished */
-
- int retval;
- size_t filesize;
- retval = fileio_size(fileio, &filesize);
- if (retval != ERROR_OK)
- return retval;
-
- mot->buffer = malloc(filesize >> 1);
- cooked_bytes = 0x0;
- image->num_sections = 0;
- section[image->num_sections].private = &mot->buffer[cooked_bytes];
- section[image->num_sections].base_address = 0x0;
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
-
- while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
- uint32_t count;
- uint32_t address;
- uint32_t record_type;
- uint32_t checksum;
- uint8_t cal_checksum = 0;
- uint32_t bytes_read = 0;
-
- /* get record type and record length */
- if (sscanf(&lpszLine[bytes_read], "S%1" SCNx32 "%2" SCNx32, &record_type,
- &count) != 2)
- return ERROR_IMAGE_FORMAT_ERROR;
-
- bytes_read += 4;
- cal_checksum += (uint8_t)count;
-
- /* skip checksum byte */
- count -= 1;
-
- if (record_type == 0) {
- /* S0 - starting record (optional) */
- int iValue;
-
- while (count-- > 0) {
- sscanf(&lpszLine[bytes_read], "%2x", &iValue);
- cal_checksum += (uint8_t)iValue;
- bytes_read += 2;
- }
- } else if (record_type >= 1 && record_type <= 3) {
- switch (record_type) {
- case 1:
- /* S1 - 16 bit address data record */
- sscanf(&lpszLine[bytes_read], "%4" SCNx32, &address);
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- bytes_read += 4;
- count -= 2;
- break;
-
- case 2:
- /* S2 - 24 bit address data record */
- sscanf(&lpszLine[bytes_read], "%6" SCNx32, &address);
- cal_checksum += (uint8_t)(address >> 16);
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- bytes_read += 6;
- count -= 3;
- break;
-
- case 3:
- /* S3 - 32 bit address data record */
- sscanf(&lpszLine[bytes_read], "%8" SCNx32, &address);
- cal_checksum += (uint8_t)(address >> 24);
- cal_checksum += (uint8_t)(address >> 16);
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- bytes_read += 8;
- count -= 4;
- break;
-
- }
-
- if (full_address != address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &mot->buffer[cooked_bytes];
- }
- section[image->num_sections].base_address = address;
- full_address = address;
- }
-
- while (count-- > 0) {
- unsigned value;
- sscanf(&lpszLine[bytes_read], "%2x", &value);
- mot->buffer[cooked_bytes] = (uint8_t)value;
- cal_checksum += (uint8_t)mot->buffer[cooked_bytes];
- bytes_read += 2;
- cooked_bytes += 1;
- section[image->num_sections].size += 1;
- full_address++;
- }
- } else if (record_type == 5) {
- /* S5 is the data count record, we ignore it */
- uint32_t dummy;
-
- while (count-- > 0) {
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
- cal_checksum += (uint8_t)dummy;
- bytes_read += 2;
- }
- } else if (record_type >= 7 && record_type <= 9) {
- /* S7, S8, S9 - ending records for 32, 24 and 16bit */
- image->num_sections++;
-
- /* copy section information */
- image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
- for (i = 0; i < image->num_sections; i++) {
- image->sections[i].private = section[i].private;
- image->sections[i].base_address = section[i].base_address;
- image->sections[i].size = section[i].size;
- image->sections[i].flags = section[i].flags;
- }
-
- return ERROR_OK;
- } else {
- LOG_ERROR("unhandled S19 record type: %i", (int)(record_type));
- return ERROR_IMAGE_FORMAT_ERROR;
- }
-
- /* account for checksum, will always be 0xFF */
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
- cal_checksum += (uint8_t)checksum;
-
- if (cal_checksum != 0xFF) {
- /* checksum failed */
- LOG_ERROR("incorrect record checksum found in S19 file");
- return ERROR_IMAGE_CHECKSUM;
- }
- }
-
- LOG_ERROR("premature end of S19 file, no end-of-file record found");
- return ERROR_IMAGE_FORMAT_ERROR;
-}
-
-/**
- * Allocate memory dynamically instead of on the stack. This
- * is important w/embedded hosts.
- */
-static int image_mot_buffer_complete(struct image *image)
-{
- char *lpszLine = malloc(1023);
- if (lpszLine == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS);
- if (section == NULL) {
- free(lpszLine);
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- int retval;
-
- retval = image_mot_buffer_complete_inner(image, lpszLine, section);
-
- free(section);
- free(lpszLine);
-
- return retval;
-}
-
-int image_open(struct image *image, const char *url, const char *type_string)
-{
- int retval = ERROR_OK;
-
- retval = identify_image_type(image, type_string, url);
- if (retval != ERROR_OK)
- return retval;
-
- if (image->type == IMAGE_BINARY) {
- struct image_binary *image_binary;
-
- image_binary = image->type_private = malloc(sizeof(struct image_binary));
-
- retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY);
- if (retval != ERROR_OK)
- return retval;
- size_t filesize;
- retval = fileio_size(image_binary->fileio, &filesize);
- if (retval != ERROR_OK) {
- fileio_close(image_binary->fileio);
- return retval;
- }
-
- image->num_sections = 1;
- image->sections = malloc(sizeof(struct imagesection));
- image->sections[0].base_address = 0x0;
- image->sections[0].size = filesize;
- image->sections[0].flags = 0;
- } else if (image->type == IMAGE_IHEX) {
- struct image_ihex *image_ihex;
-
- image_ihex = image->type_private = malloc(sizeof(struct image_ihex));
-
- retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = image_ihex_buffer_complete(image);
- if (retval != ERROR_OK) {
- LOG_ERROR(
- "failed buffering IHEX image, check daemon output for additional information");
- fileio_close(image_ihex->fileio);
- return retval;
- }
- } else if (image->type == IMAGE_ELF) {
- struct image_elf *image_elf;
-
- image_elf = image->type_private = malloc(sizeof(struct image_elf));
-
- retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY);
- if (retval != ERROR_OK)
- return retval;
-
- retval = image_elf_read_headers(image);
- if (retval != ERROR_OK) {
- fileio_close(image_elf->fileio);
- return retval;
- }
- } else if (image->type == IMAGE_MEMORY) {
- struct target *target = get_target(url);
-
- if (target == NULL) {
- LOG_ERROR("target '%s' not defined", url);
- return ERROR_FAIL;
- }
-
- struct image_memory *image_memory;
-
- image->num_sections = 1;
- image->sections = malloc(sizeof(struct imagesection));
- image->sections[0].base_address = 0x0;
- image->sections[0].size = 0xffffffff;
- image->sections[0].flags = 0;
-
- image_memory = image->type_private = malloc(sizeof(struct image_memory));
-
- image_memory->target = target;
- image_memory->cache = NULL;
- image_memory->cache_address = 0x0;
- } else if (image->type == IMAGE_SRECORD) {
- struct image_mot *image_mot;
-
- image_mot = image->type_private = malloc(sizeof(struct image_mot));
-
- retval = fileio_open(&image_mot->fileio, url, FILEIO_READ, FILEIO_TEXT);
- if (retval != ERROR_OK)
- return retval;
-
- retval = image_mot_buffer_complete(image);
- if (retval != ERROR_OK) {
- LOG_ERROR(
- "failed buffering S19 image, check daemon output for additional information");
- fileio_close(image_mot->fileio);
- return retval;
- }
- } else if (image->type == IMAGE_BUILDER) {
- image->num_sections = 0;
- image->base_address_set = 0;
- image->sections = NULL;
- image->type_private = NULL;
- }
-
- if (image->base_address_set) {
- /* relocate */
- int section;
- for (section = 0; section < image->num_sections; section++)
- image->sections[section].base_address += image->base_address;
- /* we're done relocating. The two statements below are mainly
- * for documenation purposes: stop anyone from empirically
- * thinking they should use these values henceforth. */
- image->base_address = 0;
- image->base_address_set = 0;
- }
-
- return retval;
-};
-
-int image_read_section(struct image *image,
- int section,
- uint32_t offset,
- uint32_t size,
- uint8_t *buffer,
- size_t *size_read)
-{
- int retval;
-
- /* don't read past the end of a section */
- if (offset + size > image->sections[section].size) {
- LOG_DEBUG(
- "read past end of section: 0x%8.8" PRIx32 " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "",
- offset,
- size,
- image->sections[section].size);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (image->type == IMAGE_BINARY) {
- struct image_binary *image_binary = image->type_private;
-
- /* only one section in a plain binary */
- if (section != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* seek to offset */
- retval = fileio_seek(image_binary->fileio, offset);
- if (retval != ERROR_OK)
- return retval;
-
- /* return requested bytes */
- retval = fileio_read(image_binary->fileio, size, buffer, size_read);
- if (retval != ERROR_OK)
- return retval;
- } else if (image->type == IMAGE_IHEX) {
- memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size);
- *size_read = size;
-
- return ERROR_OK;
- } else if (image->type == IMAGE_ELF)
- return image_elf_read_section(image, section, offset, size, buffer, size_read);
- else if (image->type == IMAGE_MEMORY) {
- struct image_memory *image_memory = image->type_private;
- uint32_t address = image->sections[section].base_address + offset;
-
- *size_read = 0;
-
- while ((size - *size_read) > 0) {
- uint32_t size_in_cache;
-
- if (!image_memory->cache
- || (address < image_memory->cache_address)
- || (address >=
- (image_memory->cache_address + IMAGE_MEMORY_CACHE_SIZE))) {
- if (!image_memory->cache)
- image_memory->cache = malloc(IMAGE_MEMORY_CACHE_SIZE);
-
- if (target_read_buffer(image_memory->target, address &
- ~(IMAGE_MEMORY_CACHE_SIZE - 1),
- IMAGE_MEMORY_CACHE_SIZE, image_memory->cache) != ERROR_OK) {
- free(image_memory->cache);
- image_memory->cache = NULL;
- return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE;
- }
- image_memory->cache_address = address &
- ~(IMAGE_MEMORY_CACHE_SIZE - 1);
- }
-
- size_in_cache =
- (image_memory->cache_address + IMAGE_MEMORY_CACHE_SIZE) - address;
-
- memcpy(buffer + *size_read,
- image_memory->cache + (address - image_memory->cache_address),
- (size_in_cache > size) ? size : size_in_cache
- );
-
- *size_read += (size_in_cache > size) ? size : size_in_cache;
- address += (size_in_cache > size) ? size : size_in_cache;
- }
- } else if (image->type == IMAGE_SRECORD) {
- memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size);
- *size_read = size;
-
- return ERROR_OK;
- } else if (image->type == IMAGE_BUILDER) {
- memcpy(buffer, (uint8_t *)image->sections[section].private + offset, size);
- *size_read = size;
-
- return ERROR_OK;
- }
-
- return ERROR_OK;
-}
-
-int image_add_section(struct image *image, uint32_t base, uint32_t size, int flags, uint8_t const *data)
-{
- struct imagesection *section;
-
- /* only image builder supports adding sections */
- if (image->type != IMAGE_BUILDER)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* see if there's a previous section */
- if (image->num_sections) {
- section = &image->sections[image->num_sections - 1];
-
- /* see if it's enough to extend the last section,
- * adding data to previous sections or merging is not supported */
- if (((section->base_address + section->size) == base) &&
- (section->flags == flags)) {
- section->private = realloc(section->private, section->size + size);
- memcpy((uint8_t *)section->private + section->size, data, size);
- section->size += size;
- return ERROR_OK;
- }
- }
-
- /* allocate new section */
- image->num_sections++;
- image->sections =
- realloc(image->sections, sizeof(struct imagesection) * image->num_sections);
- section = &image->sections[image->num_sections - 1];
- section->base_address = base;
- section->size = size;
- section->flags = flags;
- section->private = malloc(sizeof(uint8_t) * size);
- memcpy((uint8_t *)section->private, data, size);
-
- return ERROR_OK;
-}
-
-void image_close(struct image *image)
-{
- if (image->type == IMAGE_BINARY) {
- struct image_binary *image_binary = image->type_private;
-
- fileio_close(image_binary->fileio);
- } else if (image->type == IMAGE_IHEX) {
- struct image_ihex *image_ihex = image->type_private;
-
- fileio_close(image_ihex->fileio);
-
- if (image_ihex->buffer) {
- free(image_ihex->buffer);
- image_ihex->buffer = NULL;
- }
- } else if (image->type == IMAGE_ELF) {
- struct image_elf *image_elf = image->type_private;
-
- fileio_close(image_elf->fileio);
-
- if (image_elf->header) {
- free(image_elf->header);
- image_elf->header = NULL;
- }
-
- if (image_elf->segments) {
- free(image_elf->segments);
- image_elf->segments = NULL;
- }
- } else if (image->type == IMAGE_MEMORY) {
- struct image_memory *image_memory = image->type_private;
-
- if (image_memory->cache) {
- free(image_memory->cache);
- image_memory->cache = NULL;
- }
- } else if (image->type == IMAGE_SRECORD) {
- struct image_mot *image_mot = image->type_private;
-
- fileio_close(image_mot->fileio);
-
- if (image_mot->buffer) {
- free(image_mot->buffer);
- image_mot->buffer = NULL;
- }
- } else if (image->type == IMAGE_BUILDER) {
- int i;
-
- for (i = 0; i < image->num_sections; i++) {
- free(image->sections[i].private);
- image->sections[i].private = NULL;
- }
- }
-
- if (image->type_private) {
- free(image->type_private);
- image->type_private = NULL;
- }
-
- if (image->sections) {
- free(image->sections);
- image->sections = NULL;
- }
-}
-
-int image_calculate_checksum(uint8_t *buffer, uint32_t nbytes, uint32_t *checksum)
-{
- uint32_t crc = 0xffffffff;
- LOG_DEBUG("Calculating checksum");
-
- static uint32_t crc32_table[256];
-
- static bool first_init;
- if (!first_init) {
- /* Initialize the CRC table and the decoding table. */
- int i, j;
- unsigned int c;
- for (i = 0; i < 256; i++) {
- /* as per gdb */
- for (c = i << 24, j = 8; j > 0; --j)
- c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
- crc32_table[i] = c;
- }
-
- first_init = true;
- }
-
- while (nbytes > 0) {
- int run = nbytes;
- if (run > 32768)
- run = 32768;
- nbytes -= run;
- while (run--) {
- /* as per gdb */
- crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buffer++) & 255];
- }
- keep_alive();
- }
-
- LOG_DEBUG("Calculating checksum done");
-
- *checksum = crc;
- return ERROR_OK;
-}
diff --git a/src/target/image.h b/src/target/image.h
deleted file mode 100644
index 9bf7af3..0000000
--- a/src/target/image.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_IMAGE_H
-#define OPENOCD_TARGET_IMAGE_H
-
-#include <helper/fileio.h>
-
-#ifdef HAVE_ELF_H
-#include <elf.h>
-#endif
-
-#define IMAGE_MAX_ERROR_STRING (256)
-#define IMAGE_MAX_SECTIONS (512)
-
-#define IMAGE_MEMORY_CACHE_SIZE (2048)
-
-enum image_type {
- IMAGE_BINARY, /* plain binary */
- IMAGE_IHEX, /* intel hex-record format */
- IMAGE_MEMORY, /* target-memory pseudo-image */
- IMAGE_ELF, /* ELF binary */
- IMAGE_SRECORD, /* motorola s19 */
- IMAGE_BUILDER, /* when building a new image */
-};
-
-struct imagesection {
- uint32_t base_address;
- uint32_t size;
- int flags;
- void *private; /* private data */
-};
-
-struct image {
- enum image_type type; /* image type (plain, ihex, ...) */
- void *type_private; /* type private data */
- int num_sections; /* number of sections contained in the image */
- struct imagesection *sections; /* array of sections */
- int base_address_set; /* whether the image has a base address set (for relocation purposes) */
- long long base_address; /* base address, if one is set */
- int start_address_set; /* whether the image has a start address (entry point) associated */
- uint32_t start_address; /* start address, if one is set */
-};
-
-struct image_binary {
- struct fileio *fileio;
-};
-
-struct image_ihex {
- struct fileio *fileio;
- uint8_t *buffer;
-};
-
-struct image_memory {
- struct target *target;
- uint8_t *cache;
- uint32_t cache_address;
-};
-
-struct image_elf {
- struct fileio *fileio;
- Elf32_Ehdr *header;
- Elf32_Phdr *segments;
- uint32_t segment_count;
- uint8_t endianness;
-};
-
-struct image_mot {
- struct fileio *fileio;
- uint8_t *buffer;
-};
-
-int image_open(struct image *image, const char *url, const char *type_string);
-int image_read_section(struct image *image, int section, uint32_t offset,
- uint32_t size, uint8_t *buffer, size_t *size_read);
-void image_close(struct image *image);
-
-int image_add_section(struct image *image, uint32_t base, uint32_t size,
- int flags, uint8_t const *data);
-
-int image_calculate_checksum(uint8_t *buffer, uint32_t nbytes,
- uint32_t *checksum);
-
-#define ERROR_IMAGE_FORMAT_ERROR (-1400)
-#define ERROR_IMAGE_TYPE_UNKNOWN (-1401)
-#define ERROR_IMAGE_TEMPORARILY_UNAVAILABLE (-1402)
-#define ERROR_IMAGE_CHECKSUM (-1403)
-
-#endif /* OPENOCD_TARGET_IMAGE_H */
diff --git a/src/target/lakemont.c b/src/target/lakemont.c
deleted file mode 100644
index 27efc69..0000000
--- a/src/target/lakemont.c
+++ /dev/null
@@ -1,1125 +0,0 @@
-/*
- * Copyright(c) 2013-2016 Intel Corporation.
- *
- * Adrian Burns (adrian.burns@intel.com)
- * Thomas Faust (thomas.faust@intel.com)
- * Ivan De Cesaris (ivan.de.cesaris@intel.com)
- * Julien Carreno (julien.carreno@intel.com)
- * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
- * Jessica Gomez (jessica.gomez.hernandez@intel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Contact Information:
- * Intel Corporation
- */
-
-/*
- * @file
- * This implements the probemode operations for Lakemont 1 (LMT1).
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-
-#include "target.h"
-#include "target_type.h"
-#include "lakemont.h"
-#include "register.h"
-#include "breakpoints.h"
-#include "x86_32_common.h"
-
-static int irscan(struct target *t, uint8_t *out,
- uint8_t *in, uint8_t ir_len);
-static int drscan(struct target *t, uint8_t *out, uint8_t *in, uint8_t len);
-static int save_context(struct target *target);
-static int restore_context(struct target *target);
-static uint32_t get_tapstatus(struct target *t);
-static int enter_probemode(struct target *t);
-static int exit_probemode(struct target *t);
-static int halt_prep(struct target *t);
-static int do_halt(struct target *t);
-static int do_resume(struct target *t);
-static int read_all_core_hw_regs(struct target *t);
-static int write_all_core_hw_regs(struct target *t);
-static int read_hw_reg(struct target *t,
- int reg, uint32_t *regval, uint8_t cache);
-static int write_hw_reg(struct target *t,
- int reg, uint32_t regval, uint8_t cache);
-static struct reg_cache *lakemont_build_reg_cache
- (struct target *target);
-static int submit_reg_pir(struct target *t, int num);
-static int submit_instruction_pir(struct target *t, int num);
-static int submit_pir(struct target *t, uint64_t op);
-static int lakemont_get_core_reg(struct reg *reg);
-static int lakemont_set_core_reg(struct reg *reg, uint8_t *buf);
-
-static struct scan_blk scan;
-
-/* registers and opcodes for register access, pm_idx is used to identify the
- * registers that are modified for lakemont probemode specific operations
- */
-static const struct {
- uint8_t id;
- const char *name;
- uint64_t op;
- uint8_t pm_idx;
- unsigned bits;
- enum reg_type type;
- const char *group;
- const char *feature;
-} regs[] = {
- /* general purpose registers */
- { EAX, "eax", 0x000000D01D660000, 0, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ECX, "ecx", 0x000000501D660000, 1, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { EDX, "edx", 0x000000901D660000, 2, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { EBX, "ebx", 0x000000101D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ESP, "esp", 0x000000E01D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
- { EBP, "ebp", 0x000000601D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
- { ESI, "esi", 0x000000A01D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { EDI, "edi", 0x000000201D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
-
- /* instruction pointer & flags */
- { EIP, "eip", 0x000000C01D660000, 3, 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.i386.core" },
- { EFLAGS, "eflags", 0x000000401D660000, 4, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
-
- /* segment registers */
- { CS, "cs", 0x000000281D660000, 5, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { SS, "ss", 0x000000C81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { DS, "ds", 0x000000481D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ES, "es", 0x000000A81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FS, "fs", 0x000000881D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { GS, "gs", 0x000000081D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
-
- /* floating point unit registers - not accessible via JTAG - here to satisfy GDB */
- { ST0, "st0", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ST1, "st1", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ST2, "st2", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ST3, "st3", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ST4, "st4", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ST5, "st5", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ST6, "st6", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { ST7, "st7", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FCTRL, "fctrl", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FSTAT, "fstat", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FTAG, "ftag", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FISEG, "fiseg", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FIOFF, "fioff", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FOSEG, "foseg", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FOOFF, "fooff", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
- { FOP, "fop", 0x0, NOT_AVAIL_REG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
-
- /* control registers */
- { CR0, "cr0", 0x000000001D660000, 6, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { CR2, "cr2", 0x000000BC1D660000, 7, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { CR3, "cr3", 0x000000801D660000, 8, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { CR4, "cr4", 0x0000002C1D660000, 9, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
-
- /* debug registers */
- { DR0, "dr0", 0x0000007C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DR1, "dr1", 0x000000FC1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DR2, "dr2", 0x000000021D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DR3, "dr3", 0x000000821D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DR6, "dr6", 0x000000301D660000, 10, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DR7, "dr7", 0x000000B01D660000, 11, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
-
- /* descriptor tables */
- { IDTB, "idtbase", 0x000000581D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { IDTL, "idtlimit", 0x000000D81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { IDTAR, "idtar", 0x000000981D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { GDTB, "gdtbase", 0x000000B81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { GDTL, "gdtlimit", 0x000000781D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { GDTAR, "gdtar", 0x000000381D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { TR, "tr", 0x000000701D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { LDTR, "ldtr", 0x000000F01D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { LDTB, "ldbase", 0x000000041D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { LDTL, "ldlimit", 0x000000841D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { LDTAR, "ldtar", 0x000000F81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
-
- /* segment registers */
- { CSB, "csbase", 0x000000F41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { CSL, "cslimit", 0x0000000C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { CSAR, "csar", 0x000000741D660000, 12, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DSB, "dsbase", 0x000000941D660000, 13, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DSL, "dslimit", 0x000000541D660000, 14, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { DSAR, "dsar", 0x000000141D660000, 15, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { ESB, "esbase", 0x0000004C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { ESL, "eslimit", 0x000000CC1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { ESAR, "esar", 0x0000008C1D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { FSB, "fsbase", 0x000000641D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { FSL, "fslimit", 0x000000E41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { FSAR, "fsar", 0x000000A41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { GSB, "gsbase", 0x000000C41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { GSL, "gslimit", 0x000000241D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { GSAR, "gsar", 0x000000441D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { SSB, "ssbase", 0x000000341D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { SSL, "sslimit", 0x000000B41D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { SSAR, "ssar", 0x000000D41D660000, 16, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { TSSB, "tssbase", 0x000000E81D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { TSSL, "tsslimit", 0x000000181D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- { TSSAR, "tssar", 0x000000681D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
- /* probemode control register */
- { PMCR, "pmcr", 0x000000421D660000, 17, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.sys" },
-};
-
-static const struct {
- uint8_t id;
- const char *name;
- uint64_t op;
-} instructions[] = {
- /* memory read/write */
- { MEMRDB32, "MEMRDB32", 0x0909090909090851 },
- { MEMRDB16, "MEMRDB16", 0x09090909090851E6 },
- { MEMRDH32, "MEMRDH32", 0x090909090908D166 },
- { MEMRDH16, "MEMRDH16", 0x090909090908D1E6 },
- { MEMRDW32, "MEMRDW32", 0x09090909090908D1 },
- { MEMRDW16, "MEMRDW16", 0x0909090908D1E666 },
- { MEMWRB32, "MEMWRB32", 0x0909090909090811 },
- { MEMWRB16, "MEMWRB16", 0x09090909090811E6 },
- { MEMWRH32, "MEMWRH32", 0x0909090909089166 },
- { MEMWRH16, "MEMWRH16", 0x09090909090891E6 },
- { MEMWRW32, "MEMWRW32", 0x0909090909090891 },
- { MEMWRW16, "MEMWRW16", 0x090909090891E666 },
- /* IO read/write */
- { IORDB32, "IORDB32", 0x0909090909090937 },
- { IORDB16, "IORDB16", 0x09090909090937E6 },
- { IORDH32, "IORDH32", 0x090909090909B766 },
- { IORDH16, "IORDH16", 0x090909090909B7E6 },
- { IORDW32, "IORDW32", 0x09090909090909B7 },
- { IORDW16, "IORDW16", 0x0909090909B7E666 },
- { IOWRB32, "IOWRB32", 0x0909090909090977 },
- { IOWRB16, "IOWRB16", 0x09090909090977E6 },
- { IOWRH32, "IOWRH32", 0x090909090909F766 },
- { IOWRH16, "IOWRH16", 0x090909090909F7E6 },
- { IOWRW32, "IOWRW32", 0x09090909090909F7 },
- { IOWRW16, "IOWRW16", 0x0909090909F7E666 },
- /* lakemont1 core shadow ram access opcodes */
- { SRAMACCESS, "SRAMACCESS", 0x0000000E9D660000 },
- { SRAM2PDR, "SRAM2PDR", 0x4CF0000000000000 },
- { PDR2SRAM, "PDR2SRAM", 0x0CF0000000000000 },
- { WBINVD, "WBINVD", 0x09090909090990F0 },
-};
-
-bool check_not_halted(const struct target *t)
-{
- bool halted = t->state == TARGET_HALTED;
- if (!halted)
- LOG_ERROR("target running, halt it first");
- return !halted;
-}
-
-static int irscan(struct target *t, uint8_t *out,
- uint8_t *in, uint8_t ir_len)
-{
- int retval = ERROR_OK;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- if (NULL == t->tap) {
- retval = ERROR_FAIL;
- LOG_ERROR("%s invalid target tap", __func__);
- return retval;
- }
- if (ir_len != t->tap->ir_length) {
- retval = ERROR_FAIL;
- if (t->tap->enabled)
- LOG_ERROR("%s tap enabled but tap irlen=%d",
- __func__, t->tap->ir_length);
- else
- LOG_ERROR("%s tap not enabled and irlen=%d",
- __func__, t->tap->ir_length);
- return retval;
- }
- struct scan_field *fields = &scan.field;
- fields->num_bits = ir_len;
- fields->out_value = out;
- fields->in_value = in;
- jtag_add_ir_scan(x86_32->curr_tap, fields, TAP_IDLE);
- if (x86_32->flush) {
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- LOG_ERROR("%s failed to execute queue", __func__);
- }
- return retval;
-}
-
-static int drscan(struct target *t, uint8_t *out, uint8_t *in, uint8_t len)
-{
- int retval = ERROR_OK;
- uint64_t data = 0;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- if (NULL == t->tap) {
- retval = ERROR_FAIL;
- LOG_ERROR("%s invalid target tap", __func__);
- return retval;
- }
- if (len > MAX_SCAN_SIZE || 0 == len) {
- retval = ERROR_FAIL;
- LOG_ERROR("%s data len is %d bits, max is %d bits",
- __func__, len, MAX_SCAN_SIZE);
- return retval;
- }
- struct scan_field *fields = &scan.field;
- fields->out_value = out;
- fields->in_value = in;
- fields->num_bits = len;
- jtag_add_dr_scan(x86_32->curr_tap, 1, fields, TAP_IDLE);
- if (x86_32->flush) {
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("%s drscan failed to execute queue", __func__);
- return retval;
- }
- }
- if (in != NULL) {
- if (len >= 8) {
- for (int n = (len / 8) - 1 ; n >= 0; n--)
- data = (data << 8) + *(in+n);
- } else
- LOG_DEBUG("dr in 0x%02" PRIx8, *in);
- } else {
- LOG_ERROR("%s no drscan data", __func__);
- retval = ERROR_FAIL;
- }
- return retval;
-}
-
-static int save_context(struct target *t)
-{
- int err;
- /* read core registers from lakemont sram */
- err = read_all_core_hw_regs(t);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error reading regs", __func__);
- return err;
- }
- return ERROR_OK;
-}
-
-static int restore_context(struct target *t)
-{
- int err = ERROR_OK;
- uint32_t i;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- /* write core regs into the core PM SRAM from the reg_cache */
- err = write_all_core_hw_regs(t);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error writing regs", __func__);
- return err;
- }
-
- for (i = 0; i < (x86_32->cache->num_regs); i++) {
- x86_32->cache->reg_list[i].dirty = 0;
- x86_32->cache->reg_list[i].valid = 0;
- }
- return err;
-}
-
-/*
- * we keep reg_cache in sync with hardware at halt/resume time, we avoid
- * writing to real hardware here bacause pm_regs reflects the hardware
- * while we are halted then reg_cache syncs with hw on resume
- * TODO - in order for "reg eip force" to work it assume get/set reads
- * and writes from hardware, may be other reasons also because generally
- * other openocd targets read/write from hardware in get/set - watch this!
- */
-static int lakemont_get_core_reg(struct reg *reg)
-{
- int retval = ERROR_OK;
- struct lakemont_core_reg *lakemont_reg = reg->arch_info;
- struct target *t = lakemont_reg->target;
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- LOG_DEBUG("reg=%s, value=0x%08" PRIx32, reg->name,
- buf_get_u32(reg->value, 0, 32));
- return retval;
-}
-
-static int lakemont_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- struct lakemont_core_reg *lakemont_reg = reg->arch_info;
- struct target *t = lakemont_reg->target;
- uint32_t value = buf_get_u32(buf, 0, 32);
- LOG_DEBUG("reg=%s, newval=0x%08" PRIx32, reg->name, value);
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- buf_set_u32(reg->value, 0, 32, value);
- reg->dirty = 1;
- reg->valid = 1;
- return ERROR_OK;
-}
-
-static const struct reg_arch_type lakemont_reg_type = {
- /* these get called if reg_cache doesnt have a "valid" value
- * of an individual reg eg "reg eip" but not for "reg" block
- */
- .get = lakemont_get_core_reg,
- .set = lakemont_set_core_reg,
-};
-
-struct reg_cache *lakemont_build_reg_cache(struct target *t)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- int num_regs = ARRAY_SIZE(regs);
- struct reg_cache **cache_p = register_get_last_cache_p(&t->reg_cache);
- struct reg_cache *cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
- struct lakemont_core_reg *arch_info = malloc(sizeof(struct lakemont_core_reg) * num_regs);
- struct reg_feature *feature;
- int i;
-
- if (cache == NULL || reg_list == NULL || arch_info == NULL) {
- free(cache);
- free(reg_list);
- free(arch_info);
- LOG_ERROR("%s out of memory", __func__);
- return NULL;
- }
-
- /* Build the process context cache */
- cache->name = "lakemont registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = num_regs;
- (*cache_p) = cache;
- x86_32->cache = cache;
-
- for (i = 0; i < num_regs; i++) {
- arch_info[i].target = t;
- arch_info[i].x86_32_common = x86_32;
- arch_info[i].op = regs[i].op;
- arch_info[i].pm_idx = regs[i].pm_idx;
- reg_list[i].name = regs[i].name;
- reg_list[i].size = 32;
- reg_list[i].value = calloc(1, 4);
- reg_list[i].dirty = 0;
- reg_list[i].valid = 0;
- reg_list[i].type = &lakemont_reg_type;
- reg_list[i].arch_info = &arch_info[i];
-
- reg_list[i].group = regs[i].group;
- reg_list[i].number = i;
- reg_list[i].exist = true;
- reg_list[i].caller_save = true; /* gdb defaults to true */
-
- feature = calloc(1, sizeof(struct reg_feature));
- if (feature) {
- feature->name = regs[i].feature;
- reg_list[i].feature = feature;
- } else
- LOG_ERROR("%s unable to allocate feature list", __func__);
-
- reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
- if (reg_list[i].reg_data_type)
- reg_list[i].reg_data_type->type = regs[i].type;
- else
- LOG_ERROR("%s unable to allocate reg type list", __func__);
- }
- return cache;
-}
-
-static uint32_t get_tapstatus(struct target *t)
-{
- scan.out[0] = TAPSTATUS;
- if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
- return 0;
- if (drscan(t, NULL, scan.out, TS_SIZE) != ERROR_OK)
- return 0;
- return buf_get_u32(scan.out, 0, 32);
-}
-
-static int enter_probemode(struct target *t)
-{
- uint32_t tapstatus = 0;
- tapstatus = get_tapstatus(t);
- LOG_DEBUG("TS before PM enter = 0x%08" PRIx32, tapstatus);
- if (tapstatus & TS_PM_BIT) {
- LOG_DEBUG("core already in probemode");
- return ERROR_OK;
- }
- scan.out[0] = PROBEMODE;
- if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
- return ERROR_FAIL;
- scan.out[0] = 1;
- if (drscan(t, scan.out, scan.in, 1) != ERROR_OK)
- return ERROR_FAIL;
- tapstatus = get_tapstatus(t);
- LOG_DEBUG("TS after PM enter = 0x%08" PRIx32, tapstatus);
- if ((tapstatus & TS_PM_BIT) && (!(tapstatus & TS_EN_PM_BIT)))
- return ERROR_OK;
- else {
- LOG_ERROR("%s PM enter error, tapstatus = 0x%08" PRIx32
- , __func__, tapstatus);
- return ERROR_FAIL;
- }
-}
-
-static int exit_probemode(struct target *t)
-{
- uint32_t tapstatus = get_tapstatus(t);
- LOG_DEBUG("TS before PM exit = 0x%08" PRIx32, tapstatus);
-
- if (!(tapstatus & TS_PM_BIT)) {
- LOG_USER("core not in PM");
- return ERROR_OK;
- }
- scan.out[0] = PROBEMODE;
- if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
- return ERROR_FAIL;
- scan.out[0] = 0;
- if (drscan(t, scan.out, scan.in, 1) != ERROR_OK)
- return ERROR_FAIL;
- return ERROR_OK;
-}
-
-/* do whats needed to properly enter probemode for debug on lakemont */
-static int halt_prep(struct target *t)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- if (write_hw_reg(t, DSB, PM_DSB, 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write %s 0x%08" PRIx32, regs[DSB].name, PM_DSB);
- if (write_hw_reg(t, DSL, PM_DSL, 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write %s 0x%08" PRIx32, regs[DSL].name, PM_DSL);
- if (write_hw_reg(t, DSAR, PM_DSAR, 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write DSAR 0x%08" PRIx32, PM_DSAR);
- if (write_hw_reg(t, CSB, PM_DSB, 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSB].name, PM_DSB);
- if (write_hw_reg(t, CSL, PM_DSL, 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSL].name, PM_DSL);
- if (write_hw_reg(t, DR7, PM_DR7, 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write DR7 0x%08" PRIx32, PM_DR7);
-
- uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32);
- uint32_t csar = buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32);
- uint32_t ssar = buf_get_u32(x86_32->cache->reg_list[SSAR].value, 0, 32);
- uint32_t cr0 = buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32);
-
- /* clear VM86 and IF bits if they are set */
- LOG_DEBUG("EFLAGS = 0x%08" PRIx32 ", VM86 = %d, IF = %d", eflags,
- eflags & EFLAGS_VM86 ? 1 : 0,
- eflags & EFLAGS_IF ? 1 : 0);
- if ((eflags & EFLAGS_VM86) || (eflags & EFLAGS_IF)) {
- x86_32->pm_regs[I(EFLAGS)] = eflags & ~(EFLAGS_VM86 | EFLAGS_IF);
- if (write_hw_reg(t, EFLAGS, x86_32->pm_regs[I(EFLAGS)], 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("EFLAGS now = 0x%08" PRIx32 ", VM86 = %d, IF = %d",
- x86_32->pm_regs[I(EFLAGS)],
- x86_32->pm_regs[I(EFLAGS)] & EFLAGS_VM86 ? 1 : 0,
- x86_32->pm_regs[I(EFLAGS)] & EFLAGS_IF ? 1 : 0);
- }
-
- /* set CPL to 0 for memory access */
- if (csar & CSAR_DPL) {
- x86_32->pm_regs[I(CSAR)] = csar & ~CSAR_DPL;
- if (write_hw_reg(t, CSAR, x86_32->pm_regs[I(CSAR)], 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write CSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(CSAR)]);
- }
- if (ssar & SSAR_DPL) {
- x86_32->pm_regs[I(SSAR)] = ssar & ~SSAR_DPL;
- if (write_hw_reg(t, SSAR, x86_32->pm_regs[I(SSAR)], 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("write SSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(SSAR)]);
- }
-
- /* if cache's are enabled, disable and flush, depending on the core version */
- if (!(x86_32->core_type == LMT3_5) && !(cr0 & CR0_CD)) {
- LOG_DEBUG("caching enabled CR0 = 0x%08" PRIx32, cr0);
- if (cr0 & CR0_PG) {
- x86_32->pm_regs[I(CR0)] = cr0 & ~CR0_PG;
- if (write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("cleared paging CR0_PG = 0x%08" PRIx32, x86_32->pm_regs[I(CR0)]);
- /* submit wbinvd to flush cache */
- if (submit_reg_pir(t, WBINVD) != ERROR_OK)
- return ERROR_FAIL;
- x86_32->pm_regs[I(CR0)] =
- x86_32->pm_regs[I(CR0)] | (CR0_CD | CR0_NW | CR0_PG);
- if (write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0) != ERROR_OK)
- return ERROR_FAIL;
- LOG_DEBUG("set CD, NW and PG, CR0 = 0x%08" PRIx32, x86_32->pm_regs[I(CR0)]);
- }
- }
- return ERROR_OK;
-}
-
-static int do_halt(struct target *t)
-{
- /* needs proper handling later if doing a halt errors out */
- t->state = TARGET_DEBUG_RUNNING;
- if (enter_probemode(t) != ERROR_OK)
- return ERROR_FAIL;
-
- return lakemont_update_after_probemode_entry(t);
-}
-
-/* we need to expose the update to be able to complete the reset at SoC level */
-int lakemont_update_after_probemode_entry(struct target *t)
-{
- if (save_context(t) != ERROR_OK)
- return ERROR_FAIL;
- if (halt_prep(t) != ERROR_OK)
- return ERROR_FAIL;
- t->state = TARGET_HALTED;
-
- return target_call_event_callbacks(t, TARGET_EVENT_HALTED);
-}
-
-static int do_resume(struct target *t)
-{
- /* needs proper handling later */
- t->state = TARGET_DEBUG_RUNNING;
- if (restore_context(t) != ERROR_OK)
- return ERROR_FAIL;
- if (exit_probemode(t) != ERROR_OK)
- return ERROR_FAIL;
- t->state = TARGET_RUNNING;
-
- t->debug_reason = DBG_REASON_NOTHALTED;
- LOG_USER("target running");
-
- return target_call_event_callbacks(t, TARGET_EVENT_RESUMED);
-}
-
-static int read_all_core_hw_regs(struct target *t)
-{
- int err;
- uint32_t regval;
- unsigned i;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- for (i = 0; i < (x86_32->cache->num_regs); i++) {
- if (NOT_AVAIL_REG == regs[i].pm_idx)
- continue;
- err = read_hw_reg(t, regs[i].id, &regval, 1);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error saving reg %s",
- __func__, x86_32->cache->reg_list[i].name);
- return err;
- }
- }
- LOG_DEBUG("read_all_core_hw_regs read %u registers ok", i);
- return ERROR_OK;
-}
-
-static int write_all_core_hw_regs(struct target *t)
-{
- int err;
- unsigned i;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- for (i = 0; i < (x86_32->cache->num_regs); i++) {
- if (NOT_AVAIL_REG == regs[i].pm_idx)
- continue;
- err = write_hw_reg(t, i, 0, 1);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error restoring reg %s",
- __func__, x86_32->cache->reg_list[i].name);
- return err;
- }
- }
- LOG_DEBUG("write_all_core_hw_regs wrote %u registers ok", i);
- return ERROR_OK;
-}
-
-/* read reg from lakemont core shadow ram, update reg cache if needed */
-static int read_hw_reg(struct target *t, int reg, uint32_t *regval, uint8_t cache)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- struct lakemont_core_reg *arch_info;
- arch_info = x86_32->cache->reg_list[reg].arch_info;
- x86_32->flush = 0; /* dont flush scans till we have a batch */
- if (submit_reg_pir(t, reg) != ERROR_OK)
- return ERROR_FAIL;
- if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK)
- return ERROR_FAIL;
- if (submit_instruction_pir(t, SRAM2PDR) != ERROR_OK)
- return ERROR_FAIL;
- x86_32->flush = 1;
- scan.out[0] = RDWRPDR;
- if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
- return ERROR_FAIL;
- if (drscan(t, NULL, scan.out, PDR_SIZE) != ERROR_OK)
- return ERROR_FAIL;
-
- jtag_add_sleep(DELAY_SUBMITPIR);
- *regval = buf_get_u32(scan.out, 0, 32);
- if (cache) {
- buf_set_u32(x86_32->cache->reg_list[reg].value, 0, 32, *regval);
- x86_32->cache->reg_list[reg].valid = 1;
- x86_32->cache->reg_list[reg].dirty = 0;
- }
- LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32,
- x86_32->cache->reg_list[reg].name,
- arch_info->op,
- *regval);
- return ERROR_OK;
-}
-
-/* write lakemont core shadow ram reg, update reg cache if needed */
-static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cache)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- struct lakemont_core_reg *arch_info;
- arch_info = x86_32->cache->reg_list[reg].arch_info;
-
- uint8_t reg_buf[4];
- if (cache)
- regval = buf_get_u32(x86_32->cache->reg_list[reg].value, 0, 32);
- buf_set_u32(reg_buf, 0, 32, regval);
- LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32,
- x86_32->cache->reg_list[reg].name,
- arch_info->op,
- regval);
-
- x86_32->flush = 0; /* dont flush scans till we have a batch */
- if (submit_reg_pir(t, reg) != ERROR_OK)
- return ERROR_FAIL;
- if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK)
- return ERROR_FAIL;
- scan.out[0] = RDWRPDR;
- if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
- return ERROR_FAIL;
- if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK)
- return ERROR_FAIL;
- x86_32->flush = 1;
- if (submit_instruction_pir(t, PDR2SRAM) != ERROR_OK)
- return ERROR_FAIL;
-
- /* we are writing from the cache so ensure we reset flags */
- if (cache) {
- x86_32->cache->reg_list[reg].dirty = 0;
- x86_32->cache->reg_list[reg].valid = 0;
- }
- return ERROR_OK;
-}
-
-static bool is_paging_enabled(struct target *t)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- if (x86_32->pm_regs[I(CR0)] & CR0_PG)
- return true;
- else
- return false;
-}
-
-static uint8_t get_num_user_regs(struct target *t)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- return x86_32->cache->num_regs;
-}
-/* value of the CR0.PG (paging enabled) bit influences memory reads/writes */
-static int disable_paging(struct target *t)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- x86_32->pm_regs[I(CR0)] = x86_32->pm_regs[I(CR0)] & ~CR0_PG;
- int err = x86_32->write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error disabling paging", __func__);
- return err;
- }
- return err;
-}
-
-static int enable_paging(struct target *t)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- x86_32->pm_regs[I(CR0)] = (x86_32->pm_regs[I(CR0)] | CR0_PG);
- int err = x86_32->write_hw_reg(t, CR0, x86_32->pm_regs[I(CR0)], 0);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error enabling paging", __func__);
- return err;
- }
- return err;
-}
-
-static bool sw_bpts_supported(struct target *t)
-{
- uint32_t tapstatus = get_tapstatus(t);
- if (tapstatus & TS_SBP_BIT)
- return true;
- else
- return false;
-}
-
-static int transaction_status(struct target *t)
-{
- uint32_t tapstatus = get_tapstatus(t);
- if ((TS_EN_PM_BIT | TS_PRDY_BIT) & tapstatus) {
- LOG_ERROR("%s transaction error tapstatus = 0x%08" PRIx32
- , __func__, tapstatus);
- return ERROR_FAIL;
- } else {
- return ERROR_OK;
- }
-}
-
-static int submit_instruction(struct target *t, int num)
-{
- int err = submit_instruction_pir(t, num);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error submitting pir", __func__);
- return err;
- }
- return err;
-}
-
-static int submit_reg_pir(struct target *t, int num)
-{
- LOG_DEBUG("reg %s op=0x%016" PRIx64, regs[num].name, regs[num].op);
- int err = submit_pir(t, regs[num].op);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error submitting pir", __func__);
- return err;
- }
- return err;
-}
-
-static int submit_instruction_pir(struct target *t, int num)
-{
- LOG_DEBUG("%s op=0x%016" PRIx64, instructions[num].name,
- instructions[num].op);
- int err = submit_pir(t, instructions[num].op);
- if (err != ERROR_OK) {
- LOG_ERROR("%s error submitting pir", __func__);
- return err;
- }
- return err;
-}
-
-/*
- * PIR (Probe Mode Instruction Register), SUBMITPIR is an "IR only" TAP
- * command; there is no corresponding data register
- */
-static int submit_pir(struct target *t, uint64_t op)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- uint8_t op_buf[8];
- buf_set_u64(op_buf, 0, 64, op);
- int flush = x86_32->flush;
- x86_32->flush = 0;
- scan.out[0] = WRPIR;
- if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
- return ERROR_FAIL;
- if (drscan(t, op_buf, scan.out, PIR_SIZE) != ERROR_OK)
- return ERROR_FAIL;
- scan.out[0] = SUBMITPIR;
- x86_32->flush = flush;
- if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK)
- return ERROR_FAIL;
- jtag_add_sleep(DELAY_SUBMITPIR);
- return ERROR_OK;
-}
-
-int lakemont_init_target(struct command_context *cmd_ctx, struct target *t)
-{
- lakemont_build_reg_cache(t);
- t->state = TARGET_RUNNING;
- t->debug_reason = DBG_REASON_NOTHALTED;
- return ERROR_OK;
-}
-
-int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32)
-{
- x86_32->submit_instruction = submit_instruction;
- x86_32->transaction_status = transaction_status;
- x86_32->read_hw_reg = read_hw_reg;
- x86_32->write_hw_reg = write_hw_reg;
- x86_32->sw_bpts_supported = sw_bpts_supported;
- x86_32->get_num_user_regs = get_num_user_regs;
- x86_32->is_paging_enabled = is_paging_enabled;
- x86_32->disable_paging = disable_paging;
- x86_32->enable_paging = enable_paging;
- return ERROR_OK;
-}
-
-int lakemont_poll(struct target *t)
-{
- /* LMT1 PMCR register currently allows code breakpoints, data breakpoints,
- * single stepping and shutdowns to be redirected to PM but does not allow
- * redirecting into PM as a result of SMM enter and SMM exit
- */
- uint32_t ts = get_tapstatus(t);
-
- if (ts == 0xFFFFFFFF && t->state != TARGET_DEBUG_RUNNING) {
- /* something is wrong here */
- LOG_ERROR("tapstatus invalid - scan_chain serialization or locked JTAG access issues");
- /* TODO: Give a hint that unlocking is wrong or maybe a
- * 'jtag arp_init' helps
- */
- t->state = TARGET_DEBUG_RUNNING;
- return ERROR_OK;
- }
-
- if (t->state == TARGET_HALTED && (!(ts & TS_PM_BIT))) {
- LOG_INFO("target running for unknown reason");
- t->state = TARGET_RUNNING;
- }
-
- if (t->state == TARGET_RUNNING &&
- t->state != TARGET_DEBUG_RUNNING) {
-
- if ((ts & TS_PM_BIT) && (ts & TS_PMCR_BIT)) {
-
- LOG_DEBUG("redirect to PM, tapstatus=0x%08" PRIx32, get_tapstatus(t));
-
- t->state = TARGET_DEBUG_RUNNING;
- if (save_context(t) != ERROR_OK)
- return ERROR_FAIL;
- if (halt_prep(t) != ERROR_OK)
- return ERROR_FAIL;
- t->state = TARGET_HALTED;
- t->debug_reason = DBG_REASON_UNDEFINED;
-
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32);
- uint32_t dr6 = buf_get_u32(x86_32->cache->reg_list[DR6].value, 0, 32);
- uint32_t hwbreakpoint = (uint32_t)-1;
-
- if (dr6 & DR6_BRKDETECT_0)
- hwbreakpoint = 0;
- if (dr6 & DR6_BRKDETECT_1)
- hwbreakpoint = 1;
- if (dr6 & DR6_BRKDETECT_2)
- hwbreakpoint = 2;
- if (dr6 & DR6_BRKDETECT_3)
- hwbreakpoint = 3;
-
- if (hwbreakpoint != (uint32_t)-1) {
- uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32);
- uint32_t type = dr7 & (0x03 << (DR7_RW_SHIFT + hwbreakpoint*DR7_RW_LEN_SIZE));
- if (type == DR7_BP_EXECUTE) {
- LOG_USER("hit hardware breakpoint (hwreg=%" PRIu32 ") at 0x%08" PRIx32, hwbreakpoint, eip);
- } else {
- uint32_t address = 0;
- switch (hwbreakpoint) {
- default:
- case 0:
- address = buf_get_u32(x86_32->cache->reg_list[DR0].value, 0, 32);
- break;
- case 1:
- address = buf_get_u32(x86_32->cache->reg_list[DR1].value, 0, 32);
- break;
- case 2:
- address = buf_get_u32(x86_32->cache->reg_list[DR2].value, 0, 32);
- break;
- case 3:
- address = buf_get_u32(x86_32->cache->reg_list[DR3].value, 0, 32);
- break;
- }
- LOG_USER("hit '%s' watchpoint for 0x%08" PRIx32 " (hwreg=%" PRIu32 ") at 0x%08" PRIx32,
- type == DR7_BP_WRITE ? "write" : "access", address,
- hwbreakpoint, eip);
- }
- t->debug_reason = DBG_REASON_BREAKPOINT;
- } else {
- /* Check if the target hit a software breakpoint.
- * ! Watch out: EIP is currently pointing after the breakpoint opcode
- */
- struct breakpoint *bp = NULL;
- bp = breakpoint_find(t, eip-1);
- if (bp != NULL) {
- t->debug_reason = DBG_REASON_BREAKPOINT;
- if (bp->type == BKPT_SOFT) {
- /* The EIP is now pointing the the next byte after the
- * breakpoint instruction. This needs to be corrected.
- */
- buf_set_u32(x86_32->cache->reg_list[EIP].value, 0, 32, eip-1);
- x86_32->cache->reg_list[EIP].dirty = 1;
- x86_32->cache->reg_list[EIP].valid = 1;
- LOG_USER("hit software breakpoint at 0x%08" PRIx32, eip-1);
- } else {
- /* it's not a hardware breakpoint (checked already in DR6 state)
- * and it's also not a software breakpoint ...
- */
- LOG_USER("hit unknown breakpoint at 0x%08" PRIx32, eip);
- }
- } else {
-
- /* There is also the case that we hit an breakpoint instruction,
- * which was not set by us. This needs to be handled be the
- * application that introduced the breakpoint.
- */
-
- LOG_USER("unknown break reason at 0x%08" PRIx32, eip);
- }
- }
-
- return target_call_event_callbacks(t, TARGET_EVENT_HALTED);
- }
- }
- return ERROR_OK;
-}
-
-int lakemont_arch_state(struct target *t)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- LOG_USER("target halted due to %s at 0x%08" PRIx32 " in %s mode",
- debug_reason_name(t),
- buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32),
- (buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32) & CR0_PE) ? "protected" : "real");
-
- return ERROR_OK;
-}
-
-int lakemont_halt(struct target *t)
-{
- if (t->state == TARGET_RUNNING) {
- t->debug_reason = DBG_REASON_DBGRQ;
- if (do_halt(t) != ERROR_OK)
- return ERROR_FAIL;
- return ERROR_OK;
- } else {
- LOG_ERROR("%s target not running", __func__);
- return ERROR_FAIL;
- }
-}
-
-int lakemont_resume(struct target *t, int current, uint32_t address,
- int handle_breakpoints, int debug_execution)
-{
- struct breakpoint *bp = NULL;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- /* TODO lakemont_enable_breakpoints(t); */
- if (t->state == TARGET_HALTED) {
-
- /* running away for a software breakpoint needs some special handling */
- uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32);
- bp = breakpoint_find(t, eip);
- if (bp != NULL /*&& bp->type == BKPT_SOFT*/) {
- /* the step will step over the breakpoint */
- if (lakemont_step(t, 0, 0, 1) != ERROR_OK) {
- LOG_ERROR("%s stepping over a software breakpoint at 0x%08" PRIx32 " "
- "failed to resume the target", __func__, eip);
- return ERROR_FAIL;
- }
- }
-
- /* if breakpoints are enabled, we need to redirect these into probe mode */
- struct breakpoint *activeswbp = t->breakpoints;
- while (activeswbp != NULL && activeswbp->set == 0)
- activeswbp = activeswbp->next;
- struct watchpoint *activehwbp = t->watchpoints;
- while (activehwbp != NULL && activehwbp->set == 0)
- activehwbp = activehwbp->next;
- if (activeswbp != NULL || activehwbp != NULL)
- buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1);
- if (do_resume(t) != ERROR_OK)
- return ERROR_FAIL;
- } else {
- LOG_USER("target not halted");
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-int lakemont_step(struct target *t, int current,
- uint32_t address, int handle_breakpoints)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32);
- uint32_t eip = buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32);
- uint32_t pmcr = buf_get_u32(x86_32->cache->reg_list[PMCR].value, 0, 32);
- struct breakpoint *bp = NULL;
- int retval = ERROR_OK;
- uint32_t tapstatus = 0;
-
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- bp = breakpoint_find(t, eip);
- if (retval == ERROR_OK && bp != NULL/*&& bp->type == BKPT_SOFT*/) {
- /* TODO: This should only be done for software breakpoints.
- * Stepping from hardware breakpoints should be possible with the resume flag
- * Needs testing.
- */
- retval = x86_32_common_remove_breakpoint(t, bp);
- }
-
- /* Set EFLAGS[TF] and PMCR[IR], exit pm and wait for PRDY# */
- LOG_DEBUG("modifying PMCR = 0x%08" PRIx32 " and EFLAGS = 0x%08" PRIx32, pmcr, eflags);
- eflags = eflags | (EFLAGS_TF | EFLAGS_RF);
- buf_set_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32, eflags);
- buf_set_u32(x86_32->cache->reg_list[PMCR].value, 0, 32, 1);
- LOG_DEBUG("EFLAGS [TF] [RF] bits set=0x%08" PRIx32 ", PMCR=0x%08" PRIx32 ", EIP=0x%08" PRIx32,
- eflags, pmcr, eip);
-
- tapstatus = get_tapstatus(t);
-
- t->debug_reason = DBG_REASON_SINGLESTEP;
- t->state = TARGET_DEBUG_RUNNING;
- if (restore_context(t) != ERROR_OK)
- return ERROR_FAIL;
- if (exit_probemode(t) != ERROR_OK)
- return ERROR_FAIL;
-
- target_call_event_callbacks(t, TARGET_EVENT_RESUMED);
-
- tapstatus = get_tapstatus(t);
- if (tapstatus & (TS_PM_BIT | TS_EN_PM_BIT | TS_PRDY_BIT | TS_PMCR_BIT)) {
- /* target has stopped */
- if (save_context(t) != ERROR_OK)
- return ERROR_FAIL;
- if (halt_prep(t) != ERROR_OK)
- return ERROR_FAIL;
- t->state = TARGET_HALTED;
-
- LOG_USER("step done from EIP 0x%08" PRIx32 " to 0x%08" PRIx32, eip,
- buf_get_u32(x86_32->cache->reg_list[EIP].value, 0, 32));
- target_call_event_callbacks(t, TARGET_EVENT_HALTED);
- } else {
- /* target didn't stop
- * I hope the poll() will catch it, but the deleted breakpoint is gone
- */
- LOG_ERROR("%s target didn't stop after executing a single step", __func__);
- t->state = TARGET_RUNNING;
- return ERROR_FAIL;
- }
-
- /* try to re-apply the breakpoint, even of step failed
- * TODO: When a bp was set, we should try to stop the target - fix the return above
- */
- if (bp != NULL/*&& bp->type == BKPT_SOFT*/) {
- /* TODO: This should only be done for software breakpoints.
- * Stepping from hardware breakpoints should be possible with the resume flag
- * Needs testing.
- */
- retval = x86_32_common_add_breakpoint(t, bp);
- }
-
- return retval;
-}
-
-/* TODO - implement resetbreak fully through CLTAP registers */
-int lakemont_reset_assert(struct target *t)
-{
- LOG_DEBUG("-");
- return ERROR_OK;
-}
-
-int lakemont_reset_deassert(struct target *t)
-{
- LOG_DEBUG("-");
- return ERROR_OK;
-}
diff --git a/src/target/lakemont.h b/src/target/lakemont.h
deleted file mode 100644
index b07a056..0000000
--- a/src/target/lakemont.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright(c) 2013-2016 Intel Corporation.
- *
- * Adrian Burns (adrian.burns@intel.com)
- * Thomas Faust (thomas.faust@intel.com)
- * Ivan De Cesaris (ivan.de.cesaris@intel.com)
- * Julien Carreno (julien.carreno@intel.com)
- * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Contact Information:
- * Intel Corporation
- */
-
-/*
- * @file
- * This is the interface to the probemode operations for Lakemont 1 (LMT1).
- */
-
-#ifndef OPENOCD_TARGET_LAKEMONT_H
-#define OPENOCD_TARGET_LAKEMONT_H
-
-#include <jtag/jtag.h>
-#include <helper/types.h>
-
-/* The Intel Quark SoC X1000 Core is codenamed lakemont */
-
-#define LMT_IRLEN 8
-
-/* lakemont tap instruction opcodes */
-#define IDCODE 2
-#define SUBMITPIR 3
-#define PROBEMODE 4
-#define WRPIR 6
-#define RDWRPDR 8
-#define TAPSTATUS 11
-#define BYPASS 255
-#define NOT_NULL 2
-
-/* DR sizes */
-#define ID_SIZE 32
-#define PM_SIZE 1
-#define PIR_SIZE 64
-#define PDR_SIZE 32
-#define TS_SIZE 32
-#define BP_SIZE 1
-#define MAX_SCAN_SIZE PIR_SIZE
-
-/* needed during lakemont probemode */
-#define NOT_PMREG 0xfe
-#define NOT_AVAIL_REG 0xff
-#define PM_DSB ((uint32_t)0x00000000)
-#define PM_DSL ((uint32_t)0xFFFFFFFF)
-#define PM_DSAR ((uint32_t)0x004F9300)
-#define PM_DR7 ((uint32_t)0x00000400)
-#define DELAY_SUBMITPIR 0 /* for now 0 is working */
-
-/* lakemont tapstatus bits */
-#define TS_PRDY_BIT ((uint32_t)0x00000001)
-#define TS_EN_PM_BIT ((uint32_t)0x00000002)
-#define TS_PM_BIT ((uint32_t)0x00000004)
-#define TS_PMCR_BIT ((uint32_t)0x00000008)
-#define TS_SBP_BIT ((uint32_t)0x00000010)
-
-struct lakemont_core_reg {
- uint32_t num;
- struct target *target;
- struct x86_32_common *x86_32_common;
- uint64_t op;
- uint8_t pm_idx;
-};
-
-struct scan_blk {
- uint8_t out[MAX_SCAN_SIZE]; /* scanned out to the tap */
- uint8_t in[MAX_SCAN_SIZE]; /* in to our capture buf */
- struct scan_field field;
-};
-
-#define I(name) (((struct lakemont_core_reg *)x86_32->cache->reg_list[name].arch_info)->pm_idx)
-
-int lakemont_init_target(struct command_context *cmd_ctx, struct target *t);
-int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32);
-int lakemont_poll(struct target *t);
-int lakemont_arch_state(struct target *t);
-int lakemont_halt(struct target *t);
-int lakemont_resume(struct target *t, int current, uint32_t address,
- int handle_breakpoints, int debug_execution);
-int lakemont_step(struct target *t, int current,
- uint32_t address, int handle_breakpoints);
-int lakemont_reset_assert(struct target *t);
-int lakemont_reset_deassert(struct target *t);
-int lakemont_update_after_probemode_entry(struct target *t);
-
-#endif /* OPENOCD_TARGET_LAKEMONT_H */
diff --git a/src/target/ls1_sap.c b/src/target/ls1_sap.c
deleted file mode 100644
index 944e725..0000000
--- a/src/target/ls1_sap.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2015 by Esben Haabendal *
- * eha@deif.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "target_type.h"
-
-#include <jtag/jtag.h>
-
-struct ls1_sap {
- struct jtag_tap *tap;
-};
-
-static int ls1_sap_target_create(struct target *target, Jim_Interp *interp)
-{
- struct ls1_sap *ls1_sap = calloc(1, sizeof(struct ls1_sap));
-
- ls1_sap->tap = target->tap;
- target->arch_info = ls1_sap;
-
- return ERROR_OK;
-}
-
-static int ls1_sap_init_target(struct command_context *cmd_ctx, struct target *target)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int ls1_sap_arch_state(struct target *target)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int ls1_sap_poll(struct target *target)
-{
- if ((target->state == TARGET_UNKNOWN) ||
- (target->state == TARGET_RUNNING) ||
- (target->state == TARGET_DEBUG_RUNNING))
- target->state = TARGET_HALTED;
-
- return ERROR_OK;
-}
-
-static int ls1_sap_halt(struct target *target)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int ls1_sap_resume(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int ls1_sap_step(struct target *target, int current, uint32_t address,
- int handle_breakpoints)
-{
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int ls1_sap_assert_reset(struct target *target)
-{
- target->state = TARGET_RESET;
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static int ls1_sap_deassert_reset(struct target *target)
-{
- target->state = TARGET_RUNNING;
-
- LOG_DEBUG("%s", __func__);
- return ERROR_OK;
-}
-
-static void ls1_sap_set_instr(struct jtag_tap *tap, uint32_t new_instr)
-{
- struct scan_field field;
-
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == new_instr)
- return;
-
- field.num_bits = tap->ir_length;
- uint8_t *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_instr);
- field.in_value = NULL;
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
- free(t);
-}
-
-static void ls1_sap_set_addr_high(struct jtag_tap *tap, uint16_t addr_high)
-{
- struct scan_field field;
- uint8_t buf[2];
-
- ls1_sap_set_instr(tap, 0x21);
-
- field.num_bits = 16;
- field.out_value = buf;
- buf_set_u32(buf, 0, 16, addr_high);
- field.in_value = NULL;
- field.check_value = NULL;
- field.check_mask = NULL;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-}
-
-static void ls1_sap_memory_cmd(struct jtag_tap *tap, uint32_t address,
- int32_t size, int read)
-{
- struct scan_field field;
- uint8_t cmd[8];
-
- ls1_sap_set_instr(tap, 0x24);
-
- field.num_bits = 64;
- field.out_value = cmd;
- buf_set_u64(cmd, 0, 9, 0);
- buf_set_u64(cmd, 9, 3, size);
- buf_set_u64(cmd, 12, 1, !!read);
- buf_set_u64(cmd, 13, 3, 0);
- buf_set_u64(cmd, 16, 32, address);
- buf_set_u64(cmd, 48, 16, 0);
- field.in_value = NULL;
- field.check_value = NULL;
- field.check_mask = NULL;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-}
-
-static void ls1_sap_memory_read(struct jtag_tap *tap, uint32_t size,
- uint8_t *value)
-{
- struct scan_field field;
-
- ls1_sap_set_instr(tap, 0x25);
-
- field.num_bits = 8 * size;
- field.out_value = NULL;
- field.in_value = value;
- field.check_value = NULL;
- field.check_mask = NULL;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-}
-
-static void ls1_sap_memory_write(struct jtag_tap *tap, uint32_t size,
- const uint8_t *value)
-{
- struct scan_field field;
-
- ls1_sap_set_instr(tap, 0x25);
-
- field.num_bits = 8 * size;
- field.out_value = value;
- field.in_value = NULL;
- field.check_value = NULL;
- field.check_mask = NULL;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-}
-
-static int ls1_sap_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- LOG_DEBUG("Reading memory at physical address 0x%" PRIx32
- "; size %" PRId32 "; count %" PRId32, address, size, count);
-
- if (count == 0 || buffer == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- ls1_sap_set_addr_high(target->tap, 0);
-
- while (count--) {
- ls1_sap_memory_cmd(target->tap, address, size, 1);
- ls1_sap_memory_read(target->tap, size, buffer);
- address += size;
- buffer += size;
- }
-
- return jtag_execute_queue();
-}
-
-static int ls1_sap_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count,
- const uint8_t *buffer)
-{
- LOG_DEBUG("Writing memory at physical address 0x%" PRIx32
- "; size %" PRId32 "; count %" PRId32, address, size, count);
-
-
- if (count == 0 || buffer == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- ls1_sap_set_addr_high(target->tap, 0);
-
- while (count--) {
- ls1_sap_memory_cmd(target->tap, address, size, 0);
- ls1_sap_memory_write(target->tap, size, buffer);
- address += size;
- buffer += size;
- }
-
- return jtag_execute_queue();
-}
-
-struct target_type ls1_sap_target = {
- .name = "ls1_sap",
-
- .target_create = ls1_sap_target_create,
- .init_target = ls1_sap_init_target,
-
- .poll = ls1_sap_poll,
- .arch_state = ls1_sap_arch_state,
-
- .halt = ls1_sap_halt,
- .resume = ls1_sap_resume,
- .step = ls1_sap_step,
-
- .assert_reset = ls1_sap_assert_reset,
- .deassert_reset = ls1_sap_deassert_reset,
-
- .read_memory = ls1_sap_read_memory,
- .write_memory = ls1_sap_write_memory,
-};
diff --git a/src/target/mips32.c b/src/target/mips32.c
deleted file mode 100644
index 3292446..0000000
--- a/src/target/mips32.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2011 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mips32.h"
-#include "breakpoints.h"
-#include "algorithm.h"
-#include "register.h"
-
-static const char *mips_isa_strings[] = {
- "MIPS32", "MIPS16"
-};
-
-#define MIPS32_GDB_DUMMY_FP_REG 1
-
-/*
- * GDB registers
- * based on gdb-7.6.2/gdb/features/mips-{fpu,cp0,cpu}.xml
- */
-static const struct {
- unsigned id;
- const char *name;
- enum reg_type type;
- const char *group;
- const char *feature;
- int flag;
-} mips32_regs[] = {
- { 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 1, "r1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 2, "r2", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 3, "r3", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 4, "r4", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 5, "r5", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 6, "r6", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 7, "r7", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 8, "r8", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 9, "r9", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 10, "r10", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 11, "r11", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 12, "r12", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 13, "r13", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 14, "r14", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 15, "r15", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 16, "r16", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 17, "r17", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 18, "r18", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 19, "r19", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 20, "r20", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 21, "r21", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 22, "r22", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 23, "r23", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 24, "r24", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 25, "r25", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 26, "r26", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 27, "r27", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 28, "r28", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 29, "r29", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 30, "r30", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 31, "r31", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 32, "status", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
- { 33, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 34, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
- { 35, "badvaddr", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
- { 36, "cause", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
- { 37, "pc", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
-
- { 38, "f0", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 39, "f1", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 40, "f2", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 41, "f3", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 42, "f4", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 43, "f5", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 44, "f6", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 45, "f7", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 46, "f8", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 47, "f9", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 48, "f10", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 49, "f11", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 50, "f12", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 51, "f13", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 52, "f14", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 53, "f15", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 54, "f16", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 55, "f17", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 56, "f18", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 57, "f19", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 58, "f20", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 59, "f21", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 60, "f22", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 61, "f23", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 62, "f24", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 63, "f25", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 64, "f26", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 65, "f27", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 66, "f28", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 67, "f29", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 68, "f30", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 69, "f31", REG_TYPE_IEEE_SINGLE, NULL,
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 70, "fcsr", REG_TYPE_INT, "float",
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
- { 71, "fir", REG_TYPE_INT, "float",
- "org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
-};
-
-
-#define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs)
-
-static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
-
-static int mips32_get_core_reg(struct reg *reg)
-{
- int retval;
- struct mips32_core_reg *mips32_reg = reg->arch_info;
- struct target *target = mips32_reg->target;
- struct mips32_common *mips32_target = target_to_mips32(target);
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- retval = mips32_target->read_core_reg(target, mips32_reg->num);
-
- return retval;
-}
-
-static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- struct mips32_core_reg *mips32_reg = reg->arch_info;
- struct target *target = mips32_reg->target;
- uint32_t value = buf_get_u32(buf, 0, 32);
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- buf_set_u32(reg->value, 0, 32, value);
- reg->dirty = 1;
- reg->valid = 1;
-
- return ERROR_OK;
-}
-
-static int mips32_read_core_reg(struct target *target, unsigned int num)
-{
- uint32_t reg_value;
-
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
-
- if (num >= MIPS32_NUM_REGS)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- reg_value = mips32->core_regs[num];
- buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
- mips32->core_cache->reg_list[num].valid = 1;
- mips32->core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-}
-
-static int mips32_write_core_reg(struct target *target, unsigned int num)
-{
- uint32_t reg_value;
-
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
-
- if (num >= MIPS32_NUM_REGS)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
- mips32->core_regs[num] = reg_value;
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
- mips32->core_cache->reg_list[num].valid = 1;
- mips32->core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-}
-
-int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
- int *reg_list_size, enum target_register_class reg_class)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
- unsigned int i;
-
- /* include floating point registers */
- *reg_list_size = MIPS32_NUM_REGS;
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
-
- for (i = 0; i < MIPS32_NUM_REGS; i++)
- (*reg_list)[i] = &mips32->core_cache->reg_list[i];
-
- return ERROR_OK;
-}
-
-int mips32_save_context(struct target *target)
-{
- unsigned int i;
-
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- /* read core registers */
- mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
-
- for (i = 0; i < MIPS32_NUM_REGS; i++) {
- if (!mips32->core_cache->reg_list[i].valid)
- mips32->read_core_reg(target, i);
- }
-
- return ERROR_OK;
-}
-
-int mips32_restore_context(struct target *target)
-{
- unsigned int i;
-
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- for (i = 0; i < MIPS32_NUM_REGS; i++) {
- if (mips32->core_cache->reg_list[i].dirty)
- mips32->write_core_reg(target, i);
- }
-
- /* write core regs */
- mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
-
- return ERROR_OK;
-}
-
-int mips32_arch_state(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
-
- LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
- mips_isa_strings[mips32->isa_mode],
- debug_reason_name(target),
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type mips32_reg_type = {
- .get = mips32_get_core_reg,
- .set = mips32_set_core_reg,
-};
-
-struct reg_cache *mips32_build_reg_cache(struct target *target)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
-
- int num_regs = MIPS32_NUM_REGS;
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct reg_cache *cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
- struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs);
- struct reg_feature *feature;
- int i;
-
- /* Build the process context cache */
- cache->name = "mips32 registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = num_regs;
- (*cache_p) = cache;
- mips32->core_cache = cache;
-
- for (i = 0; i < num_regs; i++) {
- arch_info[i].num = mips32_regs[i].id;
- arch_info[i].target = target;
- arch_info[i].mips32_common = mips32;
-
- reg_list[i].name = mips32_regs[i].name;
- reg_list[i].size = 32;
-
- if (mips32_regs[i].flag == MIPS32_GDB_DUMMY_FP_REG) {
- reg_list[i].value = mips32_gdb_dummy_fp_value;
- reg_list[i].valid = 1;
- reg_list[i].arch_info = NULL;
- register_init_dummy(&reg_list[i]);
- } else {
- reg_list[i].value = calloc(1, 4);
- reg_list[i].valid = 0;
- reg_list[i].type = &mips32_reg_type;
- reg_list[i].arch_info = &arch_info[i];
-
- reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
- if (reg_list[i].reg_data_type)
- reg_list[i].reg_data_type->type = mips32_regs[i].type;
- else
- LOG_ERROR("unable to allocate reg type list");
- }
-
- reg_list[i].dirty = 0;
-
- reg_list[i].group = mips32_regs[i].group;
- reg_list[i].number = i;
- reg_list[i].exist = true;
- reg_list[i].caller_save = true; /* gdb defaults to true */
-
- feature = calloc(1, sizeof(struct reg_feature));
- if (feature) {
- feature->name = mips32_regs[i].feature;
- reg_list[i].feature = feature;
- } else
- LOG_ERROR("unable to allocate feature list");
- }
-
- return cache;
-}
-
-int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap)
-{
- target->arch_info = mips32;
- mips32->common_magic = MIPS32_COMMON_MAGIC;
- mips32->fast_data_area = NULL;
-
- /* has breakpoint/watchpoint unit been scanned */
- mips32->bp_scanned = 0;
- mips32->data_break_list = NULL;
-
- mips32->ejtag_info.tap = tap;
- mips32->read_core_reg = mips32_read_core_reg;
- mips32->write_core_reg = mips32_write_core_reg;
-
- mips32->ejtag_info.scan_delay = 2000000; /* Initial default value */
- mips32->ejtag_info.mode = 0; /* Initial default value */
-
- return ERROR_OK;
-}
-
-/* run to exit point. return error if exit point was not reached. */
-static int mips32_run_and_wait(struct target *target, uint32_t entry_point,
- int timeout_ms, uint32_t exit_point, struct mips32_common *mips32)
-{
- uint32_t pc;
- int retval;
- /* This code relies on the target specific resume() and poll()->debug_entry()
- * sequence to write register values to the processor and the read them back */
- retval = target_resume(target, 0, entry_point, 0, 1);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
- /* If the target fails to halt due to the breakpoint, force a halt */
- if (retval != ERROR_OK || target->state != TARGET_HALTED) {
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- retval = target_wait_state(target, TARGET_HALTED, 500);
- if (retval != ERROR_OK)
- return retval;
- return ERROR_TARGET_TIMEOUT;
- }
-
- pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
- if (exit_point && (pc != exit_point)) {
- LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
- return ERROR_TARGET_TIMEOUT;
- }
-
- return ERROR_OK;
-}
-
-int mips32_run_algorithm(struct target *target, int num_mem_params,
- struct mem_param *mem_params, int num_reg_params,
- struct reg_param *reg_params, uint32_t entry_point,
- uint32_t exit_point, int timeout_ms, void *arch_info)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips32_algorithm *mips32_algorithm_info = arch_info;
- enum mips32_isa_mode isa_mode = mips32->isa_mode;
-
- uint32_t context[MIPS32_NUM_REGS];
- int retval = ERROR_OK;
-
- LOG_DEBUG("Running algorithm");
-
- /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
- * at the exit point */
-
- if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
- LOG_ERROR("current target isn't a MIPS32 target");
- return ERROR_TARGET_INVALID;
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* refresh core register cache */
- for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
- if (!mips32->core_cache->reg_list[i].valid)
- mips32->read_core_reg(target, i);
- context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
- }
-
- for (int i = 0; i < num_mem_params; i++) {
- retval = target_write_buffer(target, mem_params[i].address,
- mem_params[i].size, mem_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
-
- for (int i = 0; i < num_reg_params; i++) {
- struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
-
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- mips32_set_core_reg(reg, reg_params[i].value);
- }
-
- mips32->isa_mode = mips32_algorithm_info->isa_mode;
-
- retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);
-
- if (retval != ERROR_OK)
- return retval;
-
- for (int i = 0; i < num_mem_params; i++) {
- if (mem_params[i].direction != PARAM_OUT) {
- retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
- mem_params[i].value);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- for (int i = 0; i < num_reg_params; i++) {
- if (reg_params[i].direction != PARAM_OUT) {
- struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
- if (!reg) {
- LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (reg->size != reg_params[i].size) {
- LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
- reg_params[i].reg_name);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
- }
- }
-
- /* restore everything we saved before */
- for (unsigned int i = 0; i < MIPS32_NUM_REGS; i++) {
- uint32_t regvalue;
- regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
- if (regvalue != context[i]) {
- LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
- mips32->core_cache->reg_list[i].name, context[i]);
- buf_set_u32(mips32->core_cache->reg_list[i].value,
- 0, 32, context[i]);
- mips32->core_cache->reg_list[i].valid = 1;
- mips32->core_cache->reg_list[i].dirty = 1;
- }
- }
-
- mips32->isa_mode = isa_mode;
-
- return ERROR_OK;
-}
-
-int mips32_examine(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
-
- if (!target_was_examined(target)) {
- target_set_examined(target);
-
- /* we will configure later */
- mips32->bp_scanned = 0;
- mips32->num_inst_bpoints = 0;
- mips32->num_data_bpoints = 0;
- mips32->num_inst_bpoints_avail = 0;
- mips32->num_data_bpoints_avail = 0;
- }
-
- return ERROR_OK;
-}
-
-static int mips32_configure_ibs(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- int retval, i;
- uint32_t bpinfo;
-
- /* get number of inst breakpoints */
- retval = target_read_u32(target, ejtag_info->ejtag_ibs_addr, &bpinfo);
- if (retval != ERROR_OK)
- return retval;
-
- mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
- mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
- mips32->inst_break_list = calloc(mips32->num_inst_bpoints,
- sizeof(struct mips32_comparator));
-
- for (i = 0; i < mips32->num_inst_bpoints; i++)
- mips32->inst_break_list[i].reg_address =
- ejtag_info->ejtag_iba0_addr +
- (ejtag_info->ejtag_iba_step_size * i);
-
- /* clear IBIS reg */
- retval = target_write_u32(target, ejtag_info->ejtag_ibs_addr, 0);
- return retval;
-}
-
-static int mips32_configure_dbs(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- int retval, i;
- uint32_t bpinfo;
-
- /* get number of data breakpoints */
- retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo);
- if (retval != ERROR_OK)
- return retval;
-
- mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
- mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
- mips32->data_break_list = calloc(mips32->num_data_bpoints,
- sizeof(struct mips32_comparator));
-
- for (i = 0; i < mips32->num_data_bpoints; i++)
- mips32->data_break_list[i].reg_address =
- ejtag_info->ejtag_dba0_addr +
- (ejtag_info->ejtag_dba_step_size * i);
-
- /* clear DBIS reg */
- retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0);
- return retval;
-}
-
-int mips32_configure_break_unit(struct target *target)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- int retval;
- uint32_t dcr;
-
- if (mips32->bp_scanned)
- return ERROR_OK;
-
- /* get info about breakpoint support */
- retval = target_read_u32(target, EJTAG_DCR, &dcr);
- if (retval != ERROR_OK)
- return retval;
-
- /* EJTAG 2.0 defines IB and DB bits in IMP instead of DCR. */
- if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
- ejtag_info->debug_caps = dcr & EJTAG_DCR_ENM;
- if (!(ejtag_info->impcode & EJTAG_V20_IMP_NOIB))
- ejtag_info->debug_caps |= EJTAG_DCR_IB;
- if (!(ejtag_info->impcode & EJTAG_V20_IMP_NODB))
- ejtag_info->debug_caps |= EJTAG_DCR_DB;
- } else
- /* keep debug caps for later use */
- ejtag_info->debug_caps = dcr & (EJTAG_DCR_ENM
- | EJTAG_DCR_IB | EJTAG_DCR_DB);
-
-
- if (ejtag_info->debug_caps & EJTAG_DCR_IB) {
- retval = mips32_configure_ibs(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (ejtag_info->debug_caps & EJTAG_DCR_DB) {
- retval = mips32_configure_dbs(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* check if target endianness settings matches debug control register */
- if (((ejtag_info->debug_caps & EJTAG_DCR_ENM)
- && (target->endianness == TARGET_LITTLE_ENDIAN)) ||
- (!(ejtag_info->debug_caps & EJTAG_DCR_ENM)
- && (target->endianness == TARGET_BIG_ENDIAN)))
- LOG_WARNING("DCR endianness settings does not match target settings");
-
- LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
- mips32->num_data_bpoints);
-
- mips32->bp_scanned = 1;
-
- return ERROR_OK;
-}
-
-int mips32_enable_interrupts(struct target *target, int enable)
-{
- int retval;
- int update = 0;
- uint32_t dcr;
-
- /* read debug control register */
- retval = target_read_u32(target, EJTAG_DCR, &dcr);
- if (retval != ERROR_OK)
- return retval;
-
- if (enable) {
- if (!(dcr & EJTAG_DCR_INTE)) {
- /* enable interrupts */
- dcr |= EJTAG_DCR_INTE;
- update = 1;
- }
- } else {
- if (dcr & EJTAG_DCR_INTE) {
- /* disable interrupts */
- dcr &= ~EJTAG_DCR_INTE;
- update = 1;
- }
- }
-
- if (update) {
- retval = target_write_u32(target, EJTAG_DCR, dcr);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-int mips32_checksum_memory(struct target *target, uint32_t address,
- uint32_t count, uint32_t *checksum)
-{
- struct working_area *crc_algorithm;
- struct reg_param reg_params[2];
- struct mips32_algorithm mips32_info;
-
- /* see contrib/loaders/checksum/mips32.s for src */
-
- static const uint32_t mips_crc_code[] = {
- 0x248C0000, /* addiu $t4, $a0, 0 */
- 0x24AA0000, /* addiu $t2, $a1, 0 */
- 0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */
- 0x10000010, /* beq $zero, $zero, ncomp */
- 0x240B0000, /* addiu $t3, $zero, 0 */
- /* nbyte: */
- 0x81850000, /* lb $a1, ($t4) */
- 0x218C0001, /* addi $t4, $t4, 1 */
- 0x00052E00, /* sll $a1, $a1, 24 */
- 0x3C0204C1, /* lui $v0, 0x04c1 */
- 0x00852026, /* xor $a0, $a0, $a1 */
- 0x34471DB7, /* ori $a3, $v0, 0x1db7 */
- 0x00003021, /* addu $a2, $zero, $zero */
- /* loop: */
- 0x00044040, /* sll $t0, $a0, 1 */
- 0x24C60001, /* addiu $a2, $a2, 1 */
- 0x28840000, /* slti $a0, $a0, 0 */
- 0x01074826, /* xor $t1, $t0, $a3 */
- 0x0124400B, /* movn $t0, $t1, $a0 */
- 0x28C30008, /* slti $v1, $a2, 8 */
- 0x1460FFF9, /* bne $v1, $zero, loop */
- 0x01002021, /* addu $a0, $t0, $zero */
- /* ncomp: */
- 0x154BFFF0, /* bne $t2, $t3, nbyte */
- 0x256B0001, /* addiu $t3, $t3, 1 */
- 0x7000003F, /* sdbbp */
- };
-
- /* make sure we have a working area */
- if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- /* convert mips crc code into a buffer in target endianness */
- uint8_t mips_crc_code_8[sizeof(mips_crc_code)];
- target_buffer_set_u32_array(target, mips_crc_code_8,
- ARRAY_SIZE(mips_crc_code), mips_crc_code);
-
- target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8);
-
- mips32_info.common_magic = MIPS32_COMMON_MAGIC;
- mips32_info.isa_mode = MIPS32_ISA_MIPS32;
-
- init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
- buf_set_u32(reg_params[0].value, 0, 32, address);
-
- init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- int timeout = 20000 * (1 + (count / (1024 * 1024)));
-
- int retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
- crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout,
- &mips32_info);
-
- if (retval == ERROR_OK)
- *checksum = buf_get_u32(reg_params[0].value, 0, 32);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
-
- target_free_working_area(target, crc_algorithm);
-
- return retval;
-}
-
-/** Checks whether a memory region is zeroed. */
-int mips32_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank)
-{
- struct working_area *erase_check_algorithm;
- struct reg_param reg_params[3];
- struct mips32_algorithm mips32_info;
-
- static const uint32_t erase_check_code[] = {
- /* nbyte: */
- 0x80880000, /* lb $t0, ($a0) */
- 0x00C83024, /* and $a2, $a2, $t0 */
- 0x24A5FFFF, /* addiu $a1, $a1, -1 */
- 0x14A0FFFC, /* bne $a1, $zero, nbyte */
- 0x24840001, /* addiu $a0, $a0, 1 */
- 0x7000003F /* sdbbp */
- };
-
- /* make sure we have a working area */
- if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- /* convert erase check code into a buffer in target endianness */
- uint8_t erase_check_code_8[sizeof(erase_check_code)];
- target_buffer_set_u32_array(target, erase_check_code_8,
- ARRAY_SIZE(erase_check_code), erase_check_code);
-
- target_write_buffer(target, erase_check_algorithm->address, sizeof(erase_check_code), erase_check_code_8);
-
- mips32_info.common_magic = MIPS32_COMMON_MAGIC;
- mips32_info.isa_mode = MIPS32_ISA_MIPS32;
-
- init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
- buf_set_u32(reg_params[0].value, 0, 32, address);
-
- init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
- buf_set_u32(reg_params[2].value, 0, 32, 0xff);
-
- int retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
- erase_check_algorithm->address,
- erase_check_algorithm->address + (sizeof(erase_check_code) - 4),
- 10000, &mips32_info);
-
- if (retval == ERROR_OK)
- *blank = buf_get_u32(reg_params[2].value, 0, 32);
-
- destroy_reg_param(&reg_params[0]);
- destroy_reg_param(&reg_params[1]);
- destroy_reg_param(&reg_params[2]);
-
- target_free_working_area(target, erase_check_algorithm);
-
- return retval;
-}
-
-static int mips32_verify_pointer(struct command_context *cmd_ctx,
- struct mips32_common *mips32)
-{
- if (mips32->common_magic != MIPS32_COMMON_MAGIC) {
- command_print(cmd_ctx, "target is not an MIPS32");
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-/**
- * MIPS32 targets expose command interface
- * to manipulate CP0 registers
- */
-COMMAND_HANDLER(mips32_handle_cp0_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
-
- retval = mips32_verify_pointer(CMD_CTX, mips32);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- /* two or more argument, access a single register/select (write if third argument is given) */
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- else {
- uint32_t cp0_reg, cp0_sel;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
-
- if (CMD_ARGC == 2) {
- uint32_t value;
-
- retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access reg %" PRIi32,
- cp0_reg);
- return ERROR_OK;
- }
- command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
- cp0_reg, cp0_sel, value);
-
- } else if (CMD_ARGC == 3) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
- retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
- cp0_reg, cp0_sel);
- return ERROR_OK;
- }
- command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
- cp0_reg, cp0_sel, value);
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(mips32_handle_scan_delay_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
- else if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay);
- if (ejtag_info->scan_delay >= 2000000) {
- ejtag_info->mode = 0;
- command_print(CMD_CTX, "running in legacy mode");
- } else {
- ejtag_info->mode = 1;
- command_print(CMD_CTX, "running in fast queued mode");
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration mips32_exec_command_handlers[] = {
- {
- .name = "cp0",
- .handler = mips32_handle_cp0_command,
- .mode = COMMAND_EXEC,
- .usage = "regnum select [value]",
- .help = "display/modify cp0 register",
- },
- {
- .name = "scan_delay",
- .handler = mips32_handle_scan_delay_command,
- .mode = COMMAND_ANY,
- .help = "display/set scan delay in nano seconds",
- .usage = "[value]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration mips32_command_handlers[] = {
- {
- .name = "mips32",
- .mode = COMMAND_ANY,
- .help = "mips32 command group",
- .usage = "",
- .chain = mips32_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/mips32.h b/src/target/mips32.h
deleted file mode 100644
index bfd2cf5..0000000
--- a/src/target/mips32.h
+++ /dev/null
@@ -1,252 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * Copyright (C) 2011 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_MIPS32_H
-#define OPENOCD_TARGET_MIPS32_H
-
-#include "target.h"
-#include "mips32_pracc.h"
-
-#define MIPS32_COMMON_MAGIC 0xB320B320
-
-/**
- * Memory segments (32bit kernel mode addresses)
- * These are the traditional names used in the 32-bit universe.
- */
-#define KUSEG 0x00000000
-#define KSEG0 0x80000000
-#define KSEG1 0xa0000000
-#define KSEG2 0xc0000000
-#define KSEG3 0xe0000000
-
-/** Returns the kernel segment base of a given address */
-#define KSEGX(a) ((a) & 0xe0000000)
-
-/** CP0 CONFIG regites fields */
-#define MIPS32_CONFIG0_KU_SHIFT 25
-#define MIPS32_CONFIG0_KU_MASK (0x7 << MIPS32_CONFIG0_KU_SHIFT)
-
-#define MIPS32_CONFIG0_K0_SHIFT 0
-#define MIPS32_CONFIG0_K0_MASK (0x7 << MIPS32_CONFIG0_K0_SHIFT)
-
-#define MIPS32_CONFIG0_K23_SHIFT 28
-#define MIPS32_CONFIG0_K23_MASK (0x7 << MIPS32_CONFIG0_K23_SHIFT)
-
-#define MIPS32_CONFIG0_AR_SHIFT 10
-#define MIPS32_CONFIG0_AR_MASK (0x7 << MIPS32_CONFIG0_AR_SHIFT)
-
-#define MIPS32_CONFIG1_DL_SHIFT 10
-#define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT)
-
-#define MIPS32_ARCH_REL1 0x0
-#define MIPS32_ARCH_REL2 0x1
-
-/* offsets into mips32 core register cache */
-enum {
- MIPS32_PC = 37,
- MIPS32_FIR = 71,
- MIPS32NUMCOREREGS
-};
-
-enum mips32_isa_mode {
- MIPS32_ISA_MIPS32 = 0,
- MIPS32_ISA_MIPS16E = 1,
-};
-
-struct mips32_comparator {
- int used;
- uint32_t bp_value;
- uint32_t reg_address;
-};
-
-struct mips32_common {
- uint32_t common_magic;
- void *arch_info;
- struct reg_cache *core_cache;
- struct mips_ejtag ejtag_info;
- uint32_t core_regs[MIPS32NUMCOREREGS];
- enum mips32_isa_mode isa_mode;
-
- /* working area for fastdata access */
- struct working_area *fast_data_area;
-
- int bp_scanned;
- int num_inst_bpoints;
- int num_data_bpoints;
- int num_inst_bpoints_avail;
- int num_data_bpoints_avail;
- struct mips32_comparator *inst_break_list;
- struct mips32_comparator *data_break_list;
-
- /* register cache to processor synchronization */
- int (*read_core_reg)(struct target *target, unsigned int num);
- int (*write_core_reg)(struct target *target, unsigned int num);
-};
-
-static inline struct mips32_common *
-target_to_mips32(struct target *target)
-{
- return target->arch_info;
-}
-
-struct mips32_core_reg {
- uint32_t num;
- struct target *target;
- struct mips32_common *mips32_common;
-};
-
-struct mips32_algorithm {
- int common_magic;
- enum mips32_isa_mode isa_mode;
-};
-
-#define MIPS32_OP_ADDIU 0x21
-#define MIPS32_OP_ANDI 0x0C
-#define MIPS32_OP_BEQ 0x04
-#define MIPS32_OP_BGTZ 0x07
-#define MIPS32_OP_BNE 0x05
-#define MIPS32_OP_ADDI 0x08
-#define MIPS32_OP_AND 0x24
-#define MIPS32_OP_CACHE 0x2F
-#define MIPS32_OP_COP0 0x10
-#define MIPS32_OP_J 0x02
-#define MIPS32_OP_JR 0x08
-#define MIPS32_OP_LUI 0x0F
-#define MIPS32_OP_LW 0x23
-#define MIPS32_OP_LBU 0x24
-#define MIPS32_OP_LHU 0x25
-#define MIPS32_OP_MFHI 0x10
-#define MIPS32_OP_MTHI 0x11
-#define MIPS32_OP_MFLO 0x12
-#define MIPS32_OP_MTLO 0x13
-#define MIPS32_OP_RDHWR 0x3B
-#define MIPS32_OP_SB 0x28
-#define MIPS32_OP_SH 0x29
-#define MIPS32_OP_SW 0x2B
-#define MIPS32_OP_ORI 0x0D
-#define MIPS32_OP_XORI 0x0E
-#define MIPS32_OP_XOR 0x26
-#define MIPS32_OP_SLTU 0x2B
-#define MIPS32_OP_SRL 0x03
-#define MIPS32_OP_SYNCI 0x1F
-
-#define MIPS32_OP_REGIMM 0x01
-#define MIPS32_OP_SDBBP 0x3F
-#define MIPS32_OP_SPECIAL 0x00
-#define MIPS32_OP_SPECIAL2 0x07
-#define MIPS32_OP_SPECIAL3 0x1F
-
-#define MIPS32_COP0_MF 0x00
-#define MIPS32_COP0_MT 0x04
-
-#define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) \
- (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct))
-#define MIPS32_I_INST(opcode, rs, rt, immd) \
- (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | (immd))
-#define MIPS32_J_INST(opcode, addr) (((opcode) << 26) | (addr))
-
-#define MIPS32_NOP 0
-#define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val)
-#define MIPS32_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDIU)
-#define MIPS32_AND(reg, off, val) MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OP_AND)
-#define MIPS32_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val)
-#define MIPS32_B(off) MIPS32_BEQ(0, 0, off)
-#define MIPS32_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off)
-#define MIPS32_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off)
-#define MIPS32_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off)
-#define MIPS32_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off)
-#define MIPS32_J(tar) MIPS32_J_INST(MIPS32_OP_J, tar)
-#define MIPS32_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR)
-#define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel)
-#define MIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel)
-#define MIPS32_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off)
-#define MIPS32_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off)
-#define MIPS32_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val)
-#define MIPS32_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off)
-#define MIPS32_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO)
-#define MIPS32_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI)
-#define MIPS32_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO)
-#define MIPS32_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI)
-#define MIPS32_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val)
-#define MIPS32_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val)
-#define MIPS32_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR)
-#define MIPS32_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off)
-#define MIPS32_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off)
-#define MIPS32_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off)
-#define MIPS32_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR)
-#define MIPS32_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL)
-#define MIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU)
-#define MIPS32_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off)
-
-#define MIPS32_SYNC 0xF
-#define MIPS32_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */
-
-/**
- * Cache operations definitions
- * Operation field is 5 bits long :
- * 1) bits 1..0 hold cache type
- * 2) bits 4..2 hold operation code
- */
-#define MIPS32_CACHE_D_HIT_WRITEBACK ((0x1 << 0) | (0x6 << 2))
-#define MIPS32_CACHE_I_HIT_INVALIDATE ((0x0 << 0) | (0x4 << 2))
-
-/* ejtag specific instructions */
-#define MIPS32_DRET 0x4200001F
-#define MIPS32_SDBBP 0x7000003F /* MIPS32_J_INST(MIPS32_OP_SPECIAL2, MIPS32_OP_SDBBP) */
-#define MIPS16_SDBBP 0xE801
-
-extern const struct command_registration mips32_command_handlers[];
-
-int mips32_arch_state(struct target *target);
-
-int mips32_init_arch_info(struct target *target,
- struct mips32_common *mips32, struct jtag_tap *tap);
-
-int mips32_restore_context(struct target *target);
-int mips32_save_context(struct target *target);
-
-struct reg_cache *mips32_build_reg_cache(struct target *target);
-
-int mips32_run_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info);
-
-int mips32_configure_break_unit(struct target *target);
-
-int mips32_enable_interrupts(struct target *target, int enable);
-
-int mips32_examine(struct target *target);
-
-int mips32_register_commands(struct command_context *cmd_ctx);
-
-int mips32_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class);
-int mips32_checksum_memory(struct target *target, uint32_t address,
- uint32_t count, uint32_t *checksum);
-int mips32_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank);
-
-#endif /* OPENOCD_TARGET_MIPS32_H */
diff --git a/src/target/mips32_dmaacc.c b/src/target/mips32_dmaacc.c
deleted file mode 100644
index 220ea94..0000000
--- a/src/target/mips32_dmaacc.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by John McCarthy *
- * jgmcc@magma.ca *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mips32_dmaacc.h"
-#include <helper/time_support.h>
-
-static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info,
- uint32_t addr, int count, uint8_t *buf);
-static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info,
- uint32_t addr, int count, uint16_t *buf);
-static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info,
- uint32_t addr, int count, uint32_t *buf);
-
-static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info,
- uint32_t addr, int count, const uint8_t *buf);
-static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info,
- uint32_t addr, int count, const uint16_t *buf);
-static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info,
- uint32_t addr, int count, const uint32_t *buf);
-
-/*
- * The following logic shamelessly cloned from HairyDairyMaid's wrt54g_debrick
- * to support the Broadcom BCM5352 SoC in the Linksys WRT54GL wireless router
- * (and any others that support EJTAG DMA transfers).
- * Note: This only supports memory read/write. Since the BCM5352 doesn't
- * appear to support PRACC accesses, all debug functions except halt
- * do not work. Still, this does allow erasing/writing flash as well as
- * displaying/modifying memory and memory mapped registers.
- */
-
-static int ejtag_dma_dstrt_poll(struct mips_ejtag *ejtag_info)
-{
- uint32_t ejtag_ctrl;
- int64_t start = timeval_ms();
-
- do {
- if (timeval_ms() - start > 1000) {
- LOG_ERROR("DMA time out");
- return -ETIMEDOUT;
- }
- ejtag_ctrl = EJTAG_CTRL_DMAACC | ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- } while (ejtag_ctrl & EJTAG_CTRL_DSTRT);
- return 0;
-}
-
-static int ejtag_dma_read(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *data)
-{
- uint32_t v;
- uint32_t ejtag_ctrl;
- int retries = RETRY_ATTEMPTS;
-
-begin_ejtag_dma_read:
-
- /* Setup Address */
- v = addr;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Initiate DMA Read & set DSTRT */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-
- /* Wait for DSTRT to Clear */
- ejtag_dma_dstrt_poll(ejtag_info);
-
- /* Read Data */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32(ejtag_info, data);
-
- /* Clear DMA & Check DERR */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (ejtag_ctrl & EJTAG_CTRL_DERR) {
- if (retries--) {
- LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
- goto begin_ejtag_dma_read;
- } else
- LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int ejtag_dma_read_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint16_t *data)
-{
- uint32_t v;
- uint32_t ejtag_ctrl;
- int retries = RETRY_ATTEMPTS;
-
-begin_ejtag_dma_read_h:
-
- /* Setup Address */
- v = addr;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Initiate DMA Read & set DSTRT */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_HALFWORD |
- EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-
- /* Wait for DSTRT to Clear */
- ejtag_dma_dstrt_poll(ejtag_info);
-
- /* Read Data */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Clear DMA & Check DERR */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (ejtag_ctrl & EJTAG_CTRL_DERR) {
- if (retries--) {
- LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
- goto begin_ejtag_dma_read_h;
- } else
- LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* Handle the bigendian/littleendian */
- if (addr & 0x2)
- *data = (v >> 16) & 0xffff;
- else
- *data = (v & 0x0000ffff);
-
- return ERROR_OK;
-}
-
-static int ejtag_dma_read_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint8_t *data)
-{
- uint32_t v;
- uint32_t ejtag_ctrl;
- int retries = RETRY_ATTEMPTS;
-
-begin_ejtag_dma_read_b:
-
- /* Setup Address */
- v = addr;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Initiate DMA Read & set DSTRT */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DRWN | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-
- /* Wait for DSTRT to Clear */
- ejtag_dma_dstrt_poll(ejtag_info);
-
- /* Read Data */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Clear DMA & Check DERR */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (ejtag_ctrl & EJTAG_CTRL_DERR) {
- if (retries--) {
- LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ (retrying)", addr);
- goto begin_ejtag_dma_read_b;
- } else
- LOG_ERROR("DMA Read Addr = %08" PRIx32 " Data = ERROR ON READ", addr);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- /* Handle the bigendian/littleendian */
- switch (addr & 0x3) {
- case 0:
- *data = v & 0xff;
- break;
- case 1:
- *data = (v >> 8) & 0xff;
- break;
- case 2:
- *data = (v >> 16) & 0xff;
- break;
- case 3:
- *data = (v >> 24) & 0xff;
- break;
- }
-
- return ERROR_OK;
-}
-
-static int ejtag_dma_write(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
-{
- uint32_t v;
- uint32_t ejtag_ctrl;
- int retries = RETRY_ATTEMPTS;
-
-begin_ejtag_dma_write:
-
- /* Setup Address */
- v = addr;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Setup Data */
- v = data;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Initiate DMA Write & set DSTRT */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_WORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-
- /* Wait for DSTRT to Clear */
- ejtag_dma_dstrt_poll(ejtag_info);
-
- /* Clear DMA & Check DERR */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (ejtag_ctrl & EJTAG_CTRL_DERR) {
- if (retries--) {
- LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
- goto begin_ejtag_dma_write;
- } else
- LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int ejtag_dma_write_h(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
-{
- uint32_t v;
- uint32_t ejtag_ctrl;
- int retries = RETRY_ATTEMPTS;
-
- /* Handle the bigendian/littleendian */
- data &= 0xffff;
- data |= data << 16;
-
-begin_ejtag_dma_write_h:
-
- /* Setup Address */
- v = addr;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Setup Data */
- v = data;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Initiate DMA Write & set DSTRT */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_HALFWORD | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-
- /* Wait for DSTRT to Clear */
- ejtag_dma_dstrt_poll(ejtag_info);
-
- /* Clear DMA & Check DERR */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (ejtag_ctrl & EJTAG_CTRL_DERR) {
- if (retries--) {
- LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
- goto begin_ejtag_dma_write_h;
- } else
- LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-static int ejtag_dma_write_b(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t data)
-{
- uint32_t v;
- uint32_t ejtag_ctrl;
- int retries = RETRY_ATTEMPTS;
-
- /* Handle the bigendian/littleendian */
- data &= 0xff;
- data |= data << 8;
- data |= data << 16;
-
-begin_ejtag_dma_write_b:
-
- /* Setup Address*/
- v = addr;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Setup Data */
- v = data;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32(ejtag_info, &v);
-
- /* Initiate DMA Write & set DSTRT */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = EJTAG_CTRL_DMAACC | EJTAG_CTRL_DMA_BYTE | EJTAG_CTRL_DSTRT | ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-
- /* Wait for DSTRT to Clear */
- ejtag_dma_dstrt_poll(ejtag_info);
-
- /* Clear DMA & Check DERR */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (ejtag_ctrl & EJTAG_CTRL_DERR) {
- if (retries--) {
- LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE (retrying)", addr);
- goto begin_ejtag_dma_write_b;
- } else
- LOG_ERROR("DMA Write Addr = %08" PRIx32 " Data = ERROR ON WRITE", addr);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return ERROR_OK;
-}
-
-int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
-{
- switch (size) {
- case 1:
- return mips32_dmaacc_read_mem8(ejtag_info, addr, count, (uint8_t *)buf);
- case 2:
- return mips32_dmaacc_read_mem16(ejtag_info, addr, count, (uint16_t *)buf);
- case 4:
- return mips32_dmaacc_read_mem32(ejtag_info, addr, count, (uint32_t *)buf);
- }
-
- return ERROR_OK;
-}
-
-static int mips32_dmaacc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
-{
- int i;
- int retval;
-
- for (i = 0; i < count; i++) {
- retval = ejtag_dma_read(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int mips32_dmaacc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
-{
- int i;
- int retval;
-
- for (i = 0; i < count; i++) {
- retval = ejtag_dma_read_h(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int mips32_dmaacc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
-{
- int i;
- int retval;
-
- for (i = 0; i < count; i++) {
- retval = ejtag_dma_read_b(ejtag_info, addr + i * sizeof(*buf), &buf[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf)
-{
- switch (size) {
- case 1:
- return mips32_dmaacc_write_mem8(ejtag_info, addr, count, buf);
- case 2:
- return mips32_dmaacc_write_mem16(ejtag_info, addr, count, buf);
- case 4:
- return mips32_dmaacc_write_mem32(ejtag_info, addr, count, buf);
- }
-
- return ERROR_OK;
-}
-
-static int mips32_dmaacc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint32_t *buf)
-{
- int i;
- int retval;
-
- for (i = 0; i < count; i++) {
- retval = ejtag_dma_write(ejtag_info, addr + i * sizeof(*buf), buf[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int mips32_dmaacc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint16_t *buf)
-{
- int i;
- int retval;
-
- for (i = 0; i < count; i++) {
- retval = ejtag_dma_write_h(ejtag_info, addr + i * sizeof(*buf), buf[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int mips32_dmaacc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, const uint8_t *buf)
-{
- int i;
- int retval;
-
- for (i = 0; i < count; i++) {
- retval = ejtag_dma_write_b(ejtag_info, addr + i * sizeof(*buf), buf[i]);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
diff --git a/src/target/mips32_dmaacc.h b/src/target/mips32_dmaacc.h
deleted file mode 100644
index 70fe2a7..0000000
--- a/src/target/mips32_dmaacc.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by John McCarthy *
- * jgmcc@magma.ca *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_MIPS32_DMAACC_H
-#define OPENOCD_TARGET_MIPS32_DMAACC_H
-
-#include "mips_ejtag.h"
-
-#define EJTAG_CTRL_DMA_BYTE 0x00000000
-#define EJTAG_CTRL_DMA_HALFWORD 0x00000080
-#define EJTAG_CTRL_DMA_WORD 0x00000100
-#define EJTAG_CTRL_DMA_TRIPLEBYTE 0x00000180
-
-#define RETRY_ATTEMPTS 0
-
-int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info,
- uint32_t addr, int size, int count, void *buf);
-int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info,
- uint32_t addr, int size, int count, const void *buf);
-
-#endif /* OPENOCD_TARGET_MIPS32_DMAACC_H */
diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c
deleted file mode 100644
index 7cc0424..0000000
--- a/src/target/mips32_pracc.c
+++ /dev/null
@@ -1,1117 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
- * *
- * Copyright (C) 2011 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/*
- * This version has optimized assembly routines for 32 bit operations:
- * - read word
- * - write word
- * - write array of words
- *
- * One thing to be aware of is that the MIPS32 cpu will execute the
- * instruction after a branch instruction (one delay slot).
- *
- * For example:
- * LW $2, ($5 +10)
- * B foo
- * LW $1, ($2 +100)
- *
- * The LW $1, ($2 +100) instruction is also executed. If this is
- * not wanted a NOP can be inserted:
- *
- * LW $2, ($5 +10)
- * B foo
- * NOP
- * LW $1, ($2 +100)
- *
- * or the code can be changed to:
- *
- * B foo
- * LW $2, ($5 +10)
- * LW $1, ($2 +100)
- *
- * The original code contained NOPs. I have removed these and moved
- * the branches.
- *
- * These changes result in a 35% speed increase when programming an
- * external flash.
- *
- * More improvement could be gained if the registers do no need
- * to be preserved but in that case the routines should be aware
- * OpenOCD is used as a flash programmer or as a debug tool.
- *
- * Nico Coesel
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-
-#include "mips32.h"
-#include "mips32_pracc.h"
-
-struct mips32_pracc_context {
- uint32_t *local_oparam;
- int num_oparam;
- const uint32_t *code;
- int code_len;
- uint32_t stack[32];
- int stack_offset;
- struct mips_ejtag *ejtag_info;
-};
-
-static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
-{
- uint32_t ejtag_ctrl;
- int64_t then = timeval_ms();
-
- /* wait for the PrAcc to become "1" */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
-
- while (1) {
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- if (ejtag_ctrl & EJTAG_CTRL_PRACC)
- break;
-
- int64_t timeout = timeval_ms() - then;
- if (timeout > 1000) {
- LOG_DEBUG("DEBUGMODULE: No memory access in progress!");
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
-
- *ctrl = ejtag_ctrl;
- return ERROR_OK;
-}
-
-/* Shift in control and address for a new processor access, save them in ejtag_info */
-static int mips32_pracc_read_ctrl_addr(struct mips_ejtag *ejtag_info)
-{
- int retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- ejtag_info->pa_addr = 0;
- retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr);
-
- return retval;
-}
-
-/* Finish processor access */
-static int mips32_pracc_finish(struct mips_ejtag *ejtag_info)
-{
- uint32_t ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- mips_ejtag_drscan_32_out(ejtag_info, ctrl);
-
- return jtag_execute_queue();
-}
-
-int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info)
-{
- uint32_t jt_code = MIPS32_J((0x0FFFFFFF & MIPS32_PRACC_TEXT) >> 2);
- int retval;
-
- /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */
- for (int i = 0; i != 5; i++) {
- /* Wait for pracc */
- retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- /* Data or instruction out */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- uint32_t data = (i == 3) ? jt_code : MIPS32_NOP;
- mips_ejtag_drscan_32_out(ejtag_info, data);
-
- /* finish pa */
- retval = mips32_pracc_finish(ejtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- if (ejtag_info->mode != 0) /* async mode support only for MIPS ... */
- return ERROR_OK;
-
- for (int i = 0; i != 2; i++) {
- retval = mips32_pracc_read_ctrl_addr(ejtag_info);
- if (retval != ERROR_OK)
- return retval;
-
- if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP);
- retval = mips32_pracc_finish(ejtag_info);
- if (retval != ERROR_OK)
- return retval;
- } else
- break;
- }
-
- return ERROR_OK;
-}
-
-int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out)
-{
- int code_count = 0;
- int store_pending = 0; /* increases with every store instruction at dmseg, decreases with every store pa */
- uint32_t max_store_addr = 0; /* for store pa address testing */
- bool restart = 0; /* restarting control */
- int restart_count = 0;
- uint32_t instr = 0;
- bool final_check = 0; /* set to 1 if in final checks after function code shifted out */
- bool pass = 0; /* to check the pass through pracc text after function code sent */
- int retval;
-
- while (1) {
- if (restart) {
- if (restart_count < 3) { /* max 3 restarts allowed */
- retval = mips32_pracc_clean_text_jump(ejtag_info);
- if (retval != ERROR_OK)
- return retval;
- } else
- return ERROR_JTAG_DEVICE_ERROR;
- restart_count++;
- restart = 0;
- code_count = 0;
- LOG_DEBUG("restarting code");
- }
-
- retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */
- if (retval != ERROR_OK)
- return retval;
-
- /* Check for read or write access */
- if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */
- /* Check for pending store from a previous store instruction at dmseg */
- if (store_pending == 0) {
- LOG_DEBUG("unexpected write at address %" PRIx32, ejtag_info->pa_addr);
- if (code_count < 2) { /* allow for restart */
- restart = 1;
- continue;
- } else
- return ERROR_JTAG_DEVICE_ERROR;
- } else {
- /* check address */
- if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || ejtag_info->pa_addr > max_store_addr) {
-
- LOG_DEBUG("writing at unexpected address %" PRIx32, ejtag_info->pa_addr);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
- /* read data */
- uint32_t data = 0;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- retval = mips_ejtag_drscan_32(ejtag_info, &data);
- if (retval != ERROR_OK)
- return retval;
-
- /* store data at param out, address based offset */
- param_out[(ejtag_info->pa_addr - MIPS32_PRACC_PARAM_OUT) / 4] = data;
- store_pending--;
-
- } else { /* read/fetch access */
- if (!final_check) { /* executing function code */
- /* check address */
- if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
- LOG_DEBUG("reading at unexpected address %" PRIx32 ", expected %x",
- ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
-
- /* restart code execution only in some cases */
- if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && restart_count == 0) {
- LOG_DEBUG("restarting, without clean jump");
- restart_count++;
- code_count = 0;
- continue;
- } else if (code_count < 2) {
- restart = 1;
- continue;
- }
-
- return ERROR_JTAG_DEVICE_ERROR;
- }
- /* check for store instruction at dmseg */
- uint32_t store_addr = ctx->pracc_list[ctx->max_code + code_count];
- if (store_addr != 0) {
- if (store_addr > max_store_addr)
- max_store_addr = store_addr;
- store_pending++;
- }
-
- instr = ctx->pracc_list[code_count++];
- if (code_count == ctx->code_count) /* last instruction, start final check */
- final_check = 1;
-
- } else { /* final check after function code shifted out */
- /* check address */
- if (ejtag_info->pa_addr == MIPS32_PRACC_TEXT) {
- if (!pass) { /* first pass through pracc text */
- if (store_pending == 0) /* done, normal exit */
- return ERROR_OK;
- pass = 1; /* pracc text passed */
- code_count = 0; /* restart code count */
- } else {
- LOG_DEBUG("unexpected second pass through pracc text");
- return ERROR_JTAG_DEVICE_ERROR;
- }
- } else {
- if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) {
- LOG_DEBUG("unexpected read address in final check: %" PRIx32 ", expected: %x",
- ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
- if (!pass) {
- if ((code_count - ctx->code_count) > 1) { /* allow max 2 instruction delay slot */
- LOG_DEBUG("failed to jump back to pracc text");
- return ERROR_JTAG_DEVICE_ERROR;
- }
- } else
- if (code_count > 10) { /* enough, abandone */
- LOG_DEBUG("execution abandoned, store pending: %d", store_pending);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- instr = MIPS32_NOP; /* shift out NOPs instructions */
- code_count++;
- }
-
- /* Send instruction out */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32_out(ejtag_info, instr);
- }
- /* finish processor access, let the processor eat! */
- retval = mips32_pracc_finish(ejtag_info);
- if (retval != ERROR_OK)
- return retval;
-
- if (instr == MIPS32_DRET) /* after leaving debug mode nothing to do */
- return ERROR_OK;
-
- if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */
- LOG_DEBUG("warning: store access pass pracc text");
- return ERROR_OK;
- }
- }
-}
-
-inline void pracc_queue_init(struct pracc_queue_info *ctx)
-{
- ctx->retval = ERROR_OK;
- ctx->code_count = 0;
- ctx->store_count = 0;
-
- ctx->pracc_list = malloc(2 * ctx->max_code * sizeof(uint32_t));
- if (ctx->pracc_list == NULL) {
- LOG_ERROR("Out of memory");
- ctx->retval = ERROR_FAIL;
- }
-}
-
-inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr)
-{
- ctx->pracc_list[ctx->max_code + ctx->code_count] = addr;
- ctx->pracc_list[ctx->code_count++] = instr;
- if (addr)
- ctx->store_count++;
-}
-
-inline void pracc_queue_free(struct pracc_queue_info *ctx)
-{
- if (ctx->code_count > ctx->max_code) /* Only for internal check, will be erased */
- LOG_ERROR("Internal error, code count: %d > max code: %d", ctx->code_count, ctx->max_code);
- if (ctx->pracc_list != NULL)
- free(ctx->pracc_list);
-}
-
-int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf)
-{
- if (ejtag_info->mode == 0)
- return mips32_pracc_exec(ejtag_info, ctx, buf);
-
- union scan_in {
- uint8_t scan_96[12];
- struct {
- uint8_t ctrl[4];
- uint8_t data[4];
- uint8_t addr[4];
- } scan_32;
-
- } *scan_in = malloc(sizeof(union scan_in) * (ctx->code_count + ctx->store_count));
- if (scan_in == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- unsigned num_clocks =
- ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
-
- uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL);
-
- int scan_count = 0;
- for (int i = 0; i != 2 * ctx->code_count; i++) {
- uint32_t data = 0;
- if (i & 1u) { /* Check store address from previous instruction, if not the first */
- if (i < 2 || 0 == ctx->pracc_list[ctx->max_code + (i / 2) - 1])
- continue;
- } else
- data = ctx->pracc_list[i / 2];
-
- jtag_add_clocks(num_clocks);
- mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, data, scan_in[scan_count++].scan_96);
- }
-
- int retval = jtag_execute_queue(); /* execute queued scans */
- if (retval != ERROR_OK)
- goto exit;
-
- uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */
- scan_count = 0;
- for (int i = 0; i != 2 * ctx->code_count; i++) { /* verify every pracc access */
- uint32_t store_addr = 0;
- if (i & 1u) { /* Read store addres from previous instruction, if not the first */
- store_addr = ctx->pracc_list[ctx->max_code + (i / 2) - 1];
- if (i < 2 || 0 == store_addr)
- continue;
- }
-
- ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32);
- if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) {
- LOG_ERROR("Error: access not pending count: %d", scan_count);
- retval = ERROR_FAIL;
- goto exit;
- }
-
- uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32);
-
- if (store_addr != 0) {
- if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) {
- LOG_ERROR("Not a store/write access, count: %d", scan_count);
- retval = ERROR_FAIL;
- goto exit;
- }
- if (addr != store_addr) {
- LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
- addr, store_addr, scan_count);
- retval = ERROR_FAIL;
- goto exit;
- }
- int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4;
- buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32);
-
- } else {
- if (ejtag_ctrl & EJTAG_CTRL_PRNW) {
- LOG_ERROR("Not a fetch/read access, count: %d", scan_count);
- retval = ERROR_FAIL;
- goto exit;
- }
- if (addr != fetch_addr) {
- LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d",
- addr, fetch_addr, scan_count);
- retval = ERROR_FAIL;
- goto exit;
- }
- fetch_addr += 4;
- }
- scan_count++;
- }
-exit:
- free(scan_in);
- return retval;
-}
-
-int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
-{
- struct pracc_queue_info ctx = {.max_code = 8};
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */
- pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
- MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 of $8 */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 of $8 */
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf);
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-}
-
-int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
-{
- if (count == 1 && size == 4)
- return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf);
-
- uint32_t *data = NULL;
- struct pracc_queue_info ctx = {.max_code = 256 * 3 + 8 + 1}; /* alloc memory for the worst case */
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- if (size != 4) {
- data = malloc(256 * sizeof(uint32_t));
- if (data == NULL) {
- LOG_ERROR("Out of memory");
- goto exit;
- }
- }
-
- uint32_t *buf32 = buf;
- uint16_t *buf16 = buf;
- uint8_t *buf8 = buf;
-
- while (count) {
- ctx.code_count = 0;
- ctx.store_count = 0;
- int this_round_count = (count > 256) ? 256 : count;
- uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
-
- pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
- pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */
-
- for (int i = 0; i != this_round_count; i++) { /* Main code loop */
- uint32_t upper_base_addr = UPPER16((addr + 0x8000));
- if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */
- pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr));
- last_upper_base_addr = upper_base_addr;
- }
-
- if (size == 4)
- pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */
- else if (size == 2)
- pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9));
- else
- pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9));
-
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4,
- MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */
- addr += size;
- }
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */
- pracc_add(&ctx, 0, MIPS32_LUI(9, UPPER16(ejtag_info->reg9))); /* restore upper 16 bits of reg 9 */
- pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9))); /* restore lower 16 bits of reg 9 */
-
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
-
- if (size == 4) {
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32);
- if (ctx.retval != ERROR_OK)
- goto exit;
- buf32 += this_round_count;
- } else {
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- uint32_t *data_p = data;
- for (int i = 0; i != this_round_count; i++) {
- if (size == 2)
- *buf16++ = *data_p++;
- else
- *buf8++ = *data_p++;
- }
- }
- count -= this_round_count;
- }
-exit:
- pracc_queue_free(&ctx);
- if (data != NULL)
- free(data);
- return ctx.retval;
-}
-
-int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel)
-{
- struct pracc_queue_info ctx = {.max_code = 7};
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
- pracc_add(&ctx, 0, MIPS32_MFC0(8, 0, 0) | (cp0_reg << 11) | cp0_sel); /* move COP0 [cp0_reg select] to $8 */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
- MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
- pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val);
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-
- /**
- * Note that our input parametes cp0_reg and cp0_sel
- * are numbers (not gprs) which make part of mfc0 instruction opcode.
- *
- * These are not fix, but can be different for each mips32_cp0_read() function call,
- * and that is why we must insert them directly into opcode,
- * i.e. we can not pass it on EJTAG microprogram stack (via param_in),
- * and put them into the gprs later from MIPS32_PRACC_STACK
- * because mfc0 do not use gpr as a parameter for the cp0_reg and select part,
- * but plain (immediate) number.
- *
- * MIPS32_MTC0 is implemented via MIPS32_R_INST macro.
- * In order to insert our parameters, we must change rd and funct fields.
- *
- * code[2] |= (cp0_reg << 11) | cp0_sel; change rd and funct of MIPS32_R_INST macro
- **/
-}
-
-int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel)
-{
- struct pracc_queue_info ctx = {.max_code = 6};
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val))); /* Load val to $15 */
- pracc_add(&ctx, 0, MIPS32_ORI(15, 15, LOWER16(val)));
-
- pracc_add(&ctx, 0, MIPS32_MTC0(15, 0, 0) | (cp0_reg << 11) | cp0_sel); /* write cp0 reg / sel */
-
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-
- /**
- * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro.
- * In order to insert our parameters, we must change rd and funct fields.
- * code[3] |= (cp0_reg << 11) | cp0_sel; change rd and funct fields of MIPS32_R_INST macro
- **/
-}
-
-/**
- * \b mips32_pracc_sync_cache
- *
- * Synchronize Caches to Make Instruction Writes Effective
- * (ref. doc. MIPS32 Architecture For Programmers Volume II: The MIPS32 Instruction Set,
- * Document Number: MD00086, Revision 2.00, June 9, 2003)
- *
- * When the instruction stream is written, the SYNCI instruction should be used
- * in conjunction with other instructions to make the newly-written instructions effective.
- *
- * Explanation :
- * A program that loads another program into memory is actually writing the D- side cache.
- * The instructions it has loaded can't be executed until they reach the I-cache.
- *
- * After the instructions have been written, the loader should arrange
- * to write back any containing D-cache line and invalidate any locations
- * already in the I-cache.
- *
- * If the cache coherency attribute (CCA) is set to zero, it's a write through cache, there is no need
- * to write back.
- *
- * In the latest MIPS32/64 CPUs, MIPS provides the synci instruction,
- * which does the whole job for a cache-line-sized chunk of the memory you just loaded:
- * That is, it arranges a D-cache write-back (if CCA = 3) and an I-cache invalidate.
- *
- * The line size is obtained with the rdhwr SYNCI_Step in release 2 or from cp0 config 1 register in release 1.
- */
-static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info,
- uint32_t start_addr, uint32_t end_addr, int cached, int rel)
-{
- struct pracc_queue_info ctx = {.max_code = 256 * 2 + 5};
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
- /** Find cache line size in bytes */
- uint32_t clsiz;
- if (rel) { /* Release 2 (rel = 1) */
- pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */
-
- pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */
-
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT,
- MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */
-
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- } else { /* Release 1 (rel = 0) */
- uint32_t conf;
- ctx.retval = mips32_cp0_read(ejtag_info, &conf, 16, 1);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- uint32_t dl = (conf & MIPS32_CONFIG1_DL_MASK) >> MIPS32_CONFIG1_DL_SHIFT;
-
- /* dl encoding : dl=1 => 4 bytes, dl=2 => 8 bytes, etc... max dl=6 => 128 bytes cache line size */
- clsiz = 0x2 << dl;
- if (dl == 0)
- clsiz = 0;
- }
-
- if (clsiz == 0)
- goto exit; /* Nothing to do */
-
- /* make sure clsiz is power of 2 */
- if (clsiz & (clsiz - 1)) {
- LOG_DEBUG("clsiz must be power of 2");
- ctx.retval = ERROR_FAIL;
- goto exit;
- }
-
- /* make sure start_addr and end_addr have the same offset inside de cache line */
- start_addr |= clsiz - 1;
- end_addr |= clsiz - 1;
-
- ctx.code_count = 0;
- int count = 0;
- uint32_t last_upper_base_addr = UPPER16((start_addr + 0x8000));
-
- pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load upper memory base address to $15 */
-
- while (start_addr <= end_addr) { /* main loop */
- uint32_t upper_base_addr = UPPER16((start_addr + 0x8000));
- if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15 */
- pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr));
- last_upper_base_addr = upper_base_addr;
- }
- if (rel)
- pracc_add(&ctx, 0, MIPS32_SYNCI(LOWER16(start_addr), 15)); /* synci instruction, offset($15) */
-
- else {
- if (cached == 3)
- pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK,
- LOWER16(start_addr), 15)); /* cache Hit_Writeback_D, offset($15) */
-
- pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE,
- LOWER16(start_addr), 15)); /* cache Hit_Invalidate_I, offset($15) */
- }
- start_addr += clsiz;
- count++;
- if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- ctx.code_count = 0;
- count = 0;
- }
- }
- pracc_add(&ctx, 0, MIPS32_SYNC);
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-}
-
-static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info,
- uint32_t addr, int size, int count, const void *buf)
-{
- struct pracc_queue_info ctx = {.max_code = 128 * 3 + 5 + 1}; /* alloc memory for the worst case */
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- const uint32_t *buf32 = buf;
- const uint16_t *buf16 = buf;
- const uint8_t *buf8 = buf;
-
- while (count) {
- ctx.code_count = 0;
- ctx.store_count = 0;
- int this_round_count = (count > 128) ? 128 : count;
- uint32_t last_upper_base_addr = UPPER16((addr + 0x8000));
-
- pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load $15 with memory base address */
-
- for (int i = 0; i != this_round_count; i++) {
- uint32_t upper_base_addr = UPPER16((addr + 0x8000));
- if (last_upper_base_addr != upper_base_addr) {
- pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); /* if needed, change upper address in $15*/
- last_upper_base_addr = upper_base_addr;
- }
-
- if (size == 4) { /* for word writes check if one half word is 0 and load it accordingly */
- if (LOWER16(*buf32) == 0)
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load only upper value */
- else if (UPPER16(*buf32) == 0)
- pracc_add(&ctx, 0, MIPS32_ORI(8, 0, LOWER16(*buf32))); /* load only lower */
- else {
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load upper and lower */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(*buf32)));
- }
- pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */
- buf32++;
-
- } else if (size == 2) {
- pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf16)); /* load lower value */
- pracc_add(&ctx, 0, MIPS32_SH(8, LOWER16(addr), 15)); /* store half word to memory */
- buf16++;
-
- } else {
- pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf8)); /* load lower value */
- pracc_add(&ctx, 0, MIPS32_SB(8, LOWER16(addr), 15)); /* store byte to memory */
- buf8++;
- }
- addr += size;
- }
-
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */
-
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
- if (ctx.retval != ERROR_OK)
- goto exit;
- count -= this_round_count;
- }
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-}
-
-int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf)
-{
- int retval = mips32_pracc_write_mem_generic(ejtag_info, addr, size, count, buf);
- if (retval != ERROR_OK)
- return retval;
-
- /**
- * If we are in the cacheable region and cache is activated,
- * we must clean D$ (if Cache Coherency Attribute is set to 3) + invalidate I$ after we did the write,
- * so that changes do not continue to live only in D$ (if CCA = 3), but to be
- * replicated in I$ also (maybe we wrote the istructions)
- */
- uint32_t conf = 0;
- int cached = 0;
-
- if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
- return retval; /*Nothing to do*/
-
- mips32_cp0_read(ejtag_info, &conf, 16, 0);
-
- switch (KSEGX(addr)) {
- case KUSEG:
- cached = (conf & MIPS32_CONFIG0_KU_MASK) >> MIPS32_CONFIG0_KU_SHIFT;
- break;
- case KSEG0:
- cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
- break;
- case KSEG2:
- case KSEG3:
- cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;
- break;
- default:
- /* what ? */
- break;
- }
-
- /**
- * Check cachablitiy bits coherency algorithm
- * is the region cacheable or uncached.
- * If cacheable we have to synchronize the cache
- */
- if (cached == 3 || cached == 0) { /* Write back cache or write through cache */
- uint32_t start_addr = addr;
- uint32_t end_addr = addr + count * size;
- uint32_t rel = (conf & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
- if (rel > 1) {
- LOG_DEBUG("Unknown release in cache code");
- return ERROR_FAIL;
- }
- retval = mips32_pracc_synchronize_cache(ejtag_info, start_addr, end_addr, cached, rel);
- }
-
- return retval;
-}
-
-int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
-{
- static const uint32_t cp0_write_code[] = {
- MIPS32_MTC0(1, 12, 0), /* move $1 to status */
- MIPS32_MTLO(1), /* move $1 to lo */
- MIPS32_MTHI(1), /* move $1 to hi */
- MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */
- MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/
- MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */
- };
-
- struct pracc_queue_info ctx = {.max_code = 37 * 2 + 7 + 1};
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- /* load registers 2 to 31 with lui and ori instructions, check if some instructions can be saved */
- for (int i = 2; i < 32; i++) {
- if (LOWER16((regs[i])) == 0) /* if lower half word is 0, lui instruction only */
- pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i]))));
- else if (UPPER16((regs[i])) == 0) /* if upper half word is 0, ori with $0 only*/
- pracc_add(&ctx, 0, MIPS32_ORI(i, 0, LOWER16((regs[i]))));
- else { /* default, load with lui and ori instructions */
- pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i]))));
- pracc_add(&ctx, 0, MIPS32_ORI(i, i, LOWER16((regs[i]))));
- }
- }
-
- for (int i = 0; i != 6; i++) {
- pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[i + 32])))); /* load CPO value in $1, with lui and ori */
- pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[i + 32]))));
- pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */
- }
- pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */
- pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1])))); /* load upper half word in $1 */
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
-
- ejtag_info->reg8 = regs[8];
- ejtag_info->reg9 = regs[9];
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-}
-
-int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
-{
- static int cp0_read_code[] = {
- MIPS32_MFC0(8, 12, 0), /* move status to $8 */
- MIPS32_MFLO(8), /* move lo to $8 */
- MIPS32_MFHI(8), /* move hi to $8 */
- MIPS32_MFC0(8, 8, 0), /* move badvaddr to $8 */
- MIPS32_MFC0(8, 13, 0), /* move cause to $8 */
- MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */
- };
-
- struct pracc_queue_info ctx = {.max_code = 49};
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */
- pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */
-
- for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
- MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1));
-
- for (int i = 0; i != 6; i++) {
- pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */
- MIPS32_SW(8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
- }
- pracc_add(&ctx, 0, MIPS32_MFC0(8, 31, 0)); /* move DeSave to $8, reg1 value */
- pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */
- MIPS32_SW(8, PRACC_OUT_OFFSET + 4, 1));
-
- pracc_add(&ctx, 0, MIPS32_MFC0(1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */
- pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */
-
- if (ejtag_info->mode == 0)
- ctx.store_count++; /* Needed by legacy code, due to offset from reg0 */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs);
-
- ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */
- ejtag_info->reg9 = regs[9];
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-}
-
-/* fastdata upload/download requires an initialized working area
- * to load the download code; it should not be called otherwise
- * fetch order from the fastdata area
- * 1. start addr
- * 2. end addr
- * 3. data ...
- */
-int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
- int write_t, uint32_t addr, int count, uint32_t *buf)
-{
- uint32_t handler_code[] = {
- /* caution when editing, table is modified below */
- /* r15 points to the start of this code */
- MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
- MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
- MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
- MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
- /* start of fastdata area in t0 */
- MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
- MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
- MIPS32_LW(9, 0, 8), /* start addr in t1 */
- MIPS32_LW(10, 0, 8), /* end addr to t2 */
- /* loop: */
- /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */
- /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */
- MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */
- MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */
-
- MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15),
- MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15),
- MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15),
- MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15),
-
- MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)),
- MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)),
- MIPS32_JR(15), /* jr start */
- MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */
- };
-
- uint32_t jmp_code[] = {
- /* 0 */ MIPS32_LUI(15, 0), /* addr of working area added below */
- /* 1 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */
- MIPS32_JR(15), /* jump to ram program */
- MIPS32_NOP,
- };
-
- int retval, i;
- uint32_t val, ejtag_ctrl, address;
-
- if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- if (write_t) {
- handler_code[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */
- handler_code[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */
- } else {
- handler_code[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */
- handler_code[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */
- }
-
- /* write program into RAM */
- if (write_t != ejtag_info->fast_access_save) {
- mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code);
- /* save previous operation to speed to any consecutive read/writes */
- ejtag_info->fast_access_save = write_t;
- }
-
- LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address);
-
- jmp_code[0] |= UPPER16(source->address);
- jmp_code[1] |= LOWER16(source->address);
-
- for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) {
- retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA);
- mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]);
-
- /* Clear the access pending bit (let the processor eat!) */
- ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl);
- }
-
- /* wait PrAcc pending bit for FASTDATA write */
- retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- /* next fetch to dmseg should be in FASTDATA_AREA, check */
- address = 0;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- retval = mips_ejtag_drscan_32(ejtag_info, &address);
- if (retval != ERROR_OK)
- return retval;
-
- if (address != MIPS32_PRACC_FASTDATA_AREA)
- return ERROR_FAIL;
-
- /* Send the load start address */
- val = addr;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
- mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
-
- retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- /* Send the load end address */
- val = addr + (count - 1) * 4;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA);
- mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
-
- unsigned num_clocks = 0; /* like in legacy code */
- if (ejtag_info->mode != 0)
- num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000;
-
- for (i = 0; i < count; i++) {
- jtag_add_clocks(num_clocks);
- retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("fastdata load failed");
- return retval;
- }
-
- retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- address = 0;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
- retval = mips_ejtag_drscan_32(ejtag_info, &address);
- if (retval != ERROR_OK)
- return retval;
-
- if (address != MIPS32_PRACC_TEXT)
- LOG_ERROR("mini program did not return to start");
-
- return retval;
-}
diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h
deleted file mode 100644
index 2ede5b2..0000000
--- a/src/target/mips32_pracc.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * Copyright (C) 2011 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_MIPS32_PRACC_H
-#define OPENOCD_TARGET_MIPS32_PRACC_H
-
-#include <target/mips32.h>
-#include <target/mips_ejtag.h>
-
-#define MIPS32_PRACC_FASTDATA_AREA 0xFF200000
-#define MIPS32_PRACC_FASTDATA_SIZE 16
-#define MIPS32_PRACC_BASE_ADDR 0xFF200000
-#define MIPS32_PRACC_TEXT 0xFF200200
-#define MIPS32_PRACC_PARAM_OUT 0xFF202000
-
-#define PRACC_UPPER_BASE_ADDR (MIPS32_PRACC_BASE_ADDR >> 16)
-#define PRACC_OUT_OFFSET (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_BASE_ADDR)
-
-#define MIPS32_FASTDATA_HANDLER_SIZE 0x80
-#define UPPER16(uint32_t) (uint32_t >> 16)
-#define LOWER16(uint32_t) (uint32_t & 0xFFFF)
-#define NEG16(v) (((~(v)) + 1) & 0xFFFF)
-/*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/
-
-struct pracc_queue_info {
- int retval;
- const int max_code;
- int code_count;
- int store_count;
- uint32_t *pracc_list; /* Code and store addresses */
-};
-void pracc_queue_init(struct pracc_queue_info *ctx);
-void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr);
-void pracc_queue_free(struct pracc_queue_info *ctx);
-int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info,
- struct pracc_queue_info *ctx, uint32_t *buf);
-
-int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info,
- uint32_t addr, int size, int count, void *buf);
-int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info,
- uint32_t addr, int size, int count, const void *buf);
-int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
- int write_t, uint32_t addr, int count, uint32_t *buf);
-
-int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
-int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
-
-int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out);
-
-/**
- * \b mips32_cp0_read
- *
- * Simulates mfc0 ASM instruction (Move From C0),
- * i.e. implements copro C0 Register read.
- *
- * @param[in] ejtag_info
- * @param[in] val Storage to hold read value
- * @param[in] cp0_reg Number of copro C0 register we want to read
- * @param[in] cp0_sel Select for the given C0 register
- *
- * @return ERROR_OK on Sucess, ERROR_FAIL otherwise
- */
-int mips32_cp0_read(struct mips_ejtag *ejtag_info,
- uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel);
-
-/**
- * \b mips32_cp0_write
- *
- * Simulates mtc0 ASM instruction (Move To C0),
- * i.e. implements copro C0 Register read.
- *
- * @param[in] ejtag_info
- * @param[in] val Value to be written
- * @param[in] cp0_reg Number of copro C0 register we want to write to
- * @param[in] cp0_sel Select for the given C0 register
- *
- * @return ERROR_OK on Sucess, ERROR_FAIL otherwise
- */
-int mips32_cp0_write(struct mips_ejtag *ejtag_info,
- uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel);
-
-#endif /* OPENOCD_TARGET_MIPS32_PRACC_H */
diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c
deleted file mode 100644
index 594711f..0000000
--- a/src/target/mips_ejtag.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mips32.h"
-#include "mips_ejtag.h"
-#include "mips32_dmaacc.h"
-
-void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr)
-{
- struct jtag_tap *tap;
-
- tap = ejtag_info->tap;
- assert(tap != NULL);
-
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) {
- struct scan_field field;
- uint8_t t[4];
-
- field.num_bits = tap->ir_length;
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, new_instr);
- field.in_value = NULL;
-
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
- }
-}
-
-int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode)
-{
- struct scan_field field;
- uint8_t r[4];
-
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE);
-
- field.num_bits = 32;
- field.out_value = NULL;
- field.in_value = r;
-
- jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
-
- int retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("register read failed");
- return retval;
- }
-
- *idcode = buf_get_u32(field.in_value, 0, 32);
-
- return ERROR_OK;
-}
-
-static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode)
-{
- struct scan_field field;
- uint8_t r[4];
-
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE);
-
- field.num_bits = 32;
- field.out_value = NULL;
- field.in_value = r;
-
- jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE);
-
- int retval;
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("register read failed");
- return retval;
- }
-
- *impcode = buf_get_u32(field.in_value, 0, 32);
-
- return ERROR_OK;
-}
-
-void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf)
-{
- assert(ejtag_info->tap != NULL);
- struct jtag_tap *tap = ejtag_info->tap;
-
- struct scan_field field;
- uint8_t out_scan[12];
-
- /* processor access "all" register 96 bit */
- field.num_bits = 96;
-
- field.out_value = out_scan;
- buf_set_u32(out_scan, 0, 32, ctrl);
- buf_set_u32(out_scan + 4, 0, 32, data);
- buf_set_u32(out_scan + 8, 0, 32, 0);
-
- field.in_value = in_scan_buf;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- keep_alive();
-}
-
-int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
-{
- struct jtag_tap *tap;
- tap = ejtag_info->tap;
- assert(tap != NULL);
-
- struct scan_field field;
- uint8_t t[4], r[4];
- int retval;
-
- field.num_bits = 32;
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, *data);
- field.in_value = r;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("register read failed");
- return retval;
- }
-
- *data = buf_get_u32(field.in_value, 0, 32);
-
- keep_alive();
-
- return ERROR_OK;
-}
-
-void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data)
-{
- uint8_t t[4];
- struct jtag_tap *tap;
- tap = ejtag_info->tap;
- assert(tap != NULL);
-
- struct scan_field field;
-
- field.num_bits = 32;
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, data);
-
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-}
-
-int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data)
-{
- struct jtag_tap *tap;
- tap = ejtag_info->tap;
- assert(tap != NULL);
-
- struct scan_field field;
- uint8_t t[4] = {0, 0, 0, 0}, r[4];
- int retval;
-
- field.num_bits = 8;
- field.out_value = t;
- buf_set_u32(t, 0, field.num_bits, *data);
- field.in_value = r;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("register read failed");
- return retval;
- }
-
- *data = buf_get_u32(field.in_value, 0, 32);
-
- return ERROR_OK;
-}
-
-void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data)
-{
- struct jtag_tap *tap;
- tap = ejtag_info->tap;
- assert(tap != NULL);
-
- struct scan_field field;
-
- field.num_bits = 8;
- field.out_value = &data;
- field.in_value = NULL;
-
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-}
-
-/* Set (to enable) or clear (to disable stepping) the SSt bit (bit 8) in Cp0 Debug reg (reg 23, sel 0) */
-int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step)
-{
- struct pracc_queue_info ctx = {.max_code = 7};
- pracc_queue_init(&ctx);
- if (ctx.retval != ERROR_OK)
- goto exit;
-
- pracc_add(&ctx, 0, MIPS32_MFC0(8, 23, 0)); /* move COP0 Debug to $8 */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, 0x0100)); /* set SSt bit in debug reg */
- if (!enable_step)
- pracc_add(&ctx, 0, MIPS32_XORI(8, 8, 0x0100)); /* clear SSt bit in debug reg */
-
- pracc_add(&ctx, 0, MIPS32_MTC0(8, 23, 0)); /* move $8 to COP0 Debug */
- pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */
- pracc_add(&ctx, 0, MIPS32_B(NEG16((ctx.code_count + 1)))); /* jump to start */
- pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */
-
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
-exit:
- pracc_queue_free(&ctx);
- return ctx.retval;
-}
-
-/*
- * Disable memory protection for 0xFF20.0000–0xFF3F.FFFF
- * It is needed by EJTAG 1.5-2.0, especially for BMIPS CPUs
- * For example bcm7401 and others. At leas on some
- * CPUs, DebugMode wont start if this bit is not removed.
- */
-static int disable_dcr_mp(struct mips_ejtag *ejtag_info)
-{
- uint32_t dcr;
- int retval;
-
- retval = mips32_dmaacc_read_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr);
- if (retval != ERROR_OK)
- goto error;
-
- dcr &= ~EJTAG_DCR_MP;
- retval = mips32_dmaacc_write_mem(ejtag_info, EJTAG_DCR, 4, 1, &dcr);
- if (retval != ERROR_OK)
- goto error;
- return ERROR_OK;
-error:
- LOG_ERROR("Failed to remove DCR MPbit!");
- return retval;
-}
-
-int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info)
-{
- uint32_t ejtag_ctrl;
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
-
- if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
- if (disable_dcr_mp(ejtag_info) != ERROR_OK)
- goto error;
- }
-
- /* set debug break bit */
- ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_JTAGBRK;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
-
- /* break bit will be cleared by hardware */
- ejtag_ctrl = ejtag_info->ejtag_ctrl;
- mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- LOG_DEBUG("ejtag_ctrl: 0x%8.8" PRIx32 "", ejtag_ctrl);
- if ((ejtag_ctrl & EJTAG_CTRL_BRKST) == 0)
- goto error;
-
- return ERROR_OK;
-error:
- LOG_ERROR("Failed to enter Debug Mode!");
- return ERROR_FAIL;
-}
-
-int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info)
-{
- uint32_t pracc_list[] = {MIPS32_DRET, 0};
- struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = pracc_list, .code_count = 1, .store_count = 0};
-
- /* execute our dret instruction */
- ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL);
-
- /* pic32mx workaround, false pending at low core clock */
- jtag_add_sleep(1000);
- return ctx.retval;
-}
-
-/* mips_ejtag_init_mmr - asign Memory-Mapped Registers depending
- * on EJTAG version.
- */
-static void mips_ejtag_init_mmr(struct mips_ejtag *ejtag_info)
-{
- if (ejtag_info->ejtag_version == EJTAG_VERSION_20) {
- ejtag_info->ejtag_ibs_addr = EJTAG_V20_IBS;
- ejtag_info->ejtag_iba0_addr = EJTAG_V20_IBA0;
- ejtag_info->ejtag_ibc_offs = EJTAG_V20_IBC_OFFS;
- ejtag_info->ejtag_ibm_offs = EJTAG_V20_IBM_OFFS;
-
- ejtag_info->ejtag_dbs_addr = EJTAG_V20_DBS;
- ejtag_info->ejtag_dba0_addr = EJTAG_V20_DBA0;
- ejtag_info->ejtag_dbc_offs = EJTAG_V20_DBC_OFFS;
- ejtag_info->ejtag_dbm_offs = EJTAG_V20_DBM_OFFS;
- ejtag_info->ejtag_dbv_offs = EJTAG_V20_DBV_OFFS;
-
- ejtag_info->ejtag_iba_step_size = EJTAG_V20_IBAn_STEP;
- ejtag_info->ejtag_dba_step_size = EJTAG_V20_DBAn_STEP;
- } else {
- ejtag_info->ejtag_ibs_addr = EJTAG_V25_IBS;
- ejtag_info->ejtag_iba0_addr = EJTAG_V25_IBA0;
- ejtag_info->ejtag_ibm_offs = EJTAG_V25_IBM_OFFS;
- ejtag_info->ejtag_ibasid_offs = EJTAG_V25_IBASID_OFFS;
- ejtag_info->ejtag_ibc_offs = EJTAG_V25_IBC_OFFS;
-
- ejtag_info->ejtag_dbs_addr = EJTAG_V25_DBS;
- ejtag_info->ejtag_dba0_addr = EJTAG_V25_DBA0;
- ejtag_info->ejtag_dbm_offs = EJTAG_V25_DBM_OFFS;
- ejtag_info->ejtag_dbasid_offs = EJTAG_V25_DBASID_OFFS;
- ejtag_info->ejtag_dbc_offs = EJTAG_V25_DBC_OFFS;
- ejtag_info->ejtag_dbv_offs = EJTAG_V25_DBV_OFFS;
-
- ejtag_info->ejtag_iba_step_size = EJTAG_V25_IBAn_STEP;
- ejtag_info->ejtag_dba_step_size = EJTAG_V25_DBAn_STEP;
- }
-}
-
-static void ejtag_v20_print_imp(struct mips_ejtag *ejtag_info)
-{
- LOG_DEBUG("EJTAG v2.0: features:%s%s%s%s%s%s%s%s",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_SDBBP) ? " SDBBP_SPECIAL2" : " SDBBP",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_EADDR_NO32BIT) ? " EADDR>32bit" : " EADDR=32bit",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_COMPLEX_BREAK) ? " COMPLEX_BREAK" : "",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_DCACHE_COH) ? " DCACHE_COH" : " DCACHE_NOT_COH",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_ICACHE_COH) ? " ICACHE_COH" : " ICACHE_NOT_COH",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_NOPB) ? " noPB" : " PB",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_NODB) ? " noDB" : " DB",
- EJTAG_IMP_HAS(EJTAG_V20_IMP_NOIB) ? " noIB" : " IB");
- LOG_DEBUG("EJTAG v2.0: Break Channels: %" PRIu8,
- (uint8_t)((ejtag_info->impcode >> EJTAG_V20_IMP_BCHANNELS_SHIFT) &
- EJTAG_V20_IMP_BCHANNELS_MASK));
-}
-
-static void ejtag_v26_print_imp(struct mips_ejtag *ejtag_info)
-{
- LOG_DEBUG("EJTAG v2.6: features:%s%s",
- EJTAG_IMP_HAS(EJTAG_V26_IMP_R3K) ? " R3k" : " R4k",
- EJTAG_IMP_HAS(EJTAG_V26_IMP_DINT) ? " DINT" : "");
-}
-
-static void ejtag_main_print_imp(struct mips_ejtag *ejtag_info)
-{
- LOG_DEBUG("EJTAG main: features:%s%s%s%s%s",
- EJTAG_IMP_HAS(EJTAG_IMP_ASID8) ? " ASID_8" : "",
- EJTAG_IMP_HAS(EJTAG_IMP_ASID6) ? " ASID_6" : "",
- EJTAG_IMP_HAS(EJTAG_IMP_MIPS16) ? " MIPS16" : "",
- EJTAG_IMP_HAS(EJTAG_IMP_NODMA) ? " noDMA" : " DMA",
- EJTAG_IMP_HAS(EJTAG_DCR_MIPS64) ? " MIPS64" : " MIPS32");
-
- switch (ejtag_info->ejtag_version) {
- case EJTAG_VERSION_20:
- ejtag_v20_print_imp(ejtag_info);
- break;
- case EJTAG_VERSION_25:
- case EJTAG_VERSION_26:
- case EJTAG_VERSION_31:
- case EJTAG_VERSION_41:
- case EJTAG_VERSION_51:
- ejtag_v26_print_imp(ejtag_info);
- break;
- default:
- break;
- }
-}
-
-int mips_ejtag_init(struct mips_ejtag *ejtag_info)
-{
- int retval;
-
- retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode);
-
- /* get ejtag version */
- ejtag_info->ejtag_version = ((ejtag_info->impcode >> 29) & 0x07);
-
- switch (ejtag_info->ejtag_version) {
- case EJTAG_VERSION_20:
- LOG_DEBUG("EJTAG: Version 1 or 2.0 Detected");
- break;
- case EJTAG_VERSION_25:
- LOG_DEBUG("EJTAG: Version 2.5 Detected");
- break;
- case EJTAG_VERSION_26:
- LOG_DEBUG("EJTAG: Version 2.6 Detected");
- break;
- case EJTAG_VERSION_31:
- LOG_DEBUG("EJTAG: Version 3.1 Detected");
- break;
- case EJTAG_VERSION_41:
- LOG_DEBUG("EJTAG: Version 4.1 Detected");
- break;
- case EJTAG_VERSION_51:
- LOG_DEBUG("EJTAG: Version 5.1 Detected");
- break;
- default:
- LOG_DEBUG("EJTAG: Unknown Version Detected");
- break;
- }
- ejtag_main_print_imp(ejtag_info);
-
- if ((ejtag_info->impcode & EJTAG_IMP_NODMA) == 0) {
- LOG_DEBUG("EJTAG: DMA Access Mode detected. Disabling to "
- "workaround current broken code.");
- ejtag_info->impcode |= EJTAG_IMP_NODMA;
- }
-
- ejtag_info->ejtag_ctrl = EJTAG_CTRL_PRACC | EJTAG_CTRL_PROBEN;
-
- if (ejtag_info->ejtag_version != EJTAG_VERSION_20)
- ejtag_info->ejtag_ctrl |= EJTAG_CTRL_ROCC | EJTAG_CTRL_SETDEV;
-
- ejtag_info->fast_access_save = -1;
-
- mips_ejtag_init_mmr(ejtag_info);
-
- return ERROR_OK;
-}
-
-int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data)
-{
- struct jtag_tap *tap;
-
- tap = ejtag_info->tap;
- assert(tap != NULL);
-
- struct scan_field fields[2];
- uint8_t spracc = 0;
- uint8_t t[4] = {0, 0, 0, 0};
-
- /* fastdata 1-bit register */
- fields[0].num_bits = 1;
- fields[0].out_value = &spracc;
- fields[0].in_value = NULL;
-
- /* processor access data register 32 bit */
- fields[1].num_bits = 32;
- fields[1].out_value = t;
-
- if (write_t) {
- fields[1].in_value = NULL;
- buf_set_u32(t, 0, 32, *data);
- } else
- fields[1].in_value = (uint8_t *) data;
-
- jtag_add_dr_scan(tap, 2, fields, TAP_IDLE);
-
- if (!write_t && data)
- jtag_add_callback(mips_le_to_h_u32,
- (jtag_callback_data_t) data);
-
- keep_alive();
-
- return ERROR_OK;
-}
diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h
deleted file mode 100644
index 6ef0867..0000000
--- a/src/target/mips_ejtag.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_MIPS_EJTAG_H
-#define OPENOCD_TARGET_MIPS_EJTAG_H
-
-#include <jtag/jtag.h>
-
-/* tap instructions */
-#define EJTAG_INST_IDCODE 0x01
-#define EJTAG_INST_IMPCODE 0x03
-#define EJTAG_INST_ADDRESS 0x08
-#define EJTAG_INST_DATA 0x09
-#define EJTAG_INST_CONTROL 0x0A
-#define EJTAG_INST_ALL 0x0B
-#define EJTAG_INST_EJTAGBOOT 0x0C
-#define EJTAG_INST_NORMALBOOT 0x0D
-#define EJTAG_INST_FASTDATA 0x0E
-#define EJTAG_INST_TCBCONTROLA 0x10
-#define EJTAG_INST_TCBCONTROLB 0x11
-#define EJTAG_INST_TCBDATA 0x12
-#define EJTAG_INST_BYPASS 0xFF
-
-/* microchip PIC32MX specific instructions */
-#define MTAP_SW_MTAP 0x04
-#define MTAP_SW_ETAP 0x05
-#define MTAP_COMMAND 0x07
-
-/* microchip specific cmds */
-#define MCHP_ASERT_RST 0xd1
-#define MCHP_DE_ASSERT_RST 0xd0
-#define MCHP_ERASE 0xfc
-#define MCHP_STATUS 0x00
-
-/* ejtag control register bits ECR */
-#define EJTAG_CTRL_TOF (1 << 1)
-#define EJTAG_CTRL_TIF (1 << 2)
-#define EJTAG_CTRL_BRKST (1 << 3)
-#define EJTAG_CTRL_DLOCK (1 << 5)
-#define EJTAG_CTRL_DRWN (1 << 9)
-#define EJTAG_CTRL_DERR (1 << 10)
-#define EJTAG_CTRL_DSTRT (1 << 11)
-#define EJTAG_CTRL_JTAGBRK (1 << 12)
-#define EJTAG_CTRL_SETDEV (1 << 14)
-#define EJTAG_CTRL_PROBEN (1 << 15)
-#define EJTAG_CTRL_PRRST (1 << 16)
-#define EJTAG_CTRL_DMAACC (1 << 17)
-#define EJTAG_CTRL_PRACC (1 << 18)
-#define EJTAG_CTRL_PRNW (1 << 19)
-#define EJTAG_CTRL_PERRST (1 << 20)
-#define EJTAG_CTRL_SYNC (1 << 23)
-#define EJTAG_CTRL_DNM (1 << 28)
-#define EJTAG_CTRL_ROCC (1 << 31)
-
-/* Debug Register (CP0 Register 23, Select 0) */
-
-#define EJTAG_DEBUG_DSS (1 << 0)
-#define EJTAG_DEBUG_DBP (1 << 1)
-#define EJTAG_DEBUG_DDBL (1 << 2)
-#define EJTAG_DEBUG_DDBS (1 << 3)
-#define EJTAG_DEBUG_DIB (1 << 4)
-#define EJTAG_DEBUG_DINT (1 << 5)
-#define EJTAG_DEBUG_OFFLINE (1 << 7)
-#define EJTAG_DEBUG_SST (1 << 8)
-#define EJTAG_DEBUG_NOSST (1 << 9)
-#define EJTAG_DEBUG_DDBLIMPR (1 << 18)
-#define EJTAG_DEBUG_DDBSIMPR (1 << 19)
-#define EJTAG_DEBUG_IEXI (1 << 20)
-#define EJTAG_DEBUG_DBUSEP (1 << 21)
-#define EJTAG_DEBUG_CACHEEP (1 << 22)
-#define EJTAG_DEBUG_MCHECKP (1 << 23)
-#define EJTAG_DEBUG_IBUSEP (1 << 24)
-#define EJTAG_DEBUG_COUNTDM (1 << 25)
-#define EJTAG_DEBUG_HALT (1 << 26)
-#define EJTAG_DEBUG_DOZE (1 << 27)
-#define EJTAG_DEBUG_LSNM (1 << 28)
-#define EJTAG_DEBUG_NODCR (1 << 29)
-#define EJTAG_DEBUG_DM (1 << 30)
-#define EJTAG_DEBUG_DBD (1 << 31)
-
-/* implementation MIPS register bits.
- * Bits marked with V20 or v2.0 mean that, this registers supported only
- * by EJTAG v2.0. Bits marked with Lexra or BMIPS are different from the
- * official EJATG.
- * NOTE: Lexra or BMIPS use EJTAG v2.0 */
-
-#define EJTAG_IMP_HAS(x) (ejtag_info->impcode & (x))
-/* v2.0(Lexra) 29 - 1’b1 - Lexra Internal Trace Buffer implemented. This bit
- * overlaps with version bit of MIPS EJTAG specification. */
-#define EJTAG_V26_IMP_R3K (1 << 28)
-/* v2.0 - 24:25 - 2’b00- No profiling support */
-#define EJTAG_V26_IMP_DINT (1 << 24)
-#define EJTAG_V20_IMP_SDBBP (1 << 23) /* 1’b1 - sdbbp is Special2 Opcode */
-#define EJTAG_IMP_ASID8 (1 << 22)
-#define EJTAG_IMP_ASID6 (1 << 21)
-#define EJTAG_V20_IMP_COMPLEX_BREAK (1 << 20) /* Complex Breaks supported*/
-#define EJTAG_V20_IMP_EADDR_NO32BIT (1 << 19) /* EJTAG_ADDR > 32 bits wide */
-#define EJTAG_V20_IMP_DCACHE_COH (1 << 18) /* DCache does keep DMA coherent */
-#define EJTAG_V20_IMP_ICACHE_COH (1 << 17) /* DCache does keep DMA coherent */
-#define EJTAG_IMP_MIPS16 (1 << 16)
-#define EJTAG_IMP_NODMA (1 << 14)
-/* v2.0 - 11:13 external PC trace. Trace PC Width. */
-/* v2.0 - 8:10 external PC trace. PCST Width and DCLK Division Factor */
-#define EJTAG_V20_IMP_NOPB (1 << 7) /* no processor breaks */
-#define EJTAG_V20_IMP_NODB (1 << 6) /* no data breaks */
-#define EJTAG_V20_IMP_NOIB (1 << 5) /* no instruction breaks implemented */
-/* v2.0 - 1:4 Number of Break Channels. */
-#define EJTAG_V20_IMP_BCHANNELS_MASK 0xf
-#define EJTAG_V20_IMP_BCHANNELS_SHIFT 1
-#define EJTAG_DCR_MIPS64 (1 << 0)
-
-/* Debug Control Register DCR */
-#define EJTAG_DCR 0xFF300000
-#define EJTAG_DCR_ENM (1 << 29)
-#define EJTAG_DCR_DB (1 << 17)
-#define EJTAG_DCR_IB (1 << 16)
-#define EJTAG_DCR_INTE (1 << 4)
-#define EJTAG_DCR_MP (1 << 2)
-
-/* breakpoint support */
-/* EJTAG_V20_* was tested on Broadcom BCM7401
- * and may or will differ with other hardware. For example EZ4021-FC. */
-#define EJTAG_V20_IBS 0xFF300004
-#define EJTAG_V20_IBA0 0xFF300100
-#define EJTAG_V20_IBC_OFFS 0x4 /* IBC Offset */
-#define EJTAG_V20_IBM_OFFS 0x8
-#define EJTAG_V20_IBAn_STEP 0x10 /* Offset for next channel */
-#define EJTAG_V20_DBS 0xFF300008
-#define EJTAG_V20_DBA0 0xFF300200
-#define EJTAG_V20_DBC_OFFS 0x4
-#define EJTAG_V20_DBM_OFFS 0x8
-#define EJTAG_V20_DBV_OFFS 0xc
-#define EJTAG_V20_DBAn_STEP 0x10
-
-#define EJTAG_V25_IBS 0xFF301000
-#define EJTAG_V25_IBA0 0xFF301100
-#define EJTAG_V25_IBM_OFFS 0x8
-#define EJTAG_V25_IBASID_OFFS 0x10
-#define EJTAG_V25_IBC_OFFS 0x18
-#define EJTAG_V25_IBAn_STEP 0x100
-#define EJTAG_V25_DBS 0xFF302000
-#define EJTAG_V25_DBA0 0xFF302100
-#define EJTAG_V25_DBM_OFFS 0x8
-#define EJTAG_V25_DBASID_OFFS 0x10
-#define EJTAG_V25_DBC_OFFS 0x18
-#define EJTAG_V25_DBV_OFFS 0x20
-#define EJTAG_V25_DBAn_STEP 0x100
-
-#define EJTAG_DBCn_NOSB (1 << 13)
-#define EJTAG_DBCn_NOLB (1 << 12)
-#define EJTAG_DBCn_BLM_MASK 0xff
-#define EJTAG_DBCn_BLM_SHIFT 4
-#define EJTAG_DBCn_BE (1 << 0)
-
-#define EJTAG_VERSION_20 0
-#define EJTAG_VERSION_25 1
-#define EJTAG_VERSION_26 2
-#define EJTAG_VERSION_31 3
-#define EJTAG_VERSION_41 4
-#define EJTAG_VERSION_51 5
-
-struct mips_ejtag {
- struct jtag_tap *tap;
- uint32_t impcode;
- uint32_t idcode;
- uint32_t ejtag_ctrl;
- int fast_access_save;
- uint32_t reg8;
- uint32_t reg9;
- unsigned scan_delay;
- int mode;
- uint32_t pa_ctrl;
- uint32_t pa_addr;
- unsigned int ejtag_version;
-
- /* Memory-Mapped Registers. This addresses are not same on different
- * EJTAG versions. */
- uint32_t debug_caps;
- uint32_t ejtag_ibs_addr; /* Instruction Address Break Status */
- uint32_t ejtag_iba0_addr; /* IAB channel 0 */
- uint32_t ejtag_ibc_offs; /* IAB Control offset */
- uint32_t ejtag_ibm_offs; /* IAB Mask offset */
- uint32_t ejtag_ibasid_offs; /* IAB ASID (4Kc) */
-
- uint32_t ejtag_dbs_addr; /* Data Address Break Status Register */
- uint32_t ejtag_dba0_addr; /* DAB channel 0 */
- uint32_t ejtag_dbc_offs; /* DAB Control offset */
- uint32_t ejtag_dbm_offs; /* DAB Mask offset */
- uint32_t ejtag_dbv_offs; /* DAB Value offset */
- uint32_t ejtag_dbasid_offs; /* DAB ASID (4Kc) */
-
- uint32_t ejtag_iba_step_size;
- uint32_t ejtag_dba_step_size; /* size of step till next *DBAn register. */
-};
-
-void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info,
- int new_instr);
-int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info);
-int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info);
-int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode);
-void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info,
- uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf);
-void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data);
-int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data);
-void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data);
-int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data);
-int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data);
-
-int mips_ejtag_init(struct mips_ejtag *ejtag_info);
-int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step);
-
-static inline void mips_le_to_h_u32(jtag_callback_data_t arg)
-{
- uint8_t *in = (uint8_t *)arg;
- *((uint32_t *)arg) = le_to_h_u32(in);
-}
-
-#endif /* OPENOCD_TARGET_MIPS_EJTAG_H */
diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
deleted file mode 100644
index 0daa71c..0000000
--- a/src/target/mips_m4k.c
+++ /dev/null
@@ -1,1437 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
- * *
- * Copyright (C) 2011 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "mips32.h"
-#include "mips_m4k.h"
-#include "mips32_dmaacc.h"
-#include "target_type.h"
-#include "register.h"
-
-static void mips_m4k_enable_breakpoints(struct target *target);
-static void mips_m4k_enable_watchpoints(struct target *target);
-static int mips_m4k_set_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-static int mips_m4k_unset_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-static int mips_m4k_internal_restore(struct target *target, int current,
- uint32_t address, int handle_breakpoints,
- int debug_execution);
-static int mips_m4k_halt(struct target *target);
-static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
- uint32_t count, const uint8_t *buffer);
-
-static int mips_m4k_examine_debug_reason(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- uint32_t break_status;
- int retval;
-
- if ((target->debug_reason != DBG_REASON_DBGRQ)
- && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
- if (ejtag_info->debug_caps & EJTAG_DCR_IB) {
- /* get info about inst breakpoint support */
- retval = target_read_u32(target,
- ejtag_info->ejtag_ibs_addr, &break_status);
- if (retval != ERROR_OK)
- return retval;
- if (break_status & 0x1f) {
- /* we have halted on a breakpoint */
- retval = target_write_u32(target,
- ejtag_info->ejtag_ibs_addr, 0);
- if (retval != ERROR_OK)
- return retval;
- target->debug_reason = DBG_REASON_BREAKPOINT;
- }
- }
-
- if (ejtag_info->debug_caps & EJTAG_DCR_DB) {
- /* get info about data breakpoint support */
- retval = target_read_u32(target,
- ejtag_info->ejtag_dbs_addr, &break_status);
- if (retval != ERROR_OK)
- return retval;
- if (break_status & 0x1f) {
- /* we have halted on a breakpoint */
- retval = target_write_u32(target,
- ejtag_info->ejtag_dbs_addr, 0);
- if (retval != ERROR_OK)
- return retval;
- target->debug_reason = DBG_REASON_WATCHPOINT;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-static int mips_m4k_debug_entry(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- mips32_save_context(target);
-
- /* make sure stepping disabled, SSt bit in CP0 debug register cleared */
- mips_ejtag_config_step(ejtag_info, 0);
-
- /* make sure break unit configured */
- mips32_configure_break_unit(target);
-
- /* attempt to find halt reason */
- mips_m4k_examine_debug_reason(target);
-
- /* default to mips32 isa, it will be changed below if required */
- mips32->isa_mode = MIPS32_ISA_MIPS32;
-
- if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
- mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1);
-
- LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
- target_state_name(target));
-
- return ERROR_OK;
-}
-
-static struct target *get_mips_m4k(struct target *target, int32_t coreid)
-{
- struct target_list *head;
- struct target *curr;
-
- head = target->head;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
- return curr;
- head = head->next;
- }
- return target;
-}
-
-static int mips_m4k_halt_smp(struct target *target)
-{
- int retval = ERROR_OK;
- struct target_list *head;
- struct target *curr;
- head = target->head;
- while (head != (struct target_list *)NULL) {
- int ret = ERROR_OK;
- curr = head->target;
- if ((curr != target) && (curr->state != TARGET_HALTED))
- ret = mips_m4k_halt(curr);
-
- if (ret != ERROR_OK) {
- LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid);
- retval = ret;
- }
- head = head->next;
- }
- return retval;
-}
-
-static int update_halt_gdb(struct target *target)
-{
- int retval = ERROR_OK;
- if (target->gdb_service->core[0] == -1) {
- target->gdb_service->target = target;
- target->gdb_service->core[0] = target->coreid;
- retval = mips_m4k_halt_smp(target);
- }
- return retval;
-}
-
-static int mips_m4k_poll(struct target *target)
-{
- int retval = ERROR_OK;
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl;
- enum target_state prev_target_state = target->state;
-
- /* toggle to another core is done by gdb as follow */
- /* maint packet J core_id */
- /* continue */
- /* the next polling trigger an halt event sent to gdb */
- if ((target->state == TARGET_HALTED) && (target->smp) &&
- (target->gdb_service) &&
- (target->gdb_service->target == NULL)) {
- target->gdb_service->target =
- get_mips_m4k(target, target->gdb_service->core[1]);
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- return retval;
- }
-
- /* read ejtag control reg */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (retval != ERROR_OK)
- return retval;
-
- /* clear this bit before handling polling
- * as after reset registers will read zero */
- if (ejtag_ctrl & EJTAG_CTRL_ROCC) {
- /* we have detected a reset, clear flag
- * otherwise ejtag will not work */
- ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC;
-
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("Reset Detected");
- }
-
- /* check for processor halted */
- if (ejtag_ctrl & EJTAG_CTRL_BRKST) {
- if ((target->state != TARGET_HALTED)
- && (target->state != TARGET_DEBUG_RUNNING)) {
- if (target->state == TARGET_UNKNOWN)
- LOG_DEBUG("EJTAG_CTRL_BRKST already set during server startup.");
-
- /* OpenOCD was was probably started on the board with EJTAG_CTRL_BRKST already set
- * (maybe put on by HALT-ing the board in the previous session).
- *
- * Force enable debug entry for this session.
- */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
- target->state = TARGET_HALTED;
- retval = mips_m4k_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->smp &&
- ((prev_target_state == TARGET_RUNNING)
- || (prev_target_state == TARGET_RESET))) {
- retval = update_halt_gdb(target);
- if (retval != ERROR_OK)
- return retval;
- }
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- } else if (target->state == TARGET_DEBUG_RUNNING) {
- target->state = TARGET_HALTED;
-
- retval = mips_m4k_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->smp) {
- retval = update_halt_gdb(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
- }
- } else
- target->state = TARGET_RUNNING;
-
-/* LOG_DEBUG("ctrl = 0x%08X", ejtag_ctrl); */
-
- return ERROR_OK;
-}
-
-static int mips_m4k_halt(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- LOG_DEBUG("target->state: %s", target_state_name(target));
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- if (target->state == TARGET_UNKNOWN)
- LOG_WARNING("target was in unknown state when halt was requested");
-
- if (target->state == TARGET_RESET) {
- if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
- LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
- return ERROR_TARGET_FAILURE;
- } else {
- /* we came here in a reset_halt or reset_init sequence
- * debug entry was already prepared in mips_m4k_assert_reset()
- */
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
- }
- }
-
- /* break processor */
- mips_ejtag_enter_debug(ejtag_info);
-
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int mips_m4k_assert_reset(struct target *target)
-{
- struct mips_m4k_common *mips_m4k = target_to_m4k(target);
- struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
-
- /* TODO: apply hw reset signal in not examined state */
- if (!(target_was_examined(target))) {
- LOG_WARNING("Reset is not asserted because the target is not examined.");
- LOG_WARNING("Use a reset button or power cycle the target.");
- return ERROR_TARGET_NOT_EXAMINED;
- }
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- enum reset_types jtag_reset_config = jtag_get_reset_config();
-
- /* some cores support connecting while srst is asserted
- * use that mode is it has been configured */
-
- bool srst_asserted = false;
-
- if (!(jtag_reset_config & RESET_SRST_PULLS_TRST) &&
- (jtag_reset_config & RESET_SRST_NO_GATING)) {
- jtag_add_reset(0, 1);
- srst_asserted = true;
- }
-
-
- /* EJTAG before v2.5/2.6 does not support EJTAGBOOT or NORMALBOOT */
- if (ejtag_info->ejtag_version != EJTAG_VERSION_20) {
- if (target->reset_halt) {
- /* use hardware to catch reset */
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_EJTAGBOOT);
- } else
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_NORMALBOOT);
- }
-
- if (jtag_reset_config & RESET_HAS_SRST) {
- /* here we should issue a srst only, but we may have to assert trst as well */
- if (jtag_reset_config & RESET_SRST_PULLS_TRST)
- jtag_add_reset(1, 1);
- else if (!srst_asserted)
- jtag_add_reset(0, 1);
- } else {
- if (mips_m4k->is_pic32mx) {
- LOG_DEBUG("Using MTAP reset to reset processor...");
-
- /* use microchip specific MTAP reset */
- mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
- mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
-
- mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
- mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
- mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
- } else {
- /* use ejtag reset - not supported by all cores */
- uint32_t ejtag_ctrl = ejtag_info->ejtag_ctrl | EJTAG_CTRL_PRRST | EJTAG_CTRL_PERRST;
- LOG_DEBUG("Using EJTAG reset (PRRST) to reset processor...");
- mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
- mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl);
- }
- }
-
- target->state = TARGET_RESET;
- jtag_add_sleep(50000);
-
- register_cache_invalidate(mips_m4k->mips32.core_cache);
-
- if (target->reset_halt) {
- int retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int mips_m4k_deassert_reset(struct target *target)
-{
- LOG_DEBUG("target->state: %s", target_state_name(target));
-
- /* deassert reset lines */
- jtag_add_reset(0, 0);
-
- return ERROR_OK;
-}
-
-static int mips_m4k_single_step_core(struct target *target)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- /* configure single step mode */
- mips_ejtag_config_step(ejtag_info, 1);
-
- /* disable interrupts while stepping */
- mips32_enable_interrupts(target, 0);
-
- /* exit debug mode */
- mips_ejtag_exit_debug(ejtag_info);
-
- mips_m4k_debug_entry(target);
-
- return ERROR_OK;
-}
-
-static int mips_m4k_restore_smp(struct target *target, uint32_t address, int handle_breakpoints)
-{
- int retval = ERROR_OK;
- struct target_list *head;
- struct target *curr;
-
- head = target->head;
- while (head != (struct target_list *)NULL) {
- int ret = ERROR_OK;
- curr = head->target;
- if ((curr != target) && (curr->state != TARGET_RUNNING)) {
- /* resume current address , not in step mode */
- ret = mips_m4k_internal_restore(curr, 1, address,
- handle_breakpoints, 0);
-
- if (ret != ERROR_OK) {
- LOG_ERROR("target->coreid :%" PRId32 " failed to resume at address :0x%" PRIx32,
- curr->coreid, address);
- retval = ret;
- }
- }
- head = head->next;
- }
- return retval;
-}
-
-static int mips_m4k_internal_restore(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- struct breakpoint *breakpoint = NULL;
- uint32_t resume_pc;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!debug_execution) {
- target_free_all_working_areas(target);
- mips_m4k_enable_breakpoints(target);
- mips_m4k_enable_watchpoints(target);
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current) {
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
- mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
- mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
- }
-
- if (ejtag_info->impcode & EJTAG_IMP_MIPS16)
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
-
- if (!current)
- resume_pc = address;
- else
- resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
-
- mips32_restore_context(target);
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- /* Single step past breakpoint at current address */
- breakpoint = breakpoint_find(target, resume_pc);
- if (breakpoint) {
- LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
- mips_m4k_unset_breakpoint(target, breakpoint);
- mips_m4k_single_step_core(target);
- mips_m4k_set_breakpoint(target, breakpoint);
- }
- }
-
- /* enable interrupts if we are running */
- mips32_enable_interrupts(target, !debug_execution);
-
- /* exit debug mode */
- mips_ejtag_exit_debug(ejtag_info);
- target->debug_reason = DBG_REASON_NOTHALTED;
-
- /* registers are now invalid */
- register_cache_invalidate(mips32->core_cache);
-
- if (!debug_execution) {
- target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
- }
-
- return ERROR_OK;
-}
-
-static int mips_m4k_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- int retval = ERROR_OK;
-
- /* dummy resume for smp toggle in order to reduce gdb impact */
- if ((target->smp) && (target->gdb_service->core[1] != -1)) {
- /* simulate a start and halt of target */
- target->gdb_service->target = NULL;
- target->gdb_service->core[0] = target->gdb_service->core[1];
- /* fake resume at next poll we play the target core[1], see poll*/
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- return retval;
- }
-
- retval = mips_m4k_internal_restore(target, current, address,
- handle_breakpoints,
- debug_execution);
-
- if (retval == ERROR_OK && target->smp) {
- target->gdb_service->core[0] = -1;
- retval = mips_m4k_restore_smp(target, address, handle_breakpoints);
- }
-
- return retval;
-}
-
-static int mips_m4k_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- struct breakpoint *breakpoint = NULL;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current) {
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
- mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
- mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
- }
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- breakpoint = breakpoint_find(target,
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
- if (breakpoint)
- mips_m4k_unset_breakpoint(target, breakpoint);
- }
-
- /* restore context */
- mips32_restore_context(target);
-
- /* configure single step mode */
- mips_ejtag_config_step(ejtag_info, 1);
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-
- /* disable interrupts while stepping */
- mips32_enable_interrupts(target, 0);
-
- /* exit debug mode */
- mips_ejtag_exit_debug(ejtag_info);
-
- /* registers are now invalid */
- register_cache_invalidate(mips32->core_cache);
-
- LOG_DEBUG("target stepped ");
- mips_m4k_debug_entry(target);
-
- if (breakpoint)
- mips_m4k_set_breakpoint(target, breakpoint);
-
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- return ERROR_OK;
-}
-
-static void mips_m4k_enable_breakpoints(struct target *target)
-{
- struct breakpoint *breakpoint = target->breakpoints;
-
- /* set any pending breakpoints */
- while (breakpoint) {
- if (breakpoint->set == 0)
- mips_m4k_set_breakpoint(target, breakpoint);
- breakpoint = breakpoint->next;
- }
-}
-
-static int mips_m4k_set_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- struct mips32_comparator *comparator_list = mips32->inst_break_list;
- int retval;
-
- if (breakpoint->set) {
- LOG_WARNING("breakpoint already set");
- return ERROR_OK;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- int bp_num = 0;
-
- while (comparator_list[bp_num].used && (bp_num < mips32->num_inst_bpoints))
- bp_num++;
- if (bp_num >= mips32->num_inst_bpoints) {
- LOG_ERROR("Can not find free FP Comparator(bpid: %" PRIu32 ")",
- breakpoint->unique_id);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- breakpoint->set = bp_num + 1;
- comparator_list[bp_num].used = 1;
- comparator_list[bp_num].bp_value = breakpoint->address;
-
- /* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved.
- * Warning: there is no IB ASID registers in 2.0.
- * Do not set it! :) */
- if (ejtag_info->ejtag_version == EJTAG_VERSION_20)
- comparator_list[bp_num].bp_value &= 0xFFFFFFFC;
-
- target_write_u32(target, comparator_list[bp_num].reg_address,
- comparator_list[bp_num].bp_value);
- target_write_u32(target, comparator_list[bp_num].reg_address +
- ejtag_info->ejtag_ibm_offs, 0x00000000);
- target_write_u32(target, comparator_list[bp_num].reg_address +
- ejtag_info->ejtag_ibc_offs, 1);
- LOG_DEBUG("bpid: %" PRIu32 ", bp_num %i bp_value 0x%" PRIx32 "",
- breakpoint->unique_id,
- bp_num, comparator_list[bp_num].bp_value);
- } else if (breakpoint->type == BKPT_SOFT) {
- LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
- if (breakpoint->length == 4) {
- uint32_t verify = 0xffffffff;
-
- retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u32(target, breakpoint->address, &verify);
- if (retval != ERROR_OK)
- return retval;
- if (verify != MIPS32_SDBBP) {
- LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx32
- " - check that memory is read/writable", breakpoint->address);
- return ERROR_OK;
- }
- } else {
- uint16_t verify = 0xffff;
-
- retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP);
- if (retval != ERROR_OK)
- return retval;
-
- retval = target_read_u16(target, breakpoint->address, &verify);
- if (retval != ERROR_OK)
- return retval;
- if (verify != MIPS16_SDBBP) {
- LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx32
- " - check that memory is read/writable", breakpoint->address);
- return ERROR_OK;
- }
- }
-
- breakpoint->set = 20; /* Any nice value but 0 */
- }
-
- return ERROR_OK;
-}
-
-static int mips_m4k_unset_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- struct mips32_comparator *comparator_list = mips32->inst_break_list;
- int retval;
-
- if (!breakpoint->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- int bp_num = breakpoint->set - 1;
- if ((bp_num < 0) || (bp_num >= mips32->num_inst_bpoints)) {
- LOG_DEBUG("Invalid FP Comparator number in breakpoint (bpid: %" PRIu32 ")",
- breakpoint->unique_id);
- return ERROR_OK;
- }
- LOG_DEBUG("bpid: %" PRIu32 " - releasing hw: %d",
- breakpoint->unique_id,
- bp_num);
- comparator_list[bp_num].used = 0;
- comparator_list[bp_num].bp_value = 0;
- target_write_u32(target, comparator_list[bp_num].reg_address +
- ejtag_info->ejtag_ibc_offs, 0);
-
- } else {
- /* restore original instruction (kept in target endianness) */
- LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
- if (breakpoint->length == 4) {
- uint32_t current_instr;
-
- /* check that user program has not modified breakpoint instruction */
- retval = target_read_memory(target, breakpoint->address, 4, 1,
- (uint8_t *)&current_instr);
- if (retval != ERROR_OK)
- return retval;
-
- /**
- * target_read_memory() gets us data in _target_ endianess.
- * If we want to use this data on the host for comparisons with some macros
- * we must first transform it to _host_ endianess using target_buffer_get_u32().
- */
- current_instr = target_buffer_get_u32(target, (uint8_t *)&current_instr);
-
- if (current_instr == MIPS32_SDBBP) {
- retval = target_write_memory(target, breakpoint->address, 4, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- }
- } else {
- uint16_t current_instr;
-
- /* check that user program has not modified breakpoint instruction */
- retval = target_read_memory(target, breakpoint->address, 2, 1,
- (uint8_t *)&current_instr);
- if (retval != ERROR_OK)
- return retval;
- current_instr = target_buffer_get_u16(target, (uint8_t *)&current_instr);
- if (current_instr == MIPS16_SDBBP) {
- retval = target_write_memory(target, breakpoint->address, 2, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- }
- }
- }
- breakpoint->set = 0;
-
- return ERROR_OK;
-}
-
-static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
-
- if (breakpoint->type == BKPT_HARD) {
- if (mips32->num_inst_bpoints_avail < 1) {
- LOG_INFO("no hardware breakpoint available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- mips32->num_inst_bpoints_avail--;
- }
-
- return mips_m4k_set_breakpoint(target, breakpoint);
-}
-
-static int mips_m4k_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (breakpoint->set)
- mips_m4k_unset_breakpoint(target, breakpoint);
-
- if (breakpoint->type == BKPT_HARD)
- mips32->num_inst_bpoints_avail++;
-
- return ERROR_OK;
-}
-
-static int mips_m4k_set_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- struct mips32_comparator *comparator_list = mips32->data_break_list;
- int wp_num = 0;
- /*
- * watchpoint enabled, ignore all byte lanes in value register
- * and exclude both load and store accesses from watchpoint
- * condition evaluation
- */
- int enable = EJTAG_DBCn_NOSB | EJTAG_DBCn_NOLB | EJTAG_DBCn_BE |
- (0xff << EJTAG_DBCn_BLM_SHIFT);
-
- if (watchpoint->set) {
- LOG_WARNING("watchpoint already set");
- return ERROR_OK;
- }
-
- while (comparator_list[wp_num].used && (wp_num < mips32->num_data_bpoints))
- wp_num++;
- if (wp_num >= mips32->num_data_bpoints) {
- LOG_ERROR("Can not find free FP Comparator");
- return ERROR_FAIL;
- }
-
- if (watchpoint->length != 4) {
- LOG_ERROR("Only watchpoints of length 4 are supported");
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- if (watchpoint->address % 4) {
- LOG_ERROR("Watchpoints address should be word aligned");
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- switch (watchpoint->rw) {
- case WPT_READ:
- enable &= ~EJTAG_DBCn_NOLB;
- break;
- case WPT_WRITE:
- enable &= ~EJTAG_DBCn_NOSB;
- break;
- case WPT_ACCESS:
- enable &= ~(EJTAG_DBCn_NOLB | EJTAG_DBCn_NOSB);
- break;
- default:
- LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
- }
-
- watchpoint->set = wp_num + 1;
- comparator_list[wp_num].used = 1;
- comparator_list[wp_num].bp_value = watchpoint->address;
-
- /* EJTAG 2.0 uses 29bit DBA. First 3 bits are reserved.
- * There is as well no ASID register support. */
- if (ejtag_info->ejtag_version == EJTAG_VERSION_20)
- comparator_list[wp_num].bp_value &= 0xFFFFFFF8;
- else
- target_write_u32(target, comparator_list[wp_num].reg_address +
- ejtag_info->ejtag_dbasid_offs, 0x00000000);
-
- target_write_u32(target, comparator_list[wp_num].reg_address,
- comparator_list[wp_num].bp_value);
- target_write_u32(target, comparator_list[wp_num].reg_address +
- ejtag_info->ejtag_dbm_offs, 0x00000000);
-
- target_write_u32(target, comparator_list[wp_num].reg_address +
- ejtag_info->ejtag_dbc_offs, enable);
- /* TODO: probably this value is ignored on 2.0 */
- target_write_u32(target, comparator_list[wp_num].reg_address +
- ejtag_info->ejtag_dbv_offs, 0);
- LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32 "", wp_num, comparator_list[wp_num].bp_value);
-
- return ERROR_OK;
-}
-
-static int mips_m4k_unset_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- struct mips32_comparator *comparator_list = mips32->data_break_list;
-
- if (!watchpoint->set) {
- LOG_WARNING("watchpoint not set");
- return ERROR_OK;
- }
-
- int wp_num = watchpoint->set - 1;
- if ((wp_num < 0) || (wp_num >= mips32->num_data_bpoints)) {
- LOG_DEBUG("Invalid FP Comparator number in watchpoint");
- return ERROR_OK;
- }
- comparator_list[wp_num].used = 0;
- comparator_list[wp_num].bp_value = 0;
- target_write_u32(target, comparator_list[wp_num].reg_address +
- ejtag_info->ejtag_dbc_offs, 0);
- watchpoint->set = 0;
-
- return ERROR_OK;
-}
-
-static int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
-
- if (mips32->num_data_bpoints_avail < 1) {
- LOG_INFO("no hardware watchpoints available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- mips32->num_data_bpoints_avail--;
-
- mips_m4k_set_watchpoint(target, watchpoint);
- return ERROR_OK;
-}
-
-static int mips_m4k_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- /* get pointers to arch-specific information */
- struct mips32_common *mips32 = target_to_mips32(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (watchpoint->set)
- mips_m4k_unset_watchpoint(target, watchpoint);
-
- mips32->num_data_bpoints_avail++;
-
- return ERROR_OK;
-}
-
-static void mips_m4k_enable_watchpoints(struct target *target)
-{
- struct watchpoint *watchpoint = target->watchpoints;
-
- /* set any pending watchpoints */
- while (watchpoint) {
- if (watchpoint->set == 0)
- mips_m4k_set_watchpoint(target, watchpoint);
- watchpoint = watchpoint->next;
- }
-}
-
-static int mips_m4k_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
- address, size, count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- /* since we don't know if buffer is aligned, we allocate new mem that is always aligned */
- void *t = NULL;
-
- if (size > 1) {
- t = malloc(count * size * sizeof(uint8_t));
- if (t == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
- } else
- t = buffer;
-
- /* if noDMA off, use DMAACC mode for memory read */
- int retval;
- if (ejtag_info->impcode & EJTAG_IMP_NODMA)
- retval = mips32_pracc_read_mem(ejtag_info, address, size, count, t);
- else
- retval = mips32_dmaacc_read_mem(ejtag_info, address, size, count, t);
-
- /* mips32_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */
- /* endianness, but byte array should represent target endianness */
- if (ERROR_OK == retval) {
- switch (size) {
- case 4:
- target_buffer_set_u32_array(target, buffer, count, t);
- break;
- case 2:
- target_buffer_set_u16_array(target, buffer, count, t);
- break;
- }
- }
-
- if ((size > 1) && (t != NULL))
- free(t);
-
- return retval;
-}
-
-static int mips_m4k_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
- address, size, count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (size == 4 && count > 32) {
- int retval = mips_m4k_bulk_write_memory(target, address, count, buffer);
- if (retval == ERROR_OK)
- return ERROR_OK;
- LOG_WARNING("Falling back to non-bulk write");
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- /** correct endianess if we have word or hword access */
- void *t = NULL;
- if (size > 1) {
- /* mips32_..._write_mem with size 4/2 requires uint32_t/uint16_t in host */
- /* endianness, but byte array represents target endianness */
- t = malloc(count * size * sizeof(uint8_t));
- if (t == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- switch (size) {
- case 4:
- target_buffer_get_u32_array(target, buffer, count, (uint32_t *)t);
- break;
- case 2:
- target_buffer_get_u16_array(target, buffer, count, (uint16_t *)t);
- break;
- }
- buffer = t;
- }
-
- /* if noDMA off, use DMAACC mode for memory write */
- int retval;
- if (ejtag_info->impcode & EJTAG_IMP_NODMA)
- retval = mips32_pracc_write_mem(ejtag_info, address, size, count, buffer);
- else
- retval = mips32_dmaacc_write_mem(ejtag_info, address, size, count, buffer);
-
- if (t != NULL)
- free(t);
-
- if (ERROR_OK != retval)
- return retval;
-
- return ERROR_OK;
-}
-
-static int mips_m4k_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- mips32_build_reg_cache(target);
-
- return ERROR_OK;
-}
-
-static int mips_m4k_init_arch_info(struct target *target,
- struct mips_m4k_common *mips_m4k, struct jtag_tap *tap)
-{
- struct mips32_common *mips32 = &mips_m4k->mips32;
-
- mips_m4k->common_magic = MIPSM4K_COMMON_MAGIC;
-
- /* initialize mips4k specific info */
- mips32_init_arch_info(target, mips32, tap);
- mips32->arch_info = mips_m4k;
-
- return ERROR_OK;
-}
-
-static int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
-{
- struct mips_m4k_common *mips_m4k = calloc(1, sizeof(struct mips_m4k_common));
-
- mips_m4k_init_arch_info(target, mips_m4k, target->tap);
-
- return ERROR_OK;
-}
-
-static int mips_m4k_examine(struct target *target)
-{
- int retval;
- struct mips_m4k_common *mips_m4k = target_to_m4k(target);
- struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
- uint32_t idcode = 0;
-
- if (!target_was_examined(target)) {
- retval = mips_ejtag_get_idcode(ejtag_info, &idcode);
- if (retval != ERROR_OK)
- return retval;
- ejtag_info->idcode = idcode;
-
- if (((idcode >> 1) & 0x7FF) == 0x29) {
- /* we are using a pic32mx so select ejtag port
- * as it is not selected by default */
- mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
- LOG_DEBUG("PIC32MX Detected - using EJTAG Interface");
- mips_m4k->is_pic32mx = true;
- }
- }
-
- /* init rest of ejtag interface */
- retval = mips_ejtag_init(ejtag_info);
- if (retval != ERROR_OK)
- return retval;
-
- retval = mips32_examine(target);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
- uint32_t count, const uint8_t *buffer)
-{
- struct mips32_common *mips32 = target_to_mips32(target);
- struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
- struct working_area *fast_data_area;
- int retval;
- int write_t = 1;
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count);
-
- /* check alignment */
- if (address & 0x3u)
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- if (mips32->fast_data_area == NULL) {
- /* Get memory for block write handler
- * we preserve this area between calls and gain a speed increase
- * of about 3kb/sec when writing flash
- * this will be released/nulled by the system when the target is resumed or reset */
- retval = target_alloc_working_area(target,
- MIPS32_FASTDATA_HANDLER_SIZE,
- &mips32->fast_data_area);
- if (retval != ERROR_OK) {
- LOG_ERROR("No working area available");
- return retval;
- }
-
- /* reset fastadata state so the algo get reloaded */
- ejtag_info->fast_access_save = -1;
- }
-
- fast_data_area = mips32->fast_data_area;
-
- if (address <= fast_data_area->address + fast_data_area->size &&
- fast_data_area->address <= address + count) {
- LOG_ERROR("fast_data (0x%8.8" PRIx32 ") is within write area "
- "(0x%8.8" PRIx32 "-0x%8.8" PRIx32 ").",
- fast_data_area->address, address, address + count);
- LOG_ERROR("Change work-area-phys or load_image address!");
- return ERROR_FAIL;
- }
-
- /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */
- /* but byte array represents target endianness */
- uint32_t *t = NULL;
- t = malloc(count * sizeof(uint32_t));
- if (t == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- target_buffer_get_u32_array(target, buffer, count, t);
-
- retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address,
- count, t);
-
- if (t != NULL)
- free(t);
-
- if (retval != ERROR_OK)
- LOG_ERROR("Fastdata access Failed");
-
- return retval;
-}
-
-static int mips_m4k_verify_pointer(struct command_context *cmd_ctx,
- struct mips_m4k_common *mips_m4k)
-{
- if (mips_m4k->common_magic != MIPSM4K_COMMON_MAGIC) {
- command_print(cmd_ctx, "target is not an MIPS_M4K");
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(mips_m4k_handle_cp0_command)
-{
- int retval;
- struct target *target = get_current_target(CMD_CTX);
- struct mips_m4k_common *mips_m4k = target_to_m4k(target);
- struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
-
- retval = mips_m4k_verify_pointer(CMD_CTX, mips_m4k);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- /* two or more argument, access a single register/select (write if third argument is given) */
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- else {
- uint32_t cp0_reg, cp0_sel;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], cp0_reg);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cp0_sel);
-
- if (CMD_ARGC == 2) {
- uint32_t value;
- retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access reg %" PRIi32,
- cp0_reg);
- return ERROR_OK;
- }
- command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
- cp0_reg, cp0_sel, value);
-
- } else if (CMD_ARGC == 3) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value);
- retval = mips32_cp0_write(ejtag_info, value, cp0_reg, cp0_sel);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX,
- "couldn't access cp0 reg %" PRIi32 ", select %" PRIi32,
- cp0_reg, cp0_sel);
- return ERROR_OK;
- }
- command_print(CMD_CTX, "cp0 reg %" PRIi32 ", select %" PRIi32 ": %8.8" PRIx32,
- cp0_reg, cp0_sel, value);
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(mips_m4k_handle_smp_off_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- /* check target is an smp target */
- struct target_list *head;
- struct target *curr;
- head = target->head;
- target->smp = 0;
- if (head != (struct target_list *)NULL) {
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- curr->smp = 0;
- head = head->next;
- }
- /* fixes the target display to the debugger */
- target->gdb_service->target = target;
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(mips_m4k_handle_smp_on_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct target_list *head;
- struct target *curr;
- head = target->head;
- if (head != (struct target_list *)NULL) {
- target->smp = 1;
- while (head != (struct target_list *)NULL) {
- curr = head->target;
- curr->smp = 1;
- head = head->next;
- }
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(mips_m4k_handle_smp_gdb_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- int retval = ERROR_OK;
- struct target_list *head;
- head = target->head;
- if (head != (struct target_list *)NULL) {
- if (CMD_ARGC == 1) {
- int coreid = 0;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);
- if (ERROR_OK != retval)
- return retval;
- target->gdb_service->core[1] = coreid;
-
- }
- command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
- , target->gdb_service->core[1]);
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(mips_m4k_handle_scan_delay_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct mips_m4k_common *mips_m4k = target_to_m4k(target);
- struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
-
- if (CMD_ARGC == 1)
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], ejtag_info->scan_delay);
- else if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay);
- if (ejtag_info->scan_delay >= 2000000) {
- ejtag_info->mode = 0;
- command_print(CMD_CTX, "running in legacy mode");
- } else {
- ejtag_info->mode = 1;
- command_print(CMD_CTX, "running in fast queued mode");
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration mips_m4k_exec_command_handlers[] = {
- {
- .name = "cp0",
- .handler = mips_m4k_handle_cp0_command,
- .mode = COMMAND_EXEC,
- .usage = "regnum [value]",
- .help = "display/modify cp0 register",
- },
- {
- .name = "smp_off",
- .handler = mips_m4k_handle_smp_off_command,
- .mode = COMMAND_EXEC,
- .help = "Stop smp handling",
- .usage = "",},
-
- {
- .name = "smp_on",
- .handler = mips_m4k_handle_smp_on_command,
- .mode = COMMAND_EXEC,
- .help = "Restart smp handling",
- .usage = "",
- },
- {
- .name = "smp_gdb",
- .handler = mips_m4k_handle_smp_gdb_command,
- .mode = COMMAND_EXEC,
- .help = "display/fix current core played to gdb",
- .usage = "",
- },
- {
- .name = "scan_delay",
- .handler = mips_m4k_handle_scan_delay_command,
- .mode = COMMAND_ANY,
- .help = "display/set scan delay in nano seconds",
- .usage = "[value]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration mips_m4k_command_handlers[] = {
- {
- .chain = mips32_command_handlers,
- },
- {
- .name = "mips_m4k",
- .mode = COMMAND_ANY,
- .help = "mips_m4k command group",
- .usage = "",
- .chain = mips_m4k_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct target_type mips_m4k_target = {
- .name = "mips_m4k",
-
- .poll = mips_m4k_poll,
- .arch_state = mips32_arch_state,
-
- .halt = mips_m4k_halt,
- .resume = mips_m4k_resume,
- .step = mips_m4k_step,
-
- .assert_reset = mips_m4k_assert_reset,
- .deassert_reset = mips_m4k_deassert_reset,
-
- .get_gdb_reg_list = mips32_get_gdb_reg_list,
-
- .read_memory = mips_m4k_read_memory,
- .write_memory = mips_m4k_write_memory,
- .checksum_memory = mips32_checksum_memory,
- .blank_check_memory = mips32_blank_check_memory,
-
- .run_algorithm = mips32_run_algorithm,
-
- .add_breakpoint = mips_m4k_add_breakpoint,
- .remove_breakpoint = mips_m4k_remove_breakpoint,
- .add_watchpoint = mips_m4k_add_watchpoint,
- .remove_watchpoint = mips_m4k_remove_watchpoint,
-
- .commands = mips_m4k_command_handlers,
- .target_create = mips_m4k_target_create,
- .init_target = mips_m4k_init_target,
- .examine = mips_m4k_examine,
-};
diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h
deleted file mode 100644
index cf82661..0000000
--- a/src/target/mips_m4k.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by David T.L. Wong *
- * *
- * Copyright (C) 2011 by Drasko DRASKOVIC *
- * drasko.draskovic@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_MIPS_M4K_H
-#define OPENOCD_TARGET_MIPS_M4K_H
-
-struct target;
-
-#define MIPSM4K_COMMON_MAGIC 0xB321B321
-
-struct mips_m4k_common {
- uint32_t common_magic;
- bool is_pic32mx;
- struct mips32_common mips32;
-};
-
-static inline struct mips_m4k_common *
-target_to_m4k(struct target *target)
-{
- return container_of(target->arch_info,
- struct mips_m4k_common, mips32);
-}
-
-extern const struct command_registration mips_m4k_command_handlers[];
-
-#endif /* OPENOCD_TARGET_MIPS_M4K_H */
diff --git a/src/target/nds32.c b/src/target/nds32.c
deleted file mode 100644
index 2926b23..0000000
--- a/src/target/nds32.c
+++ /dev/null
@@ -1,2628 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include <helper/binarybuffer.h>
-#include "nds32.h"
-#include "nds32_aice.h"
-#include "nds32_tlb.h"
-#include "nds32_disassembler.h"
-
-const int NDS32_BREAK_16 = 0x00EA; /* 0xEA00 */
-const int NDS32_BREAK_32 = 0x0A000064; /* 0x6400000A */
-
-struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM];
-uint32_t nds32_edm_ops_num;
-
-const char *nds32_debug_type_name[11] = {
- "SOFTWARE BREAK",
- "SOFTWARE BREAK_16",
- "HARDWARE BREAKPOINT",
- "DATA ADDR WATCHPOINT PRECISE",
- "DATA VALUE WATCHPOINT PRECISE",
- "DATA VALUE WATCHPOINT IMPRECISE",
- "DEBUG INTERRUPT",
- "HARDWARE SINGLE STEP",
- "DATA ADDR WATCHPOINT NEXT PRECISE",
- "DATA VALUE WATCHPOINT NEXT PRECISE",
- "LOAD STORE GLOBAL STOP",
-};
-
-static const int NDS32_LM_SIZE_TABLE[16] = {
- 4 * 1024,
- 8 * 1024,
- 16 * 1024,
- 32 * 1024,
- 64 * 1024,
- 128 * 1024,
- 256 * 1024,
- 512 * 1024,
- 1024 * 1024,
- 1 * 1024,
- 2 * 1024,
-};
-
-static const int NDS32_LINE_SIZE_TABLE[6] = {
- 0,
- 8,
- 16,
- 32,
- 64,
- 128,
-};
-
-static int nds32_get_core_reg(struct reg *reg)
-{
- int retval;
- struct nds32_reg *reg_arch_info = reg->arch_info;
- struct target *target = reg_arch_info->target;
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (reg->valid) {
- uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
- LOG_DEBUG("reading register(cached) %" PRIi32 "(%s), value: 0x%8.8" PRIx32,
- reg_arch_info->num, reg->name, val);
- return ERROR_OK;
- }
-
- int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
-
- if (reg_arch_info->enable == false) {
- buf_set_u32(reg_arch_info->value, 0, 32, NDS32_REGISTER_DISABLE);
- retval = ERROR_FAIL;
- } else {
- uint32_t val = 0;
- if ((nds32->fpu_enable == false)
- && (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) {
- retval = ERROR_OK;
- } else if ((nds32->audio_enable == false)
- && (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) {
- retval = ERROR_OK;
- } else {
- retval = aice_read_register(aice, mapped_regnum, &val);
- }
- buf_set_u32(reg_arch_info->value, 0, 32, val);
-
- LOG_DEBUG("reading register %" PRIi32 "(%s), value: 0x%8.8" PRIx32,
- reg_arch_info->num, reg->name, val);
- }
-
- if (retval == ERROR_OK) {
- reg->valid = true;
- reg->dirty = false;
- }
-
- return retval;
-}
-
-static int nds32_get_core_reg_64(struct reg *reg)
-{
- int retval;
- struct nds32_reg *reg_arch_info = reg->arch_info;
- struct target *target = reg_arch_info->target;
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (reg->valid)
- return ERROR_OK;
-
- if (reg_arch_info->enable == false) {
- buf_set_u64(reg_arch_info->value, 0, 64, NDS32_REGISTER_DISABLE);
- retval = ERROR_FAIL;
- } else {
- uint64_t val = 0;
- if ((nds32->fpu_enable == false)
- && ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) {
- retval = ERROR_OK;
- } else {
- retval = aice_read_reg_64(aice, reg_arch_info->num, &val);
- }
- buf_set_u64(reg_arch_info->value, 0, 64, val);
- }
-
- if (retval == ERROR_OK) {
- reg->valid = true;
- reg->dirty = false;
- }
-
- return retval;
-}
-
-static int nds32_update_psw(struct nds32 *nds32)
-{
- uint32_t value_ir0;
- struct aice_port_s *aice = target_to_aice(nds32->target);
-
- nds32_get_mapped_reg(nds32, IR0, &value_ir0);
-
- /* Save data memory endian */
- if ((value_ir0 >> 5) & 0x1) {
- nds32->data_endian = TARGET_BIG_ENDIAN;
- aice_set_data_endian(aice, AICE_BIG_ENDIAN);
- } else {
- nds32->data_endian = TARGET_LITTLE_ENDIAN;
- aice_set_data_endian(aice, AICE_LITTLE_ENDIAN);
- }
-
- /* Save translation status */
- nds32->memory.address_translation = ((value_ir0 >> 7) & 0x1) ? true : false;
-
- return ERROR_OK;
-}
-
-static int nds32_update_mmu_info(struct nds32 *nds32)
-{
- uint32_t value;
-
- /* Update MMU control status */
- nds32_get_mapped_reg(nds32, MR0, &value);
- nds32->mmu_config.default_min_page_size = value & 0x1;
- nds32->mmu_config.multiple_page_size_in_use = (value >> 10) & 0x1;
-
- return ERROR_OK;
-}
-
-static int nds32_update_cache_info(struct nds32 *nds32)
-{
- uint32_t value;
-
- if (ERROR_OK == nds32_get_mapped_reg(nds32, MR8, &value)) {
- if (value & 0x1)
- nds32->memory.icache.enable = true;
- else
- nds32->memory.icache.enable = false;
-
- if (value & 0x2)
- nds32->memory.dcache.enable = true;
- else
- nds32->memory.dcache.enable = false;
- } else {
- nds32->memory.icache.enable = false;
- nds32->memory.dcache.enable = false;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_update_lm_info(struct nds32 *nds32)
-{
- struct nds32_memory *memory = &(nds32->memory);
- uint32_t value_mr6;
- uint32_t value_mr7;
-
- nds32_get_mapped_reg(nds32, MR6, &value_mr6);
- if (value_mr6 & 0x1)
- memory->ilm_enable = true;
- else
- memory->ilm_enable = false;
-
- if (memory->ilm_align_ver == 0) { /* 1MB aligned */
- memory->ilm_start = value_mr6 & 0xFFF00000;
- memory->ilm_end = memory->ilm_start + memory->ilm_size;
- } else if (memory->ilm_align_ver == 1) { /* aligned to local memory size */
- memory->ilm_start = value_mr6 & 0xFFFFFC00;
- memory->ilm_end = memory->ilm_start + memory->ilm_size;
- } else {
- memory->ilm_start = -1;
- memory->ilm_end = -1;
- }
-
- nds32_get_mapped_reg(nds32, MR7, &value_mr7);
- if (value_mr7 & 0x1)
- memory->dlm_enable = true;
- else
- memory->dlm_enable = false;
-
- if (memory->dlm_align_ver == 0) { /* 1MB aligned */
- memory->dlm_start = value_mr7 & 0xFFF00000;
- memory->dlm_end = memory->dlm_start + memory->dlm_size;
- } else if (memory->dlm_align_ver == 1) { /* aligned to local memory size */
- memory->dlm_start = value_mr7 & 0xFFFFFC00;
- memory->dlm_end = memory->dlm_start + memory->dlm_size;
- } else {
- memory->dlm_start = -1;
- memory->dlm_end = -1;
- }
-
- return ERROR_OK;
-}
-
-/**
- * If fpu/audio is disabled, to access fpu/audio registers will cause
- * exceptions. So, we need to check if fpu/audio is enabled or not as
- * target is halted. If fpu/audio is disabled, as users access fpu/audio
- * registers, OpenOCD will return fake value 0 instead of accessing
- * registers through DIM.
- */
-static int nds32_check_extension(struct nds32 *nds32)
-{
- uint32_t value;
-
- nds32_get_mapped_reg(nds32, FUCPR, &value);
- if (value == NDS32_REGISTER_DISABLE) {
- nds32->fpu_enable = false;
- nds32->audio_enable = false;
- return ERROR_OK;
- }
-
- if (value & 0x1)
- nds32->fpu_enable = true;
- else
- nds32->fpu_enable = false;
-
- if (value & 0x80000000)
- nds32->audio_enable = true;
- else
- nds32->audio_enable = false;
-
- return ERROR_OK;
-}
-
-static int nds32_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- struct nds32_reg *reg_arch_info = reg->arch_info;
- struct target *target = reg_arch_info->target;
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- uint32_t value = buf_get_u32(buf, 0, 32);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
-
- /* ignore values that will generate exception */
- if (nds32_reg_exception(mapped_regnum, value))
- return ERROR_OK;
-
- LOG_DEBUG("writing register %" PRIi32 "(%s) with value 0x%8.8" PRIx32,
- reg_arch_info->num, reg->name, value);
-
- if ((nds32->fpu_enable == false) &&
- (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) {
-
- buf_set_u32(reg->value, 0, 32, 0);
- } else if ((nds32->audio_enable == false) &&
- (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) {
-
- buf_set_u32(reg->value, 0, 32, 0);
- } else {
- buf_set_u32(reg->value, 0, 32, value);
- uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
- aice_write_register(aice, mapped_regnum, val);
-
- /* After set value to registers, read the value from target
- * to avoid W1C inconsistency. */
- aice_read_register(aice, mapped_regnum, &val);
- buf_set_u32(reg_arch_info->value, 0, 32, val);
- }
-
- reg->valid = true;
- reg->dirty = false;
-
- /* update registers to take effect right now */
- if (IR0 == mapped_regnum) {
- nds32_update_psw(nds32);
- } else if (MR0 == mapped_regnum) {
- nds32_update_mmu_info(nds32);
- } else if ((MR6 == mapped_regnum) || (MR7 == mapped_regnum)) {
- /* update lm information */
- nds32_update_lm_info(nds32);
- } else if (MR8 == mapped_regnum) {
- nds32_update_cache_info(nds32);
- } else if (FUCPR == mapped_regnum) {
- /* update audio/fpu setting */
- nds32_check_extension(nds32);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_set_core_reg_64(struct reg *reg, uint8_t *buf)
-{
- struct nds32_reg *reg_arch_info = reg->arch_info;
- struct target *target = reg_arch_info->target;
- struct nds32 *nds32 = target_to_nds32(target);
- uint32_t low_part = buf_get_u32(buf, 0, 32);
- uint32_t high_part = buf_get_u32(buf, 32, 32);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if ((nds32->fpu_enable == false) &&
- ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) {
-
- buf_set_u32(reg->value, 0, 32, 0);
- buf_set_u32(reg->value, 32, 32, 0);
-
- reg->valid = true;
- reg->dirty = false;
- } else {
- buf_set_u32(reg->value, 0, 32, low_part);
- buf_set_u32(reg->value, 32, 32, high_part);
-
- reg->valid = true;
- reg->dirty = true;
- }
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type nds32_reg_access_type = {
- .get = nds32_get_core_reg,
- .set = nds32_set_core_reg,
-};
-
-static const struct reg_arch_type nds32_reg_access_type_64 = {
- .get = nds32_get_core_reg_64,
- .set = nds32_set_core_reg_64,
-};
-
-static struct reg_cache *nds32_build_reg_cache(struct target *target,
- struct nds32 *nds32)
-{
- struct reg_cache *cache = calloc(sizeof(struct reg_cache), 1);
- struct reg *reg_list = calloc(TOTAL_REG_NUM, sizeof(struct reg));
- struct nds32_reg *reg_arch_info = calloc(TOTAL_REG_NUM, sizeof(struct nds32_reg));
- int i;
-
- if (!cache || !reg_list || !reg_arch_info) {
- free(cache);
- free(reg_list);
- free(reg_arch_info);
- return NULL;
- }
-
- cache->name = "Andes registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = 0;
-
- for (i = 0; i < TOTAL_REG_NUM; i++) {
- reg_arch_info[i].num = i;
- reg_arch_info[i].target = target;
- reg_arch_info[i].nds32 = nds32;
- reg_arch_info[i].enable = false;
-
- reg_list[i].name = nds32_reg_simple_name(i);
- reg_list[i].number = reg_arch_info[i].num;
- reg_list[i].size = nds32_reg_size(i);
- reg_list[i].arch_info = &reg_arch_info[i];
-
- reg_list[i].reg_data_type = calloc(sizeof(struct reg_data_type), 1);
-
- if (FD0 <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31) {
- reg_list[i].value = reg_arch_info[i].value;
- reg_list[i].type = &nds32_reg_access_type_64;
-
- reg_list[i].reg_data_type->type = REG_TYPE_IEEE_DOUBLE;
- reg_list[i].reg_data_type->id = "ieee_double";
- reg_list[i].group = "float";
- } else {
- reg_list[i].value = reg_arch_info[i].value;
- reg_list[i].type = &nds32_reg_access_type;
- reg_list[i].group = "general";
-
- if ((FS0 <= reg_arch_info[i].num) && (reg_arch_info[i].num <= FS31)) {
- reg_list[i].reg_data_type->type = REG_TYPE_IEEE_SINGLE;
- reg_list[i].reg_data_type->id = "ieee_single";
- reg_list[i].group = "float";
- } else if ((reg_arch_info[i].num == FPCSR) ||
- (reg_arch_info[i].num == FPCFG)) {
- reg_list[i].group = "float";
- } else if ((reg_arch_info[i].num == R28) ||
- (reg_arch_info[i].num == R29) ||
- (reg_arch_info[i].num == R31)) {
- reg_list[i].reg_data_type->type = REG_TYPE_DATA_PTR;
- reg_list[i].reg_data_type->id = "data_ptr";
- } else if ((reg_arch_info[i].num == R30) ||
- (reg_arch_info[i].num == PC)) {
- reg_list[i].reg_data_type->type = REG_TYPE_CODE_PTR;
- reg_list[i].reg_data_type->id = "code_ptr";
- } else {
- reg_list[i].reg_data_type->type = REG_TYPE_UINT32;
- reg_list[i].reg_data_type->id = "uint32";
- }
- }
-
- if (R16 <= reg_arch_info[i].num && reg_arch_info[i].num <= R25)
- reg_list[i].caller_save = true;
- else
- reg_list[i].caller_save = false;
-
- reg_list[i].feature = malloc(sizeof(struct reg_feature));
-
- if (R0 <= reg_arch_info[i].num && reg_arch_info[i].num <= IFC_LP)
- reg_list[i].feature->name = "org.gnu.gdb.nds32.core";
- else if (CR0 <= reg_arch_info[i].num && reg_arch_info[i].num <= SECUR0)
- reg_list[i].feature->name = "org.gnu.gdb.nds32.system";
- else if (D0L24 <= reg_arch_info[i].num && reg_arch_info[i].num <= CBE3)
- reg_list[i].feature->name = "org.gnu.gdb.nds32.audio";
- else if (FPCSR <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31)
- reg_list[i].feature->name = "org.gnu.gdb.nds32.fpu";
-
- cache->num_regs++;
- }
-
- nds32->core_cache = cache;
-
- return cache;
-}
-
-static int nds32_reg_cache_init(struct target *target, struct nds32 *nds32)
-{
- struct reg_cache *cache;
-
- cache = nds32_build_reg_cache(target, nds32);
- if (!cache)
- return ERROR_FAIL;
-
- *register_get_last_cache_p(&target->reg_cache) = cache;
-
- return ERROR_OK;
-}
-
-static struct reg *nds32_reg_current(struct nds32 *nds32, unsigned regnum)
-{
- struct reg *r;
-
- r = nds32->core_cache->reg_list + regnum;
-
- return r;
-}
-
-int nds32_full_context(struct nds32 *nds32)
-{
- uint32_t value, value_ir0;
-
- /* save $pc & $psw */
- nds32_get_mapped_reg(nds32, PC, &value);
- nds32_get_mapped_reg(nds32, IR0, &value_ir0);
-
- nds32_update_psw(nds32);
- nds32_update_mmu_info(nds32);
- nds32_update_cache_info(nds32);
- nds32_update_lm_info(nds32);
-
- nds32_check_extension(nds32);
-
- return ERROR_OK;
-}
-
-/* get register value internally */
-int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *value)
-{
- struct reg_cache *reg_cache = nds32->core_cache;
- struct reg *r;
-
- if (regnum > reg_cache->num_regs)
- return ERROR_FAIL;
-
- r = nds32_reg_current(nds32, regnum);
-
- if (ERROR_OK != r->type->get(r))
- return ERROR_FAIL;
-
- *value = buf_get_u32(r->value, 0, 32);
-
- return ERROR_OK;
-}
-
-/** set register internally */
-int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value)
-{
- struct reg_cache *reg_cache = nds32->core_cache;
- struct reg *r;
- uint8_t set_value[4];
-
- if (regnum > reg_cache->num_regs)
- return ERROR_FAIL;
-
- r = nds32_reg_current(nds32, regnum);
-
- buf_set_u32(set_value, 0, 32, value);
-
- return r->type->set(r, set_value);
-}
-
-/** get general register list */
-static int nds32_get_general_reg_list(struct nds32 *nds32,
- struct reg **reg_list[], int *reg_list_size)
-{
- struct reg *reg_current;
- int i;
- int current_idx;
-
- /** freed in gdb_server.c */
- *reg_list = malloc(sizeof(struct reg *) * (IFC_LP - R0 + 1));
- current_idx = 0;
-
- for (i = R0; i < IFC_LP + 1; i++) {
- reg_current = nds32_reg_current(nds32, i);
- if (((struct nds32_reg *)reg_current->arch_info)->enable) {
- (*reg_list)[current_idx] = reg_current;
- current_idx++;
- }
- }
- *reg_list_size = current_idx;
-
- return ERROR_OK;
-}
-
-/** get all register list */
-static int nds32_get_all_reg_list(struct nds32 *nds32,
- struct reg **reg_list[], int *reg_list_size)
-{
- struct reg_cache *reg_cache = nds32->core_cache;
- struct reg *reg_current;
- unsigned int i;
-
- *reg_list_size = reg_cache->num_regs;
-
- /** freed in gdb_server.c */
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
-
- for (i = 0; i < reg_cache->num_regs; i++) {
- reg_current = nds32_reg_current(nds32, i);
- reg_current->exist = ((struct nds32_reg *)
- reg_current->arch_info)->enable;
- (*reg_list)[i] = reg_current;
- }
-
- return ERROR_OK;
-}
-
-/** get all register list */
-int nds32_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class)
-{
- struct nds32 *nds32 = target_to_nds32(target);
-
- switch (reg_class) {
- case REG_CLASS_ALL:
- return nds32_get_all_reg_list(nds32, reg_list, reg_list_size);
- case REG_CLASS_GENERAL:
- return nds32_get_general_reg_list(nds32, reg_list, reg_list_size);
- default:
- return ERROR_FAIL;
- }
-
- return ERROR_FAIL;
-}
-
-static int nds32_select_memory_mode(struct target *target, uint32_t address,
- uint32_t length, uint32_t *end_address)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_memory *memory = &(nds32->memory);
- struct nds32_edm *edm = &(nds32->edm);
- uint32_t dlm_start, dlm_end;
- uint32_t ilm_start, ilm_end;
- uint32_t address_end = address + length;
-
- /* init end_address */
- *end_address = address_end;
-
- if (NDS_MEMORY_ACC_CPU == memory->access_channel)
- return ERROR_OK;
-
- if (edm->access_control == false) {
- LOG_DEBUG("EDM does not support ACC_CTL");
- return ERROR_OK;
- }
-
- if (edm->direct_access_local_memory == false) {
- LOG_DEBUG("EDM does not support DALM");
- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
- return ERROR_OK;
- }
-
- if (NDS_MEMORY_SELECT_AUTO != memory->mode) {
- LOG_DEBUG("Memory mode is not AUTO");
- return ERROR_OK;
- }
-
- /* set default mode */
- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
-
- if ((memory->ilm_base != 0) && (memory->ilm_enable == true)) {
- ilm_start = memory->ilm_start;
- ilm_end = memory->ilm_end;
-
- /* case 1, address < ilm_start */
- if (address < ilm_start) {
- if (ilm_start < address_end) {
- /* update end_address to split non-ILM from ILM */
- *end_address = ilm_start;
- }
- /* MEM mode */
- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
- } else if ((ilm_start <= address) && (address < ilm_end)) {
- /* case 2, ilm_start <= address < ilm_end */
- if (ilm_end < address_end) {
- /* update end_address to split non-ILM from ILM */
- *end_address = ilm_end;
- }
- /* ILM mode */
- aice_memory_mode(aice, NDS_MEMORY_SELECT_ILM);
- } else { /* case 3, ilm_end <= address */
- /* MEM mode */
- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
- }
-
- return ERROR_OK;
- } else {
- LOG_DEBUG("ILM is not enabled");
- }
-
- if ((memory->dlm_base != 0) && (memory->dlm_enable == true)) {
- dlm_start = memory->dlm_start;
- dlm_end = memory->dlm_end;
-
- /* case 1, address < dlm_start */
- if (address < dlm_start) {
- if (dlm_start < address_end) {
- /* update end_address to split non-DLM from DLM */
- *end_address = dlm_start;
- }
- /* MEM mode */
- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
- } else if ((dlm_start <= address) && (address < dlm_end)) {
- /* case 2, dlm_start <= address < dlm_end */
- if (dlm_end < address_end) {
- /* update end_address to split non-DLM from DLM */
- *end_address = dlm_end;
- }
- /* DLM mode */
- aice_memory_mode(aice, NDS_MEMORY_SELECT_DLM);
- } else { /* case 3, dlm_end <= address */
- /* MEM mode */
- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
- }
-
- return ERROR_OK;
- } else {
- LOG_DEBUG("DLM is not enabled");
- }
-
- return ERROR_OK;
-}
-
-int nds32_read_buffer(struct target *target, uint32_t address,
- uint32_t size, uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("READ BUFFER: ADDR %08" PRIx32 " SIZE %08" PRIx32,
- address,
- size);
-
- int retval = ERROR_OK;
- struct aice_port_s *aice = target_to_aice(target);
- uint32_t end_address;
-
- if (((address % 2) == 0) && (size == 2)) {
- nds32_select_memory_mode(target, address, 2, &end_address);
- return aice_read_mem_unit(aice, address, 2, 1, buffer);
- }
-
- /* handle unaligned head bytes */
- if (address % 4) {
- uint32_t unaligned = 4 - (address % 4);
-
- if (unaligned > size)
- unaligned = size;
-
- nds32_select_memory_mode(target, address, unaligned, &end_address);
- retval = aice_read_mem_unit(aice, address, 1, unaligned, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- buffer += unaligned;
- address += unaligned;
- size -= unaligned;
- }
-
- /* handle aligned words */
- if (size >= 4) {
- int aligned = size - (size % 4);
- int read_len;
-
- do {
- nds32_select_memory_mode(target, address, aligned, &end_address);
-
- read_len = end_address - address;
-
- if (read_len > 8)
- retval = aice_read_mem_bulk(aice, address, read_len, buffer);
- else
- retval = aice_read_mem_unit(aice, address, 4, read_len / 4, buffer);
-
- if (retval != ERROR_OK)
- return retval;
-
- buffer += read_len;
- address += read_len;
- size -= read_len;
- aligned -= read_len;
-
- } while (aligned != 0);
- }
-
- /*prevent byte access when possible (avoid AHB access limitations in some cases)*/
- if (size >= 2) {
- int aligned = size - (size % 2);
- nds32_select_memory_mode(target, address, aligned, &end_address);
- retval = aice_read_mem_unit(aice, address, 2, aligned / 2, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- buffer += aligned;
- address += aligned;
- size -= aligned;
- }
- /* handle tail writes of less than 4 bytes */
- if (size > 0) {
- nds32_select_memory_mode(target, address, size, &end_address);
- retval = aice_read_mem_unit(aice, address, 1, size, buffer);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-int nds32_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct aice_port_s *aice = target_to_aice(target);
-
- return aice_read_mem_unit(aice, address, size, count, buffer);
-}
-
-int nds32_read_phys_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
- enum nds_memory_access orig_channel;
- int result;
-
- /* switch to BUS access mode to skip MMU */
- orig_channel = memory->access_channel;
- memory->access_channel = NDS_MEMORY_ACC_BUS;
- aice_memory_access(aice, memory->access_channel);
-
- /* The input address is physical address. No need to do address translation. */
- result = aice_read_mem_unit(aice, address, size, count, buffer);
-
- /* restore to origin access mode */
- memory->access_channel = orig_channel;
- aice_memory_access(aice, memory->access_channel);
-
- return result;
-}
-
-int nds32_write_buffer(struct target *target, uint32_t address,
- uint32_t size, const uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- LOG_DEBUG("WRITE BUFFER: ADDR %08" PRIx32 " SIZE %08" PRIx32,
- address,
- size);
-
- struct aice_port_s *aice = target_to_aice(target);
- int retval = ERROR_OK;
- uint32_t end_address;
-
- if (((address % 2) == 0) && (size == 2)) {
- nds32_select_memory_mode(target, address, 2, &end_address);
- return aice_write_mem_unit(aice, address, 2, 1, buffer);
- }
-
- /* handle unaligned head bytes */
- if (address % 4) {
- uint32_t unaligned = 4 - (address % 4);
-
- if (unaligned > size)
- unaligned = size;
-
- nds32_select_memory_mode(target, address, unaligned, &end_address);
- retval = aice_write_mem_unit(aice, address, 1, unaligned, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- buffer += unaligned;
- address += unaligned;
- size -= unaligned;
- }
-
- /* handle aligned words */
- if (size >= 4) {
- int aligned = size - (size % 4);
- int write_len;
-
- do {
- nds32_select_memory_mode(target, address, aligned, &end_address);
-
- write_len = end_address - address;
- if (write_len > 8)
- retval = aice_write_mem_bulk(aice, address, write_len, buffer);
- else
- retval = aice_write_mem_unit(aice, address, 4, write_len / 4, buffer);
- if (retval != ERROR_OK)
- return retval;
-
- buffer += write_len;
- address += write_len;
- size -= write_len;
- aligned -= write_len;
-
- } while (aligned != 0);
- }
-
- /* handle tail writes of less than 4 bytes */
- if (size > 0) {
- nds32_select_memory_mode(target, address, size, &end_address);
- retval = aice_write_mem_unit(aice, address, 1, size, buffer);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return retval;
-}
-
-int nds32_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct aice_port_s *aice = target_to_aice(target);
-
- return aice_write_mem_unit(aice, address, size, count, buffer);
-}
-
-int nds32_write_phys_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
- enum nds_memory_access orig_channel;
- int result;
-
- /* switch to BUS access mode to skip MMU */
- orig_channel = memory->access_channel;
- memory->access_channel = NDS_MEMORY_ACC_BUS;
- aice_memory_access(aice, memory->access_channel);
-
- /* The input address is physical address. No need to do address translation. */
- result = aice_write_mem_unit(aice, address, size, count, buffer);
-
- /* restore to origin access mode */
- memory->access_channel = orig_channel;
- aice_memory_access(aice, memory->access_channel);
-
- return result;
-}
-
-int nds32_mmu(struct target *target, int *enabled)
-{
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("%s: target not halted", __func__);
- return ERROR_TARGET_INVALID;
- }
-
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
- struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
-
- if ((mmu_config->memory_protection == 2) && (memory->address_translation == true))
- *enabled = 1;
- else
- *enabled = 0;
-
- return ERROR_OK;
-}
-
-int nds32_arch_state(struct target *target)
-{
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (nds32->common_magic != NDS32_COMMON_MAGIC) {
- LOG_ERROR("BUG: called for a non-Andes target");
- return ERROR_FAIL;
- }
-
- uint32_t value_pc, value_psw;
-
- nds32_get_mapped_reg(nds32, PC, &value_pc);
- nds32_get_mapped_reg(nds32, IR0, &value_psw);
-
- LOG_USER("target halted due to %s\n"
- "psw: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s",
- debug_reason_name(target),
- value_psw,
- value_pc,
- nds32->virtual_hosting ? ", virtual hosting" : "");
-
- /* save pc value to pseudo register pc */
- struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1);
- buf_set_u32(reg->value, 0, 32, value_pc);
-
- return ERROR_OK;
-}
-
-static void nds32_init_must_have_registers(struct nds32 *nds32)
-{
- struct reg_cache *reg_cache = nds32->core_cache;
-
- /** MUST have general registers */
- ((struct nds32_reg *)reg_cache->reg_list[R0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R3].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R4].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R5].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R6].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R7].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R8].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R9].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R10].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R15].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R28].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R29].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R30].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R31].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[PC].arch_info)->enable = true;
-
- /** MUST have configuration system registers */
- ((struct nds32_reg *)reg_cache->reg_list[CR0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CR1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CR2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CR3].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CR4].arch_info)->enable = true;
-
- /** MUST have interrupt system registers */
- ((struct nds32_reg *)reg_cache->reg_list[IR0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR6].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR11].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR14].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR15].arch_info)->enable = true;
-
- /** MUST have MMU system registers */
- ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = true;
-
- /** MUST have EDM system registers */
- ((struct nds32_reg *)reg_cache->reg_list[DR40].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DR42].arch_info)->enable = true;
-}
-
-static int nds32_init_memory_config(struct nds32 *nds32)
-{
- uint32_t value_cr1; /* ICM_CFG */
- uint32_t value_cr2; /* DCM_CFG */
- struct nds32_memory *memory = &(nds32->memory);
-
- /* read $cr1 to init instruction memory information */
- nds32_get_mapped_reg(nds32, CR1, &value_cr1);
- memory->icache.set = value_cr1 & 0x7;
- memory->icache.way = (value_cr1 >> 3) & 0x7;
- memory->icache.line_size = (value_cr1 >> 6) & 0x7;
- memory->icache.lock_support = (value_cr1 >> 9) & 0x1;
-
- memory->ilm_base = (value_cr1 >> 10) & 0x7;
- memory->ilm_align_ver = (value_cr1 >> 13) & 0x3;
-
- /* read $cr2 to init data memory information */
- nds32_get_mapped_reg(nds32, CR2, &value_cr2);
- memory->dcache.set = value_cr2 & 0x7;
- memory->dcache.way = (value_cr2 >> 3) & 0x7;
- memory->dcache.line_size = (value_cr2 >> 6) & 0x7;
- memory->dcache.lock_support = (value_cr2 >> 9) & 0x1;
-
- memory->dlm_base = (value_cr2 >> 10) & 0x7;
- memory->dlm_align_ver = (value_cr2 >> 13) & 0x3;
-
- return ERROR_OK;
-}
-
-static void nds32_init_config(struct nds32 *nds32)
-{
- uint32_t value_cr0;
- uint32_t value_cr3;
- uint32_t value_cr4;
- struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
- struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
- struct nds32_misc_config *misc_config = &(nds32->misc_config);
-
- nds32_get_mapped_reg(nds32, CR0, &value_cr0);
- nds32_get_mapped_reg(nds32, CR3, &value_cr3);
- nds32_get_mapped_reg(nds32, CR4, &value_cr4);
-
- /* config cpu version */
- cpu_version->performance_extension = value_cr0 & 0x1;
- cpu_version->_16bit_extension = (value_cr0 >> 1) & 0x1;
- cpu_version->performance_extension_2 = (value_cr0 >> 2) & 0x1;
- cpu_version->cop_fpu_extension = (value_cr0 >> 3) & 0x1;
- cpu_version->string_extension = (value_cr0 >> 4) & 0x1;
- cpu_version->revision = (value_cr0 >> 16) & 0xFF;
- cpu_version->cpu_id_family = (value_cr0 >> 24) & 0xF;
- cpu_version->cpu_id_version = (value_cr0 >> 28) & 0xF;
-
- /* config MMU */
- mmu_config->memory_protection = value_cr3 & 0x3;
- mmu_config->memory_protection_version = (value_cr3 >> 2) & 0x1F;
- mmu_config->fully_associative_tlb = (value_cr3 >> 7) & 0x1;
- if (mmu_config->fully_associative_tlb) {
- mmu_config->tlb_size = (value_cr3 >> 8) & 0x7F;
- } else {
- mmu_config->tlb_ways = (value_cr3 >> 8) & 0x7;
- mmu_config->tlb_sets = (value_cr3 >> 11) & 0x7;
- }
- mmu_config->_8k_page_support = (value_cr3 >> 15) & 0x1;
- mmu_config->extra_page_size_support = (value_cr3 >> 16) & 0xFF;
- mmu_config->tlb_lock = (value_cr3 >> 24) & 0x1;
- mmu_config->hardware_page_table_walker = (value_cr3 >> 25) & 0x1;
- mmu_config->default_endian = (value_cr3 >> 26) & 0x1;
- mmu_config->partition_num = (value_cr3 >> 27) & 0x1;
- mmu_config->invisible_tlb = (value_cr3 >> 28) & 0x1;
- mmu_config->vlpt = (value_cr3 >> 29) & 0x1;
- mmu_config->ntme = (value_cr3 >> 30) & 0x1;
- mmu_config->drde = (value_cr3 >> 31) & 0x1;
-
- /* config misc */
- misc_config->edm = value_cr4 & 0x1;
- misc_config->local_memory_dma = (value_cr4 >> 1) & 0x1;
- misc_config->performance_monitor = (value_cr4 >> 2) & 0x1;
- misc_config->high_speed_memory_port = (value_cr4 >> 3) & 0x1;
- misc_config->debug_tracer = (value_cr4 >> 4) & 0x1;
- misc_config->div_instruction = (value_cr4 >> 5) & 0x1;
- misc_config->mac_instruction = (value_cr4 >> 6) & 0x1;
- misc_config->audio_isa = (value_cr4 >> 7) & 0x3;
- misc_config->L2_cache = (value_cr4 >> 9) & 0x1;
- misc_config->reduce_register = (value_cr4 >> 10) & 0x1;
- misc_config->addr_24 = (value_cr4 >> 11) & 0x1;
- misc_config->interruption_level = (value_cr4 >> 12) & 0x1;
- misc_config->baseline_instruction = (value_cr4 >> 13) & 0x7;
- misc_config->no_dx_register = (value_cr4 >> 16) & 0x1;
- misc_config->implement_dependant_register = (value_cr4 >> 17) & 0x1;
- misc_config->implement_dependant_sr_encoding = (value_cr4 >> 18) & 0x1;
- misc_config->ifc = (value_cr4 >> 19) & 0x1;
- misc_config->mcu = (value_cr4 >> 20) & 0x1;
- misc_config->shadow = (value_cr4 >> 21) & 0x7;
- misc_config->ex9 = (value_cr4 >> 24) & 0x1;
-
- nds32_init_memory_config(nds32);
-}
-
-static int nds32_init_option_registers(struct nds32 *nds32)
-{
- struct reg_cache *reg_cache = nds32->core_cache;
- struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
- struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
- struct nds32_misc_config *misc_config = &(nds32->misc_config);
- struct nds32_memory *memory_config = &(nds32->memory);
-
- bool no_cr5;
- bool mr10_exist;
- bool no_racr0;
-
- if (((cpu_version->cpu_id_family == 0xC) || (cpu_version->cpu_id_family == 0xD)) &&
- ((cpu_version->revision & 0xFC) == 0)) {
- no_cr5 = true;
- mr10_exist = true;
- no_racr0 = true;
- } else {
- no_cr5 = false;
- mr10_exist = false;
- no_racr0 = false;
- }
-
- if (misc_config->reduce_register == false) {
- ((struct nds32_reg *)reg_cache->reg_list[R11].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R12].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R13].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R14].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R16].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R17].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R18].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R19].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R20].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R21].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R22].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R23].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R24].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R25].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R26].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[R27].arch_info)->enable = true;
- }
-
- if (misc_config->no_dx_register == false) {
- ((struct nds32_reg *)reg_cache->reg_list[D0LO].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[D0HI].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[D1LO].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[D1HI].arch_info)->enable = true;
- }
-
- if (misc_config->ex9)
- ((struct nds32_reg *)reg_cache->reg_list[ITB].arch_info)->enable = true;
-
- if (no_cr5 == false)
- ((struct nds32_reg *)reg_cache->reg_list[CR5].arch_info)->enable = true;
-
- if (cpu_version->cop_fpu_extension) {
- ((struct nds32_reg *)reg_cache->reg_list[CR6].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[FPCSR].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[FPCFG].arch_info)->enable = true;
- }
-
- if (mmu_config->memory_protection == 1) {
- /* Secure MPU has no IPC, IPSW, P_ITYPE */
- ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = false;
- ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = false;
- }
-
- if (nds32->privilege_level != 0)
- ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = false;
-
- if (misc_config->mcu == true)
- ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = false;
-
- if (misc_config->interruption_level == false) {
- ((struct nds32_reg *)reg_cache->reg_list[IR2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR5].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR10].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR12].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR13].arch_info)->enable = true;
-
- /* Secure MPU has no IPC, IPSW, P_ITYPE */
- if (mmu_config->memory_protection != 1)
- ((struct nds32_reg *)reg_cache->reg_list[IR7].arch_info)->enable = true;
- }
-
- if ((cpu_version->cpu_id_family == 0x9) ||
- (cpu_version->cpu_id_family == 0xA) ||
- (cpu_version->cpu_id_family == 0xC) ||
- (cpu_version->cpu_id_family == 0xD))
- ((struct nds32_reg *)reg_cache->reg_list[IR8].arch_info)->enable = true;
-
- if (misc_config->shadow == 1) {
- ((struct nds32_reg *)reg_cache->reg_list[IR16].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR17].arch_info)->enable = true;
- }
-
- if (misc_config->ifc)
- ((struct nds32_reg *)reg_cache->reg_list[IFC_LP].arch_info)->enable = true;
-
- if (nds32->privilege_level != 0)
- ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = false;
-
- if (mmu_config->memory_protection == 1) {
- if (mmu_config->memory_protection_version == 24)
- ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true;
-
- if (nds32->privilege_level == 0) {
- if ((mmu_config->memory_protection_version == 16) ||
- (mmu_config->memory_protection_version == 24)) {
- ((struct nds32_reg *)reg_cache->reg_list[MR11].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[SECUR0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR20].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR22].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR24].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR30].arch_info)->enable = true;
-
- if (misc_config->shadow == 1) {
- ((struct nds32_reg *)reg_cache->reg_list[IR21].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR23].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR25].arch_info)->enable = true;
- }
- }
- }
- } else if (mmu_config->memory_protection == 2) {
- ((struct nds32_reg *)reg_cache->reg_list[MR1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true;
-
- if ((cpu_version->cpu_id_family != 0xA) && (cpu_version->cpu_id_family != 0xC) &&
- (cpu_version->cpu_id_family != 0xD))
- ((struct nds32_reg *)reg_cache->reg_list[MR5].arch_info)->enable = true;
- }
-
- if (mmu_config->memory_protection > 0) {
- ((struct nds32_reg *)reg_cache->reg_list[MR2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[MR3].arch_info)->enable = true;
- }
-
- if (memory_config->ilm_base != 0)
- if (nds32->privilege_level == 0)
- ((struct nds32_reg *)reg_cache->reg_list[MR6].arch_info)->enable = true;
-
- if (memory_config->dlm_base != 0)
- if (nds32->privilege_level == 0)
- ((struct nds32_reg *)reg_cache->reg_list[MR7].arch_info)->enable = true;
-
- if ((memory_config->icache.line_size != 0) && (memory_config->dcache.line_size != 0))
- ((struct nds32_reg *)reg_cache->reg_list[MR8].arch_info)->enable = true;
-
- if (misc_config->high_speed_memory_port)
- ((struct nds32_reg *)reg_cache->reg_list[MR9].arch_info)->enable = true;
-
- if (mr10_exist)
- ((struct nds32_reg *)reg_cache->reg_list[MR10].arch_info)->enable = true;
-
- if (misc_config->edm) {
- int dr_reg_n = nds32->edm.breakpoint_num * 5;
-
- for (int i = 0 ; i < dr_reg_n ; i++)
- ((struct nds32_reg *)reg_cache->reg_list[DR0 + i].arch_info)->enable = true;
-
- ((struct nds32_reg *)reg_cache->reg_list[DR41].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DR43].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DR44].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DR45].arch_info)->enable = true;
- }
-
- if (misc_config->debug_tracer) {
- ((struct nds32_reg *)reg_cache->reg_list[DR46].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DR47].arch_info)->enable = true;
- }
-
- if (misc_config->performance_monitor) {
- ((struct nds32_reg *)reg_cache->reg_list[PFR0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[PFR1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[PFR2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[PFR3].arch_info)->enable = true;
- }
-
- if (misc_config->local_memory_dma) {
- ((struct nds32_reg *)reg_cache->reg_list[DMAR0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR3].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR4].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR5].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR6].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR7].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR8].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR9].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[DMAR10].arch_info)->enable = true;
- }
-
- if ((misc_config->local_memory_dma || misc_config->performance_monitor) &&
- (no_racr0 == false))
- ((struct nds32_reg *)reg_cache->reg_list[RACR].arch_info)->enable = true;
-
- if (cpu_version->cop_fpu_extension || (misc_config->audio_isa != 0))
- ((struct nds32_reg *)reg_cache->reg_list[FUCPR].arch_info)->enable = true;
-
- if (misc_config->audio_isa != 0) {
- if (misc_config->audio_isa > 1) {
- ((struct nds32_reg *)reg_cache->reg_list[D0L24].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[D1L24].arch_info)->enable = true;
- }
-
- ((struct nds32_reg *)reg_cache->reg_list[I0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[I1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[I2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[I3].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[I4].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[I5].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[I6].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[I7].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[M1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[M2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[M3].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[M5].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[M6].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[M7].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[MOD].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[LBE].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[LE].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[LC].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[ADM_VBASE].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL1].arch_info)->enable = true;
-
- uint32_t value_mod;
- uint32_t fucpr_backup;
- /* enable fpu and get configuration */
- nds32_get_mapped_reg(nds32, FUCPR, &fucpr_backup);
- if ((fucpr_backup & 0x80000000) == 0)
- nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup | 0x80000000);
- nds32_get_mapped_reg(nds32, MOD, &value_mod);
- /* restore origin fucpr value */
- if ((fucpr_backup & 0x80000000) == 0)
- nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup);
-
- if ((value_mod >> 6) & 0x1) {
- ((struct nds32_reg *)reg_cache->reg_list[CB_CTL].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBB0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBB1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBB2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBB3].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBE0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBE1].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBE2].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[CBE3].arch_info)->enable = true;
- }
- }
-
- if ((cpu_version->cpu_id_family == 0x9) ||
- (cpu_version->cpu_id_family == 0xA) ||
- (cpu_version->cpu_id_family == 0xC)) {
-
- ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IDR1].arch_info)->enable = true;
-
- if ((cpu_version->cpu_id_family == 0xC) && (cpu_version->revision == 0x0C))
- ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = false;
- }
-
- uint32_t ir3_value;
- uint32_t ivb_prog_pri_lvl;
- uint32_t ivb_ivic_ver;
-
- nds32_get_mapped_reg(nds32, IR3, &ir3_value);
- ivb_prog_pri_lvl = ir3_value & 0x1;
- ivb_ivic_ver = (ir3_value >> 11) & 0x3;
-
- if ((ivb_prog_pri_lvl == 1) || (ivb_ivic_ver >= 1)) {
- ((struct nds32_reg *)reg_cache->reg_list[IR18].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR19].arch_info)->enable = true;
- }
-
- if (ivb_ivic_ver >= 1) {
- ((struct nds32_reg *)reg_cache->reg_list[IR26].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR27].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR28].arch_info)->enable = true;
- ((struct nds32_reg *)reg_cache->reg_list[IR29].arch_info)->enable = true;
- }
-
- return ERROR_OK;
-}
-
-int nds32_init_register_table(struct nds32 *nds32)
-{
- nds32_init_must_have_registers(nds32);
-
- return ERROR_OK;
-}
-
-int nds32_add_software_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- uint32_t data;
- uint32_t check_data;
- uint32_t break_insn;
-
- /* check the breakpoint size */
- target->type->read_buffer(target, breakpoint->address, 4, (uint8_t *)&data);
-
- /* backup origin instruction
- * instruction is big-endian */
- if (*(char *)&data & 0x80) { /* 16-bits instruction */
- breakpoint->length = 2;
- break_insn = NDS32_BREAK_16;
- } else { /* 32-bits instruction */
- breakpoint->length = 4;
- break_insn = NDS32_BREAK_32;
- }
-
- if (breakpoint->orig_instr != NULL)
- free(breakpoint->orig_instr);
-
- breakpoint->orig_instr = malloc(breakpoint->length);
- memcpy(breakpoint->orig_instr, &data, breakpoint->length);
-
- /* self-modified code */
- target->type->write_buffer(target, breakpoint->address, breakpoint->length, (const uint8_t *)&break_insn);
- /* write_back & invalidate dcache & invalidate icache */
- nds32_cache_sync(target, breakpoint->address, breakpoint->length);
-
- /* read back to check */
- target->type->read_buffer(target, breakpoint->address, breakpoint->length, (uint8_t *)&check_data);
- if (memcmp(&check_data, &break_insn, breakpoint->length) == 0)
- return ERROR_OK;
-
- return ERROR_FAIL;
-}
-
-int nds32_remove_software_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- uint32_t check_data;
- uint32_t break_insn;
-
- if (breakpoint->length == 2)
- break_insn = NDS32_BREAK_16;
- else if (breakpoint->length == 4)
- break_insn = NDS32_BREAK_32;
- else
- return ERROR_FAIL;
-
- target->type->read_buffer(target, breakpoint->address, breakpoint->length,
- (uint8_t *)&check_data);
-
- /* break instruction is modified */
- if (memcmp(&check_data, &break_insn, breakpoint->length) != 0)
- return ERROR_FAIL;
-
- /* self-modified code */
- target->type->write_buffer(target, breakpoint->address, breakpoint->length,
- breakpoint->orig_instr);
-
- /* write_back & invalidate dcache & invalidate icache */
- nds32_cache_sync(target, breakpoint->address, breakpoint->length);
-
- return ERROR_OK;
-}
-
-/**
- * Restore the processor context on an Andes target. The full processor
- * context is analyzed to see if any of the registers are dirty on this end, but
- * have a valid new value. If this is the case, the processor is changed to the
- * appropriate mode and the new register values are written out to the
- * processor. If there happens to be a dirty register with an invalid value, an
- * error will be logged.
- *
- * @param target Pointer to the Andes target to have its context restored
- * @return Error status if the target is not halted.
- */
-int nds32_restore_context(struct target *target)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct reg_cache *reg_cache = nds32->core_cache;
- struct reg *reg;
- struct nds32_reg *reg_arch_info;
- unsigned int i;
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* check if there are dirty registers */
- for (i = 0; i < reg_cache->num_regs; i++) {
- reg = &(reg_cache->reg_list[i]);
- if (reg->dirty == true) {
- if (reg->valid == true) {
-
- LOG_DEBUG("examining dirty reg: %s", reg->name);
- LOG_DEBUG("writing register %d with value 0x%8.8" PRIx32,
- i, buf_get_u32(reg->value, 0, 32));
-
- reg_arch_info = reg->arch_info;
- if (FD0 <= reg_arch_info->num && reg_arch_info->num <= FD31) {
- uint64_t val = buf_get_u64(reg_arch_info->value, 0, 64);
- aice_write_reg_64(aice, reg_arch_info->num, val);
- } else {
- uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
- aice_write_register(aice, reg_arch_info->num, val);
- }
-
- reg->valid = true;
- reg->dirty = false;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-int nds32_edm_config(struct nds32 *nds32)
-{
- struct target *target = nds32->target;
- struct aice_port_s *aice = target_to_aice(target);
- uint32_t edm_cfg;
- uint32_t edm_ctl;
-
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
-
- nds32->edm.version = (edm_cfg >> 16) & 0xFFFF;
- LOG_INFO("EDM version 0x%04x", nds32->edm.version);
-
- nds32->edm.breakpoint_num = (edm_cfg & 0x7) + 1;
-
- if ((nds32->edm.version & 0x1000) || (0x60 <= nds32->edm.version))
- nds32->edm.access_control = true;
- else
- nds32->edm.access_control = false;
-
- if ((edm_cfg >> 4) & 0x1)
- nds32->edm.direct_access_local_memory = true;
- else
- nds32->edm.direct_access_local_memory = false;
-
- if (nds32->edm.version <= 0x20)
- nds32->edm.direct_access_local_memory = false;
-
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
- if (edm_ctl & (0x1 << 29))
- nds32->edm.support_max_stop = true;
- else
- nds32->edm.support_max_stop = false;
-
- /* set passcode for secure MCU */
- nds32_login(nds32);
-
- return ERROR_OK;
-}
-
-int nds32_config(struct nds32 *nds32)
-{
- nds32_init_config(nds32);
-
- /* init optional system registers according to config registers */
- nds32_init_option_registers(nds32);
-
- /* get max interrupt level */
- if (nds32->misc_config.interruption_level)
- nds32->max_interrupt_level = 2;
- else
- nds32->max_interrupt_level = 3;
-
- /* get ILM/DLM size from MR6/MR7 */
- uint32_t value_mr6, value_mr7;
- uint32_t size_index;
- nds32_get_mapped_reg(nds32, MR6, &value_mr6);
- size_index = (value_mr6 >> 1) & 0xF;
- nds32->memory.ilm_size = NDS32_LM_SIZE_TABLE[size_index];
-
- nds32_get_mapped_reg(nds32, MR7, &value_mr7);
- size_index = (value_mr7 >> 1) & 0xF;
- nds32->memory.dlm_size = NDS32_LM_SIZE_TABLE[size_index];
-
- return ERROR_OK;
-}
-
-int nds32_init_arch_info(struct target *target, struct nds32 *nds32)
-{
- target->arch_info = nds32;
- nds32->target = target;
-
- nds32->common_magic = NDS32_COMMON_MAGIC;
- nds32->init_arch_info_after_halted = false;
- nds32->auto_convert_hw_bp = true;
- nds32->global_stop = false;
- nds32->soft_reset_halt = false;
- nds32->edm_passcode = NULL;
- nds32->privilege_level = 0;
- nds32->boot_time = 1500;
- nds32->reset_halt_as_examine = false;
- nds32->keep_target_edm_ctl = false;
- nds32->word_access_mem = false;
- nds32->virtual_hosting = true;
- nds32->hit_syscall = false;
- nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED;
- nds32->virtual_hosting_errno = 0;
- nds32->virtual_hosting_ctrl_c = false;
- nds32->attached = false;
-
- nds32->syscall_break.asid = 0;
- nds32->syscall_break.length = 4;
- nds32->syscall_break.set = 0;
- nds32->syscall_break.orig_instr = NULL;
- nds32->syscall_break.next = NULL;
- nds32->syscall_break.unique_id = 0x515CAll + target->target_number;
- nds32->syscall_break.linked_BRP = 0;
-
- nds32_reg_init();
-
- if (ERROR_FAIL == nds32_reg_cache_init(target, nds32))
- return ERROR_FAIL;
-
- if (ERROR_OK != nds32_init_register_table(nds32))
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical)
-{
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (nds32->memory.address_translation == false) {
- *physical = address;
- return ERROR_OK;
- }
-
- if (ERROR_OK == nds32_probe_tlb(nds32, address, physical))
- return ERROR_OK;
-
- if (ERROR_OK == nds32_walk_page_table(nds32, address, physical))
- return ERROR_OK;
-
- return ERROR_FAIL;
-}
-
-int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_cache *dcache = &(nds32->memory.dcache);
- struct nds32_cache *icache = &(nds32->memory.icache);
- uint32_t dcache_line_size = NDS32_LINE_SIZE_TABLE[dcache->line_size];
- uint32_t icache_line_size = NDS32_LINE_SIZE_TABLE[icache->line_size];
- uint32_t cur_address;
- int result;
- uint32_t start_line, end_line;
- uint32_t cur_line;
-
- if ((dcache->line_size != 0) && (dcache->enable == true)) {
- /* address / dcache_line_size */
- start_line = address >> (dcache->line_size + 2);
- /* (address + length - 1) / dcache_line_size */
- end_line = (address + length - 1) >> (dcache->line_size + 2);
-
- for (cur_address = address, cur_line = start_line ;
- cur_line <= end_line ;
- cur_address += dcache_line_size, cur_line++) {
- /* D$ write back */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_WB, cur_address);
- if (result != ERROR_OK)
- return result;
-
- /* D$ invalidate */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_INVAL, cur_address);
- if (result != ERROR_OK)
- return result;
- }
- }
-
- if ((icache->line_size != 0) && (icache->enable == true)) {
- /* address / icache_line_size */
- start_line = address >> (icache->line_size + 2);
- /* (address + length - 1) / icache_line_size */
- end_line = (address + length - 1) >> (icache->line_size + 2);
-
- for (cur_address = address, cur_line = start_line ;
- cur_line <= end_line ;
- cur_address += icache_line_size, cur_line++) {
- /* Because PSW.IT is turned off under debug exception, address MUST
- * be physical address. L1I_VA_INVALIDATE uses PSW.IT to decide
- * address translation or not. */
- uint32_t physical_addr;
- if (ERROR_FAIL == target->type->virt2phys(target, cur_address,
- &physical_addr))
- return ERROR_FAIL;
-
- /* I$ invalidate */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_VA_INVAL, physical_addr);
- if (result != ERROR_OK)
- return result;
- }
- }
-
- return ERROR_OK;
-}
-
-uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address)
-{
- if (!current)
- nds32_set_mapped_reg(nds32, PC, address);
- else
- nds32_get_mapped_reg(nds32, PC, &address);
-
- return address;
-}
-
-int nds32_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- struct nds32 *nds32 = target_to_nds32(target);
-
- address = nds32_nextpc(nds32, current, address);
-
- LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : "");
-
- /** set DSSIM */
- uint32_t ir14_value;
- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
- if (nds32->step_isr_enable)
- ir14_value |= (0x1 << 31);
- else
- ir14_value &= ~(0x1 << 31);
- nds32_set_mapped_reg(nds32, IR14, ir14_value);
-
- /* check hit_syscall before leave_debug_state() because
- * leave_debug_state() may clear hit_syscall flag */
- bool no_step = false;
- if (nds32->hit_syscall)
- /* step after hit_syscall should be ignored because
- * leave_debug_state will step implicitly to skip the
- * syscall */
- no_step = true;
-
- /********* TODO: maybe create another function to handle this part */
- CHECK_RETVAL(nds32->leave_debug_state(nds32, true));
- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
-
- if (no_step == false) {
- struct aice_port_s *aice = target_to_aice(target);
- if (ERROR_OK != aice_step(aice))
- return ERROR_FAIL;
- }
-
- /* save state */
- CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
- /********* TODO: maybe create another function to handle this part */
-
- /* restore DSSIM */
- if (nds32->step_isr_enable) {
- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
- ir14_value &= ~(0x1 << 31);
- nds32_set_mapped_reg(nds32, IR14, ir14_value);
- }
-
- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
-
- return ERROR_OK;
-}
-
-static int nds32_step_without_watchpoint(struct nds32 *nds32)
-{
- struct target *target = nds32->target;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /** set DSSIM */
- uint32_t ir14_value;
- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
- if (nds32->step_isr_enable)
- ir14_value |= (0x1 << 31);
- else
- ir14_value &= ~(0x1 << 31);
- nds32_set_mapped_reg(nds32, IR14, ir14_value);
-
- /********* TODO: maybe create another function to handle this part */
- CHECK_RETVAL(nds32->leave_debug_state(nds32, false));
-
- struct aice_port_s *aice = target_to_aice(target);
-
- if (ERROR_OK != aice_step(aice))
- return ERROR_FAIL;
-
- /* save state */
- CHECK_RETVAL(nds32->enter_debug_state(nds32, false));
- /********* TODO: maybe create another function to handle this part */
-
- /* restore DSSIM */
- if (nds32->step_isr_enable) {
- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
- ir14_value &= ~(0x1 << 31);
- nds32_set_mapped_reg(nds32, IR14, ir14_value);
- }
-
- return ERROR_OK;
-}
-
-int nds32_target_state(struct nds32 *nds32, enum target_state *state)
-{
- struct aice_port_s *aice = target_to_aice(nds32->target);
- enum aice_target_state_s nds32_state;
-
- if (aice_state(aice, &nds32_state) != ERROR_OK)
- return ERROR_FAIL;
-
- switch (nds32_state) {
- case AICE_DISCONNECT:
- LOG_INFO("USB is disconnected");
- return ERROR_FAIL;
- case AICE_TARGET_DETACH:
- LOG_INFO("Target is disconnected");
- return ERROR_FAIL;
- case AICE_TARGET_UNKNOWN:
- *state = TARGET_UNKNOWN;
- break;
- case AICE_TARGET_RUNNING:
- *state = TARGET_RUNNING;
- break;
- case AICE_TARGET_HALTED:
- *state = TARGET_HALTED;
- break;
- case AICE_TARGET_RESET:
- *state = TARGET_RESET;
- break;
- case AICE_TARGET_DEBUG_RUNNING:
- *state = TARGET_DEBUG_RUNNING;
- break;
- default:
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-int nds32_examine_debug_reason(struct nds32 *nds32)
-{
- uint32_t reason;
- struct target *target = nds32->target;
-
- if (nds32->hit_syscall == true) {
- LOG_DEBUG("Hit syscall breakpoint");
- target->debug_reason = DBG_REASON_BREAKPOINT;
- return ERROR_OK;
- }
-
- nds32->get_debug_reason(nds32, &reason);
-
- LOG_DEBUG("nds32 examines debug reason: %s", nds32_debug_type_name[reason]);
-
- /* Examine debug reason */
- switch (reason) {
- case NDS32_DEBUG_BREAK:
- case NDS32_DEBUG_BREAK_16:
- case NDS32_DEBUG_INST_BREAK:
- {
- uint32_t value_pc;
- uint32_t opcode;
- struct nds32_instruction instruction;
-
- nds32_get_mapped_reg(nds32, PC, &value_pc);
-
- if (ERROR_OK != nds32_read_opcode(nds32, value_pc, &opcode))
- return ERROR_FAIL;
- if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, value_pc,
- &instruction))
- return ERROR_FAIL;
-
- /* hit 'break 0x7FFF' */
- if ((instruction.info.opc_6 == 0x32) &&
- (instruction.info.sub_opc == 0xA) &&
- (instruction.info.imm == 0x7FFF)) {
- target->debug_reason = DBG_REASON_EXIT;
- } else
- target->debug_reason = DBG_REASON_BREAKPOINT;
- }
- break;
- case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE:
- case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_PRECISE:
- case NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP: /* GLOBAL_STOP is precise exception */
- {
- int result;
-
- result = nds32->get_watched_address(nds32,
- &(nds32->watched_address), reason);
- /* do single step(without watchpoints) to skip the "watched" instruction */
- nds32_step_without_watchpoint(nds32);
-
- /* before single_step, save exception address */
- if (ERROR_OK != result)
- return ERROR_FAIL;
-
- target->debug_reason = DBG_REASON_WATCHPOINT;
- }
- break;
- case NDS32_DEBUG_DEBUG_INTERRUPT:
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case NDS32_DEBUG_HARDWARE_SINGLE_STEP:
- target->debug_reason = DBG_REASON_SINGLESTEP;
- break;
- case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_IMPRECISE:
- case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE:
- case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE:
- if (ERROR_OK != nds32->get_watched_address(nds32,
- &(nds32->watched_address), reason))
- return ERROR_FAIL;
-
- target->debug_reason = DBG_REASON_WATCHPOINT;
- break;
- default:
- target->debug_reason = DBG_REASON_UNDEFINED;
- break;
- }
-
- return ERROR_OK;
-}
-
-int nds32_login(struct nds32 *nds32)
-{
- struct target *target = nds32->target;
- struct aice_port_s *aice = target_to_aice(target);
- uint32_t passcode_length;
- char command_sequence[129];
- char command_str[33];
- char code_str[9];
- uint32_t copy_length;
- uint32_t code;
- uint32_t i;
-
- LOG_DEBUG("nds32_login");
-
- if (nds32->edm_passcode != NULL) {
- /* convert EDM passcode to command sequences */
- passcode_length = strlen(nds32->edm_passcode);
- command_sequence[0] = '\0';
- for (i = 0; i < passcode_length; i += 8) {
- if (passcode_length - i < 8)
- copy_length = passcode_length - i;
- else
- copy_length = 8;
-
- strncpy(code_str, nds32->edm_passcode + i, copy_length);
- code_str[copy_length] = '\0';
- code = strtoul(code_str, NULL, 16);
-
- sprintf(command_str, "write_misc gen_port0 0x%" PRIx32 ";", code);
- strcat(command_sequence, command_str);
- }
-
- if (ERROR_OK != aice_program_edm(aice, command_sequence))
- return ERROR_FAIL;
-
- /* get current privilege level */
- uint32_t value_edmsw;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &value_edmsw);
- nds32->privilege_level = (value_edmsw >> 16) & 0x3;
- LOG_INFO("Current privilege level: %d", nds32->privilege_level);
- }
-
- if (nds32_edm_ops_num > 0) {
- const char *reg_name;
- for (i = 0 ; i < nds32_edm_ops_num ; i++) {
- code = nds32_edm_ops[i].value;
- if (nds32_edm_ops[i].reg_no == 6)
- reg_name = "gen_port0";
- else if (nds32_edm_ops[i].reg_no == 7)
- reg_name = "gen_port1";
- else
- return ERROR_FAIL;
-
- sprintf(command_str, "write_misc %s 0x%" PRIx32 ";", reg_name, code);
- if (ERROR_OK != aice_program_edm(aice, command_str))
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-int nds32_halt(struct target *target)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- enum target_state state;
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- }
-
- if (nds32_target_state(nds32, &state) != ERROR_OK)
- return ERROR_FAIL;
-
- if (TARGET_HALTED != state)
- /* TODO: if state == TARGET_HALTED, check ETYPE is DBGI or not */
- if (ERROR_OK != aice_halt(aice))
- return ERROR_FAIL;
-
- CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
-
- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
-
- return ERROR_OK;
-}
-
-/* poll current target status */
-int nds32_poll(struct target *target)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- enum target_state state;
-
- if (nds32_target_state(nds32, &state) != ERROR_OK)
- return ERROR_FAIL;
-
- if (state == TARGET_HALTED) {
- if (target->state != TARGET_HALTED) {
- /* if false_hit, continue free_run */
- if (ERROR_OK != nds32->enter_debug_state(nds32, true)) {
- struct aice_port_s *aice = target_to_aice(target);
- aice_run(aice);
- return ERROR_OK;
- }
-
- LOG_DEBUG("Change target state to TARGET_HALTED.");
-
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- }
- } else if (state == TARGET_RESET) {
- if (target->state == TARGET_HALTED) {
- /* similar to assert srst */
- register_cache_invalidate(nds32->core_cache);
- target->state = TARGET_RESET;
-
- /* TODO: deassert srst */
- } else if (target->state == TARGET_RUNNING) {
- /* reset as running */
- LOG_WARNING("<-- TARGET WARNING! The debug target has been reset. -->");
- }
- } else {
- if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) {
- LOG_DEBUG("Change target state to TARGET_RUNNING.");
- target->state = TARGET_RUNNING;
- target->debug_reason = DBG_REASON_NOTHALTED;
- }
- }
-
- return ERROR_OK;
-}
-
-int nds32_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- LOG_DEBUG("current %d address %08" PRIx32
- " handle_breakpoints %d"
- " debug_execution %d",
- current, address, handle_breakpoints, debug_execution);
-
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- address = nds32_nextpc(nds32, current, address);
-
- LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : "");
-
- if (!debug_execution)
- target_free_all_working_areas(target);
-
- /* Disable HSS to avoid users misuse HSS */
- if (nds32_reach_max_interrupt_level(nds32) == false) {
- uint32_t value_ir0;
- nds32_get_mapped_reg(nds32, IR0, &value_ir0);
- value_ir0 &= ~(0x1 << 11);
- nds32_set_mapped_reg(nds32, IR0, value_ir0);
- }
-
- CHECK_RETVAL(nds32->leave_debug_state(nds32, true));
- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
-
- if (nds32->virtual_hosting_ctrl_c == false) {
- struct aice_port_s *aice = target_to_aice(target);
- aice_run(aice);
- } else
- nds32->virtual_hosting_ctrl_c = false;
-
- target->debug_reason = DBG_REASON_NOTHALTED;
- if (!debug_execution)
- target->state = TARGET_RUNNING;
- else
- target->state = TARGET_DEBUG_RUNNING;
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- return ERROR_OK;
-}
-
-static int nds32_soft_reset_halt(struct target *target)
-{
- /* TODO: test it */
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
-
- aice_assert_srst(aice, AICE_SRST);
-
- /* halt core and set pc to 0x0 */
- int retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* start fetching from IVB */
- uint32_t value_ir3;
- nds32_get_mapped_reg(nds32, IR3, &value_ir3);
- nds32_set_mapped_reg(nds32, PC, value_ir3 & 0xFFFF0000);
-
- return ERROR_OK;
-}
-
-int nds32_assert_reset(struct target *target)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
-
- /* TODO: apply hw reset signal in not examined state */
- if (!(target_was_examined(target))) {
- LOG_WARNING("Reset is not asserted because the target is not examined.");
- LOG_WARNING("Use a reset button or power cycle the target.");
- return ERROR_TARGET_NOT_EXAMINED;
- }
-
- if (target->reset_halt) {
- if ((nds32->soft_reset_halt)
- || (nds32->edm.version < 0x51)
- || ((nds32->edm.version == 0x51)
- && (cpu_version->revision == 0x1C)
- && (cpu_version->cpu_id_family == 0xC)
- && (cpu_version->cpu_id_version == 0x0)))
- nds32_soft_reset_halt(target);
- else
- aice_assert_srst(aice, AICE_RESET_HOLD);
- } else {
- aice_assert_srst(aice, AICE_SRST);
- alive_sleep(nds32->boot_time);
- }
-
- /* set passcode for secure MCU after core reset */
- nds32_login(nds32);
-
- /* registers are now invalid */
- register_cache_invalidate(nds32->core_cache);
-
- target->state = TARGET_RESET;
-
- return ERROR_OK;
-}
-
-static int nds32_gdb_attach(struct nds32 *nds32)
-{
- LOG_DEBUG("nds32_gdb_attach, target coreid: %" PRId32, nds32->target->coreid);
-
- if (nds32->attached == false) {
-
- if (nds32->keep_target_edm_ctl) {
- /* backup target EDM_CTL */
- struct aice_port_s *aice = target_to_aice(nds32->target);
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &nds32->backup_edm_ctl);
- }
-
- target_halt(nds32->target);
-
- nds32->attached = true;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_gdb_detach(struct nds32 *nds32)
-{
- LOG_DEBUG("nds32_gdb_detach");
- bool backup_virtual_hosting_setting;
-
- if (nds32->attached) {
-
- backup_virtual_hosting_setting = nds32->virtual_hosting;
- /* turn off virtual hosting before resume as gdb-detach */
- nds32->virtual_hosting = false;
- target_resume(nds32->target, 1, 0, 0, 0);
- nds32->virtual_hosting = backup_virtual_hosting_setting;
-
- if (nds32->keep_target_edm_ctl) {
- /* restore target EDM_CTL */
- struct aice_port_s *aice = target_to_aice(nds32->target);
- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, nds32->backup_edm_ctl);
- }
-
- nds32->attached = false;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_callback_event_handler(struct target *target,
- enum target_event event, void *priv)
-{
- int retval = ERROR_OK;
- int target_number = *(int *)priv;
-
- if (target_number != target->target_number)
- return ERROR_OK;
-
- struct nds32 *nds32 = target_to_nds32(target);
-
- switch (event) {
- case TARGET_EVENT_GDB_ATTACH:
- retval = nds32_gdb_attach(nds32);
- break;
- case TARGET_EVENT_GDB_DETACH:
- retval = nds32_gdb_detach(nds32);
- break;
- default:
- break;
- }
-
- return retval;
-}
-
-int nds32_init(struct nds32 *nds32)
-{
- /* Initialize anything we can set up without talking to the target */
- nds32->memory.access_channel = NDS_MEMORY_ACC_CPU;
-
- /* register event callback */
- target_register_event_callback(nds32_callback_event_handler,
- &(nds32->target->target_number));
-
- return ERROR_OK;
-}
-
-int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
-{
- /* fill syscall parameters to file-I/O info */
- if (NULL == fileio_info) {
- LOG_ERROR("Target has not initial file-I/O data structure");
- return ERROR_FAIL;
- }
-
- struct nds32 *nds32 = target_to_nds32(target);
- uint32_t value_ir6;
- uint32_t syscall_id;
-
- if (nds32->hit_syscall == false)
- return ERROR_FAIL;
-
- nds32_get_mapped_reg(nds32, IR6, &value_ir6);
- syscall_id = (value_ir6 >> 16) & 0x7FFF;
- nds32->active_syscall_id = syscall_id;
-
- LOG_DEBUG("hit syscall ID: 0x%" PRIx32, syscall_id);
-
- /* free previous identifier storage */
- if (NULL != fileio_info->identifier) {
- free(fileio_info->identifier);
- fileio_info->identifier = NULL;
- }
-
- switch (syscall_id) {
- case NDS32_SYSCALL_EXIT:
- fileio_info->identifier = malloc(5);
- sprintf(fileio_info->identifier, "exit");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- break;
- case NDS32_SYSCALL_OPEN:
- {
- uint8_t filename[256];
- fileio_info->identifier = malloc(5);
- sprintf(fileio_info->identifier, "open");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- /* reserve fileio_info->param_2 for length of path */
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3));
- nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_4));
-
- target->type->read_buffer(target, fileio_info->param_1,
- 256, filename);
- fileio_info->param_2 = strlen((char *)filename) + 1;
- }
- break;
- case NDS32_SYSCALL_CLOSE:
- fileio_info->identifier = malloc(6);
- sprintf(fileio_info->identifier, "close");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- break;
- case NDS32_SYSCALL_READ:
- fileio_info->identifier = malloc(5);
- sprintf(fileio_info->identifier, "read");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2));
- nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3));
- break;
- case NDS32_SYSCALL_WRITE:
- fileio_info->identifier = malloc(6);
- sprintf(fileio_info->identifier, "write");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2));
- nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3));
- break;
- case NDS32_SYSCALL_LSEEK:
- fileio_info->identifier = malloc(6);
- sprintf(fileio_info->identifier, "lseek");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2));
- nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3));
- break;
- case NDS32_SYSCALL_UNLINK:
- {
- uint8_t filename[256];
- fileio_info->identifier = malloc(7);
- sprintf(fileio_info->identifier, "unlink");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- /* reserve fileio_info->param_2 for length of path */
-
- target->type->read_buffer(target, fileio_info->param_1,
- 256, filename);
- fileio_info->param_2 = strlen((char *)filename) + 1;
- }
- break;
- case NDS32_SYSCALL_RENAME:
- {
- uint8_t filename[256];
- fileio_info->identifier = malloc(7);
- sprintf(fileio_info->identifier, "rename");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- /* reserve fileio_info->param_2 for length of old path */
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3));
- /* reserve fileio_info->param_4 for length of new path */
-
- target->type->read_buffer(target, fileio_info->param_1,
- 256, filename);
- fileio_info->param_2 = strlen((char *)filename) + 1;
-
- target->type->read_buffer(target, fileio_info->param_3,
- 256, filename);
- fileio_info->param_4 = strlen((char *)filename) + 1;
- }
- break;
- case NDS32_SYSCALL_FSTAT:
- fileio_info->identifier = malloc(6);
- sprintf(fileio_info->identifier, "fstat");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2));
- break;
- case NDS32_SYSCALL_STAT:
- {
- uint8_t filename[256];
- fileio_info->identifier = malloc(5);
- sprintf(fileio_info->identifier, "stat");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- /* reserve fileio_info->param_2 for length of old path */
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3));
-
- target->type->read_buffer(target, fileio_info->param_1,
- 256, filename);
- fileio_info->param_2 = strlen((char *)filename) + 1;
- }
- break;
- case NDS32_SYSCALL_GETTIMEOFDAY:
- fileio_info->identifier = malloc(13);
- sprintf(fileio_info->identifier, "gettimeofday");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2));
- break;
- case NDS32_SYSCALL_ISATTY:
- fileio_info->identifier = malloc(7);
- sprintf(fileio_info->identifier, "isatty");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- break;
- case NDS32_SYSCALL_SYSTEM:
- {
- uint8_t command[256];
- fileio_info->identifier = malloc(7);
- sprintf(fileio_info->identifier, "system");
- nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1));
- /* reserve fileio_info->param_2 for length of old path */
-
- target->type->read_buffer(target, fileio_info->param_1,
- 256, command);
- fileio_info->param_2 = strlen((char *)command) + 1;
- }
- break;
- case NDS32_SYSCALL_ERRNO:
- fileio_info->identifier = malloc(6);
- sprintf(fileio_info->identifier, "errno");
- nds32_set_mapped_reg(nds32, R0, nds32->virtual_hosting_errno);
- break;
- default:
- fileio_info->identifier = malloc(8);
- sprintf(fileio_info->identifier, "unknown");
- break;
- }
-
- return ERROR_OK;
-}
-
-int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
-{
- LOG_DEBUG("syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s",
- retcode, fileio_errno, ctrl_c ? "true" : "false");
-
- struct nds32 *nds32 = target_to_nds32(target);
-
- nds32_set_mapped_reg(nds32, R0, (uint32_t)retcode);
-
- nds32->virtual_hosting_errno = fileio_errno;
- nds32->virtual_hosting_ctrl_c = ctrl_c;
- nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED;
-
- return ERROR_OK;
-}
-
-int nds32_profiling(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
-{
- /* sample $PC every 10 milliseconds */
- uint32_t iteration = seconds * 100;
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (max_num_samples < iteration)
- iteration = max_num_samples;
-
- int pc_regnum = nds32->register_map(nds32, PC);
- aice_profiling(aice, 10, iteration, pc_regnum, samples, num_samples);
-
- register_cache_invalidate(nds32->core_cache);
-
- return ERROR_OK;
-}
-
-int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address,
- uint32_t size, const uint8_t *buffer)
-{
- if ((NDS32_SYSCALL_FSTAT == nds32->active_syscall_id) ||
- (NDS32_SYSCALL_STAT == nds32->active_syscall_id)) {
- /* If doing GDB file-I/O, target should convert 'struct stat'
- * from gdb-format to target-format */
- uint8_t stat_buffer[NDS32_STRUCT_STAT_SIZE];
- /* st_dev 2 */
- stat_buffer[0] = buffer[3];
- stat_buffer[1] = buffer[2];
- /* st_ino 2 */
- stat_buffer[2] = buffer[7];
- stat_buffer[3] = buffer[6];
- /* st_mode 4 */
- stat_buffer[4] = buffer[11];
- stat_buffer[5] = buffer[10];
- stat_buffer[6] = buffer[9];
- stat_buffer[7] = buffer[8];
- /* st_nlink 2 */
- stat_buffer[8] = buffer[15];
- stat_buffer[9] = buffer[16];
- /* st_uid 2 */
- stat_buffer[10] = buffer[19];
- stat_buffer[11] = buffer[18];
- /* st_gid 2 */
- stat_buffer[12] = buffer[23];
- stat_buffer[13] = buffer[22];
- /* st_rdev 2 */
- stat_buffer[14] = buffer[27];
- stat_buffer[15] = buffer[26];
- /* st_size 4 */
- stat_buffer[16] = buffer[35];
- stat_buffer[17] = buffer[34];
- stat_buffer[18] = buffer[33];
- stat_buffer[19] = buffer[32];
- /* st_atime 4 */
- stat_buffer[20] = buffer[55];
- stat_buffer[21] = buffer[54];
- stat_buffer[22] = buffer[53];
- stat_buffer[23] = buffer[52];
- /* st_spare1 4 */
- stat_buffer[24] = 0;
- stat_buffer[25] = 0;
- stat_buffer[26] = 0;
- stat_buffer[27] = 0;
- /* st_mtime 4 */
- stat_buffer[28] = buffer[59];
- stat_buffer[29] = buffer[58];
- stat_buffer[30] = buffer[57];
- stat_buffer[31] = buffer[56];
- /* st_spare2 4 */
- stat_buffer[32] = 0;
- stat_buffer[33] = 0;
- stat_buffer[34] = 0;
- stat_buffer[35] = 0;
- /* st_ctime 4 */
- stat_buffer[36] = buffer[63];
- stat_buffer[37] = buffer[62];
- stat_buffer[38] = buffer[61];
- stat_buffer[39] = buffer[60];
- /* st_spare3 4 */
- stat_buffer[40] = 0;
- stat_buffer[41] = 0;
- stat_buffer[42] = 0;
- stat_buffer[43] = 0;
- /* st_blksize 4 */
- stat_buffer[44] = buffer[43];
- stat_buffer[45] = buffer[42];
- stat_buffer[46] = buffer[41];
- stat_buffer[47] = buffer[40];
- /* st_blocks 4 */
- stat_buffer[48] = buffer[51];
- stat_buffer[49] = buffer[50];
- stat_buffer[50] = buffer[49];
- stat_buffer[51] = buffer[48];
- /* st_spare4 8 */
- stat_buffer[52] = 0;
- stat_buffer[53] = 0;
- stat_buffer[54] = 0;
- stat_buffer[55] = 0;
- stat_buffer[56] = 0;
- stat_buffer[57] = 0;
- stat_buffer[58] = 0;
- stat_buffer[59] = 0;
-
- return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_STAT_SIZE, stat_buffer);
- } else if (NDS32_SYSCALL_GETTIMEOFDAY == nds32->active_syscall_id) {
- /* If doing GDB file-I/O, target should convert 'struct timeval'
- * from gdb-format to target-format */
- uint8_t timeval_buffer[NDS32_STRUCT_TIMEVAL_SIZE];
- timeval_buffer[0] = buffer[3];
- timeval_buffer[1] = buffer[2];
- timeval_buffer[2] = buffer[1];
- timeval_buffer[3] = buffer[0];
- timeval_buffer[4] = buffer[11];
- timeval_buffer[5] = buffer[10];
- timeval_buffer[6] = buffer[9];
- timeval_buffer[7] = buffer[8];
-
- return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_TIMEVAL_SIZE, timeval_buffer);
- }
-
- return nds32_write_buffer(nds32->target, address, size, buffer);
-}
-
-int nds32_reset_halt(struct nds32 *nds32)
-{
- LOG_INFO("reset halt as init");
-
- struct aice_port_s *aice = target_to_aice(nds32->target);
- aice_assert_srst(aice, AICE_RESET_HOLD);
-
- return ERROR_OK;
-}
diff --git a/src/target/nds32.h b/src/target/nds32.h
deleted file mode 100644
index 88af4f3..0000000
--- a/src/target/nds32.h
+++ /dev/null
@@ -1,457 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_H
-#define OPENOCD_TARGET_NDS32_H
-
-#include <jtag/jtag.h>
-#include "target.h"
-#include "target_type.h"
-#include "register.h"
-#include "breakpoints.h"
-#include "nds32_reg.h"
-#include "nds32_insn.h"
-#include "nds32_edm.h"
-
-#define NDS32_EDM_OPERATION_MAX_NUM 64
-
-#define CHECK_RETVAL(action) \
- do { \
- int __retval = (action); \
- if (__retval != ERROR_OK) { \
- LOG_DEBUG("error while calling \"%s\"", \
- # action); \
- return __retval; \
- } \
- } while (0)
-
-/**
- * @file
- * Holds the interface to Andes cores.
- */
-
-extern const char *nds32_debug_type_name[11];
-
-enum nds32_debug_reason {
- NDS32_DEBUG_BREAK = 0,
- NDS32_DEBUG_BREAK_16,
- NDS32_DEBUG_INST_BREAK,
- NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE,
- NDS32_DEBUG_DATA_VALUE_WATCHPOINT_PRECISE,
- NDS32_DEBUG_DATA_VALUE_WATCHPOINT_IMPRECISE,
- NDS32_DEBUG_DEBUG_INTERRUPT,
- NDS32_DEBUG_HARDWARE_SINGLE_STEP,
- NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE,
- NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE,
- NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP,
-};
-
-#define NDS32_STRUCT_STAT_SIZE 60
-#define NDS32_STRUCT_TIMEVAL_SIZE 8
-
-enum nds32_syscall_id {
- NDS32_SYSCALL_UNDEFINED = 0,
- NDS32_SYSCALL_EXIT = 1,
- NDS32_SYSCALL_OPEN = 2,
- NDS32_SYSCALL_CLOSE = 3,
- NDS32_SYSCALL_READ = 4,
- NDS32_SYSCALL_WRITE = 5,
- NDS32_SYSCALL_LSEEK = 6,
- NDS32_SYSCALL_UNLINK = 7,
- NDS32_SYSCALL_RENAME = 3001,
- NDS32_SYSCALL_FSTAT = 10,
- NDS32_SYSCALL_STAT = 15,
- NDS32_SYSCALL_GETTIMEOFDAY = 19,
- NDS32_SYSCALL_ISATTY = 3002,
- NDS32_SYSCALL_SYSTEM = 3003,
- NDS32_SYSCALL_ERRNO = 6001,
-};
-
-#define NDS32_COMMON_MAGIC (int)0xADE5ADE5
-
-struct nds32_edm {
-
- /** EDM_CFG.VER, indicate the EDM version */
- int version;
-
- /** The number of hardware breakpoints */
- int breakpoint_num;
-
- /** EDM_CFG.DALM, indicate if direct local memory access
- * feature is supported or not */
- bool direct_access_local_memory;
-
- /** Support ACC_CTL register */
- bool access_control;
-
- /** */
- bool support_max_stop;
-};
-
-struct nds32_cache {
-
- /** enable cache or not */
- bool enable;
-
- /** cache sets per way */
- int set;
-
- /** cache ways */
- int way;
-
- /** cache line size */
- int line_size;
-
- /** cache locking support */
- bool lock_support;
-};
-
-struct nds32_memory {
-
- /** ICache */
- struct nds32_cache icache;
-
- /** DCache */
- struct nds32_cache dcache;
-
- /** On-chip instruction local memory base */
- int ilm_base;
-
- /** On-chip instruction local memory size */
- int ilm_size;
-
- /** ILM base register alignment version */
- int ilm_align_ver;
-
- /** DLM is enabled or not */
- bool ilm_enable;
-
- /** DLM start address */
- int ilm_start;
-
- /** DLM end address */
- int ilm_end;
-
- /** On-chip data local memory base */
- int dlm_base;
-
- /** On-chip data local memory size */
- int dlm_size;
-
- /** DLM base register alignment version */
- int dlm_align_ver;
-
- /** DLM is enabled or not */
- bool dlm_enable;
-
- /** DLM start address */
- int dlm_start;
-
- /** DLM end address */
- int dlm_end;
-
- /** Memory access method */
- enum nds_memory_access access_channel;
-
- /** Memory access mode */
- enum nds_memory_select mode;
-
- /** Address translation */
- bool address_translation;
-};
-
-struct nds32_cpu_version {
- bool performance_extension;
- bool _16bit_extension;
- bool performance_extension_2;
- bool cop_fpu_extension;
- bool string_extension;
-
- int revision;
- int cpu_id_family;
- int cpu_id_version;
-};
-
-struct nds32_mmu_config {
- int memory_protection;
- int memory_protection_version;
- bool fully_associative_tlb;
- int tlb_size;
- int tlb_ways;
- int tlb_sets;
- bool _8k_page_support;
- int extra_page_size_support;
- bool tlb_lock;
- bool hardware_page_table_walker;
- bool default_endian;
- int partition_num;
- bool invisible_tlb;
- bool vlpt;
- bool ntme;
- bool drde;
- int default_min_page_size;
- bool multiple_page_size_in_use;
-};
-
-struct nds32_misc_config {
- bool edm;
- bool local_memory_dma;
- bool performance_monitor;
- bool high_speed_memory_port;
- bool debug_tracer;
- bool div_instruction;
- bool mac_instruction;
- int audio_isa;
- bool L2_cache;
- bool reduce_register;
- bool addr_24;
- bool interruption_level;
- int baseline_instruction;
- bool no_dx_register;
- bool implement_dependant_register;
- bool implement_dependant_sr_encoding;
- bool ifc;
- bool mcu;
- bool ex9;
- int shadow;
-};
-
-/**
- * Represents a generic Andes core.
- */
-struct nds32 {
- int common_magic;
- struct reg_cache *core_cache;
-
- /** Handle for the debug module. */
- struct nds32_edm edm;
-
- /** Memory information */
- struct nds32_memory memory;
-
- /** cpu version */
- struct nds32_cpu_version cpu_version;
-
- /** MMU configuration */
- struct nds32_mmu_config mmu_config;
-
- /** Misc configuration */
- struct nds32_misc_config misc_config;
-
- /** Retrieve all core registers, for display. */
- int (*full_context)(struct nds32 *nds32);
-
- /** Register mappings */
- int (*register_map)(struct nds32 *nds32, int reg_no);
-
- /** Get debug exception virtual address */
- int (*get_debug_reason)(struct nds32 *nds32, uint32_t *reason);
-
- /** Restore target registers may be modified in debug state */
- int (*leave_debug_state)(struct nds32 *nds32, bool enable_watchpoint);
-
- /** Backup target registers may be modified in debug state */
- int (*enter_debug_state)(struct nds32 *nds32, bool enable_watchpoint);
-
- /** Get address hit watchpoint */
- int (*get_watched_address)(struct nds32 *nds32, uint32_t *address, uint32_t reason);
-
- /** maximum interrupt level */
- uint32_t max_interrupt_level;
-
- /** current interrupt level */
- uint32_t current_interrupt_level;
-
- uint32_t watched_address;
-
- /** Flag reporting whether virtual hosting is active. */
- bool virtual_hosting;
-
- /** Flag reporting whether continue/step hits syscall or not */
- bool hit_syscall;
-
- /** Value to be returned by virtual hosting SYS_ERRNO request. */
- int virtual_hosting_errno;
-
- /** Flag reporting whether syscall is aborted */
- bool virtual_hosting_ctrl_c;
-
- /** Record syscall ID for other operations to do special processing for target */
- int active_syscall_id;
-
- struct breakpoint syscall_break;
-
- /** Flag reporting whether global stop is active. */
- bool global_stop;
-
- /** Flag reporting whether to use soft-reset-halt or not as issuing reset-halt. */
- bool soft_reset_halt;
-
- /** reset-halt as target examine */
- bool reset_halt_as_examine;
-
- /** backup/restore target EDM_CTL value. As debugging target debug
- * handler, it should be true. */
- bool keep_target_edm_ctl;
-
- /* Value of $EDM_CTL before target enters debug mode */
- uint32_t backup_edm_ctl;
-
- /** always use word-aligned address to access memory */
- bool word_access_mem;
-
- /** EDM passcode for debugging secure MCU */
- char *edm_passcode;
-
- /** current privilege_level if using secure MCU. value 0 is the highest level. */
- int privilege_level;
-
- /** Period to wait after SRST. */
- uint32_t boot_time;
-
- /** Flag to indicate HSS steps into ISR or not */
- bool step_isr_enable;
-
- /** Flag to indicate register table is ready or not */
- bool init_arch_info_after_halted;
-
- /** Flag to indicate audio-extension is enabled or not */
- bool audio_enable;
-
- /** Flag to indicate fpu-extension is enabled or not */
- bool fpu_enable;
-
- /* Andes Core has mixed endian model. Instruction is always big-endian.
- * Data may be big or little endian. Device registers may have different
- * endian from data and instruction. */
- /** Endian of data memory */
- enum target_endianness data_endian;
-
- /** Endian of device registers */
- enum target_endianness device_reg_endian;
-
- /** Flag to indicate if auto convert software breakpoints to
- * hardware breakpoints or not in ROM */
- bool auto_convert_hw_bp;
-
- /* Flag to indicate the target is attached by debugger or not */
- bool attached;
-
- /** Backpointer to the target. */
- struct target *target;
-
- void *arch_info;
-};
-
-struct nds32_reg {
- int32_t num;
- uint8_t value[8];
- struct target *target;
- struct nds32 *nds32;
- bool enable;
-};
-
-struct nds32_edm_operation {
- uint32_t reg_no;
- uint32_t value;
-};
-
-extern int nds32_config(struct nds32 *nds32);
-extern int nds32_init_arch_info(struct target *target, struct nds32 *nds32);
-extern int nds32_full_context(struct nds32 *nds32);
-extern int nds32_arch_state(struct target *target);
-extern int nds32_add_software_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-extern int nds32_remove_software_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-
-extern int nds32_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class);
-
-extern int nds32_write_buffer(struct target *target, uint32_t address,
- uint32_t size, const uint8_t *buffer);
-extern int nds32_read_buffer(struct target *target, uint32_t address,
- uint32_t size, uint8_t *buffer);
-extern int nds32_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer);
-extern int nds32_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-
-extern int nds32_init_register_table(struct nds32 *nds32);
-extern int nds32_init_memory_info(struct nds32 *nds32);
-extern int nds32_restore_context(struct target *target);
-extern int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *value);
-extern int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value);
-
-extern int nds32_edm_config(struct nds32 *nds32);
-extern int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length);
-extern int nds32_mmu(struct target *target, int *enabled);
-extern int nds32_virtual_to_physical(struct target *target, uint32_t address,
- uint32_t *physical);
-extern int nds32_read_phys_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer);
-extern int nds32_write_phys_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-extern uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address);
-extern int nds32_examine_debug_reason(struct nds32 *nds32);
-extern int nds32_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints);
-extern int nds32_target_state(struct nds32 *nds32, enum target_state *state);
-extern int nds32_halt(struct target *target);
-extern int nds32_poll(struct target *target);
-extern int nds32_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution);
-extern int nds32_assert_reset(struct target *target);
-extern int nds32_init(struct nds32 *nds32);
-extern int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info);
-extern int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address,
- uint32_t size, const uint8_t *buffer);
-extern int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c);
-extern int nds32_reset_halt(struct nds32 *nds32);
-extern int nds32_login(struct nds32 *nds32);
-extern int nds32_profiling(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
-
-/** Convert target handle to generic Andes target state handle. */
-static inline struct nds32 *target_to_nds32(struct target *target)
-{
- assert(target != NULL);
- return target->arch_info;
-}
-
-/** */
-static inline struct aice_port_s *target_to_aice(struct target *target)
-{
- assert(target != NULL);
- return target->tap->priv;
-}
-
-static inline bool is_nds32(struct nds32 *nds32)
-{
- assert(nds32 != NULL);
- return nds32->common_magic == NDS32_COMMON_MAGIC;
-}
-
-static inline bool nds32_reach_max_interrupt_level(struct nds32 *nds32)
-{
- assert(nds32 != NULL);
- return nds32->max_interrupt_level == nds32->current_interrupt_level;
-}
-
-#endif /* OPENOCD_TARGET_NDS32_H */
diff --git a/src/target/nds32_aice.c b/src/target/nds32_aice.c
deleted file mode 100644
index bdfafb5..0000000
--- a/src/target/nds32_aice.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes technology. *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include "nds32_aice.h"
-
-int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val)
-{
- if (aice->port->api->read_reg_64 == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->read_reg_64(aice->coreid, num, val);
-}
-
-int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val)
-{
- if (aice->port->api->write_reg_64 == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->write_reg_64(aice->coreid, num, val);
-}
-
-int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address,
- uint32_t *physical_address)
-{
- if (aice->port->api->read_tlb == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->read_tlb(aice->coreid, virtual_address, physical_address);
-}
-
-int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address)
-{
- if (aice->port->api->cache_ctl == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->cache_ctl(aice->coreid, subtype, address);
-}
-
-int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times)
-{
- if (aice->port->api->set_retry_times == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->set_retry_times(a_retry_times);
-}
-
-int aice_program_edm(struct aice_port_s *aice, char *command_sequence)
-{
- if (aice->port->api->program_edm == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->program_edm(aice->coreid, command_sequence);
-}
-
-int aice_set_command_mode(struct aice_port_s *aice,
- enum aice_command_mode command_mode)
-{
- if (aice->port->api->set_command_mode == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->set_command_mode(command_mode);
-}
-
-int aice_execute(struct aice_port_s *aice, uint32_t *instructions,
- uint32_t instruction_num)
-{
- if (aice->port->api->execute == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->execute(aice->coreid, instructions, instruction_num);
-}
-
-int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script)
-{
- if (aice->port->api->set_custom_srst_script == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->set_custom_srst_script(script);
-}
-
-int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script)
-{
- if (aice->port->api->set_custom_trst_script == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->set_custom_trst_script(script);
-}
-
-int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script)
-{
- if (aice->port->api->set_custom_restart_script == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->set_custom_restart_script(script);
-}
-
-int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check)
-{
- if (aice->port->api->set_count_to_check_dbger == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->set_count_to_check_dbger(count_to_check);
-}
-
-int aice_profiling(struct aice_port_s *aice, uint32_t interval, uint32_t iteration,
- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples)
-{
- if (aice->port->api->profiling == NULL) {
- LOG_WARNING("Not implemented: %s", __func__);
- return ERROR_FAIL;
- }
-
- return aice->port->api->profiling(aice->coreid, interval, iteration,
- reg_no, samples, num_samples);
-}
diff --git a/src/target/nds32_aice.h b/src/target/nds32_aice.h
deleted file mode 100644
index ae801ed..0000000
--- a/src/target/nds32_aice.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes technology. *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_AICE_H
-#define OPENOCD_TARGET_NDS32_AICE_H
-
-#include <jtag/aice/aice_port.h>
-
-int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val);
-int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val);
-int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address,
- uint32_t *physical_address);
-int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address);
-int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times);
-int aice_program_edm(struct aice_port_s *aice, char *command_sequence);
-int aice_set_command_mode(struct aice_port_s *aice,
- enum aice_command_mode command_mode);
-int aice_execute(struct aice_port_s *aice, uint32_t *instructions,
- uint32_t instruction_num);
-int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script);
-int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script);
-int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script);
-int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check);
-int aice_profiling(struct aice_port_s *aice, uint32_t interval, uint32_t iteration,
- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples);
-
-static inline int aice_open(struct aice_port_s *aice, struct aice_port_param_s *param)
-{
- return aice->port->api->open(param);
-}
-
-static inline int aice_close(struct aice_port_s *aice)
-{
- return aice->port->api->close();
-}
-
-static inline int aice_reset(struct aice_port_s *aice)
-{
- return aice->port->api->reset();
-}
-
-static inline int aice_assert_srst(struct aice_port_s *aice,
- enum aice_srst_type_s srst)
-{
- return aice->port->api->assert_srst(aice->coreid, srst);
-}
-
-static inline int aice_run(struct aice_port_s *aice)
-{
- return aice->port->api->run(aice->coreid);
-}
-
-static inline int aice_halt(struct aice_port_s *aice)
-{
- return aice->port->api->halt(aice->coreid);
-}
-
-static inline int aice_step(struct aice_port_s *aice)
-{
- return aice->port->api->step(aice->coreid);
-}
-
-static inline int aice_read_register(struct aice_port_s *aice, uint32_t num,
- uint32_t *val)
-{
- return aice->port->api->read_reg(aice->coreid, num, val);
-}
-
-static inline int aice_write_register(struct aice_port_s *aice, uint32_t num,
- uint32_t val)
-{
- return aice->port->api->write_reg(aice->coreid, num, val);
-}
-
-static inline int aice_read_debug_reg(struct aice_port_s *aice, uint32_t addr,
- uint32_t *val)
-{
- return aice->port->api->read_debug_reg(aice->coreid, addr, val);
-}
-
-static inline int aice_write_debug_reg(struct aice_port_s *aice, uint32_t addr,
- const uint32_t val)
-{
- return aice->port->api->write_debug_reg(aice->coreid, addr, val);
-}
-
-static inline int aice_read_mem_unit(struct aice_port_s *aice, uint32_t addr,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- return aice->port->api->read_mem_unit(aice->coreid, addr, size, count, buffer);
-}
-
-static inline int aice_write_mem_unit(struct aice_port_s *aice, uint32_t addr,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- return aice->port->api->write_mem_unit(aice->coreid, addr, size, count, buffer);
-}
-
-static inline int aice_read_mem_bulk(struct aice_port_s *aice, uint32_t addr,
- uint32_t length, uint8_t *buffer)
-{
- return aice->port->api->read_mem_bulk(aice->coreid, addr, length, buffer);
-}
-
-static inline int aice_write_mem_bulk(struct aice_port_s *aice, uint32_t addr,
- uint32_t length, const uint8_t *buffer)
-{
- return aice->port->api->write_mem_bulk(aice->coreid, addr, length, buffer);
-}
-
-static inline int aice_idcode(struct aice_port_s *aice, uint32_t *idcode,
- uint8_t *num_of_idcode)
-{
- return aice->port->api->idcode(idcode, num_of_idcode);
-}
-
-static inline int aice_state(struct aice_port_s *aice,
- enum aice_target_state_s *state)
-{
- return aice->port->api->state(aice->coreid, state);
-}
-
-static inline int aice_set_jtag_clock(struct aice_port_s *aice, uint32_t a_clock)
-{
- return aice->port->api->set_jtag_clock(a_clock);
-}
-
-static inline int aice_memory_access(struct aice_port_s *aice,
- enum nds_memory_access a_access)
-{
- return aice->port->api->memory_access(aice->coreid, a_access);
-}
-
-static inline int aice_memory_mode(struct aice_port_s *aice,
- enum nds_memory_select mem_select)
-{
- return aice->port->api->memory_mode(aice->coreid, mem_select);
-}
-
-static inline int aice_set_data_endian(struct aice_port_s *aice,
- enum aice_target_endian target_data_endian)
-{
- return aice->port->api->set_data_endian(aice->coreid, target_data_endian);
-}
-
-#endif /* OPENOCD_TARGET_NDS32_AICE_H */
diff --git a/src/target/nds32_cmd.c b/src/target/nds32_cmd.c
deleted file mode 100644
index edb4872..0000000
--- a/src/target/nds32_cmd.c
+++ /dev/null
@@ -1,1126 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/command.h>
-#include "nds32.h"
-#include "nds32_aice.h"
-#include "nds32_disassembler.h"
-
-extern struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM];
-extern uint32_t nds32_edm_ops_num;
-
-static const char *const NDS_MEMORY_ACCESS_NAME[] = {
- "BUS",
- "CPU",
-};
-
-static const char *const NDS_MEMORY_SELECT_NAME[] = {
- "AUTO",
- "MEM",
- "ILM",
- "DLM",
-};
-
-COMMAND_HANDLER(handle_nds32_dssim_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->step_isr_enable = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->step_isr_enable = false;
- }
-
- command_print(CMD_CTX, "%s: $INT_MASK.DSSIM: %d", target_name(target),
- nds32->step_isr_enable);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_memory_access_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "bus") == 0)
- memory->access_channel = NDS_MEMORY_ACC_BUS;
- else if (strcmp(CMD_ARGV[0], "cpu") == 0)
- memory->access_channel = NDS_MEMORY_ACC_CPU;
- else /* default access channel is NDS_MEMORY_ACC_CPU */
- memory->access_channel = NDS_MEMORY_ACC_CPU;
-
- LOG_DEBUG("memory access channel is changed to %s",
- NDS_MEMORY_ACCESS_NAME[memory->access_channel]);
-
- aice_memory_access(aice, memory->access_channel);
- } else {
- command_print(CMD_CTX, "%s: memory access channel: %s",
- target_name(target),
- NDS_MEMORY_ACCESS_NAME[memory->access_channel]);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_memory_mode_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
-
- if (nds32->edm.access_control == false) {
- command_print(CMD_CTX, "%s does not support ACC_CTL. "
- "Set memory mode to MEMORY", target_name(target));
- nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
- } else if (nds32->edm.direct_access_local_memory == false) {
- command_print(CMD_CTX, "%s does not support direct access "
- "local memory. Set memory mode to MEMORY",
- target_name(target));
- nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
-
- /* set to ACC_CTL */
- aice_memory_mode(aice, nds32->memory.mode);
- } else {
- if (strcmp(CMD_ARGV[0], "auto") == 0) {
- nds32->memory.mode = NDS_MEMORY_SELECT_AUTO;
- } else if (strcmp(CMD_ARGV[0], "mem") == 0) {
- nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
- } else if (strcmp(CMD_ARGV[0], "ilm") == 0) {
- if (nds32->memory.ilm_base == 0)
- command_print(CMD_CTX, "%s does not support ILM",
- target_name(target));
- else
- nds32->memory.mode = NDS_MEMORY_SELECT_ILM;
- } else if (strcmp(CMD_ARGV[0], "dlm") == 0) {
- if (nds32->memory.dlm_base == 0)
- command_print(CMD_CTX, "%s does not support DLM",
- target_name(target));
- else
- nds32->memory.mode = NDS_MEMORY_SELECT_DLM;
- }
-
- /* set to ACC_CTL */
- aice_memory_mode(aice, nds32->memory.mode);
- }
- }
-
- command_print(CMD_CTX, "%s: memory mode: %s",
- target_name(target),
- NDS_MEMORY_SELECT_NAME[nds32->memory.mode]);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_cache_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_cache *icache = &(nds32->memory.icache);
- struct nds32_cache *dcache = &(nds32->memory.dcache);
- int result;
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
-
- if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
- if ((dcache->line_size != 0) && (dcache->enable == true)) {
- /* D$ write back */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0);
- if (result != ERROR_OK) {
- command_print(CMD_CTX, "%s: Write back data cache...failed",
- target_name(target));
- return result;
- }
-
- command_print(CMD_CTX, "%s: Write back data cache...done",
- target_name(target));
-
- /* D$ invalidate */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0);
- if (result != ERROR_OK) {
- command_print(CMD_CTX, "%s: Invalidate data cache...failed",
- target_name(target));
- return result;
- }
-
- command_print(CMD_CTX, "%s: Invalidate data cache...done",
- target_name(target));
- } else {
- if (dcache->line_size == 0)
- command_print(CMD_CTX, "%s: No data cache",
- target_name(target));
- else
- command_print(CMD_CTX, "%s: Data cache disabled",
- target_name(target));
- }
-
- if ((icache->line_size != 0) && (icache->enable == true)) {
- /* I$ invalidate */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0);
- if (result != ERROR_OK) {
- command_print(CMD_CTX, "%s: Invalidate instruction cache...failed",
- target_name(target));
- return result;
- }
-
- command_print(CMD_CTX, "%s: Invalidate instruction cache...done",
- target_name(target));
- } else {
- if (icache->line_size == 0)
- command_print(CMD_CTX, "%s: No instruction cache",
- target_name(target));
- else
- command_print(CMD_CTX, "%s: Instruction cache disabled",
- target_name(target));
- }
- } else
- command_print(CMD_CTX, "No valid parameter");
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_icache_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_cache *icache = &(nds32->memory.icache);
- int result;
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
-
- if (icache->line_size == 0) {
- command_print(CMD_CTX, "%s: No instruction cache",
- target_name(target));
- return ERROR_OK;
- }
-
- if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
- if (icache->enable == true) {
- /* I$ invalidate */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0);
- if (result != ERROR_OK) {
- command_print(CMD_CTX, "%s: Invalidate instruction cache...failed",
- target_name(target));
- return result;
- }
-
- command_print(CMD_CTX, "%s: Invalidate instruction cache...done",
- target_name(target));
- } else {
- command_print(CMD_CTX, "%s: Instruction cache disabled",
- target_name(target));
- }
- } else if (strcmp(CMD_ARGV[0], "enable") == 0) {
- uint32_t value;
- nds32_get_mapped_reg(nds32, IR8, &value);
- nds32_set_mapped_reg(nds32, IR8, value | 0x1);
- } else if (strcmp(CMD_ARGV[0], "disable") == 0) {
- uint32_t value;
- nds32_get_mapped_reg(nds32, IR8, &value);
- nds32_set_mapped_reg(nds32, IR8, value & ~0x1);
- } else if (strcmp(CMD_ARGV[0], "dump") == 0) {
- /* TODO: dump cache content */
- } else {
- command_print(CMD_CTX, "%s: No valid parameter", target_name(target));
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_dcache_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_cache *dcache = &(nds32->memory.dcache);
- int result;
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
-
- if (dcache->line_size == 0) {
- command_print(CMD_CTX, "%s: No data cache", target_name(target));
- return ERROR_OK;
- }
-
- if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
- if (dcache->enable == true) {
- /* D$ write back */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0);
- if (result != ERROR_OK) {
- command_print(CMD_CTX, "%s: Write back data cache...failed",
- target_name(target));
- return result;
- }
-
- command_print(CMD_CTX, "%s: Write back data cache...done",
- target_name(target));
-
- /* D$ invalidate */
- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0);
- if (result != ERROR_OK) {
- command_print(CMD_CTX, "%s: Invalidate data cache...failed",
- target_name(target));
- return result;
- }
-
- command_print(CMD_CTX, "%s: Invalidate data cache...done",
- target_name(target));
- } else {
- command_print(CMD_CTX, "%s: Data cache disabled",
- target_name(target));
- }
- } else if (strcmp(CMD_ARGV[0], "enable") == 0) {
- uint32_t value;
- nds32_get_mapped_reg(nds32, IR8, &value);
- nds32_set_mapped_reg(nds32, IR8, value | 0x2);
- } else if (strcmp(CMD_ARGV[0], "disable") == 0) {
- uint32_t value;
- nds32_get_mapped_reg(nds32, IR8, &value);
- nds32_set_mapped_reg(nds32, IR8, value & ~0x2);
- } else if (strcmp(CMD_ARGV[0], "dump") == 0) {
- /* TODO: dump cache content */
- } else {
- command_print(CMD_CTX, "%s: No valid parameter", target_name(target));
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_auto_break_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->auto_convert_hw_bp = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->auto_convert_hw_bp = false;
- }
-
- if (nds32->auto_convert_hw_bp)
- command_print(CMD_CTX, "%s: convert sw break to hw break on ROM: on",
- target_name(target));
- else
- command_print(CMD_CTX, "%s: convert sw break to hw break on ROM: off",
- target_name(target));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_virtual_hosting_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->virtual_hosting = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->virtual_hosting = false;
- }
-
- if (nds32->virtual_hosting)
- command_print(CMD_CTX, "%s: virtual hosting: on", target_name(target));
- else
- command_print(CMD_CTX, "%s: virtual hosting: off", target_name(target));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_global_stop_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->global_stop = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->global_stop = false;
- }
-
- if (nds32->global_stop)
- LOG_INFO("%s: global stop: on", target_name(target));
- else
- LOG_INFO("%s: global stop: off", target_name(target));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_soft_reset_halt_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->soft_reset_halt = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->soft_reset_halt = false;
- }
-
- if (nds32->soft_reset_halt)
- LOG_INFO("%s: soft-reset-halt: on", target_name(target));
- else
- LOG_INFO("%s: soft-reset-halt: off", target_name(target));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_boot_time_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], nds32->boot_time);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_login_edm_passcode_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- nds32->edm_passcode = strdup(CMD_ARGV[0]);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_login_edm_operation_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 1) {
-
- uint32_t misc_reg_no;
- uint32_t data;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], misc_reg_no);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], data);
-
- if (nds32_edm_ops_num >= NDS32_EDM_OPERATION_MAX_NUM)
- return ERROR_FAIL;
-
- /* Just save the operation. Execute it in nds32_login() */
- nds32_edm_ops[nds32_edm_ops_num].reg_no = misc_reg_no;
- nds32_edm_ops[nds32_edm_ops_num].value = data;
- nds32_edm_ops_num++;
- } else
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_reset_halt_as_init_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->reset_halt_as_examine = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->reset_halt_as_examine = false;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_keep_target_edm_ctl_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->keep_target_edm_ctl = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->keep_target_edm_ctl = false;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_decode_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 1) {
-
- uint32_t addr;
- uint32_t insn_count;
- uint32_t opcode;
- uint32_t read_addr;
- uint32_t i;
- struct nds32_instruction instruction;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], insn_count);
-
- read_addr = addr;
- i = 0;
- while (i < insn_count) {
- if (ERROR_OK != nds32_read_opcode(nds32, read_addr, &opcode))
- return ERROR_FAIL;
- if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode,
- read_addr, &instruction))
- return ERROR_FAIL;
-
- command_print(CMD_CTX, "%s", instruction.text);
-
- read_addr += instruction.instruction_size;
- i++;
- }
- } else if (CMD_ARGC == 1) {
-
- uint32_t addr;
- uint32_t opcode;
- struct nds32_instruction instruction;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
-
- if (ERROR_OK != nds32_read_opcode(nds32, addr, &opcode))
- return ERROR_FAIL;
- if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, addr, &instruction))
- return ERROR_FAIL;
-
- command_print(CMD_CTX, "%s", instruction.text);
- } else
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_word_access_mem_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC > 0) {
- if (strcmp(CMD_ARGV[0], "on") == 0)
- nds32->word_access_mem = true;
- if (strcmp(CMD_ARGV[0], "off") == 0)
- nds32->word_access_mem = false;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_query_target_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- command_print(CMD_CTX, "OCD");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_query_endian_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- uint32_t value_psw;
- nds32_get_mapped_reg(nds32, IR0, &value_psw);
-
- if (value_psw & 0x20)
- command_print(CMD_CTX, "%s: BE", target_name(target));
- else
- command_print(CMD_CTX, "%s: LE", target_name(target));
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_nds32_query_cpuid_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct nds32 *nds32 = target_to_nds32(target);
-
- if (!is_nds32(nds32)) {
- command_print(CMD_CTX, "current target isn't an Andes core");
- return ERROR_FAIL;
- }
-
- command_print(CMD_CTX, "CPUID: %s", target_name(target));
-
- return ERROR_OK;
-}
-
-static int jim_nds32_bulk_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
-
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if (goi.argc < 3) {
- Jim_SetResultFormatted(goi.interp,
- "usage: %s <address> <count> <data>", cmd_name);
- return JIM_ERR;
- }
-
- int e;
- jim_wide address;
- e = Jim_GetOpt_Wide(&goi, &address);
- if (e != JIM_OK)
- return e;
-
- jim_wide count;
- e = Jim_GetOpt_Wide(&goi, &count);
- if (e != JIM_OK)
- return e;
-
- uint32_t *data = malloc(count * sizeof(uint32_t));
- if (data == NULL)
- return JIM_ERR;
-
- jim_wide i;
- for (i = 0; i < count; i++) {
- jim_wide tmp;
- e = Jim_GetOpt_Wide(&goi, &tmp);
- if (e != JIM_OK) {
- free(data);
- return e;
- }
- data[i] = (uint32_t)tmp;
- }
-
- /* all args must be consumed */
- if (goi.argc != 0) {
- free(data);
- return JIM_ERR;
- }
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- int result;
-
- result = target_write_buffer(target, address, count * 4, (const uint8_t *)data);
-
- free(data);
-
- return result;
-}
-
-static int jim_nds32_multi_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
-
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if (goi.argc < 3) {
- Jim_SetResultFormatted(goi.interp,
- "usage: %s # of pairs [<address> <data>]+", cmd_name);
- return JIM_ERR;
- }
-
- int e;
- jim_wide num_of_pairs;
- e = Jim_GetOpt_Wide(&goi, &num_of_pairs);
- if (e != JIM_OK)
- return e;
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- struct aice_port_s *aice = target_to_aice(target);
- int result;
- uint32_t address;
- uint32_t data;
- jim_wide i;
-
- aice_set_command_mode(aice, AICE_COMMAND_MODE_PACK);
- for (i = 0; i < num_of_pairs; i++) {
- jim_wide tmp;
- e = Jim_GetOpt_Wide(&goi, &tmp);
- if (e != JIM_OK)
- break;
- address = (uint32_t)tmp;
-
- e = Jim_GetOpt_Wide(&goi, &tmp);
- if (e != JIM_OK)
- break;
- data = (uint32_t)tmp;
-
- result = target_write_buffer(target, address, 4, (const uint8_t *)&data);
- if (result != ERROR_OK)
- break;
- }
- aice_set_command_mode(aice, AICE_COMMAND_MODE_NORMAL);
-
- /* all args must be consumed */
- if (goi.argc != 0)
- return JIM_ERR;
-
- return ERROR_OK;
-}
-
-static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
-
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if (goi.argc < 2) {
- Jim_SetResultFormatted(goi.interp,
- "usage: %s <address> <count>", cmd_name);
- return JIM_ERR;
- }
-
- int e;
- jim_wide address;
- e = Jim_GetOpt_Wide(&goi, &address);
- if (e != JIM_OK)
- return e;
-
- jim_wide count;
- e = Jim_GetOpt_Wide(&goi, &count);
- if (e != JIM_OK)
- return e;
-
- /* all args must be consumed */
- if (goi.argc != 0)
- return JIM_ERR;
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- uint32_t *data = malloc(count * sizeof(uint32_t));
- int result;
- result = target_read_buffer(target, address, count * 4, (uint8_t *)data);
- char data_str[11];
-
- jim_wide i;
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- for (i = 0; i < count; i++) {
- sprintf(data_str, "0x%08" PRIx32 " ", data[i]);
- Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL);
- }
-
- free(data);
-
- return result;
-}
-
-static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
-
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if (goi.argc < 1) {
- Jim_SetResultFormatted(goi.interp,
- "usage: %s <edm_sr_name>", cmd_name);
- return JIM_ERR;
- }
-
- int e;
- const char *edm_sr_name;
- int edm_sr_name_len;
- e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len);
- if (e != JIM_OK)
- return e;
-
- /* all args must be consumed */
- if (goi.argc != 0)
- return JIM_ERR;
-
- uint32_t edm_sr_number;
- uint32_t edm_sr_value;
- if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0)
- edm_sr_number = NDS_EDM_SR_EDM_DTR;
- else if (strncmp(edm_sr_name, "edmsw", edm_sr_name_len) == 0)
- edm_sr_number = NDS_EDM_SR_EDMSW;
- else
- return ERROR_FAIL;
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- struct aice_port_s *aice = target_to_aice(target);
- char data_str[11];
-
- aice_read_debug_reg(aice, edm_sr_number, &edm_sr_value);
-
- sprintf(data_str, "0x%08" PRIx32, edm_sr_value);
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL);
-
- return ERROR_OK;
-}
-
-static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
-
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if (goi.argc < 2) {
- Jim_SetResultFormatted(goi.interp,
- "usage: %s <edm_sr_name> <value>", cmd_name);
- return JIM_ERR;
- }
-
- int e;
- const char *edm_sr_name;
- int edm_sr_name_len;
- e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len);
- if (e != JIM_OK)
- return e;
-
- jim_wide value;
- e = Jim_GetOpt_Wide(&goi, &value);
- if (e != JIM_OK)
- return e;
-
- /* all args must be consumed */
- if (goi.argc != 0)
- return JIM_ERR;
-
- uint32_t edm_sr_number;
- if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0)
- edm_sr_number = NDS_EDM_SR_EDM_DTR;
- else
- return ERROR_FAIL;
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- struct aice_port_s *aice = target_to_aice(target);
-
- aice_write_debug_reg(aice, edm_sr_number, value);
-
- return ERROR_OK;
-}
-
-static const struct command_registration nds32_query_command_handlers[] = {
- {
- .name = "target",
- .handler = handle_nds32_query_target_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "reply 'OCD' for gdb to identify server-side is OpenOCD",
- },
- {
- .name = "endian",
- .handler = handle_nds32_query_endian_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "query target endian",
- },
- {
- .name = "cpuid",
- .handler = handle_nds32_query_cpuid_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "query CPU ID",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration nds32_exec_command_handlers[] = {
- {
- .name = "dssim",
- .handler = handle_nds32_dssim_command,
- .mode = COMMAND_EXEC,
- .usage = "['on'|'off']",
- .help = "display/change $INT_MASK.DSSIM status",
- },
- {
- .name = "mem_access",
- .handler = handle_nds32_memory_access_command,
- .mode = COMMAND_EXEC,
- .usage = "['bus'|'cpu']",
- .help = "display/change memory access channel",
- },
- {
- .name = "mem_mode",
- .handler = handle_nds32_memory_mode_command,
- .mode = COMMAND_EXEC,
- .usage = "['auto'|'mem'|'ilm'|'dlm']",
- .help = "display/change memory mode",
- },
- {
- .name = "cache",
- .handler = handle_nds32_cache_command,
- .mode = COMMAND_EXEC,
- .usage = "['invalidate']",
- .help = "cache control",
- },
- {
- .name = "icache",
- .handler = handle_nds32_icache_command,
- .mode = COMMAND_EXEC,
- .usage = "['invalidate'|'enable'|'disable'|'dump']",
- .help = "icache control",
- },
- {
- .name = "dcache",
- .handler = handle_nds32_dcache_command,
- .mode = COMMAND_EXEC,
- .usage = "['invalidate'|'enable'|'disable'|'dump']",
- .help = "dcache control",
- },
- {
- .name = "auto_break",
- .handler = handle_nds32_auto_break_command,
- .mode = COMMAND_EXEC,
- .usage = "['on'|'off']",
- .help = "convert software breakpoints to hardware breakpoints if needed",
- },
- {
- .name = "virtual_hosting",
- .handler = handle_nds32_virtual_hosting_command,
- .mode = COMMAND_ANY,
- .usage = "['on'|'off']",
- .help = "turn on/off virtual hosting",
- },
- {
- .name = "global_stop",
- .handler = handle_nds32_global_stop_command,
- .mode = COMMAND_ANY,
- .usage = "['on'|'off']",
- .help = "turn on/off global stop. After turning on, every load/store" \
- "instructions will be stopped to check memory access.",
- },
- {
- .name = "soft_reset_halt",
- .handler = handle_nds32_soft_reset_halt_command,
- .mode = COMMAND_ANY,
- .usage = "['on'|'off']",
- .help = "as issuing rest-halt, to use soft-reset-halt or not." \
- "the feature is for backward-compatible.",
- },
- {
- .name = "boot_time",
- .handler = handle_nds32_boot_time_command,
- .mode = COMMAND_CONFIG,
- .usage = "milliseconds",
- .help = "set the period to wait after srst.",
- },
- {
- .name = "login_edm_passcode",
- .handler = handle_nds32_login_edm_passcode_command,
- .mode = COMMAND_CONFIG,
- .usage = "passcode",
- .help = "set EDM passcode for secure MCU debugging.",
- },
- {
- .name = "login_edm_operation",
- .handler = handle_nds32_login_edm_operation_command,
- .mode = COMMAND_CONFIG,
- .usage = "login_edm_operation misc_reg_no value",
- .help = "add EDM operations for secure MCU debugging.",
- },
- {
- .name = "reset_halt_as_init",
- .handler = handle_nds32_reset_halt_as_init_command,
- .mode = COMMAND_CONFIG,
- .usage = "['on'|'off']",
- .help = "reset halt as openocd init.",
- },
- {
- .name = "keep_target_edm_ctl",
- .handler = handle_nds32_keep_target_edm_ctl_command,
- .mode = COMMAND_CONFIG,
- .usage = "['on'|'off']",
- .help = "Backup/Restore target EDM_CTL register.",
- },
- {
- .name = "decode",
- .handler = handle_nds32_decode_command,
- .mode = COMMAND_EXEC,
- .usage = "address icount",
- .help = "decode instruction.",
- },
- {
- .name = "word_access_mem",
- .handler = handle_nds32_word_access_mem_command,
- .mode = COMMAND_ANY,
- .usage = "['on'|'off']",
- .help = "Always use word-aligned address to access memory.",
- },
- {
- .name = "bulk_write",
- .jim_handler = jim_nds32_bulk_write,
- .mode = COMMAND_EXEC,
- .help = "Write multiple 32-bit words to target memory",
- .usage = "address count data",
- },
- {
- .name = "multi_write",
- .jim_handler = jim_nds32_multi_write,
- .mode = COMMAND_EXEC,
- .help = "Write multiple addresses/words to target memory",
- .usage = "num_of_pairs [address data]+",
- },
- {
- .name = "bulk_read",
- .jim_handler = jim_nds32_bulk_read,
- .mode = COMMAND_EXEC,
- .help = "Read multiple 32-bit words from target memory",
- .usage = "address count",
- },
- {
- .name = "read_edmsr",
- .jim_handler = jim_nds32_read_edm_sr,
- .mode = COMMAND_EXEC,
- .help = "Read EDM system register",
- .usage = "['edmsw'|'edm_dtr']",
- },
- {
- .name = "write_edmsr",
- .jim_handler = jim_nds32_write_edm_sr,
- .mode = COMMAND_EXEC,
- .help = "Write EDM system register",
- .usage = "['edm_dtr'] value",
- },
- {
- .name = "query",
- .mode = COMMAND_EXEC,
- .help = "Andes query command group",
- .usage = "",
- .chain = nds32_query_command_handlers,
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration nds32_command_handlers[] = {
- {
- .name = "nds",
- .mode = COMMAND_ANY,
- .help = "Andes command group",
- .usage = "",
- .chain = nds32_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
diff --git a/src/target/nds32_cmd.h b/src/target/nds32_cmd.h
deleted file mode 100644
index 543ba54..0000000
--- a/src/target/nds32_cmd.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_CMD_H
-#define OPENOCD_TARGET_NDS32_CMD_H
-
-#include <helper/command.h>
-
-extern const struct command_registration nds32_command_handlers[];
-
-#endif /* OPENOCD_TARGET_NDS32_CMD_H */
diff --git a/src/target/nds32_disassembler.c b/src/target/nds32_disassembler.c
deleted file mode 100644
index f27aba2..0000000
--- a/src/target/nds32_disassembler.c
+++ /dev/null
@@ -1,3858 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include <target/target.h>
-#include "nds32_disassembler.h"
-
-static const int enable4_bits[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
-
-int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value)
-{
- struct target *target = nds32->target;
- uint8_t value_buf[4];
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- int retval = target_read_buffer(target, address, 4, value_buf);
-
- if (retval == ERROR_OK) {
- /* instructions are always big-endian */
- *value = be_to_h_u32(value_buf);
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
- address,
- *value);
- } else {
- *value = 0x0;
- LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
- address);
- }
-
- return retval;
-}
-
-static int nds32_parse_type_0(uint32_t opcode, int32_t *imm)
-{
- *imm = opcode & 0x1FFFFFF;
-
- return ERROR_OK;
-}
-
-static int nds32_parse_type_1(uint32_t opcode, uint8_t *rt, int32_t *imm)
-{
- *rt = (opcode >> 20) & 0x1F;
- *imm = opcode & 0xFFFFF;
-
- return ERROR_OK;
-}
-
-static int nds32_parse_type_2(uint32_t opcode, uint8_t *rt, uint8_t *ra, int32_t *imm)
-{
- *rt = (opcode >> 20) & 0x1F;
- *ra = (opcode >> 15) & 0x1F;
- *imm = opcode & 0x7FFF;
-
- return ERROR_OK;
-}
-
-static int nds32_parse_type_3(uint32_t opcode, uint8_t *rt, uint8_t *ra,
- uint8_t *rb, int32_t *imm)
-{
- *rt = (opcode >> 20) & 0x1F;
- *ra = (opcode >> 15) & 0x1F;
- *rb = (opcode >> 10) & 0x1F;
- *imm = opcode & 0x3FF;
-
- return ERROR_OK;
-}
-
-static int nds32_parse_type_4(uint32_t opcode, uint8_t *rt, uint8_t *ra,
- uint8_t *rb, uint8_t *rd, uint8_t *sub_opc)
-{
- *rt = (opcode >> 20) & 0x1F;
- *ra = (opcode >> 15) & 0x1F;
- *rb = (opcode >> 10) & 0x1F;
- *rd = (opcode >> 5) & 0x1F;
- *sub_opc = opcode & 0x1F;
-
- return ERROR_OK;
-}
-
-/* LBI, LHI, LWI, LBI.bi, LHI.bi, LWI.bi */
-static int nds32_parse_group_0_insn(struct nds32 *nds32, uint32_t opcode,
- uint32_t address,
- struct nds32_instruction *instruction)
-{
- uint8_t opc_6;
-
- opc_6 = instruction->info.opc_6;
-
- switch (opc_6 & 0x7) {
- case 0: /* LBI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 1: /* LHI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 2: /* LWI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLWI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 4: /* LBI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 5: /* LHI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 6: /* LWI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLWI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32 "",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_1_insn(struct nds32 *nds32, uint32_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- uint8_t opc_6;
-
- opc_6 = instruction->info.opc_6;
-
- switch (opc_6 & 0x7) {
- case 0: /* SBI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSBI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 1: /* SHI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSHI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 2: /* SWI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSWI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 4: /* SBI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSBI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 5: /* SHI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSHI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 6: /* SWI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSWI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_2_insn(struct nds32 *nds32, uint32_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- uint8_t opc_6;
-
- opc_6 = instruction->info.opc_6;
-
- switch (opc_6 & 0x7) {
- case 0: /* LBSI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBSI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 1: /* LHSI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHSI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 3: { /* DPREFI */
- uint8_t sub_type;
- nds32_parse_type_2(opcode, &sub_type, &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->info.sub_opc = sub_type & 0xF;
- instruction->type = NDS32_INSN_MISC;
- if (sub_type & 0x10) { /* DPREFI.d */
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 17) >> 14;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tDPREFI.d\t%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.sub_opc,
- instruction->info.ra, instruction->info.imm);
- } else { /* DPREFI.w */
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 17) >> 15;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tDPREFI.w\t%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
- address,
- opcode, instruction->info.sub_opc,
- instruction->info.ra, instruction->info.imm);
- }
- }
- break;
- case 4: /* LBSI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBSI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 5: /* LHSI.bi */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHSI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 6: /* LBGP */
- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- if ((instruction->info.imm >> 19) & 0x1) { /* LBSI.gp */
- instruction->info.imm = (instruction->info.imm << 13) >> 13;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBSI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- } else { /* LBI.gp */
- instruction->info.imm = (instruction->info.imm << 13) >> 13;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_mem(struct nds32 *nds32, uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- uint32_t sub_opcode = opcode & 0x3F;
- uint32_t val_ra, val_rb;
- switch (sub_opcode >> 3) {
- case 0:
- switch (sub_opcode & 0x7) {
- case 0: /* LB */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra), \
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLB\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 1: /* LH */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLH\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 2: /* LW */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 4: /* LB.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLB.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt,
- instruction->info.ra, instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 5: /* LH.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLH.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 6: /* LW.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLW.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- }
- break;
- case 1:
- switch (sub_opcode & 0x7) {
- case 0: /* SB */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSB\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt,
- instruction->info.ra, instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 1: /* SH */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSH\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 2: /* SW */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt,
- instruction->info.ra, instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 4: /* SB.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSB.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 5: /* SH.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSH.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 6: /* SW.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSW.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- }
- break;
- case 2:
- switch (sub_opcode & 0x7) {
- case 0: /* LBS */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBS\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt,
- instruction->info.ra, instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 1: /* LHS */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHS\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 3: /* DPREF */
- nds32_parse_type_3(opcode, &(instruction->info.sub_opc),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tDPREF\t#%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<#%" PRId32 ")]",
- address,
- opcode, instruction->info.sub_opc,
- instruction->info.ra, instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 4: /* LBS.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBS.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 5: /* LHS.bi */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHS.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- }
- break;
- case 3:
- switch (sub_opcode & 0x7) {
- case 0: /* LLW */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLLW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 1: /* SCW */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSCW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- }
- break;
- case 4:
- switch (sub_opcode & 0x7) {
- case 0: /* LBUP */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLBUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 2: /* LWUP */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLWUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- }
- break;
- case 5:
- switch (sub_opcode & 0x7) {
- case 0: /* SBUP */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSBUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- case 2: /* SWUP */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
- instruction->access_start = val_ra +
- (val_rb << ((instruction->info.imm >> 8) & 0x3));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSWUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- (instruction->info.imm >> 8) & 0x3);
- break;
- }
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_calculate_lsmw_access_range(struct nds32 *nds32,
- struct nds32_instruction *instruction)
-{
- uint8_t ba;
- uint8_t id;
- uint8_t enable4;
-
- enable4 = (instruction->info.imm >> 6) & 0xF;
- ba = (instruction->info.imm >> 4) & 0x1;
- id = (instruction->info.imm >> 3) & 0x1;
-
- if (ba) {
- nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start));
- if (id) { /* decrease */
- /* access_end is the (last_element+1), so no need to minus 4 */
- /* instruction->access_end -= 4; */
- instruction->access_end = instruction->access_start;
- } else { /* increase */
- instruction->access_start += 4;
- }
- } else {
- nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start));
- instruction->access_end = instruction->access_start - 4;
- }
-
- if (id) { /* decrease */
- instruction->access_start = instruction->access_end -
- 4 * (instruction->info.rd - instruction->info.rb + 1);
- instruction->access_start -= (4 * enable4_bits[enable4]);
- } else { /* increase */
- instruction->access_end = instruction->access_start +
- 4 * (instruction->info.rd - instruction->info.rb + 1);
- instruction->access_end += (4 * enable4_bits[enable4]);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_lsmw(struct nds32 *nds32, uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- if (opcode & 0x20) { /* SMW, SMWA, SMWZB */
- switch (opcode & 0x3) {
- /* TODO */
- case 0: /* SMW */
- /* use rd as re */
- nds32_parse_type_3(opcode, &(instruction->info.rb),
- &(instruction->info.ra),
- &(instruction->info.rd), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_calculate_lsmw_access_range(nds32, instruction);
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSMW\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rb, instruction->info.ra,
- instruction->info.rd,
- (instruction->info.imm >> 6) & 0xF);
- break;
- case 1: /* SMWA */
- nds32_parse_type_3(opcode, &(instruction->info.rb),
- &(instruction->info.ra),
- &(instruction->info.rd), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_calculate_lsmw_access_range(nds32, instruction);
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSMWA\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rb, instruction->info.ra,
- instruction->info.rd,
- (instruction->info.imm >> 6) & 0xF);
- break;
- case 2: /* SMWZB */
- nds32_parse_type_3(opcode, &(instruction->info.rb),
- &(instruction->info.ra),
- &(instruction->info.rd), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- /* TODO: calculate access_start/access_end */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSMWZB\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rb, instruction->info.ra,
- instruction->info.rd,
- (instruction->info.imm >> 6) & 0xF);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
- } else { /* LMW, LMWA, LMWZB */
- switch (opcode & 0x3) {
- case 0: /* LMW */
- nds32_parse_type_3(opcode, &(instruction->info.rb),
- &(instruction->info.ra),
- &(instruction->info.rd), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_calculate_lsmw_access_range(nds32, instruction);
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLMW\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rb, instruction->info.ra,
- instruction->info.rd,
- (instruction->info.imm >> 6) & 0xF);
- break;
- case 1: /* LMWA */
- nds32_parse_type_3(opcode, &(instruction->info.rb),
- &(instruction->info.ra),
- &(instruction->info.rd), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_calculate_lsmw_access_range(nds32, instruction);
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLMWA\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rb, instruction->info.ra,
- instruction->info.rd,
- (instruction->info.imm >> 6) & 0xF);
- break;
- case 2: /* LMWZB */
- nds32_parse_type_3(opcode, &(instruction->info.rb),
- &(instruction->info.ra),
- &(instruction->info.rd), &(instruction->info.imm));
- instruction->type = NDS32_INSN_LOAD_STORE;
- /* TODO: calculate access_start/access_end */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLMWZB\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rb, instruction->info.ra,
- instruction->info.rd,
- (instruction->info.imm >> 6) & 0xF);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_hwgp(struct nds32 *nds32, uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- switch ((opcode >> 18) & 0x3) {
- case 0: /* LHI.gp */
- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHI.gp\t$r%" PRIu8 ",[#%" PRId32"]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 1: /* LHSI.gp */
- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLHSI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 2: /* SHI.gp */
- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSHI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 3:
- instruction->type = NDS32_INSN_LOAD_STORE;
- if ((opcode >> 17) & 0x1) { /* SWI.gp */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 15) >> 13;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSWI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- } else { /* LWI.gp */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 15) >> 13;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tLWI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
-
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_sbgp(struct nds32 *nds32, uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- switch ((opcode >> 19) & 0x1) {
- case 0: /* SBI.gp */
- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSBI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 1: /* ADDI.gp */
- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tADDI.gp\t$r%" PRIu8 ",#%" PRId32 "",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_3_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- uint8_t opc_6;
-
- opc_6 = instruction->info.opc_6;
-
- switch (opc_6 & 0x7) {
- case 4: /* MEM */
- nds32_parse_mem(nds32, opcode, address, instruction);
- break;
- case 5: /* LSMW */
- nds32_parse_lsmw(nds32, opcode, address, instruction);
- break;
- case 6: /* HWGP */
- nds32_parse_hwgp(nds32, opcode, address, instruction);
- break;
- case 7: /* SBGP */
- nds32_parse_sbgp(nds32, opcode, address, instruction);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_alu_1(uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- switch (opcode & 0x1F) {
- case 0: /* ADD */
- nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tADD_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tADD\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 1: /* SUB */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSUB_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSUB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 "",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 2: /* AND */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tAND_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tAND\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 "",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 3: /* XOR */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tXOR_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tXOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 4: /* OR */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tOR_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 5: /* NOR */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tNOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 6: /* SLT */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSLT\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 7: /* SLTS */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSLTS\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 8: { /* SLLI */
- uint8_t imm;
- int32_t sub_op;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &sub_op);
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSLLI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 9: { /* SRLI */
- uint8_t imm;
- int32_t sub_op;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &sub_op);
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSRLI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 10: { /* SRAI */
- uint8_t imm;
- int32_t sub_op;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &sub_op);
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSRAI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 11: { /* ROTRI */
- uint8_t imm;
- int32_t sub_op;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &sub_op);
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tROTRI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 12: { /* SLL */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSLL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 13: { /* SRL */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSRL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 14: { /* SRA */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSRA\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 15: { /* ROTR */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tROTR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 16: { /* SEB */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSEB\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- }
- break;
- case 17: { /* SEH */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSEH\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- }
- break;
- case 18: /* BITC */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBITC\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 19: { /* ZEH */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tZEH\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- }
- break;
- case 20: { /* WSBH */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tWSBH\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- }
- break;
- case 21: /* OR_SRLI */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tOR_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 22: { /* DIVSR */
- nds32_parse_type_4(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.rd),
- &(instruction->info.sub_opc));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tDIVSR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.rd);
- }
- break;
- case 23: { /* DIVR */
- nds32_parse_type_4(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.rd),
- &(instruction->info.sub_opc));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tDIVR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.rd);
- }
- break;
- case 24: { /* SVA */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSVA\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 25: { /* SVS */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSVS\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 26: { /* CMOVZ */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tCMOVZ\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 27: { /* CMOVN */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tCMOVN\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 28: /* ADD_SRLI */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tADD_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tADD\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 29: /* SUB_SRLI */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSUB_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSUB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 30: /* AND_SRLI */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tAND_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tAND\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 31: /* XOR_SRLI */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
- if (instruction->info.imm)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tXOR_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb,
- instruction->info.imm);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tXOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_alu_2(uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- switch (opcode & 0x3F) {
- case 0: /* MAX */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMAX\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 1: /* MIN */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMIN\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 2: /* AVE */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tAVE\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 3: /* ABS */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tAVE\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 4: { /* CLIPS */
- uint8_t imm;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &(instruction->info.imm));
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tCLIPS\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 5: { /* CLIP */
- uint8_t imm;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &(instruction->info.imm));
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tCLIP\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 6: /* CLO */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tCLO\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 7: /* CLZ */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tCLZ\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 8: { /* BSET */
- uint8_t imm;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &(instruction->info.imm));
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBSET\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 9: { /* BCLR */
- uint8_t imm;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &(instruction->info.imm));
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBCLR\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 10: { /* BTGL */
- uint8_t imm;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &(instruction->info.imm));
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBTGL\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 11: { /* BTST */
- uint8_t imm;
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &imm, &(instruction->info.imm));
- instruction->info.imm = imm;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBTST\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- case 12: /* BSE */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBSE\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 13: /* BSP */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBSP\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 14: /* FFB */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tFFB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 15: /* FFMISM */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tFFMISM\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 23: /* FFZMISM */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tFFZMISM\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 32: /* MFUSR */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMFUSR\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt,
- (instruction->info.imm >> 10) & 0x3FF);
- break;
- case 33: /* MTUSR */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMTUSR\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt,
- (instruction->info.imm >> 10) & 0x3FF);
- break;
- case 36: /* MUL */
- nds32_parse_type_3(opcode, &(instruction->info.rt),
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMUL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- break;
- case 40: { /* MULTS64 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val,
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMULTS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 41: { /* MULT64 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val,
- &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMULT64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 42: { /* MADDS64 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMADDS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 43: { /* MADD64 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMADD64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 44: { /* MSUBS64 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMSUBS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 45: { /* MSUB64 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMSUB64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 46: { /* DIVS */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tDIVS\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 47: { /* DIV */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tDIV\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 49: { /* MULT32 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMULT32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 51: { /* MADD32 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMADD32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 53: { /* MSUB32 */
- uint8_t dt_val;
- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
- &(instruction->info.rb), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMSUB32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
- instruction->info.rb);
- }
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_4_insn(struct nds32 *nds32, uint32_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- uint8_t opc_6;
-
- opc_6 = instruction->info.opc_6;
-
- switch (opc_6 & 0x7) {
- case 0: /* ALU_1 */
- nds32_parse_alu_1(opcode, address, instruction);
- break;
- case 1: /* ALU_2 */
- nds32_parse_alu_2(opcode, address, instruction);
- break;
- case 2: /* MOVI */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 12) >> 12;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMOVI\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 3: /* SETHI */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSETHI\t$r%" PRIu8 ",0x%8.8" PRIx32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 4: /* JI */
- nds32_parse_type_0(opcode, &(instruction->info.imm));
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 8) >> 8;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- if ((instruction->info.imm >> 24) & 0x1) { /* JAL */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tJAL\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- } else { /* J */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tJ\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- }
- break;
- case 5: { /* JREG */
- int32_t imm;
- nds32_parse_type_0(opcode, &imm);
- instruction->info.rb = (imm >> 10) & 0x1F;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- switch (imm & 0x1F) {
- /* TODO */
- case 0: /* JR */
- if (imm & 0x20) { /* RET */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tRET\t$r%" PRIu8,
- address,
- opcode, instruction->info.rb);
- } else { /* JR */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tJR\t$r%" PRIu8,
- address,
- opcode, instruction->info.rb);
- }
- break;
- case 1: /* JRAL */
- instruction->info.rt = (imm >> 20) & 0x1F;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tJRAL\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.rb);
- break;
- case 2: /* JRNEZ */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tJRNEZ\t$r%" PRIu8,
- address,
- opcode, instruction->info.rb);
- break;
- case 3: /* JRALNEZ */
- instruction->info.rt = (imm >> 20) & 0x1F;
- if (instruction->info.rt == R30)
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tJRALNEZ\t$r%" PRIu8,
- address,
- opcode, instruction->info.rb);
- else
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tJRALNEZ\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode,
- instruction->info.rt,
- instruction->info.rb);
- break;
- }
- }
- break;
- case 6: { /* BR1 */
- int32_t imm;
-
- nds32_parse_type_0(opcode, &imm);
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- if ((imm >> 14) & 0x1) { /* BNE */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 18) >> 18;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBNE\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- } else { /* BEQ */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- /* sign-extend */
- instruction->info.imm = (instruction->info.imm << 18) >> 18;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBEQ\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt,
- instruction->info.ra,
- instruction->info.imm);
- }
- }
- break;
- case 7: { /* BR2 */
- int32_t imm;
-
- nds32_parse_type_0(opcode, &imm);
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- switch ((imm >> 16) & 0xF) {
- case 2: /* BEQZ */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBEQZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 3: /* BNEZ */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBNEZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 4: /* BGEZ */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBGEZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 5: /* BLTZ */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBLTZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 6: /* BGTZ */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBGTZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 7: /* BLEZ */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBLEZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 12: /* BGEZAL */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBGEZAL\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 13: /* BLTZAL */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 16) >> 16;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBLTZAL\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- }
- }
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_5_insn(struct nds32 *nds32, uint32_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- uint8_t opc_6;
-
- opc_6 = instruction->info.opc_6;
-
- switch (opc_6 & 0x7) {
- case 0: /* ADDI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tADDI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 1: /* SUBRI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSUBRI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 2: /* ANDI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tANDI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 3: /* XORI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tXORI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 4: /* ORI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tORI\t$r%" PRIu8 ",$r%" PRIu8 ",0x%8.8" PRIx32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 6: /* SLTI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSLTI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 7: /* SLTSI */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSLTSI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_6_insn(struct nds32 *nds32, uint32_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- uint8_t opc_6;
-
- opc_6 = instruction->info.opc_6;
-
- switch (opc_6 & 0x7) {
- case 2: { /* MISC */
- int32_t imm;
- uint8_t sub_opc;
-
- nds32_parse_type_0(opcode, &imm);
-
- sub_opc = imm & 0x1F;
- switch (sub_opc) {
- case 0: /* STANDBY */
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSTANDBY\t#%" PRIu32,
- address,
- opcode, (opcode >> 5) & 0x3);
- break;
- case 1: /* CCTL */
- /* TODO */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCCTL",
- address,
- opcode);
- break;
- case 2: /* MFSR */
- nds32_parse_type_1(opcode, &(instruction->info.rt),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMFSR\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt,
- (instruction->info.imm >> 10) & 0x3FF);
- break;
- case 3: /* MTSR */
- nds32_parse_type_1(opcode, &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMTSR\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.ra,
- (instruction->info.imm >> 10) & 0x3FF);
- break;
- case 4: /* IRET */
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tIRET",
- address,
- opcode);
- break;
- case 5: /* TRAP */
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tTRAP\t#%" PRId32,
- address,
- opcode, (imm >> 5) & 0x7FFF);
- break;
- case 6: /* TEQZ */
- nds32_parse_type_1(opcode, &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tTEQZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.ra,
- (instruction->info.imm >> 5) & 0x7FFF);
- break;
- case 7: /* TNEZ */
- nds32_parse_type_1(opcode, &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tTNEZ\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.ra,
- (instruction->info.imm >> 5) & 0x7FFF);
- break;
- case 8: /* DSB */
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB",
- address,
- opcode);
- break;
- case 9: /* ISB */
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB",
- address,
- opcode);
- break;
- case 10: /* BREAK */
- instruction->type = NDS32_INSN_MISC;
- instruction->info.sub_opc = imm & 0x1F;
- instruction->info.imm = (imm >> 5) & 0x7FFF;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tBREAK\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- break;
- case 11: /* SYSCALL */
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tSYSCALL\t#%" PRId32,
- address,
- opcode, (imm >> 5) & 0x7FFF);
- break;
- case 12: /* MSYNC */
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tMSYNC\t#%" PRId32,
- address,
- opcode, (imm >> 5) & 0x7);
- break;
- case 13: /* ISYNC */
- nds32_parse_type_1(opcode, &(instruction->info.ra),
- &(instruction->info.imm));
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
- "\tISYNC\t$r%" PRIu8,
- address,
- opcode, instruction->info.ra);
- break;
- case 14: /* TLBOP */
- /* TODO */
- nds32_parse_type_2(opcode, &(instruction->info.rt),
- &(instruction->info.ra), &(instruction->info.imm));
- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tTLBOP",
- address,
- opcode);
- break;
- }
-
- break;
- }
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static uint32_t field_mask[9] = {
- 0x0,
- 0x1,
- 0x3,
- 0x7,
- 0xF,
- 0x1F,
- 0x3F,
- 0x7F,
- 0xFF,
-};
-
-static uint8_t nds32_extract_field_8u(uint16_t opcode, uint32_t start, uint32_t length)
-{
- if (0 < length && length < 9)
- return (opcode >> start) & field_mask[length];
-
- return 0;
-}
-
-static int nds32_parse_group_0_insn_16(struct nds32 *nds32, uint16_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- switch ((opcode >> 10) & 0x7) {
- case 0: /* MOV55 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 5);
- instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tMOV55\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 1: /* MOVI55 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 5);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
- instruction->info.imm = (instruction->info.imm << 27) >> 27;
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tMOVI55\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 2: /* ADD45, SUB45 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADD45 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tADD45\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.rb);
- } else { /* SUB45 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSUB45\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.rb);
- }
-
- break;
- case 3: /* ADDI45, SUBI45 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADDI45 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tADDI45\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- } else { /* SUBI45 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSUBI45\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
- break;
- case 4: /* SRAI45, SRLI45 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* SRAI45 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSRAI45\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- } else { /* SRLI45 */
- if ((instruction->info.rt == 0) && (instruction->info.imm == 0)) {
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tNOP",
- address,
- opcode);
- } else {
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSRLI45\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
- }
- break;
- case 5:
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->type = NDS32_INSN_DATA_PROC;
- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* SLLI333 */
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSLLI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- } else {
- instruction->info.sub_opc = nds32_extract_field_8u(opcode, 0, 3);
- switch (instruction->info.sub_opc) {
- case 0: /* ZEB33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tZEB33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 1: /* ZEH33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tZEH33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 2: /* SEB33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSEB33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 3: /* SEH33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSEH33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 4: /* XLSB33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tXLSB33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 5: /* XLLB33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tXLLB33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 6: /* BMSKI33 */
- instruction->info.ra = 0;
- instruction->info.imm = nds32_extract_field_8u(opcode, 3, 3);
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBMSKI33\t$r%" PRIu8 ",$r%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 7: /* FEXTI33 */
- instruction->info.ra = 0;
- instruction->info.imm = nds32_extract_field_8u(opcode, 3, 3);
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tFEXTI33\t$r%" PRIu8 ",$r%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16
- "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
- }
- break;
- case 6: /* ADD333, SUB333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 3);
- instruction->type = NDS32_INSN_DATA_PROC;
- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADD333 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tADD333\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- } else { /* SUB333 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSUB333\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.rb);
- }
- break;
- case 7: /* ADDI333, SUBI333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
- instruction->type = NDS32_INSN_DATA_PROC;
- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADDI333 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tADDI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- } else { /* SUBI333 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSUBI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- }
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_1_insn_16(struct nds32 *nds32, uint16_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- switch ((opcode >> 9) & 0xF) {
- case 0: /* LWI333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLWI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 1: /* LWI333.BI */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLWI333.BI\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm << 2);
- break;
- case 2: /* LHI333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 1;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 3: /* LBI333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLBI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 4: /* SWI333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSWI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 5: /* SWI333.BI */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSWI333.BI\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 6: /* SHI333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 1;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 2;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 7: /* SBI333 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 1;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
- address,
- opcode, instruction->info.rt, instruction->info.ra,
- instruction->info.imm);
- break;
- case 8: /* ADDRI36.SP */
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 6) << 2;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tADDRI36.SP\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 9: /* LWI45.FE */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
- instruction->info.imm -= 32;
- instruction->info.imm <<= 2;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, R8, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLWI45.FE\t$r%" PRIu8 ",[#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 10: /* LWI450 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLWI450\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 11: /* SWI450 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, instruction->info.ra,
- &(instruction->access_start));
- instruction->access_end = instruction->access_start + 4;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSWI450\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 12:
- case 13:
- case 14:
- case 15: /* LWI37, SWI37 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 7) << 2;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, R28, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- if (nds32_extract_field_8u(opcode, 7, 1) == 0) { /* LWI37 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLWI37\t$r%" PRIu8 ",[fp+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- } else { /* SWI37 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSWI37\t$r%" PRIu8 ",[fp+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
- break;
- default: /* ERROR */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_2_insn_16(struct nds32 *nds32, uint16_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- switch ((opcode >> 11) & 0x3) {
- case 0: /* BEQZ38 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
- instruction->info.imm = (instruction->info.imm << 24) >> 24;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBEQZ38\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 1: /* BNEZ38 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
- instruction->info.imm = (instruction->info.imm << 24) >> 24;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBNEZ38\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 2: /* BEQS38,J8 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
- instruction->info.imm = (instruction->info.imm << 24) >> 24;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- if (instruction->info.rt == 5) { /* J8 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tJ8\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- } else { /* BEQS38 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBEQS38\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
- break;
- case 3: /* BNES38, JR5, RET5, JRAL5 */
- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
- instruction->info.imm = (instruction->info.imm << 24) >> 24;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- if (instruction->info.rt == 5) {
- instruction->info.imm = 0;
- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
- switch (nds32_extract_field_8u(opcode, 5, 3)) {
- case 0: /* JR5 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tJR5\t$r%" PRIu8,
- address,
- opcode, instruction->info.rb);
- break;
- case 1: /* JRAL5 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tJRAL5\t$r%" PRIu8,
- address,
- opcode, instruction->info.rb);
- break;
- case 2: /* EX9.IT */
- instruction->info.rb = 0;
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
- /* TODO: implement real instruction semantics */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tEX9.IT\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- break;
- case 4: /* RET5 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tRET5\t$r%" PRIu8,
- address,
- opcode, instruction->info.rb);
- break;
- case 5: /* ADD5.PC */
- instruction->info.rt = 0;
- instruction->info.rt = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tADD5.PC\t$r%" PRIu8,
- address,
- opcode, instruction->info.rt);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16
- "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
- } else { /* BNES38 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBNES38\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
- break;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_parse_group_3_insn_16(struct nds32 *nds32, uint16_t opcode,
- uint32_t address, struct nds32_instruction *instruction)
-{
- switch ((opcode >> 11) & 0x3) {
- case 0:
- switch ((opcode >> 9) & 0x3) {
- case 0: /* SLTS45 */
- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSLTS45\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.ra, instruction->info.rb);
- break;
- case 1: /* SLT45 */
- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSLT45\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.ra, instruction->info.rb);
- break;
- case 2: /* SLTSI45 */
- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSLTSI45\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.ra, instruction->info.imm);
- break;
- case 3: /* SLTI45 */
- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSLTI45\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.ra, instruction->info.imm);
- break;
- }
- break;
- case 1:
- switch ((opcode >> 9) & 0x3) {
- case 0:
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
- instruction->info.imm = (instruction->info.imm << 24) >> 24;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- if (nds32_extract_field_8u(opcode, 8, 1) == 0) { /* BEQZS8 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBEQZS8\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- } else { /* BNEZS8 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBNEZS8\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- }
- break;
- case 1: /* BREAK16 */
- if (((opcode >> 5) & 0xF) == 0) {
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tBREAK16\t#%" PRId16,
- address,
- opcode, (int16_t)(opcode & 0x1F));
- } else { /* EX9.IT */
- instruction->type = NDS32_INSN_MISC;
- /* TODO: implement real instruction semantics */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tEX9.IT\t#%" PRId16,
- address,
- opcode, (int16_t)(opcode & 0x1FF));
- }
- break;
- case 2: /* ADDI10S */
- case 3:
- instruction->info.imm = opcode & 0x3FF;
- instruction->info.imm = (instruction->info.imm << 22) >> 22;
- instruction->type = NDS32_INSN_DATA_PROC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tADDI10.SP\t#%" PRId32,
- address,
- opcode, instruction->info.imm);
- break;
- }
- break;
- case 2:
- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 7) << 2;
- instruction->type = NDS32_INSN_LOAD_STORE;
- nds32_get_mapped_reg(nds32, R31, &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end = instruction->access_start + 4;
- if (nds32_extract_field_8u(opcode, 7, 1) == 0) { /* LWI37.SP */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tLWI37.SP\t$r%" PRIu8 ",[+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- } else { /* SWI37.SP */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tSWI37.SP\t$r%" PRIu8 ",[+#%" PRId32 "]",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- }
- break;
- case 3:
- switch ((opcode >> 9) & 0x3) {
- case 0: /* IFCALL9 */
- instruction->info.imm = opcode & 0x1FF;
- instruction->type = NDS32_INSN_JUMP_BRANCH;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tIFCALL9\t#%" PRId32 "",
- address,
- opcode, instruction->info.imm);
- break;
- case 1: /* MOVPI45 */
- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5) + 16;
- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tMOVPI45\t$r%" PRIu8 ",#%" PRId32 "",
- address,
- opcode, instruction->info.rt, instruction->info.imm);
- break;
- case 2: /* PUSH25, POP25, MOVD44 */
- switch ((opcode >> 7) & 0x3) {
- case 0: /* PUSH25 */
- {
- uint8_t re;
- uint8_t gpr_count;
-
- instruction->type = NDS32_INSN_LOAD_STORE;
- instruction->info.imm =
- nds32_extract_field_8u(opcode, 0, 5) << 3;
- re = nds32_extract_field_8u(opcode, 5, 2);
-
- if (re == 0)
- re = 6;
- else if (re == 1)
- re = 8;
- else if (re == 2)
- re = 10;
- else if (re == 3)
- re = 14;
-
- instruction->info.rd = re;
- /* GPRs list: R6 ~ Re and fp, gp, lp */
- gpr_count = 3 + (re - 5);
-
- nds32_get_mapped_reg(nds32, R31,
- &(instruction->access_end));
- instruction->access_start =
- instruction->access_end - (gpr_count * 4);
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tPUSH25\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rd,
- instruction->info.imm);
- }
- break;
- case 1: /* POP25 */
- {
- uint8_t re;
- uint8_t gpr_count;
-
- instruction->type = NDS32_INSN_LOAD_STORE;
- instruction->info.imm =
- nds32_extract_field_8u(opcode, 0, 5) << 3;
- re = nds32_extract_field_8u(opcode, 5, 2);
-
- if (re == 0)
- re = 6;
- else if (re == 1)
- re = 8;
- else if (re == 2)
- re = 10;
- else if (re == 3)
- re = 14;
-
- instruction->info.rd = re;
- /* GPRs list: R6 ~ Re and fp, gp, lp */
- gpr_count = 3 + (re - 5);
-
- nds32_get_mapped_reg(nds32, R31,
- &(instruction->access_start));
- instruction->access_start += instruction->info.imm;
- instruction->access_end =
- instruction->access_start + (gpr_count * 4);
-
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tPOP25\t$r%" PRIu8 ",#%" PRId32,
- address,
- opcode, instruction->info.rd,
- instruction->info.imm);
- }
- break;
- case 2: /* MOVD44 */
- case 3:
- instruction->info.ra =
- nds32_extract_field_8u(opcode, 0, 4) * 2;
- instruction->info.rt =
- nds32_extract_field_8u(opcode, 4, 4) * 2;
- instruction->type = NDS32_INSN_MISC;
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tMOVD44\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- }
- break;
- case 3: /* NEG33, NOT33, MUL33, XOR33, AND33, OR33 */
- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
- instruction->type = NDS32_INSN_DATA_PROC;
- switch (opcode & 0x7) {
- case 2: /* NEG33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tNEG33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 3: /* NOT33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tNOT33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 4: /* MUL33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tMUL33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 5: /* XOR33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tXOR33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 6: /* AND33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tAND33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- case 7: /* OR33 */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
- "\t\tOR33\t$r%" PRIu8 ",$r%" PRIu8,
- address,
- opcode, instruction->info.rt, instruction->info.ra);
- break;
- }
- break;
- }
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-int nds32_evaluate_opcode(struct nds32 *nds32, uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction)
-{
- int retval = ERROR_OK;
-
- /* clear fields, to avoid confusion */
- memset(instruction, 0, sizeof(struct nds32_instruction));
-
- if (opcode >> 31) {
- /* 16 bits instruction */
- instruction->instruction_size = 2;
- opcode = (opcode >> 16) & 0xFFFF;
- instruction->opcode = opcode;
-
- switch ((opcode >> 13) & 0x3) {
- case 0:
- retval = nds32_parse_group_0_insn_16(nds32, opcode, address, instruction);
- break;
- case 1:
- retval = nds32_parse_group_1_insn_16(nds32, opcode, address, instruction);
- break;
- case 2:
- retval = nds32_parse_group_2_insn_16(nds32, opcode, address, instruction);
- break;
- case 3:
- retval = nds32_parse_group_3_insn_16(nds32, opcode, address, instruction);
- break;
- default:
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
- } else {
- /* 32 bits instruction */
- instruction->instruction_size = 4;
- instruction->opcode = opcode;
-
- uint8_t opc_6;
- opc_6 = opcode >> 25;
- instruction->info.opc_6 = opc_6;
-
- switch ((opc_6 >> 3) & 0x7) {
- case 0: /* LBI, LHI, LWI, LBI.bi, LHI.bi, LWI.bi */
- retval = nds32_parse_group_0_insn(nds32, opcode, address, instruction);
- break;
- case 1: /* SBI, SHI, SWI, SBI.bi, SHI.bi, SWI.bi */
- retval = nds32_parse_group_1_insn(nds32, opcode, address, instruction);
- break;
- case 2: /* LBSI, LHSI, DPREFI, LBSI.bi, LHSI.bi, LBGP */
- retval = nds32_parse_group_2_insn(nds32, opcode, address, instruction);
- break;
- case 3: /* MEM, LSMW, HWGP, SBGP */
- retval = nds32_parse_group_3_insn(nds32, opcode, address, instruction);
- break;
- case 4: /* ALU_1, ALU_2, MOVI, SETHI, JI, JREG, BR1, BR2 */
- retval = nds32_parse_group_4_insn(nds32, opcode, address, instruction);
- break;
- case 5: /* ADDI, SUBRI, ANDI, XORI, ORI, SLTI, SLTSI */
- retval = nds32_parse_group_5_insn(nds32, opcode, address, instruction);
- break;
- case 6: /* MISC */
- retval = nds32_parse_group_6_insn(nds32, opcode, address, instruction);
- break;
- default: /* ERROR */
- snprintf(instruction->text,
- 128,
- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
- address,
- opcode);
- return ERROR_FAIL;
- }
- }
-
- return retval;
-}
diff --git a/src/target/nds32_disassembler.h b/src/target/nds32_disassembler.h
deleted file mode 100644
index 9117cbb..0000000
--- a/src/target/nds32_disassembler.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_DISASSEMBLER_H
-#define OPENOCD_TARGET_NDS32_DISASSEMBLER_H
-
-#include <target/nds32.h>
-
-enum nds32_instruction_type {
- NDS32_INSN_DATA_PROC = 0,
- NDS32_INSN_LOAD_STORE,
- NDS32_INSN_JUMP_BRANCH,
- NDS32_INSN_RESOURCE_ACCESS,
- NDS32_INSN_MISC,
-};
-
-struct nds32_instruction {
- enum nds32_instruction_type type;
- char text[128];
- uint32_t opcode;
- uint8_t instruction_size;
- uint32_t access_start;
- uint32_t access_end;
-
- struct {
- uint8_t opc_6;
- uint8_t rt;
- uint8_t ra;
- uint8_t rb;
- uint8_t rd;
- uint8_t sub_opc;
- int32_t imm;
- } info;
-
-};
-
-int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value);
-int nds32_evaluate_opcode(struct nds32 *nds32, uint32_t opcode, uint32_t address,
- struct nds32_instruction *instruction);
-
-#endif /* OPENOCD_TARGET_NDS32_DISASSEMBLER_H */
diff --git a/src/target/nds32_edm.h b/src/target/nds32_edm.h
deleted file mode 100644
index 1dec190..0000000
--- a/src/target/nds32_edm.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_EDM_H
-#define OPENOCD_TARGET_NDS32_EDM_H
-
-/**
- * @file
- * This is the interface to the Embedded Debug Module for Andes cores.
- */
-
-/* EDM misc registers */
-enum nds_edm_misc_reg {
- NDS_EDM_MISC_DIMIR = 0x0,
- NDS_EDM_MISC_SBAR,
- NDS_EDM_MISC_EDM_CMDR,
- NDS_EDM_MISC_DBGER,
- NDS_EDM_MISC_ACC_CTL,
- NDS_EDM_MISC_EDM_PROBE,
- NDS_EDM_MISC_GEN_PORT0,
- NDS_EDM_MISC_GEN_PORT1,
-};
-
-/* EDM system registers */
-enum nds_edm_system_reg {
- NDS_EDM_SR_BPC0 = 0x00,
- NDS_EDM_SR_BPC1,
- NDS_EDM_SR_BPC2,
- NDS_EDM_SR_BPC3,
- NDS_EDM_SR_BPC4,
- NDS_EDM_SR_BPC5,
- NDS_EDM_SR_BPC6,
- NDS_EDM_SR_BPC7,
- NDS_EDM_SR_BPA0 = 0x08,
- NDS_EDM_SR_BPA1,
- NDS_EDM_SR_BPA2,
- NDS_EDM_SR_BPA3,
- NDS_EDM_SR_BPA4,
- NDS_EDM_SR_BPA5,
- NDS_EDM_SR_BPA6,
- NDS_EDM_SR_BPA7,
- NDS_EDM_SR_BPAM0 = 0x10,
- NDS_EDM_SR_BPAM1,
- NDS_EDM_SR_BPAM2,
- NDS_EDM_SR_BPAM3,
- NDS_EDM_SR_BPAM4,
- NDS_EDM_SR_BPAM5,
- NDS_EDM_SR_BPAM6,
- NDS_EDM_SR_BPAM7,
- NDS_EDM_SR_BPV0 = 0x18,
- NDS_EDM_SR_BPV1,
- NDS_EDM_SR_BPV2,
- NDS_EDM_SR_BPV3,
- NDS_EDM_SR_BPV4,
- NDS_EDM_SR_BPV5,
- NDS_EDM_SR_BPV6,
- NDS_EDM_SR_BPV7,
- NDS_EDM_SR_BPCID0 = 0x20,
- NDS_EDM_SR_BPCID1,
- NDS_EDM_SR_BPCID2,
- NDS_EDM_SR_BPCID3,
- NDS_EDM_SR_BPCID4,
- NDS_EDM_SR_BPCID5,
- NDS_EDM_SR_BPCID6,
- NDS_EDM_SR_BPCID7,
- NDS_EDM_SR_EDM_CFG = 0x28,
- NDS_EDM_SR_EDMSW = 0x30,
- NDS_EDM_SR_EDM_CTL = 0x38,
- NDS_EDM_SR_EDM_DTR = 0x40,
- NDS_EDM_SR_BPMTV = 0x48,
- NDS_EDM_SR_DIMBR = 0x50,
- NDS_EDM_SR_TECR0 = 0x70,
- NDS_EDM_SR_TECR1 = 0x71,
-};
-
-enum nds_memory_access {
- NDS_MEMORY_ACC_BUS = 0,
- NDS_MEMORY_ACC_CPU,
-};
-
-enum nds_memory_select {
- NDS_MEMORY_SELECT_AUTO = 0,
- NDS_MEMORY_SELECT_MEM = 1,
- NDS_MEMORY_SELECT_ILM = 2,
- NDS_MEMORY_SELECT_DLM = 3,
-};
-
-#define NDS_DBGER_DEX (0x1)
-#define NDS_DBGER_DPED (0x2)
-#define NDS_DBGER_CRST (0x4)
-#define NDS_DBGER_AT_MAX (0x8)
-#define NDS_DBGER_ILL_SEC_ACC (0x10)
-#define NDS_DBGER_ALL_SUPRS_EX (0x40000000)
-#define NDS_DBGER_RESACC (0x80000000)
-#define NDS_DBGER_CLEAR_ALL (0x1F)
-
-#define NDS_EDMSW_WDV (1 << 0)
-#define NDS_EDMSW_RDV (1 << 1)
-
-#endif /* OPENOCD_TARGET_NDS32_EDM_H */
diff --git a/src/target/nds32_insn.h b/src/target/nds32_insn.h
deleted file mode 100644
index eb66645..0000000
--- a/src/target/nds32_insn.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_INSN_H
-#define OPENOCD_TARGET_NDS32_INSN_H
-
-#define NOP (0x40000009)
-#define DSB (0x64000008)
-#define ISB (0x64000009)
-#define BEQ_MINUS_12 (0x4C000000 | 0x3FFA)
-#define MTSR_DTR(a) (0x64000003 | (((0x03 << 7) | (0x08 << 3) | (0x00 << 0)) << 10) | (((a) & 0x1F) << 20))
-#define MFSR_DTR(a) (0x64000002 | (((0x03 << 7) | (0x08 << 3) | (0x00 << 0)) << 10) | (((a) & 0x1F) << 20))
-#define SETHI(a, b) (0x46000000 | ((a) << 20) | (b))
-#define ORI(a, b, c) (0x58000000 | ((a) << 20) | ((b) << 15) | (c))
-#define LWI_BI(a, b) (0x0C000001 | (a << 20) | (b << 15))
-#define LHI_BI(a, b) (0x0A000001 | (a << 20) | (b << 15))
-#define LBI_BI(a, b) (0x08000001 | (a << 20) | (b << 15))
-#define SWI_BI(a, b) (0x1C000001 | (a << 20) | (b << 15))
-#define SHI_BI(a, b) (0x1A000001 | (a << 20) | (b << 15))
-#define SBI_BI(a, b) (0x18000001 | (a << 20) | (b << 15))
-#define IRET (0x64000004)
-#define L1D_IX_WB(a) (0x64000021 | ((a) << 15))
-#define L1D_IX_INVAL(a) (0x64000001 | ((a) << 15))
-#define L1D_VA_INVAL(a) (0x64000101 | ((a) << 15))
-#define L1D_VA_WB(a) (0x64000121 | ((a) << 15))
-#define L1D_IX_RTAG(a) (0x64000061 | ((a) << 15))
-#define L1D_IX_RWD(a) (0x64000081 | ((a) << 15))
-#define L1I_IX_INVAL(a) (0x64000201 | ((a) << 15))
-#define L1I_VA_INVAL(a) (0x64000301 | ((a) << 15))
-#define L1I_IX_RTAG(a) (0x64000261 | ((a) << 15))
-#define L1I_IX_RWD(a) (0x64000281 | ((a) << 15))
-#define L1I_VA_FILLCK(a) (0x64000361 | ((a) << 15))
-#define ISYNC(a) (0x6400000d | ((a) << 20))
-#define MSYNC_STORE (0x6400002c)
-#define MSYNC_ALL (0x6400000c)
-#define TLBOP_TARGET_READ(a) (0x6400000e | ((a) << 15))
-#define TLBOP_TARGET_PROBE(a, b) (0x640000AE | ((a) << 20) | ((b) << 15))
-#define MFCPD(a, b, c) (0x6A000041 | (a << 20) | (b << 8) | (c << 4))
-#define MFCPW(a, b, c) (0x6A000001 | (a << 20) | (b << 8) | (c << 4))
-#define MTCPD(a, b, c) (0x6A000049 | (a << 20) | (b << 8) | (c << 4))
-#define MTCPW(a, b, c) (0x6A000009 | (a << 20) | (b << 8) | (c << 4))
-#define MOVI_(a, b) (0x44000000 | (a << 20) | (b & 0xFFFFF))
-#define MFUSR_G0(a, b) (0x42000020 | (a << 20) | (b << 15))
-#define MTUSR_G0(a, b) (0x42000021 | (a << 20) | (b << 15))
-#define MFSR(a, b) (0x64000002 | (b << 10) | (a << 20))
-#define MTSR(a, b) (0x64000003 | (b << 10) | (a << 20))
-#define AMFAR(a, b) (0x60300060 | (a << 15) | b)
-#define AMTAR(a, b) (0x60300040 | (a << 15) | b)
-#define AMFAR2(a, b) (0x60300260 | (a << 15) | b)
-#define AMTAR2(a, b) (0x60300240 | (a << 15) | b)
-#define FMFCSR (0x6A000701)
-#define FMTCSR (0x6A000709)
-#define FMFCFG (0x6A000301)
-#define FMFSR(a, b) (0x6A000001 | ((a) << 20) | ((b) << 15))
-#define FMTSR(a, b) (0x6A000009 | ((a) << 20) | ((b) << 15))
-#define FMFDR(a, b) (0x6A000041 | ((a) << 20) | ((b) << 15))
-#define FMTDR(a, b) (0x6A000049 | ((a) << 20) | ((b) << 15))
-
-/* break instructions */
-extern const int NDS32_BREAK_16;
-extern const int NDS32_BREAK_32;
-
-#endif /* OPENOCD_TARGET_NDS32_INSN_H */
diff --git a/src/target/nds32_reg.c b/src/target/nds32_reg.c
deleted file mode 100644
index 7cefcb1..0000000
--- a/src/target/nds32_reg.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include "nds32_reg.h"
-
-static bool nds32_reg_init_done;
-static struct nds32_reg_s nds32_regs[TOTAL_REG_NUM];
-static const struct nds32_reg_exception_s nds32_ex_reg_values[] = {
- {IR0, 3, 0x3, 2},
- {IR0, 3, 0x3, 3},
- {IR1, 3, 0x3, 2},
- {IR1, 3, 0x3, 3},
- {IR2, 3, 0x3, 2},
- {IR2, 3, 0x3, 3},
- {MR3, 1, 0x7, 0},
- {MR3, 1, 0x7, 4},
- {MR3, 1, 0x7, 6},
- {MR3, 8, 0x7, 3},
- {0, 0, 0, 0},
-};
-
-static inline void nds32_reg_set(uint32_t number, const char *simple_mnemonic,
- const char *symbolic_mnemonic, uint32_t sr_index,
- enum nds32_reg_type_s type, uint8_t size)
-{
- nds32_regs[number].simple_mnemonic = simple_mnemonic;
- nds32_regs[number].symbolic_mnemonic = symbolic_mnemonic;
- nds32_regs[number].sr_index = sr_index;
- nds32_regs[number].type = type;
- nds32_regs[number].size = size;
-}
-
-void nds32_reg_init(void)
-{
- if (nds32_reg_init_done == true)
- return;
-
- nds32_reg_set(R0, "r0", "r0", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R1, "r1", "r1", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R2, "r2", "r2", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R3, "r3", "r3", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R4, "r4", "r4", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R5, "r5", "r5", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R6, "r6", "r6", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R7, "r7", "r7", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R8, "r8", "r8", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R9, "r9", "r9", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R10, "r10", "r10", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R11, "r11", "r11", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R12, "r12", "r12", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R13, "r13", "r13", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R14, "r14", "r14", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R15, "r15", "r15", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R16, "r16", "r16", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R17, "r17", "r17", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R18, "r18", "r18", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R19, "r19", "r19", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R20, "r20", "r20", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R21, "r21", "r21", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R22, "r22", "r22", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R23, "r23", "r23", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R24, "r24", "r24", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R25, "r25", "r25", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R26, "r26", "p0", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R27, "r27", "p1", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R28, "fp", "fp", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R29, "gp", "gp", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R30, "lp", "lp", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(R31, "sp", "sp", 0, NDS32_REG_TYPE_GPR, 32);
- nds32_reg_set(PC, "pc", "pc", 31, NDS32_REG_TYPE_SPR, 32);
-
- nds32_reg_set(D0LO, "d0lo", "d0lo", 0, NDS32_REG_TYPE_SPR, 32);
- nds32_reg_set(D0HI, "d0hi", "d0hi", 1, NDS32_REG_TYPE_SPR, 32);
- nds32_reg_set(D1LO, "d1lo", "d1lo", 2, NDS32_REG_TYPE_SPR, 32);
- nds32_reg_set(D1HI, "d1hi", "d1hi", 3, NDS32_REG_TYPE_SPR, 32);
- nds32_reg_set(ITB, "itb", "itb", 28, NDS32_REG_TYPE_SPR, 32);
- nds32_reg_set(IFC_LP, "ifc_lp", "ifc_lp", 29, NDS32_REG_TYPE_SPR, 32);
-
- nds32_reg_set(CR0, "cr0", "CPU_VER", SRIDX(0, 0, 0), NDS32_REG_TYPE_CR, 32);
- nds32_reg_set(CR1, "cr1", "ICM_CFG", SRIDX(0, 1, 0), NDS32_REG_TYPE_CR, 32);
- nds32_reg_set(CR2, "cr2", "DCM_CFG", SRIDX(0, 2, 0), NDS32_REG_TYPE_CR, 32);
- nds32_reg_set(CR3, "cr3", "MMU_CFG", SRIDX(0, 3, 0), NDS32_REG_TYPE_CR, 32);
- nds32_reg_set(CR4, "cr4", "MSC_CFG", SRIDX(0, 4, 0), NDS32_REG_TYPE_CR, 32);
- nds32_reg_set(CR5, "cr5", "CORE_ID", SRIDX(0, 0, 1), NDS32_REG_TYPE_CR, 32);
- nds32_reg_set(CR6, "cr6", "FUCOP_EXIST", SRIDX(0, 5, 0), NDS32_REG_TYPE_CR, 32);
-
- nds32_reg_set(IR0, "ir0", "PSW", SRIDX(1, 0, 0), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR1, "ir1", "IPSW", SRIDX(1, 0, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR2, "ir2", "P_IPSW", SRIDX(1, 0, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR3, "ir3", "IVB", SRIDX(1, 1, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR4, "ir4", "EVA", SRIDX(1, 2, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR5, "ir5", "P_EVA", SRIDX(1, 2, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR6, "ir6", "ITYPE", SRIDX(1, 3, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR7, "ir7", "P_ITYPE", SRIDX(1, 3, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR8, "ir8", "MERR", SRIDX(1, 4, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR9, "ir9", "IPC", SRIDX(1, 5, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR10, "ir10", "P_IPC", SRIDX(1, 5, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR11, "ir11", "OIPC", SRIDX(1, 5, 3), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR12, "ir12", "P_P0", SRIDX(1, 6, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR13, "ir13", "P_P1", SRIDX(1, 7, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR14, "ir14", "INT_MASK", SRIDX(1, 8, 0), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR15, "ir15", "INT_PEND", SRIDX(1, 9, 0), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR16, "ir16", "", SRIDX(1, 10, 0), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR17, "ir17", "", SRIDX(1, 10, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR18, "ir18", "", SRIDX(1, 11, 0), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR19, "ir19", "", SRIDX(1, 1, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR20, "ir20", "", SRIDX(1, 10, 2), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR21, "ir21", "", SRIDX(1, 10, 3), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR22, "ir22", "", SRIDX(1, 10, 4), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR23, "ir23", "", SRIDX(1, 10, 5), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR24, "ir24", "", SRIDX(1, 10, 6), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR25, "ir25", "", SRIDX(1, 10, 7), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR26, "ir26", "", SRIDX(1, 8, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR27, "ir27", "", SRIDX(1, 9, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR28, "ir28", "", SRIDX(1, 11, 1), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR29, "ir29", "", SRIDX(1, 9, 4), NDS32_REG_TYPE_IR, 32);
- nds32_reg_set(IR30, "ir30", "", SRIDX(1, 1, 3), NDS32_REG_TYPE_IR, 32);
-
- nds32_reg_set(MR0, "mr0", "MMU_CTL", SRIDX(2, 0, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR1, "mr1", "L1_PPTB", SRIDX(2, 1, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR2, "mr2", "TLB_VPN", SRIDX(2, 2, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR3, "mr3", "TLB_DATA", SRIDX(2, 3, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR4, "mr4", "TLB_MISC", SRIDX(2, 4, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR5, "mr5", "VLPT_IDX", SRIDX(2, 5, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR6, "mr6", "ILMB", SRIDX(2, 6, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR7, "mr7", "DLMB", SRIDX(2, 7, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR8, "mr8", "CACHE_CTL", SRIDX(2, 8, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR9, "mr9", "HSMP_SADDR", SRIDX(2, 9, 0), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR10, "mr10", "HSMP_EADDR", SRIDX(2, 9, 1), NDS32_REG_TYPE_MR, 32);
- nds32_reg_set(MR11, "mr11", "", SRIDX(2, 0, 1), NDS32_REG_TYPE_MR, 32);
-
- nds32_reg_set(DR0, "dr0", "BPC0", SRIDX(3, 0, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR1, "dr1", "BPA0", SRIDX(3, 1, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR2, "dr2", "BPAM0", SRIDX(3, 2, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR3, "dr3", "BPV0", SRIDX(3, 3, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR4, "dr4", "BPCID0", SRIDX(3, 4, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR5, "dr5", "BPC1", SRIDX(3, 0, 1), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR6, "dr6", "BPA1", SRIDX(3, 1, 1), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR7, "dr7", "BPAM1", SRIDX(3, 2, 1), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR8, "dr8", "BPV1", SRIDX(3, 3, 1), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR9, "dr9", "BPCID1", SRIDX(3, 4, 1), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR10, "dr10", "BPC2", SRIDX(3, 0, 2), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR11, "dr11", "BPA2", SRIDX(3, 1, 2), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR12, "dr12", "BPAM2", SRIDX(3, 2, 2), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR13, "dr13", "BPV2", SRIDX(3, 3, 2), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR14, "dr14", "BPCID2", SRIDX(3, 4, 2), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR15, "dr15", "BPC3", SRIDX(3, 0, 3), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR16, "dr16", "BPA3", SRIDX(3, 1, 3), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR17, "dr17", "BPAM3", SRIDX(3, 2, 3), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR18, "dr18", "BPV3", SRIDX(3, 3, 3), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR19, "dr19", "BPCID3", SRIDX(3, 4, 3), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR20, "dr20", "BPC4", SRIDX(3, 0, 4), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR21, "dr21", "BPA4", SRIDX(3, 1, 4), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR22, "dr22", "BPAM4", SRIDX(3, 2, 4), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR23, "dr23", "BPV4", SRIDX(3, 3, 4), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR24, "dr24", "BPCID4", SRIDX(3, 4, 4), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR25, "dr25", "BPC5", SRIDX(3, 0, 5), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR26, "dr26", "BPA5", SRIDX(3, 1, 5), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR27, "dr27", "BPAM5", SRIDX(3, 2, 5), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR28, "dr28", "BPV5", SRIDX(3, 3, 5), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR29, "dr29", "BPCID5", SRIDX(3, 4, 5), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR30, "dr30", "BPC6", SRIDX(3, 0, 6), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR31, "dr31", "BPA6", SRIDX(3, 1, 6), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR32, "dr32", "BPAM6", SRIDX(3, 2, 6), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR33, "dr33", "BPV6", SRIDX(3, 3, 6), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR34, "dr34", "BPCID6", SRIDX(3, 4, 6), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR35, "dr35", "BPC7", SRIDX(3, 0, 7), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR36, "dr36", "BPA7", SRIDX(3, 1, 7), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR37, "dr37", "BPAM7", SRIDX(3, 2, 7), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR38, "dr38", "BPV7", SRIDX(3, 3, 7), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR39, "dr39", "BPCID7", SRIDX(3, 4, 7), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR40, "dr40", "EDM_CFG", SRIDX(3, 5, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR41, "dr41", "EDMSW", SRIDX(3, 6, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR42, "dr42", "EDM_CTL", SRIDX(3, 7, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR43, "dr43", "EDM_DTR", SRIDX(3, 8, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR44, "dr44", "BPMTC", SRIDX(3, 9, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR45, "dr45", "DIMBR", SRIDX(3, 10, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR46, "dr46", "TECR0", SRIDX(3, 14, 0), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR47, "dr47", "TECR1", SRIDX(3, 14, 1), NDS32_REG_TYPE_DR, 32);
- nds32_reg_set(DR48, "dr48", "", SRIDX(3, 11, 0), NDS32_REG_TYPE_DR, 32);
-
- nds32_reg_set(PFR0, "pfr0", "PFMC0", SRIDX(4, 0, 0), NDS32_REG_TYPE_PFR, 32);
- nds32_reg_set(PFR1, "pfr1", "PFMC1", SRIDX(4, 0, 1), NDS32_REG_TYPE_PFR, 32);
- nds32_reg_set(PFR2, "pfr2", "PFMC2", SRIDX(4, 0, 2), NDS32_REG_TYPE_PFR, 32);
- nds32_reg_set(PFR3, "pfr3", "PFM_CTL", SRIDX(4, 1, 0), NDS32_REG_TYPE_PFR, 32);
-
- nds32_reg_set(DMAR0, "dmar0", "DMA_CFG", SRIDX(5, 0, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR1, "dmar1", "DMA_GCSW", SRIDX(5, 1, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR2, "dmar2", "DMA_CHNSEL", SRIDX(5, 2, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR3, "dmar3", "DMA_ACT", SRIDX(5, 3, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR4, "dmar4", "DMA_SETUP", SRIDX(5, 4, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR5, "dmar5", "DMA_ISADDR", SRIDX(5, 5, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR6, "dmar6", "DMA_ESADDR", SRIDX(5, 6, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR7, "dmar7", "DMA_TCNT", SRIDX(5, 7, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR8, "dmar8", "DMA_STATUS", SRIDX(5, 8, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR9, "dmar9", "DMA_2DSET", SRIDX(5, 9, 0), NDS32_REG_TYPE_DMAR, 32);
- nds32_reg_set(DMAR10, "dmar10", "DMA_2DSCTL", SRIDX(5, 9, 1), NDS32_REG_TYPE_DMAR, 32);
-
- nds32_reg_set(RACR, "racr", "PRUSR_ACC_CTL", SRIDX(4, 4, 0), NDS32_REG_TYPE_RACR, 32);
- nds32_reg_set(FUCPR, "fucpr", "FUCOP_CTL", SRIDX(4, 5, 0), NDS32_REG_TYPE_RACR, 32);
-
- nds32_reg_set(IDR0, "idr0", "SDZ_CTL", SRIDX(2, 15, 0), NDS32_REG_TYPE_IDR, 32);
- nds32_reg_set(IDR1, "idr1", "MISC_CTL", SRIDX(2, 15, 1), NDS32_REG_TYPE_IDR, 32);
-
- nds32_reg_set(SECUR0, "secur0", "", SRIDX(6, 0, 0), NDS32_REG_TYPE_SECURE, 32);
-
- nds32_reg_set(D0L24, "D0L24", "D0L24", 0x10, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(D1L24, "D1L24", "D1L24", 0x11, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I0, "I0", "I0", 0x0, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I1, "I1", "I1", 0x1, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I2, "I2", "I2", 0x2, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I3, "I3", "I3", 0x3, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I4, "I4", "I4", 0x4, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I5, "I5", "I5", 0x5, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I6, "I6", "I6", 0x6, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(I7, "I7", "I7", 0x7, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(M1, "M1", "M1", 0x9, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(M2, "M2", "M2", 0xA, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(M3, "M3", "M3", 0xB, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(M5, "M5", "M5", 0xD, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(M6, "M6", "M6", 0xE, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(M7, "M7", "M7", 0xF, NDS32_REG_TYPE_AUMR, 32);
-
- nds32_reg_set(MOD, "MOD", "MOD", 0x8, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(LBE, "LBE", "LBE", 0x18, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(LE, "LE", "LE", 0x19, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(LC, "LC", "LC", 0x1A, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(ADM_VBASE, "ADM_VBASE", "ADM_VBASE", 0x1B, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(SHFT_CTL0, "SHFT_CTL0", "SHFT_CTL0", 0x12, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(SHFT_CTL1, "SHFT_CTL1", "SHFT_CTL1", 0x13, NDS32_REG_TYPE_AUMR, 32);
-
- nds32_reg_set(CB_CTL, "CB_CTL", "CB_CTL", 0x1F, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBB0, "CBB0", "CBB0", 0x0, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBB1, "CBB1", "CBB1", 0x1, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBB2, "CBB2", "CBB2", 0x2, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBB3, "CBB3", "CBB3", 0x3, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBE0, "CBE0", "CBE0", 0x4, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBE1, "CBE1", "CBE1", 0x5, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBE2, "CBE2", "CBE2", 0x6, NDS32_REG_TYPE_AUMR, 32);
- nds32_reg_set(CBE3, "CBE3", "CBE3", 0x7, NDS32_REG_TYPE_AUMR, 32);
-
- nds32_reg_set(FPCSR, "fpcsr", "FPCSR", 0x7, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FPCFG, "fpcfg", "FPCFG", 0x7, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS0, "fs0", "FS0", 0, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS1, "fs1", "FS1", 1, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS2, "fs2", "FS2", 2, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS3, "fs3", "FS3", 3, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS4, "fs4", "FS4", 4, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS5, "fs5", "FS5", 5, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS6, "fs6", "FS6", 6, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS7, "fs7", "FS7", 7, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS8, "fs8", "FS8", 8, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS9, "fs9", "FS9", 9, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS10, "fs10", "FS10", 10, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS11, "fs11", "FS11", 11, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS12, "fs12", "FS12", 12, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS13, "fs13", "FS13", 13, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS14, "fs14", "FS14", 14, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS15, "fs15", "FS15", 15, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS16, "fs16", "FS16", 16, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS17, "fs17", "FS17", 17, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS18, "fs18", "FS18", 18, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS19, "fs19", "FS19", 19, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS20, "fs20", "FS20", 20, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS21, "fs21", "FS21", 21, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS22, "fs22", "FS22", 22, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS23, "fs23", "FS23", 23, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS24, "fs24", "FS24", 24, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS25, "fs25", "FS25", 25, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS26, "fs26", "FS26", 26, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS27, "fs27", "FS27", 27, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS28, "fs28", "FS28", 28, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS29, "fs29", "FS29", 29, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS30, "fs30", "FS30", 30, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FS31, "fs31", "FS31", 31, NDS32_REG_TYPE_FPU, 32);
- nds32_reg_set(FD0, "fd0", "FD0", 0, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD1, "fd1", "FD1", 1, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD2, "fd2", "FD2", 2, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD3, "fd3", "FD3", 3, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD4, "fd4", "FD4", 4, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD5, "fd5", "FD5", 5, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD6, "fd6", "FD6", 6, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD7, "fd7", "FD7", 7, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD8, "fd8", "FD8", 8, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD9, "fd9", "FD9", 9, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD10, "fd10", "FD10", 10, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD11, "fd11", "FD11", 11, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD12, "fd12", "FD12", 12, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD13, "fd13", "FD13", 13, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD14, "fd14", "FD14", 14, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD15, "fd15", "FD15", 15, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD16, "fd16", "FD16", 16, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD17, "fd17", "FD17", 17, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD18, "fd18", "FD18", 18, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD19, "fd19", "FD19", 19, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD20, "fd20", "FD20", 20, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD21, "fd21", "FD21", 21, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD22, "fd22", "FD22", 22, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD23, "fd23", "FD23", 23, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD24, "fd24", "FD24", 24, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD25, "fd25", "FD25", 25, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD26, "fd26", "FD26", 26, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD27, "fd27", "FD27", 27, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD28, "fd28", "FD28", 28, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD29, "fd29", "FD29", 29, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD30, "fd30", "FD30", 30, NDS32_REG_TYPE_FPU, 64);
- nds32_reg_set(FD31, "fd31", "FD31", 31, NDS32_REG_TYPE_FPU, 64);
-
- nds32_reg_init_done = true;
-}
-
-uint32_t nds32_reg_sr_index(uint32_t number)
-{
- return nds32_regs[number].sr_index;
-}
-
-enum nds32_reg_type_s nds32_reg_type(uint32_t number)
-{
- return nds32_regs[number].type;
-}
-
-uint8_t nds32_reg_size(uint32_t number)
-{
- return nds32_regs[number].size;
-}
-
-const char *nds32_reg_simple_name(uint32_t number)
-{
- return nds32_regs[number].simple_mnemonic;
-}
-
-const char *nds32_reg_symbolic_name(uint32_t number)
-{
- return nds32_regs[number].symbolic_mnemonic;
-}
-
-bool nds32_reg_exception(uint32_t number, uint32_t value)
-{
- int i;
- const struct nds32_reg_exception_s *ex_reg_value;
- uint32_t field_value;
-
- i = 0;
- while (nds32_ex_reg_values[i].reg_num != 0) {
- ex_reg_value = nds32_ex_reg_values + i;
-
- if (ex_reg_value->reg_num == number) {
- field_value = (value >> ex_reg_value->ex_value_bit_pos) &
- ex_reg_value->ex_value_mask;
- if (field_value == ex_reg_value->ex_value) {
- LOG_WARNING("It will generate exceptions as setting %" PRId32 " to %s",
- value, nds32_regs[number].simple_mnemonic);
- return true;
- }
- }
-
- i++;
- }
-
- return false;
-}
diff --git a/src/target/nds32_reg.h b/src/target/nds32_reg.h
deleted file mode 100644
index 8808cd2..0000000
--- a/src/target/nds32_reg.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_REG_H
-#define OPENOCD_TARGET_NDS32_REG_H
-
-#define SRIDX(a, b, c) ((a << 7) | (b << 3) | c)
-#define NDS32_REGISTER_DISABLE (0x0)
-
-enum nds32_reg_number_s {
- R0 = 0, /* general registers */
- R1,
- R2,
- R3,
- R4,
- R5,
- R6,
- R7,
- R8,
- R9,
- R10,
- R11,
- R12,
- R13,
- R14,
- R15,
- R16,
- R17,
- R18,
- R19,
- R20,
- R21,
- R22,
- R23,
- R24,
- R25,
- R26,
- R27,
- R28,
- R29,
- R30,
- R31,
- PC,
- D0LO,
- D0HI,
- D1LO,
- D1HI,
- ITB,
- IFC_LP,
- CR0, /* system registers */
- CR1,
- CR2,
- CR3,
- CR4,
- CR5,
- CR6,
- IR0,
- IR1,
- IR2,
- IR3,
- IR4,
- IR5,
- IR6,
- IR7,
- IR8,
- IR9,
- IR10,
- IR11,
- IR12,
- IR13,
- IR14,
- IR15,
- IR16,
- IR17,
- IR18,
- IR19,
- IR20,
- IR21,
- IR22,
- IR23,
- IR24,
- IR25,
- IR26,
- IR27,
- IR28,
- IR29,
- IR30,
- MR0,
- MR1,
- MR2,
- MR3,
- MR4,
- MR5,
- MR6,
- MR7,
- MR8,
- MR9,
- MR10,
- MR11,
- DR0,
- DR1,
- DR2,
- DR3,
- DR4,
- DR5,
- DR6,
- DR7,
- DR8,
- DR9,
- DR10,
- DR11,
- DR12,
- DR13,
- DR14,
- DR15,
- DR16,
- DR17,
- DR18,
- DR19,
- DR20,
- DR21,
- DR22,
- DR23,
- DR24,
- DR25,
- DR26,
- DR27,
- DR28,
- DR29,
- DR30,
- DR31,
- DR32,
- DR33,
- DR34,
- DR35,
- DR36,
- DR37,
- DR38,
- DR39,
- DR40,
- DR41,
- DR42,
- DR43,
- DR44,
- DR45,
- DR46,
- DR47,
- DR48,
- PFR0,
- PFR1,
- PFR2,
- PFR3,
- DMAR0,
- DMAR1,
- DMAR2,
- DMAR3,
- DMAR4,
- DMAR5,
- DMAR6,
- DMAR7,
- DMAR8,
- DMAR9,
- DMAR10,
- RACR,
- FUCPR,
- IDR0,
- IDR1,
- SECUR0,
- D0L24, /* audio registers */
- D1L24,
- I0,
- I1,
- I2,
- I3,
- I4,
- I5,
- I6,
- I7,
- M1,
- M2,
- M3,
- M5,
- M6,
- M7,
- MOD,
- LBE,
- LE,
- LC,
- ADM_VBASE,
- SHFT_CTL0,
- SHFT_CTL1,
- CB_CTL,
- CBB0,
- CBB1,
- CBB2,
- CBB3,
- CBE0,
- CBE1,
- CBE2,
- CBE3,
- FPCSR, /* fpu */
- FPCFG,
- FS0,
- FS1,
- FS2,
- FS3,
- FS4,
- FS5,
- FS6,
- FS7,
- FS8,
- FS9,
- FS10,
- FS11,
- FS12,
- FS13,
- FS14,
- FS15,
- FS16,
- FS17,
- FS18,
- FS19,
- FS20,
- FS21,
- FS22,
- FS23,
- FS24,
- FS25,
- FS26,
- FS27,
- FS28,
- FS29,
- FS30,
- FS31,
- FD0,
- FD1,
- FD2,
- FD3,
- FD4,
- FD5,
- FD6,
- FD7,
- FD8,
- FD9,
- FD10,
- FD11,
- FD12,
- FD13,
- FD14,
- FD15,
- FD16,
- FD17,
- FD18,
- FD19,
- FD20,
- FD21,
- FD22,
- FD23,
- FD24,
- FD25,
- FD26,
- FD27,
- FD28,
- FD29,
- FD30,
- FD31,
-
- TOTAL_REG_NUM,
-};
-
-enum nds32_reg_type_s {
- NDS32_REG_TYPE_GPR = 0,
- NDS32_REG_TYPE_SPR,
- NDS32_REG_TYPE_CR,
- NDS32_REG_TYPE_IR,
- NDS32_REG_TYPE_MR,
- NDS32_REG_TYPE_DR,
- NDS32_REG_TYPE_PFR,
- NDS32_REG_TYPE_DMAR,
- NDS32_REG_TYPE_RACR,
- NDS32_REG_TYPE_IDR,
- NDS32_REG_TYPE_AUMR,
- NDS32_REG_TYPE_SECURE,
- NDS32_REG_TYPE_FPU,
-};
-
-struct nds32_reg_s {
- const char *simple_mnemonic;
- const char *symbolic_mnemonic;
- uint32_t sr_index;
- enum nds32_reg_type_s type;
- uint8_t size;
-};
-
-struct nds32_reg_exception_s {
- uint32_t reg_num;
- uint32_t ex_value_bit_pos;
- uint32_t ex_value_mask;
- uint32_t ex_value;
-};
-
-void nds32_reg_init(void);
-uint32_t nds32_reg_sr_index(uint32_t number);
-enum nds32_reg_type_s nds32_reg_type(uint32_t number);
-uint8_t nds32_reg_size(uint32_t number);
-const char *nds32_reg_simple_name(uint32_t number);
-const char *nds32_reg_symbolic_name(uint32_t number);
-bool nds32_reg_exception(uint32_t number, uint32_t value);
-
-#endif /* OPENOCD_TARGET_NDS32_REG_H */
diff --git a/src/target/nds32_tlb.c b/src/target/nds32_tlb.c
deleted file mode 100644
index 6a91a0f..0000000
--- a/src/target/nds32_tlb.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "nds32_aice.h"
-#include "nds32_tlb.h"
-
-int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address,
- uint32_t *physical_address)
-{
- struct target *target = nds32->target;
- struct aice_port_s *aice = target_to_aice(target);
-
- return aice_read_tlb(aice, virtual_address, physical_address);
-}
-
-struct page_table_walker_info_s page_table_info[PAGE_SIZE_NUM] = {
- /* 4K page */
- {0xFFC00000, 20, 0x003FF000, 10, 0x00000FFF, 0xFFFFF000, 0xFFFFF000, 0xFFFFF000},
- /* 8K page */
- {0xFF000000, 22, 0x00FFE000, 11, 0x00001FFF, 0xFFFFF000, 0xFFFFE000, 0xFFFFE000},
-};
-
-int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address,
- uint32_t *physical_address)
-{
- struct target *target = nds32->target;
- uint32_t value_mr1;
- uint32_t load_address;
- uint32_t L1_page_table_entry;
- uint32_t L2_page_table_entry;
- uint32_t page_size_index = nds32->mmu_config.default_min_page_size;
- struct page_table_walker_info_s *page_table_info_p =
- &(page_table_info[page_size_index]);
-
- /* Read L1 Physical Page Table */
- nds32_get_mapped_reg(nds32, MR1, &value_mr1);
- load_address = (value_mr1 & page_table_info_p->L1_base_mask) |
- ((virtual_address & page_table_info_p->L1_offset_mask) >>
- page_table_info_p->L1_offset_shift);
- /* load_address is physical address */
- nds32_read_buffer(target, load_address, 4, (uint8_t *)&L1_page_table_entry);
-
- /* Read L2 Physical Page Table */
- if (L1_page_table_entry & 0x1) /* L1_PTE not present */
- return ERROR_FAIL;
-
- load_address = (L1_page_table_entry & page_table_info_p->L2_base_mask) |
- ((virtual_address & page_table_info_p->L2_offset_mask) >>
- page_table_info_p->L2_offset_shift);
- /* load_address is physical address */
- nds32_read_buffer(target, load_address, 4, (uint8_t *)&L2_page_table_entry);
-
- if ((L2_page_table_entry & 0x1) != 0x1) /* L2_PTE not valid */
- return ERROR_FAIL;
-
- *physical_address = (L2_page_table_entry & page_table_info_p->ppn_mask) |
- (virtual_address & page_table_info_p->va_offset_mask);
-
- return ERROR_OK;
-}
diff --git a/src/target/nds32_tlb.h b/src/target/nds32_tlb.h
deleted file mode 100644
index ada2c19..0000000
--- a/src/target/nds32_tlb.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_TLB_H
-#define OPENOCD_TARGET_NDS32_TLB_H
-
-#include "nds32.h"
-
-enum {
- PAGE_SIZE_4K = 0,
- PAGE_SIZE_8K,
- PAGE_SIZE_NUM,
-};
-
-struct page_table_walker_info_s {
-
- uint32_t L1_offset_mask;
- uint32_t L1_offset_shift;
- uint32_t L2_offset_mask;
- uint32_t L2_offset_shift;
- uint32_t va_offset_mask;
- uint32_t L1_base_mask;
- uint32_t L2_base_mask;
- uint32_t ppn_mask;
-};
-
-extern int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address,
- uint32_t *physical_address);
-extern int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address,
- uint32_t *physical_address);
-
-#endif /* OPENOCD_TARGET_NDS32_TLB_H */
diff --git a/src/target/nds32_v2.c b/src/target/nds32_v2.c
deleted file mode 100644
index da8bbbc..0000000
--- a/src/target/nds32_v2.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <helper/binarybuffer.h>
-#include "breakpoints.h"
-#include "nds32_insn.h"
-#include "nds32_reg.h"
-#include "nds32_edm.h"
-#include "nds32_cmd.h"
-#include "nds32_v2.h"
-#include "nds32_aice.h"
-#include "target_type.h"
-
-static int nds32_v2_register_mapping(struct nds32 *nds32, int reg_no)
-{
- uint32_t max_level = nds32->max_interrupt_level;
- uint32_t cur_level = nds32->current_interrupt_level;
-
- if ((1 <= cur_level) && (cur_level < max_level)) {
- if (IR0 == reg_no) {
- LOG_DEBUG("Map PSW to IPSW");
- return IR1;
- } else if (PC == reg_no) {
- LOG_DEBUG("Map PC to IPC");
- return IR9;
- }
- } else if ((2 <= cur_level) && (cur_level < max_level)) {
- if (R26 == reg_no) {
- LOG_DEBUG("Mapping P0 to P_P0");
- return IR12;
- } else if (R27 == reg_no) {
- LOG_DEBUG("Mapping P1 to P_P1");
- return IR13;
- } else if (IR1 == reg_no) {
- LOG_DEBUG("Mapping IPSW to P_IPSW");
- return IR2;
- } else if (IR4 == reg_no) {
- LOG_DEBUG("Mapping EVA to P_EVA");
- return IR5;
- } else if (IR6 == reg_no) {
- LOG_DEBUG("Mapping ITYPE to P_ITYPE");
- return IR7;
- } else if (IR9 == reg_no) {
- LOG_DEBUG("Mapping IPC to P_IPC");
- return IR10;
- }
- } else if (cur_level == max_level) {
- if (PC == reg_no) {
- LOG_DEBUG("Mapping PC to O_IPC");
- return IR11;
- }
- }
-
- return reg_no;
-}
-
-static int nds32_v2_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
-{
- uint32_t val_itype;
- struct aice_port_s *aice = target_to_aice(nds32->target);
-
- aice_read_register(aice, IR6, &val_itype);
-
- *reason = val_itype & 0x0F;
-
- return ERROR_OK;
-}
-
-static int nds32_v2_activate_hardware_breakpoint(struct target *target)
-{
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct breakpoint *bp;
- int32_t hbr_index = 0;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- if (bp->type == BKPT_SOFT) {
- /* already set at nds32_v2_add_breakpoint() */
- continue;
- } else if (bp->type == BKPT_HARD) {
- /* set address */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
- /* set mask */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
- /* set value */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
-
- if (nds32_v2->nds32.memory.address_translation)
- /* enable breakpoint (virtual address) */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
- else
- /* enable breakpoint (physical address) */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
-
- LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index,
- bp->address);
-
- hbr_index++;
- } else {
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v2_deactivate_hardware_breakpoint(struct target *target)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct breakpoint *bp;
- int32_t hbr_index = 0;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- if (bp->type == BKPT_SOFT)
- continue;
- else if (bp->type == BKPT_HARD)
- /* disable breakpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
- else
- return ERROR_FAIL;
-
- LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index,
- bp->address);
-
- hbr_index++;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v2_activate_hardware_watchpoint(struct target *target)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
- struct watchpoint *wp;
- int32_t wp_num = nds32_v2->next_hbr_index;
- uint32_t wp_config = 0;
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
-
- wp_num--;
- wp->mask = wp->length - 1;
- if ((wp->address % wp->length) != 0)
- wp->mask = (wp->mask << 1) + 1;
-
- if (wp->rw == WPT_READ)
- wp_config = 0x3;
- else if (wp->rw == WPT_WRITE)
- wp_config = 0x5;
- else if (wp->rw == WPT_ACCESS)
- wp_config = 0x7;
-
- /* set/unset physical address bit of BPCn according to PSW.DT */
- if (nds32_v2->nds32.memory.address_translation == false)
- wp_config |= 0x8;
-
- /* set address */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
- wp->address - (wp->address % wp->length));
- /* set mask */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
- /* enable watchpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
- /* set value */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
-
- LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num,
- wp->address, wp->mask);
-
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v2_deactivate_hardware_watchpoint(struct target *target)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
- int32_t wp_num = nds32_v2->next_hbr_index;
- struct watchpoint *wp;
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
- wp_num--;
- /* disable watchpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
-
- LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32,
- wp_num, wp->address, wp->mask);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v2_check_interrupt_stack(struct nds32_v2_common *nds32_v2)
-{
- struct nds32 *nds32 = &(nds32_v2->nds32);
- struct aice_port_s *aice = target_to_aice(nds32->target);
- uint32_t val_ir0;
- uint32_t val_ir1;
- uint32_t val_ir2;
- uint32_t modified_psw;
-
- /* Save interrupt level */
- aice_read_register(aice, IR0, &val_ir0); /* get $IR0 directly */
-
- /* backup $IR0 */
- nds32_v2->backup_ir0 = val_ir0;
-
- nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
-
- if (nds32_reach_max_interrupt_level(nds32)) {
- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
- nds32->current_interrupt_level);
-
- /* decrease interrupt level */
- modified_psw = val_ir0 - 0x2;
-
- /* disable GIE, IT, DT, HSS */
- modified_psw &= (~0x8C1);
-
- aice_write_register(aice, IR0, modified_psw);
-
- return ERROR_OK;
- }
-
- /* There is a case that single step also trigger another interrupt,
- then HSS bit in psw(ir0) will push to ipsw(ir1).
- Then hit debug interrupt HSS bit in ipsw(ir1) will push to (p_ipsw)ir2
- Therefore, HSS bit in p_ipsw(ir2) also need clear.
-
- Only update $ir2 as current interrupt level is 2, because $ir2 will be random
- value if the target never reaches interrupt level 2. */
- if ((nds32->max_interrupt_level == 3) && (nds32->current_interrupt_level == 2)) {
- aice_read_register(aice, IR2, &val_ir2); /* get $IR2 directly */
- val_ir2 &= ~(0x01 << 11);
- aice_write_register(aice, IR2, val_ir2);
- }
-
- /* get origianl DT bit and set to current state let debugger has same memory view
- PSW.IT MUST be turned off. Otherwise, DIM could not operate normally. */
- aice_read_register(aice, IR1, &val_ir1);
- modified_psw = val_ir0 | (val_ir1 & 0x80);
- aice_write_register(aice, IR0, modified_psw);
-
- return ERROR_OK;
-}
-
-static int nds32_v2_restore_interrupt_stack(struct nds32_v2_common *nds32_v2)
-{
- struct nds32 *nds32 = &(nds32_v2->nds32);
- struct aice_port_s *aice = target_to_aice(nds32->target);
-
- /* restore origin $IR0 */
- aice_write_register(aice, IR0, nds32_v2->backup_ir0);
-
- return ERROR_OK;
-}
-
-/**
- * Save processor state. This is called after a HALT instruction
- * succeeds, and on other occasions the processor enters debug mode
- * (breakpoint, watchpoint, etc).
- */
-static int nds32_v2_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
-{
- LOG_DEBUG("nds32_v2_debug_entry");
-
- if (nds32->virtual_hosting)
- LOG_WARNING("<-- TARGET WARNING! Virtual hosting is not supported "
- "under V1/V2 architecture. -->");
-
- enum target_state backup_state = nds32->target->state;
- nds32->target->state = TARGET_HALTED;
-
- if (nds32->init_arch_info_after_halted == false) {
- /* init architecture info according to config registers */
- CHECK_RETVAL(nds32_config(nds32));
-
- nds32->init_arch_info_after_halted = true;
- }
-
- /* REVISIT entire cache should already be invalid !!! */
- register_cache_invalidate(nds32->core_cache);
-
- /* deactivate all hardware breakpoints */
- CHECK_RETVAL(nds32_v2_deactivate_hardware_breakpoint(nds32->target));
-
- if (enable_watchpoint)
- CHECK_RETVAL(nds32_v2_deactivate_hardware_watchpoint(nds32->target));
-
- if (ERROR_OK != nds32_examine_debug_reason(nds32)) {
- nds32->target->state = backup_state;
-
- /* re-activate all hardware breakpoints & watchpoints */
- CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
-
- if (enable_watchpoint) {
- /* activate all watchpoints */
- CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
- }
-
- return ERROR_FAIL;
- }
-
- /* check interrupt level before .full_context(), because
- * get_mapped_reg() in nds32_full_context() needs current_interrupt_level
- * information */
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
- nds32_v2_check_interrupt_stack(nds32_v2);
-
- /* Save registers. */
- nds32_full_context(nds32);
-
- return ERROR_OK;
-}
-
-/* target request support */
-static int nds32_v2_target_request_data(struct target *target,
- uint32_t size, uint8_t *buffer)
-{
- /* AndesCore could use DTR register to communicate with OpenOCD
- * to output messages
- * Target data will be put in buffer
- * The format of DTR is as follow
- * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
- * target_req_cmd has three possible values:
- * TARGET_REQ_TRACEMSG
- * TARGET_REQ_DEBUGMSG
- * TARGET_REQ_DEBUGCHAR
- * if size == 0, target will call target_asciimsg(),
- * else call target_hexmsg()
- */
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_OK;
-}
-
-/**
- * Restore processor state.
- */
-static int nds32_v2_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
-{
- LOG_DEBUG("nds32_v2_leave_debug_state");
-
- struct target *target = nds32->target;
-
- /* activate all hardware breakpoints */
- CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
-
- if (enable_watchpoint) {
- /* activate all watchpoints */
- CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
- }
-
- /* restore interrupt stack */
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
- nds32_v2_restore_interrupt_stack(nds32_v2);
-
- /* restore PSW, PC, and R0 ... after flushing any modified
- * registers.
- */
- CHECK_RETVAL(nds32_restore_context(target));
-
- register_cache_invalidate(nds32->core_cache);
-
- return ERROR_OK;
-}
-
-static int nds32_v2_deassert_reset(struct target *target)
-{
- int retval;
-
- CHECK_RETVAL(nds32_poll(target));
-
- if (target->state != TARGET_HALTED) {
- /* reset only */
- LOG_WARNING("%s: ran after reset and before halt ...",
- target_name(target));
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v2_checksum_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *checksum)
-{
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_FAIL;
-}
-
-static int nds32_v2_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
- struct nds32 *nds32 = &(nds32_v2->nds32);
- int result;
-
- if (breakpoint->type == BKPT_HARD) {
- /* check hardware resource */
- if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
- "breakpoints/watchpoints! The limit of "
- "combined hardware breakpoints/watchpoints "
- "is %" PRId32 ". -->", nds32_v2->n_hbr);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* update next place to put hardware breakpoint */
- nds32_v2->next_hbr_index++;
-
- /* hardware breakpoint insertion occurs before 'continue' actually */
- return ERROR_OK;
- } else if (breakpoint->type == BKPT_SOFT) {
- result = nds32_add_software_breakpoint(target, breakpoint);
- if (ERROR_OK != result) {
- /* auto convert to hardware breakpoint if failed */
- if (nds32->auto_convert_hw_bp) {
- /* convert to hardware breakpoint */
- breakpoint->type = BKPT_HARD;
-
- return nds32_v2_add_breakpoint(target, breakpoint);
- }
- }
-
- return result;
- } else /* unrecognized breakpoint type */
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int nds32_v2_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
-
- if (breakpoint->type == BKPT_HARD) {
- if (nds32_v2->next_hbr_index <= 0)
- return ERROR_FAIL;
-
- /* update next place to put hardware breakpoint */
- nds32_v2->next_hbr_index--;
-
- /* hardware breakpoint removal occurs after 'halted' actually */
- return ERROR_OK;
- } else if (breakpoint->type == BKPT_SOFT) {
- return nds32_remove_software_breakpoint(target, breakpoint);
- } else /* unrecognized breakpoint type */
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int nds32_v2_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
-
- /* check hardware resource */
- if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
- "breakpoints/watchpoints! The limit of "
- "combined hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v2->n_hbr);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* update next place to put hardware watchpoint */
- nds32_v2->next_hbr_index++;
-
- return ERROR_OK;
-}
-
-static int nds32_v2_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
-
- if (nds32_v2->next_hbr_index <= 0)
- return ERROR_FAIL;
-
- /* update next place to put hardware breakpoint */
- nds32_v2->next_hbr_index--;
-
- return ERROR_OK;
-}
-
-static int nds32_v2_get_exception_address(struct nds32 *nds32,
- uint32_t *address, uint32_t reason)
-{
- struct aice_port_s *aice = target_to_aice(nds32->target);
-
- aice_read_register(aice, IR4, address); /* read $EVA directly */
-
- /* TODO: hit multiple watchpoints */
-
- return ERROR_OK;
-}
-
-/**
- * find out which watchpoint hits
- * get exception address and compare the address to watchpoints
- */
-static int nds32_v2_hit_watchpoint(struct target *target,
- struct watchpoint **hit_watchpoint)
-{
- uint32_t exception_address;
- struct watchpoint *wp;
- static struct watchpoint scan_all_watchpoint;
- struct nds32 *nds32 = target_to_nds32(target);
-
- scan_all_watchpoint.address = 0;
- scan_all_watchpoint.rw = WPT_WRITE;
- scan_all_watchpoint.next = 0;
- scan_all_watchpoint.unique_id = 0x5CA8;
-
- exception_address = nds32->watched_address;
-
- if (exception_address == 0) {
- /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
- *hit_watchpoint = &scan_all_watchpoint;
- return ERROR_OK;
- }
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
- if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
- /* TODO: dispel false match */
- *hit_watchpoint = wp;
- return ERROR_OK;
- }
- }
-
- return ERROR_FAIL;
-}
-
-static int nds32_v2_run_algorithm(struct target *target,
- int num_mem_params,
- struct mem_param *mem_params,
- int num_reg_params,
- struct reg_param *reg_params,
- uint32_t entry_point,
- uint32_t exit_point,
- int timeout_ms,
- void *arch_info)
-{
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_FAIL;
-}
-
-static int nds32_v2_target_create(struct target *target, Jim_Interp *interp)
-{
- struct nds32_v2_common *nds32_v2;
-
- nds32_v2 = calloc(1, sizeof(*nds32_v2));
- if (!nds32_v2)
- return ERROR_FAIL;
-
- nds32_v2->nds32.register_map = nds32_v2_register_mapping;
- nds32_v2->nds32.get_debug_reason = nds32_v2_get_debug_reason;
- nds32_v2->nds32.enter_debug_state = nds32_v2_debug_entry;
- nds32_v2->nds32.leave_debug_state = nds32_v2_leave_debug_state;
- nds32_v2->nds32.get_watched_address = nds32_v2_get_exception_address;
-
- nds32_init_arch_info(target, &(nds32_v2->nds32));
-
- return ERROR_OK;
-}
-
-static int nds32_v2_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- /* Initialize anything we can set up without talking to the target */
-
- struct nds32 *nds32 = target_to_nds32(target);
-
- nds32_init(nds32);
-
- return ERROR_OK;
-}
-
-/* talk to the target and set things up */
-static int nds32_v2_examine(struct target *target)
-{
- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
- struct nds32 *nds32 = &(nds32_v2->nds32);
- struct aice_port_s *aice = target_to_aice(target);
-
- if (!target_was_examined(target)) {
- CHECK_RETVAL(nds32_edm_config(nds32));
-
- if (nds32->reset_halt_as_examine)
- CHECK_RETVAL(nds32_reset_halt(nds32));
- }
-
- uint32_t edm_cfg;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
-
- /* get the number of hardware breakpoints */
- nds32_v2->n_hbr = (edm_cfg & 0x7) + 1;
-
- nds32_v2->next_hbr_index = 0;
-
- LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target),
- nds32_v2->n_hbr);
-
- nds32->target->state = TARGET_RUNNING;
- nds32->target->debug_reason = DBG_REASON_NOTHALTED;
-
- target_set_examined(target);
-
- return ERROR_OK;
-}
-
-static int nds32_v2_translate_address(struct target *target, uint32_t *address)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
- uint32_t physical_address;
-
- /* Following conditions need to do address translation
- * 1. BUS mode
- * 2. CPU mode under maximum interrupt level */
- if ((NDS_MEMORY_ACC_BUS == memory->access_channel) ||
- ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- nds32_reach_max_interrupt_level(nds32))) {
- if (ERROR_OK == target->type->virt2phys(target, *address, &physical_address))
- *address = physical_address;
- else
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v2_read_buffer(struct target *target, uint32_t address,
- uint32_t size, uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- nds32_v2_translate_address(target, &address);
-
- return nds32_read_buffer(target, address, size, buffer);
-}
-
-static int nds32_v2_write_buffer(struct target *target, uint32_t address,
- uint32_t size, const uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- nds32_v2_translate_address(target, &address);
-
- return nds32_write_buffer(target, address, size, buffer);
-}
-
-static int nds32_v2_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- nds32_v2_translate_address(target, &address);
-
- return nds32_read_memory(target, address, size, count, buffer);
-}
-
-static int nds32_v2_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- nds32_v2_translate_address(target, &address);
-
- return nds32_write_memory(target, address, size, count, buffer);
-}
-
-/** Holds methods for V2 targets. */
-struct target_type nds32_v2_target = {
- .name = "nds32_v2",
-
- .poll = nds32_poll,
- .arch_state = nds32_arch_state,
-
- .target_request_data = nds32_v2_target_request_data,
-
- .halt = nds32_halt,
- .resume = nds32_resume,
- .step = nds32_step,
-
- .assert_reset = nds32_assert_reset,
- .deassert_reset = nds32_v2_deassert_reset,
-
- /* register access */
- .get_gdb_reg_list = nds32_get_gdb_reg_list,
-
- /* memory access */
- .read_buffer = nds32_v2_read_buffer,
- .write_buffer = nds32_v2_write_buffer,
- .read_memory = nds32_v2_read_memory,
- .write_memory = nds32_v2_write_memory,
-
- .checksum_memory = nds32_v2_checksum_memory,
-
- /* breakpoint/watchpoint */
- .add_breakpoint = nds32_v2_add_breakpoint,
- .remove_breakpoint = nds32_v2_remove_breakpoint,
- .add_watchpoint = nds32_v2_add_watchpoint,
- .remove_watchpoint = nds32_v2_remove_watchpoint,
- .hit_watchpoint = nds32_v2_hit_watchpoint,
-
- /* MMU */
- .mmu = nds32_mmu,
- .virt2phys = nds32_virtual_to_physical,
- .read_phys_memory = nds32_read_phys_memory,
- .write_phys_memory = nds32_write_phys_memory,
-
- .run_algorithm = nds32_v2_run_algorithm,
-
- .commands = nds32_command_handlers,
- .target_create = nds32_v2_target_create,
- .init_target = nds32_v2_init_target,
- .examine = nds32_v2_examine,
-};
diff --git a/src/target/nds32_v2.h b/src/target/nds32_v2.h
deleted file mode 100644
index dcc08c2..0000000
--- a/src/target/nds32_v2.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_V2_H
-#define OPENOCD_TARGET_NDS32_V2_H
-
-#include "nds32.h"
-
-struct nds32_v2_common {
- struct nds32 nds32;
-
- uint32_t backup_ir0;
-
- /** number of hardware breakpoints */
- int32_t n_hbr;
-
- /** next hardware breakpoint index */
- /** increase from low index to high index */
- int32_t next_hbr_index;
-};
-
-static inline struct nds32_v2_common *target_to_nds32_v2(struct target *target)
-{
- return container_of(target->arch_info, struct nds32_v2_common, nds32);
-}
-
-#endif /* OPENOCD_TARGET_NDS32_V2_H */
diff --git a/src/target/nds32_v3.c b/src/target/nds32_v3.c
deleted file mode 100644
index 43d7054..0000000
--- a/src/target/nds32_v3.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "nds32_cmd.h"
-#include "nds32_aice.h"
-#include "nds32_v3.h"
-#include "nds32_v3_common.h"
-
-static int nds32_v3_activate_hardware_breakpoint(struct target *target)
-{
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct breakpoint *bp;
- int32_t hbr_index = nds32_v3->next_hbr_index;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- if (bp->type == BKPT_SOFT) {
- /* already set at nds32_v3_add_breakpoint() */
- continue;
- } else if (bp->type == BKPT_HARD) {
- hbr_index--;
- /* set address */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
- /* set mask */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
- /* set value */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
-
- if (nds32_v3->nds32.memory.address_translation)
- /* enable breakpoint (virtual address) */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
- else
- /* enable breakpoint (physical address) */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
-
- LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index,
- bp->address);
- } else {
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3_deactivate_hardware_breakpoint(struct target *target)
-{
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct breakpoint *bp;
- int32_t hbr_index = nds32_v3->next_hbr_index;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- if (bp->type == BKPT_SOFT) {
- continue;
- } else if (bp->type == BKPT_HARD) {
- hbr_index--;
- /* disable breakpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
- } else {
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index,
- bp->address);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3_activate_hardware_watchpoint(struct target *target)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
- struct watchpoint *wp;
- int32_t wp_num = 0;
- uint32_t wp_config = 0;
- bool ld_stop, st_stop;
-
- if (nds32_v3->nds32.global_stop)
- ld_stop = st_stop = false;
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
-
- if (wp_num < nds32_v3->used_n_wp) {
- wp->mask = wp->length - 1;
- if ((wp->address % wp->length) != 0)
- wp->mask = (wp->mask << 1) + 1;
-
- if (wp->rw == WPT_READ)
- wp_config = 0x3;
- else if (wp->rw == WPT_WRITE)
- wp_config = 0x5;
- else if (wp->rw == WPT_ACCESS)
- wp_config = 0x7;
-
- /* set/unset physical address bit of BPCn according to PSW.DT */
- if (nds32_v3->nds32.memory.address_translation == false)
- wp_config |= 0x8;
-
- /* set address */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
- wp->address - (wp->address % wp->length));
- /* set mask */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
- /* enable watchpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
- /* set value */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
-
- LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32,
- wp_num, wp->address, wp->mask);
-
- wp_num++;
- } else if (nds32_v3->nds32.global_stop) {
- if (wp->rw == WPT_READ)
- ld_stop = true;
- else if (wp->rw == WPT_WRITE)
- st_stop = true;
- else if (wp->rw == WPT_ACCESS)
- ld_stop = st_stop = true;
- }
- }
-
- if (nds32_v3->nds32.global_stop) {
- uint32_t edm_ctl;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
- if (ld_stop)
- edm_ctl |= 0x10;
- if (st_stop)
- edm_ctl |= 0x20;
- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3_deactivate_hardware_watchpoint(struct target *target)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
- int32_t wp_num = 0;
- struct watchpoint *wp;
- bool clean_global_stop = false;
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
-
- if (wp_num < nds32_v3->used_n_wp) {
- /* disable watchpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
-
- LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32
- " mask %08" PRIx32, wp_num,
- wp->address, wp->mask);
- wp_num++;
- } else if (nds32_v3->nds32.global_stop) {
- clean_global_stop = true;
- }
- }
-
- if (clean_global_stop) {
- uint32_t edm_ctl;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
- edm_ctl = edm_ctl & (~0x30);
- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3_check_interrupt_stack(struct nds32 *nds32)
-{
- uint32_t val_ir0;
- uint32_t value;
-
- /* Save interrupt level */
- nds32_get_mapped_reg(nds32, IR0, &val_ir0);
- nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
-
- if (nds32_reach_max_interrupt_level(nds32))
- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
- nds32->current_interrupt_level);
-
- /* backup $ir4 & $ir6 to avoid suppressed exception overwrite */
- nds32_get_mapped_reg(nds32, IR4, &value);
- nds32_get_mapped_reg(nds32, IR6, &value);
-
- return ERROR_OK;
-}
-
-static int nds32_v3_restore_interrupt_stack(struct nds32 *nds32)
-{
- uint32_t value;
-
- /* get backup value from cache */
- /* then set back to make the register dirty */
- nds32_get_mapped_reg(nds32, IR0, &value);
- nds32_set_mapped_reg(nds32, IR0, value);
-
- nds32_get_mapped_reg(nds32, IR4, &value);
- nds32_set_mapped_reg(nds32, IR4, value);
-
- nds32_get_mapped_reg(nds32, IR6, &value);
- nds32_set_mapped_reg(nds32, IR6, value);
-
- return ERROR_OK;
-}
-
-static int nds32_v3_deassert_reset(struct target *target)
-{
- int retval;
- struct aice_port_s *aice = target_to_aice(target);
- bool switch_to_v3_stack = false;
- uint32_t value_edm_ctl;
-
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &value_edm_ctl);
- if (((value_edm_ctl >> 6) & 0x1) == 0) { /* reset to V2 EDM mode */
- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, value_edm_ctl | (0x1 << 6));
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &value_edm_ctl);
- if (((value_edm_ctl >> 6) & 0x1) == 1)
- switch_to_v3_stack = true;
- } else
- switch_to_v3_stack = false;
-
- CHECK_RETVAL(nds32_poll(target));
-
- if (target->state != TARGET_HALTED) {
- /* reset only */
- LOG_WARNING("%s: ran after reset and before halt ...",
- target_name(target));
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- } else {
- /* reset-halt */
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
- struct nds32 *nds32 = &(nds32_v3->nds32);
- uint32_t value;
- uint32_t interrupt_level;
-
- if (switch_to_v3_stack == true) {
- /* PSW.INTL-- */
- nds32_get_mapped_reg(nds32, IR0, &value);
- interrupt_level = (value >> 1) & 0x3;
- interrupt_level--;
- value &= ~(0x6);
- value |= (interrupt_level << 1);
- value |= 0x400; /* set PSW.DEX */
- nds32_set_mapped_reg(nds32, IR0, value);
-
- /* copy IPC to OIPC */
- if ((interrupt_level + 1) < nds32->max_interrupt_level) {
- nds32_get_mapped_reg(nds32, IR9, &value);
- nds32_set_mapped_reg(nds32, IR11, value);
- }
- }
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
- struct nds32 *nds32 = &(nds32_v3->nds32);
- int result;
-
- if (breakpoint->type == BKPT_HARD) {
- /* check hardware resource */
- if (nds32_v3->n_hbr <= nds32_v3->next_hbr_index) {
- LOG_WARNING("<-- TARGET WARNING! Insert too many "
- "hardware breakpoints/watchpoints! "
- "The limit of combined hardware "
- "breakpoints/watchpoints is %" PRId32 ". -->",
- nds32_v3->n_hbr);
- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
- "hardware breakpoint: %" PRId32 ", hardware "
- "watchpoints: %" PRId32 ". -->",
- nds32_v3->next_hbr_index - nds32_v3->used_n_wp,
- nds32_v3->used_n_wp);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* update next place to put hardware breakpoint */
- nds32_v3->next_hbr_index++;
-
- /* hardware breakpoint insertion occurs before 'continue' actually */
- return ERROR_OK;
- } else if (breakpoint->type == BKPT_SOFT) {
- result = nds32_add_software_breakpoint(target, breakpoint);
- if (ERROR_OK != result) {
- /* auto convert to hardware breakpoint if failed */
- if (nds32->auto_convert_hw_bp) {
- /* convert to hardware breakpoint */
- breakpoint->type = BKPT_HARD;
-
- return nds32_v3_add_breakpoint(target, breakpoint);
- }
- }
-
- return result;
- } else /* unrecognized breakpoint type */
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int nds32_v3_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
-
- if (breakpoint->type == BKPT_HARD) {
- if (nds32_v3->next_hbr_index <= 0)
- return ERROR_FAIL;
-
- /* update next place to put hardware breakpoint */
- nds32_v3->next_hbr_index--;
-
- /* hardware breakpoint removal occurs after 'halted' actually */
- return ERROR_OK;
- } else if (breakpoint->type == BKPT_SOFT) {
- return nds32_remove_software_breakpoint(target, breakpoint);
- } else /* unrecognized breakpoint type */
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int nds32_v3_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
-
- /* check hardware resource */
- if (nds32_v3->n_hbr <= nds32_v3->next_hbr_index) {
- /* No hardware resource */
- if (nds32_v3->nds32.global_stop) {
- LOG_WARNING("<-- TARGET WARNING! The number of "
- "watchpoints exceeds the hardware "
- "resources. Stop at every load/store "
- "instruction to check for watchpoint matches. -->");
- return ERROR_OK;
- }
-
- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
- "breakpoints/watchpoints! The limit of combined "
- "hardware breakpoints/watchpoints is %" PRId32 ". -->",
- nds32_v3->n_hbr);
- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
- "hardware breakpoint: %" PRId32 ", hardware "
- "watchpoints: %" PRId32 ". -->",
- nds32_v3->next_hbr_index - nds32_v3->used_n_wp,
- nds32_v3->used_n_wp);
-
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* update next place to put hardware watchpoint */
- nds32_v3->next_hbr_index++;
- nds32_v3->used_n_wp++;
-
- return ERROR_OK;
-}
-
-static int nds32_v3_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
-
- if (nds32_v3->next_hbr_index <= 0) {
- if (nds32_v3->nds32.global_stop)
- return ERROR_OK;
-
- return ERROR_FAIL;
- }
-
- /* update next place to put hardware breakpoint */
- nds32_v3->next_hbr_index--;
- nds32_v3->used_n_wp--;
-
- return ERROR_OK;
-}
-
-struct nds32_v3_common_callback nds32_v3_common_callback = {
- .check_interrupt_stack = nds32_v3_check_interrupt_stack,
- .restore_interrupt_stack = nds32_v3_restore_interrupt_stack,
- .activate_hardware_breakpoint = nds32_v3_activate_hardware_breakpoint,
- .activate_hardware_watchpoint = nds32_v3_activate_hardware_watchpoint,
- .deactivate_hardware_breakpoint = nds32_v3_deactivate_hardware_breakpoint,
- .deactivate_hardware_watchpoint = nds32_v3_deactivate_hardware_watchpoint,
-};
-
-static int nds32_v3_target_create(struct target *target, Jim_Interp *interp)
-{
- struct nds32_v3_common *nds32_v3;
-
- nds32_v3 = calloc(1, sizeof(*nds32_v3));
- if (!nds32_v3)
- return ERROR_FAIL;
-
- nds32_v3_common_register_callback(&nds32_v3_common_callback);
- nds32_v3_target_create_common(target, &(nds32_v3->nds32));
-
- return ERROR_OK;
-}
-
-/* talk to the target and set things up */
-static int nds32_v3_examine(struct target *target)
-{
- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
- struct nds32 *nds32 = &(nds32_v3->nds32);
- struct aice_port_s *aice = target_to_aice(target);
-
- if (!target_was_examined(target)) {
- CHECK_RETVAL(nds32_edm_config(nds32));
-
- if (nds32->reset_halt_as_examine)
- CHECK_RETVAL(nds32_reset_halt(nds32));
- }
-
- uint32_t edm_cfg;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
-
- /* get the number of hardware breakpoints */
- nds32_v3->n_hbr = (edm_cfg & 0x7) + 1;
-
- /* low interference profiling */
- if (edm_cfg & 0x100)
- nds32_v3->low_interference_profile = true;
- else
- nds32_v3->low_interference_profile = false;
-
- nds32_v3->next_hbr_index = 0;
- nds32_v3->used_n_wp = 0;
-
- LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target),
- nds32_v3->n_hbr);
-
- nds32->target->state = TARGET_RUNNING;
- nds32->target->debug_reason = DBG_REASON_NOTHALTED;
-
- target_set_examined(target);
-
- return ERROR_OK;
-}
-
-/** Holds methods for Andes1337 targets. */
-struct target_type nds32_v3_target = {
- .name = "nds32_v3",
-
- .poll = nds32_poll,
- .arch_state = nds32_arch_state,
-
- .target_request_data = nds32_v3_target_request_data,
-
- .halt = nds32_halt,
- .resume = nds32_resume,
- .step = nds32_step,
-
- .assert_reset = nds32_assert_reset,
- .deassert_reset = nds32_v3_deassert_reset,
-
- /* register access */
- .get_gdb_reg_list = nds32_get_gdb_reg_list,
-
- /* memory access */
- .read_buffer = nds32_v3_read_buffer,
- .write_buffer = nds32_v3_write_buffer,
- .read_memory = nds32_v3_read_memory,
- .write_memory = nds32_v3_write_memory,
-
- .checksum_memory = nds32_v3_checksum_memory,
-
- /* breakpoint/watchpoint */
- .add_breakpoint = nds32_v3_add_breakpoint,
- .remove_breakpoint = nds32_v3_remove_breakpoint,
- .add_watchpoint = nds32_v3_add_watchpoint,
- .remove_watchpoint = nds32_v3_remove_watchpoint,
- .hit_watchpoint = nds32_v3_hit_watchpoint,
-
- /* MMU */
- .mmu = nds32_mmu,
- .virt2phys = nds32_virtual_to_physical,
- .read_phys_memory = nds32_read_phys_memory,
- .write_phys_memory = nds32_write_phys_memory,
-
- .run_algorithm = nds32_v3_run_algorithm,
-
- .commands = nds32_command_handlers,
- .target_create = nds32_v3_target_create,
- .init_target = nds32_v3_init_target,
- .examine = nds32_v3_examine,
-
- .get_gdb_fileio_info = nds32_get_gdb_fileio_info,
- .gdb_fileio_end = nds32_gdb_fileio_end,
-
- .profiling = nds32_profiling,
-};
diff --git a/src/target/nds32_v3.h b/src/target/nds32_v3.h
deleted file mode 100644
index a5df8fe..0000000
--- a/src/target/nds32_v3.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_V3_H
-#define OPENOCD_TARGET_NDS32_V3_H
-
-#include "nds32.h"
-
-struct nds32_v3_common {
- struct nds32 nds32;
-
- /** number of hardware breakpoints */
- int32_t n_hbr;
-
- /** number of used hardware watchpoints */
- int32_t used_n_wp;
-
- /** next hardware breakpoint index */
- int32_t next_hbr_index;
-
- /** low interference profiling */
- bool low_interference_profile;
-};
-
-static inline struct nds32_v3_common *target_to_nds32_v3(struct target *target)
-{
- return container_of(target->arch_info, struct nds32_v3_common, nds32);
-}
-
-#endif /* OPENOCD_TARGET_NDS32_V3_H */
diff --git a/src/target/nds32_v3_common.c b/src/target/nds32_v3_common.c
deleted file mode 100644
index 191f4b5..0000000
--- a/src/target/nds32_v3_common.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "nds32_reg.h"
-#include "nds32_disassembler.h"
-#include "nds32.h"
-#include "nds32_aice.h"
-#include "nds32_v3_common.h"
-
-static struct nds32_v3_common_callback *v3_common_callback;
-
-static int nds32_v3_register_mapping(struct nds32 *nds32, int reg_no)
-{
- if (reg_no == PC)
- return IR11;
-
- return reg_no;
-}
-
-static int nds32_v3_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
-{
- uint32_t edmsw;
- struct aice_port_s *aice = target_to_aice(nds32->target);
- aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw);
-
- *reason = (edmsw >> 12) & 0x0F;
-
- return ERROR_OK;
-}
-
-/**
- * Save processor state. This is called after a HALT instruction
- * succeeds, and on other occasions the processor enters debug mode
- * (breakpoint, watchpoint, etc).
- */
-static int nds32_v3_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
-{
- LOG_DEBUG("nds32_v3_debug_entry");
-
- enum target_state backup_state = nds32->target->state;
- nds32->target->state = TARGET_HALTED;
-
- if (nds32->init_arch_info_after_halted == false) {
- /* init architecture info according to config registers */
- CHECK_RETVAL(nds32_config(nds32));
-
- nds32->init_arch_info_after_halted = true;
- }
-
- /* REVISIT entire cache should already be invalid !!! */
- register_cache_invalidate(nds32->core_cache);
-
- /* deactivate all hardware breakpoints */
- CHECK_RETVAL(v3_common_callback->deactivate_hardware_breakpoint(nds32->target));
-
- if (enable_watchpoint)
- CHECK_RETVAL(v3_common_callback->deactivate_hardware_watchpoint(nds32->target));
-
- struct breakpoint *syscall_break = &(nds32->syscall_break);
- if (nds32->virtual_hosting) {
- if (syscall_break->set) {
- /** disable virtual hosting */
-
- /* remove breakpoint at syscall entry */
- target_remove_breakpoint(nds32->target, syscall_break);
- syscall_break->set = 0;
-
- uint32_t value_pc;
- nds32_get_mapped_reg(nds32, PC, &value_pc);
- if (value_pc == syscall_break->address)
- /** process syscall for virtual hosting */
- nds32->hit_syscall = true;
- }
- }
-
- if (ERROR_OK != nds32_examine_debug_reason(nds32)) {
- nds32->target->state = backup_state;
-
- /* re-activate all hardware breakpoints & watchpoints */
- CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(nds32->target));
-
- if (enable_watchpoint)
- CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(nds32->target));
-
- return ERROR_FAIL;
- }
-
- /* Save registers. */
- nds32_full_context(nds32);
-
- /* check interrupt level */
- v3_common_callback->check_interrupt_stack(nds32);
-
- return ERROR_OK;
-}
-
-/**
- * Restore processor state.
- */
-static int nds32_v3_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
-{
- LOG_DEBUG("nds32_v3_leave_debug_state");
-
- struct target *target = nds32->target;
-
- /* activate all hardware breakpoints */
- CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(target));
-
- if (enable_watchpoint) {
- /* activate all watchpoints */
- CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(target));
- }
-
- /* restore interrupt stack */
- v3_common_callback->restore_interrupt_stack(nds32);
-
- /* REVISIT once we start caring about MMU and cache state,
- * address it here ...
- */
-
- /* restore PSW, PC, and R0 ... after flushing any modified
- * registers.
- */
- CHECK_RETVAL(nds32_restore_context(target));
-
- if (nds32->virtual_hosting) {
- /** enable virtual hosting */
- uint32_t value_ir3;
- uint32_t entry_size;
- uint32_t syscall_address;
-
- /* get syscall entry address */
- nds32_get_mapped_reg(nds32, IR3, &value_ir3);
- entry_size = 0x4 << (((value_ir3 >> 14) & 0x3) << 1);
- syscall_address = (value_ir3 & 0xFFFF0000) + entry_size * 8; /* The index of SYSCALL is 8 */
-
- if (nds32->hit_syscall) {
- /* single step to skip syscall entry */
- /* use IRET to skip syscall */
- struct aice_port_s *aice = target_to_aice(target);
- uint32_t value_ir9;
- uint32_t value_ir6;
- uint32_t syscall_id;
-
- nds32_get_mapped_reg(nds32, IR6, &value_ir6);
- syscall_id = (value_ir6 >> 16) & 0x7FFF;
-
- if (syscall_id == NDS32_SYSCALL_EXIT) {
- /* If target hits exit syscall, do not use IRET to skip handler. */
- aice_step(aice);
- } else {
- /* use api->read/write_reg to skip nds32 register cache */
- uint32_t value_dimbr;
- aice_read_debug_reg(aice, NDS_EDM_SR_DIMBR, &value_dimbr);
- aice_write_register(aice, IR11, value_dimbr + 0xC);
-
- aice_read_register(aice, IR9, &value_ir9);
- value_ir9 += 4; /* syscall is always 4 bytes */
- aice_write_register(aice, IR9, value_ir9);
-
- /* backup hardware breakpoint 0 */
- uint32_t backup_bpa, backup_bpam, backup_bpc;
- aice_read_debug_reg(aice, NDS_EDM_SR_BPA0, &backup_bpa);
- aice_read_debug_reg(aice, NDS_EDM_SR_BPAM0, &backup_bpam);
- aice_read_debug_reg(aice, NDS_EDM_SR_BPC0, &backup_bpc);
-
- /* use hardware breakpoint 0 to stop cpu after skipping syscall */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, value_ir9);
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, 0);
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, 0xA);
-
- /* Execute two IRET.
- * First IRET is used to quit debug mode.
- * Second IRET is used to quit current syscall. */
- uint32_t dim_inst[4] = {NOP, NOP, IRET, IRET};
- aice_execute(aice, dim_inst, 4);
-
- /* restore origin hardware breakpoint 0 */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, backup_bpa);
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, backup_bpam);
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, backup_bpc);
- }
-
- nds32->hit_syscall = false;
- }
-
- /* insert breakpoint at syscall entry */
- struct breakpoint *syscall_break = &(nds32->syscall_break);
-
- syscall_break->address = syscall_address;
- syscall_break->type = BKPT_SOFT;
- syscall_break->set = 1;
- target_add_breakpoint(target, syscall_break);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3_get_exception_address(struct nds32 *nds32,
- uint32_t *address, uint32_t reason)
-{
- LOG_DEBUG("nds32_v3_get_exception_address");
-
- struct aice_port_s *aice = target_to_aice(nds32->target);
- struct target *target = nds32->target;
- uint32_t edmsw;
- uint32_t edm_cfg;
- uint32_t match_bits;
- uint32_t match_count;
- int32_t i;
- static int32_t number_of_hard_break;
- uint32_t bp_control;
-
- if (number_of_hard_break == 0) {
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
- number_of_hard_break = (edm_cfg & 0x7) + 1;
- }
-
- aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw);
- /* clear matching bits (write-one-clear) */
- aice_write_debug_reg(aice, NDS_EDM_SR_EDMSW, edmsw);
- match_bits = (edmsw >> 4) & 0xFF;
- match_count = 0;
- for (i = 0 ; i < number_of_hard_break ; i++) {
- if (match_bits & (1 << i)) {
- aice_read_debug_reg(aice, NDS_EDM_SR_BPA0 + i, address);
- match_count++;
-
- /* If target hits multiple read/access watchpoint,
- * select the first one. */
- aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &bp_control);
- if (0x3 == (bp_control & 0x3)) {
- match_count = 1;
- break;
- }
- }
- }
-
- if (match_count > 1) { /* multiple hits */
- *address = 0;
- return ERROR_OK;
- } else if (match_count == 1) {
- uint32_t val_pc;
- uint32_t opcode;
- struct nds32_instruction instruction;
- struct watchpoint *wp;
- bool hit;
-
- nds32_get_mapped_reg(nds32, PC, &val_pc);
-
- if ((NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE == reason) ||
- (NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE == reason)) {
- if (edmsw & 0x4) /* check EDMSW.IS_16BIT */
- val_pc -= 2;
- else
- val_pc -= 4;
- }
-
- nds32_read_opcode(nds32, val_pc, &opcode);
- nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction);
-
- LOG_DEBUG("PC: 0x%08" PRIx32 ", access start: 0x%08" PRIx32 ", end: 0x%08" PRIx32,
- val_pc, instruction.access_start, instruction.access_end);
-
- /* check if multiple hits in the access range */
- uint32_t in_range_watch_count = 0;
- for (wp = target->watchpoints; wp; wp = wp->next) {
- if ((instruction.access_start <= wp->address) &&
- (wp->address < instruction.access_end))
- in_range_watch_count++;
- }
- if (in_range_watch_count > 1) {
- /* Hit LSMW instruction. */
- *address = 0;
- return ERROR_OK;
- }
-
- /* dispel false match */
- hit = false;
- for (wp = target->watchpoints; wp; wp = wp->next) {
- if (((*address ^ wp->address) & (~wp->mask)) == 0) {
- uint32_t watch_start;
- uint32_t watch_end;
-
- watch_start = wp->address;
- watch_end = wp->address + wp->length;
-
- if ((watch_end <= instruction.access_start) ||
- (instruction.access_end <= watch_start))
- continue;
-
- hit = true;
- break;
- }
- }
-
- if (hit)
- return ERROR_OK;
- else
- return ERROR_FAIL;
- } else if (match_count == 0) {
- /* global stop is precise exception */
- if ((NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP == reason) && nds32->global_stop) {
- /* parse instruction to get correct access address */
- uint32_t val_pc;
- uint32_t opcode;
- struct nds32_instruction instruction;
-
- nds32_get_mapped_reg(nds32, PC, &val_pc);
- nds32_read_opcode(nds32, val_pc, &opcode);
- nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction);
-
- *address = instruction.access_start;
-
- return ERROR_OK;
- }
- }
-
- *address = 0xFFFFFFFF;
- return ERROR_FAIL;
-}
-
-void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback)
-{
- v3_common_callback = callback;
-}
-
-/** target_type functions: */
-/* target request support */
-int nds32_v3_target_request_data(struct target *target,
- uint32_t size, uint8_t *buffer)
-{
- /* AndesCore could use DTR register to communicate with OpenOCD
- * to output messages
- * Target data will be put in buffer
- * The format of DTR is as follow
- * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
- * target_req_cmd has three possible values:
- * TARGET_REQ_TRACEMSG
- * TARGET_REQ_DEBUGMSG
- * TARGET_REQ_DEBUGCHAR
- * if size == 0, target will call target_asciimsg(),
- * else call target_hexmsg()
- */
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_OK;
-}
-
-int nds32_v3_checksum_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *checksum)
-{
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_FAIL;
-}
-
-/**
- * find out which watchpoint hits
- * get exception address and compare the address to watchpoints
- */
-int nds32_v3_hit_watchpoint(struct target *target,
- struct watchpoint **hit_watchpoint)
-{
- static struct watchpoint scan_all_watchpoint;
-
- uint32_t exception_address;
- struct watchpoint *wp;
- struct nds32 *nds32 = target_to_nds32(target);
-
- exception_address = nds32->watched_address;
-
- if (exception_address == 0xFFFFFFFF)
- return ERROR_FAIL;
-
- if (exception_address == 0) {
- scan_all_watchpoint.address = 0;
- scan_all_watchpoint.rw = WPT_WRITE;
- scan_all_watchpoint.next = 0;
- scan_all_watchpoint.unique_id = 0x5CA8;
-
- *hit_watchpoint = &scan_all_watchpoint;
- return ERROR_OK;
- }
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
- if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
- *hit_watchpoint = wp;
-
- return ERROR_OK;
- }
- }
-
- return ERROR_FAIL;
-}
-
-int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32)
-{
- nds32->register_map = nds32_v3_register_mapping;
- nds32->get_debug_reason = nds32_v3_get_debug_reason;
- nds32->enter_debug_state = nds32_v3_debug_entry;
- nds32->leave_debug_state = nds32_v3_leave_debug_state;
- nds32->get_watched_address = nds32_v3_get_exception_address;
-
- /* Init target->arch_info in nds32_init_arch_info().
- * After this, user could use target_to_nds32() to get nds32 object */
- nds32_init_arch_info(target, nds32);
-
- return ERROR_OK;
-}
-
-int nds32_v3_run_algorithm(struct target *target,
- int num_mem_params,
- struct mem_param *mem_params,
- int num_reg_params,
- struct reg_param *reg_params,
- uint32_t entry_point,
- uint32_t exit_point,
- int timeout_ms,
- void *arch_info)
-{
- LOG_WARNING("Not implemented: %s", __func__);
-
- return ERROR_FAIL;
-}
-
-int nds32_v3_read_buffer(struct target *target, uint32_t address,
- uint32_t size, uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t physical_address;
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- /* When DEX is set to one, hardware will enforce the following behavior without
- * modifying the corresponding control bits in PSW.
- *
- * Disable all interrupts
- * Become superuser mode
- * Turn off IT/DT
- * Use MMU_CFG.DE as the data access endian
- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
- * Disable audio special features
- * Disable inline function call
- *
- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
- * to physical address.
- */
- if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
- address = physical_address;
- else
- return ERROR_FAIL;
-
- int result;
- struct aice_port_s *aice = target_to_aice(target);
- /* give arbitrary initial value to avoid warning messages */
- enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU;
-
- if (nds32->hit_syscall) {
- /* Use bus mode to access memory during virtual hosting */
- origin_access_channel = memory->access_channel;
- memory->access_channel = NDS_MEMORY_ACC_BUS;
- aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
- }
-
- result = nds32_read_buffer(target, address, size, buffer);
-
- if (nds32->hit_syscall) {
- /* Restore access_channel after virtual hosting */
- memory->access_channel = origin_access_channel;
- aice_memory_access(aice, origin_access_channel);
- }
-
- return result;
-}
-
-int nds32_v3_write_buffer(struct target *target, uint32_t address,
- uint32_t size, const uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t physical_address;
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- /* When DEX is set to one, hardware will enforce the following behavior without
- * modifying the corresponding control bits in PSW.
- *
- * Disable all interrupts
- * Become superuser mode
- * Turn off IT/DT
- * Use MMU_CFG.DE as the data access endian
- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
- * Disable audio special features
- * Disable inline function call
- *
- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
- * to physical address.
- */
- if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
- address = physical_address;
- else
- return ERROR_FAIL;
-
- if (nds32->hit_syscall) {
- struct aice_port_s *aice = target_to_aice(target);
- enum nds_memory_access origin_access_channel;
- origin_access_channel = memory->access_channel;
-
- /* If target has no cache, use BUS mode to access memory. */
- if ((memory->dcache.line_size == 0)
- || (memory->dcache.enable == false)) {
- /* There is no Dcache or Dcache is disabled. */
- memory->access_channel = NDS_MEMORY_ACC_BUS;
- aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
- }
-
- int result;
- result = nds32_gdb_fileio_write_memory(nds32, address, size, buffer);
-
- if (NDS_MEMORY_ACC_CPU == origin_access_channel) {
- memory->access_channel = NDS_MEMORY_ACC_CPU;
- aice_memory_access(aice, NDS_MEMORY_ACC_CPU);
- }
-
- return result;
- }
-
- return nds32_write_buffer(target, address, size, buffer);
-}
-
-int nds32_v3_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t physical_address;
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- /* When DEX is set to one, hardware will enforce the following behavior without
- * modifying the corresponding control bits in PSW.
- *
- * Disable all interrupts
- * Become superuser mode
- * Turn off IT/DT
- * Use MMU_CFG.DE as the data access endian
- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
- * Disable audio special features
- * Disable inline function call
- *
- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
- * to physical address.
- */
- if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
- address = physical_address;
- else
- return ERROR_FAIL;
-
- struct aice_port_s *aice = target_to_aice(target);
- /* give arbitrary initial value to avoid warning messages */
- enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU;
- int result;
-
- if (nds32->hit_syscall) {
- /* Use bus mode to access memory during virtual hosting */
- origin_access_channel = memory->access_channel;
- memory->access_channel = NDS_MEMORY_ACC_BUS;
- aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
- }
-
- result = nds32_read_memory(target, address, size, count, buffer);
-
- if (nds32->hit_syscall) {
- /* Restore access_channel after virtual hosting */
- memory->access_channel = origin_access_channel;
- aice_memory_access(aice, origin_access_channel);
- }
-
- return result;
-}
-
-int nds32_v3_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct nds32 *nds32 = target_to_nds32(target);
- struct nds32_memory *memory = &(nds32->memory);
-
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
- (target->state != TARGET_HALTED)) {
- LOG_WARNING("target was not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint32_t physical_address;
- /* BUG: If access range crosses multiple pages, the translation will not correct
- * for second page or so. */
-
- /* When DEX is set to one, hardware will enforce the following behavior without
- * modifying the corresponding control bits in PSW.
- *
- * Disable all interrupts
- * Become superuser mode
- * Turn off IT/DT
- * Use MMU_CFG.DE as the data access endian
- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
- * Disable audio special features
- * Disable inline function call
- *
- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
- * to physical address.
- */
- if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
- address = physical_address;
- else
- return ERROR_FAIL;
-
- return nds32_write_memory(target, address, size, count, buffer);
-}
-
-int nds32_v3_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- /* Initialize anything we can set up without talking to the target */
- struct nds32 *nds32 = target_to_nds32(target);
-
- nds32_init(nds32);
-
- target->fileio_info = malloc(sizeof(struct gdb_fileio_info));
- target->fileio_info->identifier = NULL;
-
- return ERROR_OK;
-}
diff --git a/src/target/nds32_v3_common.h b/src/target/nds32_v3_common.h
deleted file mode 100644
index 1f5df19..0000000
--- a/src/target/nds32_v3_common.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_V3_COMMON_H
-#define OPENOCD_TARGET_NDS32_V3_COMMON_H
-
-#include "target.h"
-
-struct nds32_v3_common_callback {
- int (*check_interrupt_stack)(struct nds32 *nds32);
- int (*restore_interrupt_stack)(struct nds32 *nds32);
- int (*activate_hardware_breakpoint)(struct target *target);
- int (*activate_hardware_watchpoint)(struct target *target);
- int (*deactivate_hardware_breakpoint)(struct target *target);
- int (*deactivate_hardware_watchpoint)(struct target *target);
-};
-
-void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback);
-int nds32_v3_target_request_data(struct target *target,
- uint32_t size, uint8_t *buffer);
-int nds32_v3_checksum_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *checksum);
-int nds32_v3_hit_watchpoint(struct target *target,
- struct watchpoint **hit_watchpoint);
-int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32);
-int nds32_v3_run_algorithm(struct target *target,
- int num_mem_params,
- struct mem_param *mem_params,
- int num_reg_params,
- struct reg_param *reg_params,
- uint32_t entry_point,
- uint32_t exit_point,
- int timeout_ms,
- void *arch_info);
-int nds32_v3_read_buffer(struct target *target, uint32_t address,
- uint32_t size, uint8_t *buffer);
-int nds32_v3_write_buffer(struct target *target, uint32_t address,
- uint32_t size, const uint8_t *buffer);
-int nds32_v3_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer);
-int nds32_v3_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-int nds32_v3_init_target(struct command_context *cmd_ctx,
- struct target *target);
-
-#endif /* OPENOCD_TARGET_NDS32_V3_COMMON_H */
diff --git a/src/target/nds32_v3m.c b/src/target/nds32_v3m.c
deleted file mode 100644
index 919c0c8..0000000
--- a/src/target/nds32_v3m.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "nds32_cmd.h"
-#include "nds32_aice.h"
-#include "nds32_v3m.h"
-#include "nds32_v3_common.h"
-
-static int nds32_v3m_activate_hardware_breakpoint(struct target *target)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct breakpoint *bp;
- unsigned brp_num = nds32_v3m->n_hbr - 1;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- if (bp->type == BKPT_SOFT) {
- /* already set at nds32_v3m_add_breakpoint() */
- continue;
- } else if (bp->type == BKPT_HARD) {
- /* set address */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + brp_num, bp->address);
- /* set mask */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + brp_num, 0);
-
- if (nds32_v3m->nds32.memory.address_translation)
- /* enable breakpoint (virtual address) */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0x2);
- else
- /* enable breakpoint (physical address) */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0xA);
-
- LOG_DEBUG("Add hardware BP %u at %08" PRIx32, brp_num,
- bp->address);
-
- brp_num--;
- } else {
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_deactivate_hardware_breakpoint(struct target *target)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct breakpoint *bp;
- unsigned brp_num = nds32_v3m->n_hbr - 1;
-
- for (bp = target->breakpoints; bp; bp = bp->next) {
- if (bp->type == BKPT_SOFT)
- continue;
- else if (bp->type == BKPT_HARD)
- /* disable breakpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0x0);
- else
- return ERROR_FAIL;
-
- LOG_DEBUG("Remove hardware BP %u at %08" PRIx32, brp_num,
- bp->address);
-
- brp_num--;
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_activate_hardware_watchpoint(struct target *target)
-{
- struct aice_port_s *aice = target_to_aice(target);
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
- struct watchpoint *wp;
- int32_t wp_num = 0;
- uint32_t wp_config = 0;
- bool ld_stop, st_stop;
-
- if (nds32_v3m->nds32.global_stop)
- ld_stop = st_stop = false;
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
-
- if (wp_num < nds32_v3m->used_n_wp) {
- wp->mask = wp->length - 1;
- if ((wp->address % wp->length) != 0)
- wp->mask = (wp->mask << 1) + 1;
-
- if (wp->rw == WPT_READ)
- wp_config = 0x3;
- else if (wp->rw == WPT_WRITE)
- wp_config = 0x5;
- else if (wp->rw == WPT_ACCESS)
- wp_config = 0x7;
-
- /* set/unset physical address bit of BPCn according to PSW.DT */
- if (nds32_v3m->nds32.memory.address_translation == false)
- wp_config |= 0x8;
-
- /* set address */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
- wp->address - (wp->address % wp->length));
- /* set mask */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
- /* enable watchpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
-
- LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32
- " mask %08" PRIx32, wp_num, wp->address, wp->mask);
-
- wp_num++;
- } else if (nds32_v3m->nds32.global_stop) {
- if (wp->rw == WPT_READ)
- ld_stop = true;
- else if (wp->rw == WPT_WRITE)
- st_stop = true;
- else if (wp->rw == WPT_ACCESS)
- ld_stop = st_stop = true;
- }
- }
-
- if (nds32_v3m->nds32.global_stop) {
- uint32_t edm_ctl;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
- if (ld_stop)
- edm_ctl |= 0x10;
- if (st_stop)
- edm_ctl |= 0x20;
- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_deactivate_hardware_watchpoint(struct target *target)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
- struct aice_port_s *aice = target_to_aice(target);
- struct watchpoint *wp;
- int32_t wp_num = 0;
- bool clean_global_stop = false;
-
- for (wp = target->watchpoints; wp; wp = wp->next) {
-
- if (wp_num < nds32_v3m->used_n_wp) {
- /* disable watchpoint */
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
-
- LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32
- " mask %08" PRIx32, wp_num, wp->address, wp->mask);
- wp_num++;
- } else if (nds32_v3m->nds32.global_stop) {
- clean_global_stop = true;
- }
- }
-
- if (clean_global_stop) {
- uint32_t edm_ctl;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
- edm_ctl = edm_ctl & (~0x30);
- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_check_interrupt_stack(struct nds32 *nds32)
-{
- uint32_t val_ir0;
- uint32_t value;
-
- /* Save interrupt level */
- nds32_get_mapped_reg(nds32, IR0, &val_ir0);
- nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
-
- if (nds32_reach_max_interrupt_level(nds32))
- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
- nds32->current_interrupt_level);
-
- /* backup $ir6 to avoid suppressed exception overwrite */
- nds32_get_mapped_reg(nds32, IR6, &value);
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_restore_interrupt_stack(struct nds32 *nds32)
-{
- uint32_t value;
-
- /* get backup value from cache */
- /* then set back to make the register dirty */
- nds32_get_mapped_reg(nds32, IR0, &value);
- nds32_set_mapped_reg(nds32, IR0, value);
-
- nds32_get_mapped_reg(nds32, IR6, &value);
- nds32_set_mapped_reg(nds32, IR6, value);
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_deassert_reset(struct target *target)
-{
- int retval;
-
- CHECK_RETVAL(nds32_poll(target));
-
- if (target->state != TARGET_HALTED) {
- /* reset only */
- LOG_WARNING("%s: ran after reset and before halt ...",
- target_name(target));
- retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- }
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
- struct nds32 *nds32 = &(nds32_v3m->nds32);
- int result;
-
- if (breakpoint->type == BKPT_HARD) {
- /* check hardware resource */
- if (nds32_v3m->next_hbr_index < nds32_v3m->next_hwp_index) {
- LOG_WARNING("<-- TARGET WARNING! Insert too many "
- "hardware breakpoints/watchpoints! "
- "The limit of combined hardware "
- "breakpoints/watchpoints is %" PRId32 ". -->",
- nds32_v3m->n_hbr);
- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
- "hardware breakpoint: %" PRId32 ", hardware "
- "watchpoints: %" PRId32 ". -->",
- nds32_v3m->n_hbr - nds32_v3m->next_hbr_index - 1,
- nds32_v3m->used_n_wp);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* update next place to put hardware breakpoint */
- nds32_v3m->next_hbr_index--;
-
- /* hardware breakpoint insertion occurs before 'continue' actually */
- return ERROR_OK;
- } else if (breakpoint->type == BKPT_SOFT) {
- result = nds32_add_software_breakpoint(target, breakpoint);
- if (ERROR_OK != result) {
- /* auto convert to hardware breakpoint if failed */
- if (nds32->auto_convert_hw_bp) {
- /* convert to hardware breakpoint */
- breakpoint->type = BKPT_HARD;
-
- return nds32_v3m_add_breakpoint(target, breakpoint);
- }
- }
-
- return result;
- } else /* unrecognized breakpoint type */
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
-
- if (breakpoint->type == BKPT_HARD) {
- if (nds32_v3m->next_hbr_index >= nds32_v3m->n_hbr - 1)
- return ERROR_FAIL;
-
- /* update next place to put hardware breakpoint */
- nds32_v3m->next_hbr_index++;
-
- /* hardware breakpoint removal occurs after 'halted' actually */
- return ERROR_OK;
- } else if (breakpoint->type == BKPT_SOFT) {
- return nds32_remove_software_breakpoint(target, breakpoint);
- } else /* unrecognized breakpoint type */
- return ERROR_FAIL;
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
-
- /* check hardware resource */
- if (nds32_v3m->next_hwp_index >= nds32_v3m->n_hwp) {
- /* No hardware resource */
- if (nds32_v3m->nds32.global_stop) {
- LOG_WARNING("<-- TARGET WARNING! The number of "
- "watchpoints exceeds the hardware "
- "resources. Stop at every load/store "
- "instruction to check for watchpoint matches. -->");
- return ERROR_OK;
- }
-
- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
- "watchpoints! The limit of hardware watchpoints "
- "is %" PRId32 ". -->", nds32_v3m->n_hwp);
- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
- "hardware watchpoint: %" PRId32 ". -->",
- nds32_v3m->used_n_wp);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (nds32_v3m->next_hwp_index > nds32_v3m->next_hbr_index) {
- /* No hardware resource */
- if (nds32_v3m->nds32.global_stop) {
- LOG_WARNING("<-- TARGET WARNING! The number of "
- "watchpoints exceeds the hardware "
- "resources. Stop at every load/store "
- "instruction to check for watchpoint matches. -->");
- return ERROR_OK;
- }
-
- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
- "breakpoints/watchpoints! The limit of combined "
- "hardware breakpoints/watchpoints is %" PRId32 ". -->",
- nds32_v3m->n_hbr);
- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
- "hardware breakpoint: %" PRId32 ", hardware "
- "watchpoints: %" PRId32 ". -->",
- nds32_v3m->n_hbr - nds32_v3m->next_hbr_index - 1,
- nds32_v3m->used_n_wp);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* update next place to put hardware watchpoint */
- nds32_v3m->next_hwp_index++;
- nds32_v3m->used_n_wp++;
-
- return ERROR_OK;
-}
-
-static int nds32_v3m_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
-
- if (nds32_v3m->next_hwp_index <= 0) {
- if (nds32_v3m->nds32.global_stop)
- return ERROR_OK;
-
- return ERROR_FAIL;
- }
-
- /* update next place to put hardware watchpoint */
- nds32_v3m->next_hwp_index--;
- nds32_v3m->used_n_wp--;
-
- return ERROR_OK;
-}
-
-struct nds32_v3_common_callback nds32_v3m_common_callback = {
- .check_interrupt_stack = nds32_v3m_check_interrupt_stack,
- .restore_interrupt_stack = nds32_v3m_restore_interrupt_stack,
- .activate_hardware_breakpoint = nds32_v3m_activate_hardware_breakpoint,
- .activate_hardware_watchpoint = nds32_v3m_activate_hardware_watchpoint,
- .deactivate_hardware_breakpoint = nds32_v3m_deactivate_hardware_breakpoint,
- .deactivate_hardware_watchpoint = nds32_v3m_deactivate_hardware_watchpoint,
-};
-
-static int nds32_v3m_target_create(struct target *target, Jim_Interp *interp)
-{
- struct nds32_v3m_common *nds32_v3m;
-
- nds32_v3m = calloc(1, sizeof(*nds32_v3m));
- if (!nds32_v3m)
- return ERROR_FAIL;
-
- nds32_v3_common_register_callback(&nds32_v3m_common_callback);
- nds32_v3_target_create_common(target, &(nds32_v3m->nds32));
-
- return ERROR_OK;
-}
-
-/* talk to the target and set things up */
-static int nds32_v3m_examine(struct target *target)
-{
- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
- struct nds32 *nds32 = &(nds32_v3m->nds32);
- struct aice_port_s *aice = target_to_aice(target);
-
- if (!target_was_examined(target)) {
- CHECK_RETVAL(nds32_edm_config(nds32));
-
- if (nds32->reset_halt_as_examine)
- CHECK_RETVAL(nds32_reset_halt(nds32));
- }
-
- uint32_t edm_cfg;
- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
-
- /* get the number of hardware breakpoints */
- nds32_v3m->n_hbr = (edm_cfg & 0x7) + 1;
- nds32_v3m->used_n_wp = 0;
-
- /* get the number of hardware watchpoints */
- /* If the WP field is hardwired to zero, it means this is a
- * simple breakpoint. Otherwise, if the WP field is writable
- * then it means this is a regular watchpoints. */
- nds32_v3m->n_hwp = 0;
- for (int32_t i = 0 ; i < nds32_v3m->n_hbr ; i++) {
- /** check the hardware breakpoint is simple or not */
- uint32_t tmp_value;
- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + i, 0x1);
- aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &tmp_value);
-
- if (tmp_value)
- nds32_v3m->n_hwp++;
- }
- /* hardware breakpoint is inserted from high index to low index */
- nds32_v3m->next_hbr_index = nds32_v3m->n_hbr - 1;
- /* hardware watchpoint is inserted from low index to high index */
- nds32_v3m->next_hwp_index = 0;
-
- LOG_INFO("%s: total hardware breakpoint %" PRId32 " (simple breakpoint %" PRId32 ")",
- target_name(target), nds32_v3m->n_hbr, nds32_v3m->n_hbr - nds32_v3m->n_hwp);
- LOG_INFO("%s: total hardware watchpoint %" PRId32, target_name(target), nds32_v3m->n_hwp);
-
- nds32->target->state = TARGET_RUNNING;
- nds32->target->debug_reason = DBG_REASON_NOTHALTED;
-
- target_set_examined(target);
-
- return ERROR_OK;
-}
-
-/** Holds methods for NDS32 V3m targets. */
-struct target_type nds32_v3m_target = {
- .name = "nds32_v3m",
-
- .poll = nds32_poll,
- .arch_state = nds32_arch_state,
-
- .target_request_data = nds32_v3_target_request_data,
-
- .halt = nds32_halt,
- .resume = nds32_resume,
- .step = nds32_step,
-
- .assert_reset = nds32_assert_reset,
- .deassert_reset = nds32_v3m_deassert_reset,
-
- /* register access */
- .get_gdb_reg_list = nds32_get_gdb_reg_list,
-
- /* memory access */
- .read_buffer = nds32_v3_read_buffer,
- .write_buffer = nds32_v3_write_buffer,
- .read_memory = nds32_v3_read_memory,
- .write_memory = nds32_v3_write_memory,
-
- .checksum_memory = nds32_v3_checksum_memory,
-
- /* breakpoint/watchpoint */
- .add_breakpoint = nds32_v3m_add_breakpoint,
- .remove_breakpoint = nds32_v3m_remove_breakpoint,
- .add_watchpoint = nds32_v3m_add_watchpoint,
- .remove_watchpoint = nds32_v3m_remove_watchpoint,
- .hit_watchpoint = nds32_v3_hit_watchpoint,
-
- /* MMU */
- .mmu = nds32_mmu,
- .virt2phys = nds32_virtual_to_physical,
- .read_phys_memory = nds32_read_phys_memory,
- .write_phys_memory = nds32_write_phys_memory,
-
- .run_algorithm = nds32_v3_run_algorithm,
-
- .commands = nds32_command_handlers,
- .target_create = nds32_v3m_target_create,
- .init_target = nds32_v3_init_target,
- .examine = nds32_v3m_examine,
-
- .get_gdb_fileio_info = nds32_get_gdb_fileio_info,
- .gdb_fileio_end = nds32_gdb_fileio_end,
-};
diff --git a/src/target/nds32_v3m.h b/src/target/nds32_v3m.h
deleted file mode 100644
index 1e7427c..0000000
--- a/src/target/nds32_v3m.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Andes Technology *
- * Hsiangkai Wang <hkwang@andestech.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_NDS32_V3M_H
-#define OPENOCD_TARGET_NDS32_V3M_H
-
-#include "nds32.h"
-
-struct nds32_v3m_common {
- struct nds32 nds32;
-
- /** number of hardware breakpoints */
- int32_t n_hbr;
-
- /** number of hardware watchpoints */
- int32_t n_hwp;
-
- /** number of used hardware watchpoints */
- int32_t used_n_wp;
-
- /** next hardware breakpoint index */
- /** for simple breakpoints, hardware breakpoints are inserted
- * from high index to low index */
- int32_t next_hbr_index;
-
- /** next hardware watchpoint index */
- /** increase from low index to high index */
- int32_t next_hwp_index;
-};
-
-static inline struct nds32_v3m_common *target_to_nds32_v3m(struct target *target)
-{
- return container_of(target->arch_info, struct nds32_v3m_common, nds32);
-}
-
-#endif /* OPENOCD_TARGET_NDS32_V3M_H */
diff --git a/src/target/oocd_trace.c b/src/target/oocd_trace.c
deleted file mode 100644
index 627366d..0000000
--- a/src/target/oocd_trace.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm.h"
-#include "etm.h"
-#include "oocd_trace.h"
-
-/*
- * This is "proof of concept" code, for prototype hardware:
- * https://lists.berlios.de/pipermail/openocd-development/2007-September/000336.html
- */
-
-static int oocd_trace_read_reg(struct oocd_trace *oocd_trace, int reg, uint32_t *value)
-{
- size_t bytes_written, bytes_read, bytes_to_read;
- uint8_t cmd;
-
- cmd = 0x10 | (reg & 0x7);
- bytes_written = write(oocd_trace->tty_fd, &cmd, 1);
- if (bytes_written < 1)
- return ERROR_FAIL;
-
- bytes_to_read = 4;
- while (bytes_to_read > 0) {
- bytes_read = read(oocd_trace->tty_fd, ((uint8_t *)value) + 4 - bytes_to_read, bytes_to_read);
- bytes_to_read -= bytes_read;
- }
-
- LOG_DEBUG("reg #%i: 0x%8.8x", reg, *value);
-
- return ERROR_OK;
-}
-
-static int oocd_trace_write_reg(struct oocd_trace *oocd_trace, int reg, uint32_t value)
-{
- size_t bytes_written;
- uint8_t data[5];
-
- data[0] = 0x18 | (reg & 0x7);
- data[1] = value & 0xff;
- data[2] = (value & 0xff00) >> 8;
- data[3] = (value & 0xff0000) >> 16;
- data[4] = (value & 0xff000000) >> 24;
-
- bytes_written = write(oocd_trace->tty_fd, data, 5);
- if (bytes_written < 5)
- return ERROR_FAIL;
-
- LOG_DEBUG("reg #%i: 0x%8.8x", reg, value);
-
- return ERROR_OK;
-}
-
-static int oocd_trace_read_memory(struct oocd_trace *oocd_trace, uint8_t *data, uint32_t address, uint32_t size)
-{
- size_t bytes_written, bytes_to_read;
- ssize_t bytes_read;
- uint8_t cmd;
-
- oocd_trace_write_reg(oocd_trace, OOCD_TRACE_ADDRESS, address);
- oocd_trace_write_reg(oocd_trace, OOCD_TRACE_SDRAM_COUNTER, size);
-
- cmd = 0x20;
- bytes_written = write(oocd_trace->tty_fd, &cmd, 1);
- if (bytes_written < 1)
- return ERROR_FAIL;
-
- bytes_to_read = size * 16;
- while (bytes_to_read > 0) {
- bytes_read = read(oocd_trace->tty_fd,
- ((uint8_t *)data) + (size * 16) - bytes_to_read, bytes_to_read);
- if (bytes_read < 0)
- LOG_DEBUG("read() returned %zi (%s)", bytes_read, strerror(errno));
- else
- bytes_to_read -= bytes_read;
- }
-
- return ERROR_OK;
-}
-
-static int oocd_trace_init(struct etm_context *etm_ctx)
-{
- uint8_t trash[256];
- struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv;
- size_t bytes_read;
-
- oocd_trace->tty_fd = open(oocd_trace->tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
-
- if (oocd_trace->tty_fd < 0) {
- LOG_ERROR("can't open tty");
- return ERROR_ETM_CAPTURE_INIT_FAILED;
- }
-
- /* clear input & output buffers, then switch to "blocking mode" */
- tcflush(oocd_trace->tty_fd, TCOFLUSH);
- tcflush(oocd_trace->tty_fd, TCIFLUSH);
- fcntl(oocd_trace->tty_fd, F_SETFL, fcntl(oocd_trace->tty_fd, F_GETFL) & ~O_NONBLOCK);
-
- tcgetattr(oocd_trace->tty_fd, &oocd_trace->oldtio); /* save current port settings */
-
- bzero(&oocd_trace->newtio, sizeof(oocd_trace->newtio));
- oocd_trace->newtio.c_cflag = CS8 | CLOCAL | CREAD | B2500000;
-
- oocd_trace->newtio.c_iflag = IGNPAR | IGNBRK | IXON | IXOFF;
- oocd_trace->newtio.c_oflag = 0;
-
- /* set input mode (non-canonical, no echo,...) */
- oocd_trace->newtio.c_lflag = 0;
-
- cfmakeraw(&oocd_trace->newtio);
- oocd_trace->newtio.c_cc[VTIME] = 1; /* inter-character timer used */
- oocd_trace->newtio.c_cc[VMIN] = 0; /* blocking read until 0 chars received */
-
- tcflush(oocd_trace->tty_fd, TCIFLUSH);
- tcsetattr(oocd_trace->tty_fd, TCSANOW, &oocd_trace->newtio);
-
- /* occasionally one bogus character is left in the input buffer
- * read up any leftover characters to ensure communication is in sync */
- do {
- bytes_read = read(oocd_trace->tty_fd, trash, sizeof(trash));
- if (bytes_read)
- LOG_DEBUG("%zi bytes read", bytes_read);
- } while (bytes_read > 0);
-
- return ERROR_OK;
-}
-
-static trace_status_t oocd_trace_status(struct etm_context *etm_ctx)
-{
- struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv;
- uint32_t status;
-
- oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status);
-
- /* if tracing is currently idle, return this information */
- if (etm_ctx->capture_status == TRACE_IDLE)
- return etm_ctx->capture_status;
- else if (etm_ctx->capture_status & TRACE_RUNNING) {
- /* check Full bit to identify an overflow */
- if (status & 0x4)
- etm_ctx->capture_status |= TRACE_OVERFLOWED;
-
- /* check Triggered bit to identify trigger condition */
- if (status & 0x2)
- etm_ctx->capture_status |= TRACE_TRIGGERED;
-
- if (status & 0x1) {
- etm_ctx->capture_status &= ~TRACE_RUNNING;
- etm_ctx->capture_status |= TRACE_COMPLETED;
- }
- }
-
- return etm_ctx->capture_status;
-}
-
-static int oocd_trace_read_trace(struct etm_context *etm_ctx)
-{
- struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv;
- uint32_t status, address;
- uint32_t first_frame = 0x0;
- uint32_t num_frames = 1048576;
- uint8_t *trace_data;
- uint32_t i;
-
- oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status);
- oocd_trace_read_reg(oocd_trace, OOCD_TRACE_ADDRESS, &address);
-
- /* check if we overflowed, and adjust first frame of the trace accordingly
- * if we didn't overflow, read only up to the frame that would be written next,
- * i.e. don't read invalid entries
- */
- if (status & 0x4)
- first_frame = address;
- else
- num_frames = address;
-
- /* read data into temporary array for unpacking
- * one frame from OpenOCD + trace corresponds to 16 trace cycles
- */
- trace_data = malloc(sizeof(uint8_t) * num_frames * 16);
- oocd_trace_read_memory(oocd_trace, trace_data, first_frame, num_frames);
-
- if (etm_ctx->trace_depth > 0)
- free(etm_ctx->trace_data);
-
- etm_ctx->trace_depth = num_frames * 16;
- etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth);
-
- for (i = 0; i < num_frames * 16; i++) {
- etm_ctx->trace_data[i].pipestat = (trace_data[i] & 0x7);
- etm_ctx->trace_data[i].packet = (trace_data[i] & 0x78) >> 3;
- etm_ctx->trace_data[i].flags = 0;
-
- if ((trace_data[i] & 0x80) >> 7)
- etm_ctx->trace_data[i].flags |= ETMV1_TRACESYNC_CYCLE;
-
- if (etm_ctx->trace_data[i].pipestat == STAT_TR) {
- etm_ctx->trace_data[i].pipestat = etm_ctx->trace_data[i].packet & 0x7;
- etm_ctx->trace_data[i].flags |= ETMV1_TRIGGER_CYCLE;
- }
- }
-
- free(trace_data);
-
- return ERROR_OK;
-}
-
-static int oocd_trace_start_capture(struct etm_context *etm_ctx)
-{
- struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv;
- uint32_t control = 0x1; /* 0x1: enabled */
- uint32_t trigger_count;
-
- if (((etm_ctx->control & ETM_PORT_MODE_MASK) != ETM_PORT_NORMAL)
- || ((etm_ctx->control & ETM_PORT_WIDTH_MASK) != ETM_PORT_4BIT)) {
- LOG_DEBUG("OpenOCD + trace only supports normal 4-bit ETM mode");
- return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
- }
-
- if ((etm_ctx->control & ETM_PORT_CLOCK_MASK) == ETM_PORT_HALF_CLOCK)
- control |= 0x2; /* half rate clock, capture at twice the clock rate */
-
- /* OpenOCD + trace holds up to 16 million samples,
- * but trigger counts is set in multiples of 16 */
- trigger_count = (1048576 * /* trigger_percent */ 50) / 100;
-
- /* capturing always starts at address zero */
- oocd_trace_write_reg(oocd_trace, OOCD_TRACE_ADDRESS, 0x0);
- oocd_trace_write_reg(oocd_trace, OOCD_TRACE_TRIGGER_COUNTER, trigger_count);
- oocd_trace_write_reg(oocd_trace, OOCD_TRACE_CONTROL, control);
-
- /* we're starting a new trace, initialize capture status */
- etm_ctx->capture_status = TRACE_RUNNING;
-
- return ERROR_OK;
-}
-
-static int oocd_trace_stop_capture(struct etm_context *etm_ctx)
-{
- struct oocd_trace *oocd_trace = etm_ctx->capture_driver_priv;
-
- /* trace stopped, just clear running flag, but preserve others */
- etm_ctx->capture_status &= ~TRACE_RUNNING;
-
- oocd_trace_write_reg(oocd_trace, OOCD_TRACE_CONTROL, 0x0);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_oocd_trace_config_command)
-{
- struct target *target;
- struct arm *arm;
-
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_current_target(CMD_CTX);
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- if (arm->etm) {
- struct oocd_trace *oocd_trace = malloc(sizeof(struct oocd_trace));
-
- arm->etm->capture_driver_priv = oocd_trace;
- oocd_trace->etm_ctx = arm->etm;
-
- /* copy name of TTY device used to communicate with OpenOCD + trace */
- oocd_trace->tty = strndup(CMD_ARGV[1], 256);
- } else
- LOG_ERROR("target has no ETM defined, OpenOCD + trace left unconfigured");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_oocd_trace_status_command)
-{
- struct target *target;
- struct arm *arm;
- struct oocd_trace *oocd_trace;
- uint32_t status;
-
- target = get_current_target(CMD_CTX);
-
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- if (!arm->etm) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0) {
- command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'");
- return ERROR_FAIL;
- }
-
- oocd_trace = (struct oocd_trace *)arm->etm->capture_driver_priv;
-
- oocd_trace_read_reg(oocd_trace, OOCD_TRACE_STATUS, &status);
-
- if (status & 0x8)
- command_print(CMD_CTX, "trace clock locked");
- else
- command_print(CMD_CTX, "no trace clock");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_oocd_trace_resync_command)
-{
- struct target *target;
- struct arm *arm;
- struct oocd_trace *oocd_trace;
- size_t bytes_written;
- uint8_t cmd_array[1];
-
- target = get_current_target(CMD_CTX);
-
- arm = target_to_arm(target);
- if (!is_arm(arm)) {
- command_print(CMD_CTX, "current target isn't an ARM");
- return ERROR_FAIL;
- }
-
- if (!arm->etm) {
- command_print(CMD_CTX, "current target doesn't have an ETM configured");
- return ERROR_FAIL;
- }
-
- if (strcmp(arm->etm->capture_driver->name, "oocd_trace") != 0) {
- command_print(CMD_CTX, "current target's ETM capture driver isn't 'oocd_trace'");
- return ERROR_FAIL;
- }
-
- oocd_trace = (struct oocd_trace *)arm->etm->capture_driver_priv;
-
- cmd_array[0] = 0xf0;
-
- bytes_written = write(oocd_trace->tty_fd, cmd_array, 1);
- if (bytes_written < 1)
- return ERROR_FAIL;
-
- command_print(CMD_CTX, "requesting traceclock resync");
- LOG_DEBUG("resyncing traceclk pll");
-
- return ERROR_OK;
-}
-
-static const struct command_registration oocd_trace_all_command_handlers[] = {
- {
- .name = "config",
- .handler = handle_oocd_trace_config_command,
- .mode = COMMAND_CONFIG,
- .usage = "<target> <tty>",
- },
- {
- .name = "status",
- .handler = handle_oocd_trace_status_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "display OpenOCD + trace status",
- },
- {
- .name = "resync",
- .handler = handle_oocd_trace_resync_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "resync OpenOCD + trace capture clock",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration oocd_trace_command_handlers[] = {
- {
- .name = "oocd_trace",
- .mode = COMMAND_ANY,
- .help = "OpenOCD trace capture driver command group",
- .usage = "",
- .chain = oocd_trace_all_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct etm_capture_driver oocd_trace_capture_driver = {
- .name = "oocd_trace",
- .commands = oocd_trace_command_handlers,
- .init = oocd_trace_init,
- .status = oocd_trace_status,
- .start_capture = oocd_trace_start_capture,
- .stop_capture = oocd_trace_stop_capture,
- .read_trace = oocd_trace_read_trace,
-};
diff --git a/src/target/oocd_trace.h b/src/target/oocd_trace.h
deleted file mode 100644
index e7584e4..0000000
--- a/src/target/oocd_trace.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_OOCD_TRACE_H
-#define OPENOCD_TARGET_OOCD_TRACE_H
-
-#include <termios.h>
-
-/* registers */
-enum {
- OOCD_TRACE_ID = 0x7,
- OOCD_TRACE_ADDRESS = 0x0,
- OOCD_TRACE_TRIGGER_COUNTER = 0x01,
- OOCD_TRACE_CONTROL = 0x2,
- OOCD_TRACE_STATUS = 0x3,
- OOCD_TRACE_SDRAM_COUNTER = 0x4,
-};
-
-/* commands */
-enum {
- OOCD_TRACE_NOP = 0x0,
- OOCD_TRACE_READ_REG = 0x10,
- OOCD_TRACE_WRITE_REG = 0x18,
- OOCD_TRACE_READ_RAM = 0x20,
-/* OOCD_TRACE_WRITE_RAM = 0x28, */
- OOCD_TRACE_RESYNC = 0xf0,
-};
-
-struct oocd_trace {
- struct etm_context *etm_ctx;
- char *tty;
- int tty_fd;
- struct termios oldtio, newtio;
-};
-
-extern struct etm_capture_driver oocd_trace_capture_driver;
-
-#endif /* OPENOCD_TARGET_OOCD_TRACE_H */
diff --git a/src/target/openrisc/Makefile.am b/src/target/openrisc/Makefile.am
deleted file mode 100644
index b00a30d..0000000
--- a/src/target/openrisc/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-include $(top_srcdir)/common.mk
-
-noinst_LTLIBRARIES = libopenrisc.la
-libopenrisc_la_SOURCES = $(OPENRISC_SRC)
-
-OPENRISC_SRC = \
- or1k.c \
- or1k_du_adv.c \
- or1k_tap_mohor.c \
- or1k_tap_vjtag.c \
- or1k_tap_xilinx_bscan.c \
- jsp_server.c
-
-noinst_HEADERS = \
- or1k.h \
- or1k_du.h \
- or1k_tap.h \
- jsp_server.h
diff --git a/src/target/openrisc/jsp_server.c b/src/target/openrisc/jsp_server.c
deleted file mode 100644
index e581fb8..0000000
--- a/src/target/openrisc/jsp_server.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2014 by Franck Jullien *
- * franck.jullien@gmail.com *
- * *
- * Based on ./src/server/telnet_server.c *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <server/telnet_server.h>
-
-#include "or1k_tap.h"
-#include "or1k_du.h"
-#include "jsp_server.h"
-
-static char *jsp_port;
-
-/**A skim of the relevant RFCs suggests that if my application simply sent the
- * characters IAC DONT LINEMODE (\377\376\042) as soon as the client connects,
- * the client should be forced into character mode. However it doesn't make any difference.
- */
-
-static const char * const negotiate =
- "\xFF\xFB\x03" /* IAC WILL Suppress Go Ahead */
- "\xFF\xFB\x01" /* IAC WILL Echo */
- "\xFF\xFD\x03" /* IAC DO Suppress Go Ahead */
- "\xFF\xFE\x01"; /* IAC DON'T Echo */
-
-/* The only way we can detect that the socket is closed is the first time
- * we write to it, we will fail. Subsequent write operations will
- * succeed. Shudder!
- */
-static int telnet_write(struct connection *connection, const void *data, int len)
-{
- struct telnet_connection *t_con = connection->priv;
- if (t_con->closed)
- return ERROR_SERVER_REMOTE_CLOSED;
-
- if (connection_write(connection, data, len) == len)
- return ERROR_OK;
- t_con->closed = 1;
- return ERROR_SERVER_REMOTE_CLOSED;
-}
-
-int jsp_poll_read(void *priv)
-{
- struct jsp_service *jsp_service = (struct jsp_service *)priv;
- unsigned char out_buffer[10];
- unsigned char in_buffer[10];
- int out_len = 0;
- int in_len;
-
- if (!jsp_service->connection)
- return ERROR_FAIL;
-
- memset(out_buffer, 0, 10);
-
- or1k_adv_jtag_jsp_xfer(jsp_service->jtag_info, &out_len, out_buffer, &in_len, in_buffer);
- if (in_len)
- telnet_write(jsp_service->connection, in_buffer, in_len);
-
- return ERROR_OK;
-}
-
-static int jsp_new_connection(struct connection *connection)
-{
- struct telnet_connection *telnet_connection = malloc(sizeof(struct telnet_connection));
- struct jsp_service *jsp_service = connection->service->priv;
-
- connection->priv = telnet_connection;
-
- /* initialize telnet connection information */
- telnet_connection->closed = 0;
- telnet_connection->line_size = 0;
- telnet_connection->line_cursor = 0;
- telnet_connection->option_size = 0;
- telnet_connection->state = TELNET_STATE_DATA;
-
- /* negotiate telnet options */
- telnet_write(connection, negotiate, strlen(negotiate));
-
- /* print connection banner */
- if (jsp_service->banner) {
- telnet_write(connection, jsp_service->banner, strlen(jsp_service->banner));
- telnet_write(connection, "\r\n", 2);
- }
-
- jsp_service->connection = connection;
-
- int retval = target_register_timer_callback(&jsp_poll_read, 1, 1, jsp_service);
- if (ERROR_OK != retval)
- return retval;
-
- return ERROR_OK;
-}
-
-static int jsp_input(struct connection *connection)
-{
- int bytes_read;
- unsigned char buffer[TELNET_BUFFER_SIZE];
- unsigned char *buf_p;
- struct telnet_connection *t_con = connection->priv;
- struct jsp_service *jsp_service = connection->service->priv;
-
- bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE);
-
- if (bytes_read == 0)
- return ERROR_SERVER_REMOTE_CLOSED;
- else if (bytes_read == -1) {
- LOG_ERROR("error during read: %s", strerror(errno));
- return ERROR_SERVER_REMOTE_CLOSED;
- }
-
- buf_p = buffer;
- while (bytes_read) {
- switch (t_con->state) {
- case TELNET_STATE_DATA:
- if (*buf_p == 0xff)
- t_con->state = TELNET_STATE_IAC;
- else {
- int out_len = 1;
- int in_len;
- unsigned char in_buffer[10];
- or1k_adv_jtag_jsp_xfer(jsp_service->jtag_info,
- &out_len, buf_p, &in_len,
- in_buffer);
- if (in_len)
- telnet_write(connection,
- in_buffer, in_len);
- }
- break;
- case TELNET_STATE_IAC:
- switch (*buf_p) {
- case 0xfe:
- t_con->state = TELNET_STATE_DONT;
- break;
- case 0xfd:
- t_con->state = TELNET_STATE_DO;
- break;
- case 0xfc:
- t_con->state = TELNET_STATE_WONT;
- break;
- case 0xfb:
- t_con->state = TELNET_STATE_WILL;
- break;
- }
- break;
- case TELNET_STATE_SB:
- break;
- case TELNET_STATE_SE:
- break;
- case TELNET_STATE_WILL:
- case TELNET_STATE_WONT:
- case TELNET_STATE_DO:
- case TELNET_STATE_DONT:
- t_con->state = TELNET_STATE_DATA;
- break;
- default:
- LOG_ERROR("unknown telnet state");
- exit(-1);
- }
-
- bytes_read--;
- buf_p++;
- }
-
- return ERROR_OK;
-}
-
-static int jsp_connection_closed(struct connection *connection)
-{
- struct telnet_connection *t_con = connection->priv;
- struct jsp_service *jsp_service = connection->service->priv;
-
- if (t_con->prompt) {
- free(t_con->prompt);
- t_con->prompt = NULL;
- }
-
- int retval = target_unregister_timer_callback(&jsp_poll_read, jsp_service);
- if (ERROR_OK != retval)
- return retval;
-
- if (connection->priv) {
- free(connection->priv);
- connection->priv = NULL;
- } else
- LOG_ERROR("BUG: connection->priv == NULL");
-
- return ERROR_OK;
-}
-
-int jsp_init(struct or1k_jtag *jtag_info, char *banner)
-{
- struct jsp_service *jsp_service = malloc(sizeof(struct jsp_service));
- jsp_service->banner = banner;
- jsp_service->jtag_info = jtag_info;
-
- return add_service("jsp",
- jsp_port,
- 1,
- jsp_new_connection,
- jsp_input,
- jsp_connection_closed,
- jsp_service);
-}
-
-COMMAND_HANDLER(handle_jsp_port_command)
-{
- return CALL_COMMAND_HANDLER(server_pipe_command, &jsp_port);
-}
-
-static const struct command_registration jsp_command_handlers[] = {
- {
- .name = "jsp_port",
- .handler = handle_jsp_port_command,
- .mode = COMMAND_ANY,
- .help = "Specify port on which to listen "
- "for incoming JSP telnet connections.",
- .usage = "[port_num]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int jsp_register_commands(struct command_context *cmd_ctx)
-{
- jsp_port = strdup("7777");
- return register_commands(cmd_ctx, NULL, jsp_command_handlers);
-}
-
diff --git a/src/target/openrisc/jsp_server.h b/src/target/openrisc/jsp_server.h
deleted file mode 100644
index f8e7121..0000000
--- a/src/target/openrisc/jsp_server.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef OPENOCD_TARGET_OPENRISC_JSP_SERVER_H
-#define OPENOCD_TARGET_OPENRISC_JSP_SERVER_H
-
-#include "or1k_tap.h"
-#include "or1k.h"
-#include "or1k_du.h"
-
-struct jsp_service {
- char *banner;
- struct or1k_jtag *jtag_info;
- struct connection *connection;
-};
-
-int jsp_init(struct or1k_jtag *jtag_info, char *banner);
-int jsp_register_commands(struct command_context *cmd_ctx);
-
-#endif /* OPENOCD_TARGET_OPENRISC_JSP_SERVER_H */
diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c
deleted file mode 100644
index 2cc869f..0000000
--- a/src/target/openrisc/or1k.c
+++ /dev/null
@@ -1,1462 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Julius Baxter *
- * julius@opencores.org *
- * *
- * Copyright (C) 2013 by Marek Czerski *
- * ma.czerski@gmail.com *
- * *
- * Copyright (C) 2013 by Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <jtag/jtag.h>
-#include <target/register.h>
-#include <target/target.h>
-#include <target/breakpoints.h>
-#include <target/target_type.h>
-#include <helper/time_support.h>
-#include <helper/fileio.h>
-#include "or1k_tap.h"
-#include "or1k.h"
-#include "or1k_du.h"
-
-LIST_HEAD(tap_list);
-LIST_HEAD(du_list);
-
-static int or1k_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-
-static int or1k_read_core_reg(struct target *target, int num);
-static int or1k_write_core_reg(struct target *target, int num);
-
-static struct or1k_core_reg *or1k_core_reg_list_arch_info;
-
-static const struct or1k_core_reg_init or1k_init_reg_list[] = {
- {"r0" , GROUP0 + 1024, "org.gnu.gdb.or1k.group0", NULL},
- {"r1" , GROUP0 + 1025, "org.gnu.gdb.or1k.group0", NULL},
- {"r2" , GROUP0 + 1026, "org.gnu.gdb.or1k.group0", NULL},
- {"r3" , GROUP0 + 1027, "org.gnu.gdb.or1k.group0", NULL},
- {"r4" , GROUP0 + 1028, "org.gnu.gdb.or1k.group0", NULL},
- {"r5" , GROUP0 + 1029, "org.gnu.gdb.or1k.group0", NULL},
- {"r6" , GROUP0 + 1030, "org.gnu.gdb.or1k.group0", NULL},
- {"r7" , GROUP0 + 1031, "org.gnu.gdb.or1k.group0", NULL},
- {"r8" , GROUP0 + 1032, "org.gnu.gdb.or1k.group0", NULL},
- {"r9" , GROUP0 + 1033, "org.gnu.gdb.or1k.group0", NULL},
- {"r10" , GROUP0 + 1034, "org.gnu.gdb.or1k.group0", NULL},
- {"r11" , GROUP0 + 1035, "org.gnu.gdb.or1k.group0", NULL},
- {"r12" , GROUP0 + 1036, "org.gnu.gdb.or1k.group0", NULL},
- {"r13" , GROUP0 + 1037, "org.gnu.gdb.or1k.group0", NULL},
- {"r14" , GROUP0 + 1038, "org.gnu.gdb.or1k.group0", NULL},
- {"r15" , GROUP0 + 1039, "org.gnu.gdb.or1k.group0", NULL},
- {"r16" , GROUP0 + 1040, "org.gnu.gdb.or1k.group0", NULL},
- {"r17" , GROUP0 + 1041, "org.gnu.gdb.or1k.group0", NULL},
- {"r18" , GROUP0 + 1042, "org.gnu.gdb.or1k.group0", NULL},
- {"r19" , GROUP0 + 1043, "org.gnu.gdb.or1k.group0", NULL},
- {"r20" , GROUP0 + 1044, "org.gnu.gdb.or1k.group0", NULL},
- {"r21" , GROUP0 + 1045, "org.gnu.gdb.or1k.group0", NULL},
- {"r22" , GROUP0 + 1046, "org.gnu.gdb.or1k.group0", NULL},
- {"r23" , GROUP0 + 1047, "org.gnu.gdb.or1k.group0", NULL},
- {"r24" , GROUP0 + 1048, "org.gnu.gdb.or1k.group0", NULL},
- {"r25" , GROUP0 + 1049, "org.gnu.gdb.or1k.group0", NULL},
- {"r26" , GROUP0 + 1050, "org.gnu.gdb.or1k.group0", NULL},
- {"r27" , GROUP0 + 1051, "org.gnu.gdb.or1k.group0", NULL},
- {"r28" , GROUP0 + 1052, "org.gnu.gdb.or1k.group0", NULL},
- {"r29" , GROUP0 + 1053, "org.gnu.gdb.or1k.group0", NULL},
- {"r30" , GROUP0 + 1054, "org.gnu.gdb.or1k.group0", NULL},
- {"r31" , GROUP0 + 1055, "org.gnu.gdb.or1k.group0", NULL},
- {"ppc" , GROUP0 + 18, "org.gnu.gdb.or1k.group0", NULL},
- {"npc" , GROUP0 + 16, "org.gnu.gdb.or1k.group0", NULL},
- {"sr" , GROUP0 + 17, "org.gnu.gdb.or1k.group0", NULL},
- {"vr" , GROUP0 + 0, "org.gnu.gdb.or1k.group0", "system"},
- {"upr" , GROUP0 + 1, "org.gnu.gdb.or1k.group0", "system"},
- {"cpucfgr" , GROUP0 + 2, "org.gnu.gdb.or1k.group0", "system"},
- {"dmmucfgr" , GROUP0 + 3, "org.gnu.gdb.or1k.group0", "system"},
- {"immucfgr" , GROUP0 + 4, "org.gnu.gdb.or1k.group0", "system"},
- {"dccfgr" , GROUP0 + 5, "org.gnu.gdb.or1k.group0", "system"},
- {"iccfgr" , GROUP0 + 6, "org.gnu.gdb.or1k.group0", "system"},
- {"dcfgr" , GROUP0 + 7, "org.gnu.gdb.or1k.group0", "system"},
- {"pccfgr" , GROUP0 + 8, "org.gnu.gdb.or1k.group0", "system"},
- {"fpcsr" , GROUP0 + 20, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr0" , GROUP0 + 32, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr1" , GROUP0 + 33, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr2" , GROUP0 + 34, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr3" , GROUP0 + 35, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr4" , GROUP0 + 36, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr5" , GROUP0 + 37, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr6" , GROUP0 + 38, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr7" , GROUP0 + 39, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr8" , GROUP0 + 40, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr9" , GROUP0 + 41, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr10" , GROUP0 + 42, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr11" , GROUP0 + 43, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr12" , GROUP0 + 44, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr13" , GROUP0 + 45, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr14" , GROUP0 + 46, "org.gnu.gdb.or1k.group0", "system"},
- {"epcr15" , GROUP0 + 47, "org.gnu.gdb.or1k.group0", "system"},
- {"eear0" , GROUP0 + 48, "org.gnu.gdb.or1k.group0", "system"},
- {"eear1" , GROUP0 + 49, "org.gnu.gdb.or1k.group0", "system"},
- {"eear2" , GROUP0 + 50, "org.gnu.gdb.or1k.group0", "system"},
- {"eear3" , GROUP0 + 51, "org.gnu.gdb.or1k.group0", "system"},
- {"eear4" , GROUP0 + 52, "org.gnu.gdb.or1k.group0", "system"},
- {"eear5" , GROUP0 + 53, "org.gnu.gdb.or1k.group0", "system"},
- {"eear6" , GROUP0 + 54, "org.gnu.gdb.or1k.group0", "system"},
- {"eear7" , GROUP0 + 55, "org.gnu.gdb.or1k.group0", "system"},
- {"eear8" , GROUP0 + 56, "org.gnu.gdb.or1k.group0", "system"},
- {"eear9" , GROUP0 + 57, "org.gnu.gdb.or1k.group0", "system"},
- {"eear10" , GROUP0 + 58, "org.gnu.gdb.or1k.group0", "system"},
- {"eear11" , GROUP0 + 59, "org.gnu.gdb.or1k.group0", "system"},
- {"eear12" , GROUP0 + 60, "org.gnu.gdb.or1k.group0", "system"},
- {"eear13" , GROUP0 + 61, "org.gnu.gdb.or1k.group0", "system"},
- {"eear14" , GROUP0 + 62, "org.gnu.gdb.or1k.group0", "system"},
- {"eear15" , GROUP0 + 63, "org.gnu.gdb.or1k.group0", "system"},
- {"esr0" , GROUP0 + 64, "org.gnu.gdb.or1k.group0", "system"},
- {"esr1" , GROUP0 + 65, "org.gnu.gdb.or1k.group0", "system"},
- {"esr2" , GROUP0 + 66, "org.gnu.gdb.or1k.group0", "system"},
- {"esr3" , GROUP0 + 67, "org.gnu.gdb.or1k.group0", "system"},
- {"esr4" , GROUP0 + 68, "org.gnu.gdb.or1k.group0", "system"},
- {"esr5" , GROUP0 + 69, "org.gnu.gdb.or1k.group0", "system"},
- {"esr6" , GROUP0 + 70, "org.gnu.gdb.or1k.group0", "system"},
- {"esr7" , GROUP0 + 71, "org.gnu.gdb.or1k.group0", "system"},
- {"esr8" , GROUP0 + 72, "org.gnu.gdb.or1k.group0", "system"},
- {"esr9" , GROUP0 + 73, "org.gnu.gdb.or1k.group0", "system"},
- {"esr10" , GROUP0 + 74, "org.gnu.gdb.or1k.group0", "system"},
- {"esr11" , GROUP0 + 75, "org.gnu.gdb.or1k.group0", "system"},
- {"esr12" , GROUP0 + 76, "org.gnu.gdb.or1k.group0", "system"},
- {"esr13" , GROUP0 + 77, "org.gnu.gdb.or1k.group0", "system"},
- {"esr14" , GROUP0 + 78, "org.gnu.gdb.or1k.group0", "system"},
- {"esr15" , GROUP0 + 79, "org.gnu.gdb.or1k.group0", "system"},
-
- {"dmmuucr" , GROUP1 + 0, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"dmmuupr" , GROUP1 + 1, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"dtlbeir" , GROUP1 + 2, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbmr0" , GROUP1 + 4, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbmr1" , GROUP1 + 5, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbmr2" , GROUP1 + 6, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbmr3" , GROUP1 + 7, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbtr0" , GROUP1 + 8, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbtr1" , GROUP1 + 9, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbtr2" , GROUP1 + 10, "org.gnu.gdb.or1k.group1", "dmmu"},
- {"datbtr3" , GROUP1 + 11, "org.gnu.gdb.or1k.group1", "dmmu"},
-
- {"immucr" , GROUP2 + 0, "org.gnu.gdb.or1k.group2", "immu"},
- {"immupr" , GROUP2 + 1, "org.gnu.gdb.or1k.group2", "immu"},
- {"itlbeir" , GROUP2 + 2, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbmr0" , GROUP2 + 4, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbmr1" , GROUP2 + 5, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbmr2" , GROUP2 + 6, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbmr3" , GROUP2 + 7, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbtr0" , GROUP2 + 8, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbtr1" , GROUP2 + 9, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbtr2" , GROUP2 + 10, "org.gnu.gdb.or1k.group2", "immu"},
- {"iatbtr3" , GROUP2 + 11, "org.gnu.gdb.or1k.group2", "immu"},
-
- {"dccr" , GROUP3 + 0, "org.gnu.gdb.or1k.group3", "dcache"},
- {"dcbpr" , GROUP3 + 1, "org.gnu.gdb.or1k.group3", "dcache"},
- {"dcbfr" , GROUP3 + 2, "org.gnu.gdb.or1k.group3", "dcache"},
- {"dcbir" , GROUP3 + 3, "org.gnu.gdb.or1k.group3", "dcache"},
- {"dcbwr" , GROUP3 + 4, "org.gnu.gdb.or1k.group3", "dcache"},
- {"dcblr" , GROUP3 + 5, "org.gnu.gdb.or1k.group3", "dcache"},
-
- {"iccr" , GROUP4 + 0, "org.gnu.gdb.or1k.group4", "icache"},
- {"icbpr" , GROUP4 + 1, "org.gnu.gdb.or1k.group4", "icache"},
- {"icbir" , GROUP4 + 2, "org.gnu.gdb.or1k.group4", "icache"},
- {"icblr" , GROUP4 + 3, "org.gnu.gdb.or1k.group4", "icache"},
-
- {"maclo" , GROUP5 + 0, "org.gnu.gdb.or1k.group5", "mac"},
- {"machi" , GROUP5 + 1, "org.gnu.gdb.or1k.group5", "mac"},
-
- {"dvr0" , GROUP6 + 0, "org.gnu.gdb.or1k.group6", "debug"},
- {"dvr1" , GROUP6 + 1, "org.gnu.gdb.or1k.group6", "debug"},
- {"dvr2" , GROUP6 + 2, "org.gnu.gdb.or1k.group6", "debug"},
- {"dvr3" , GROUP6 + 3, "org.gnu.gdb.or1k.group6", "debug"},
- {"dvr4" , GROUP6 + 4, "org.gnu.gdb.or1k.group6", "debug"},
- {"dvr5" , GROUP6 + 5, "org.gnu.gdb.or1k.group6", "debug"},
- {"dvr6" , GROUP6 + 6, "org.gnu.gdb.or1k.group6", "debug"},
- {"dvr7" , GROUP6 + 7, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr0" , GROUP6 + 8, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr1" , GROUP6 + 9, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr2" , GROUP6 + 10, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr3" , GROUP6 + 11, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr4" , GROUP6 + 12, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr5" , GROUP6 + 13, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr6" , GROUP6 + 14, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcr7" , GROUP6 + 15, "org.gnu.gdb.or1k.group6", "debug"},
- {"dmr1" , GROUP6 + 16, "org.gnu.gdb.or1k.group6", "debug"},
- {"dmr2" , GROUP6 + 17, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcwr0" , GROUP6 + 18, "org.gnu.gdb.or1k.group6", "debug"},
- {"dcwr1" , GROUP6 + 19, "org.gnu.gdb.or1k.group6", "debug"},
- {"dsr" , GROUP6 + 20, "org.gnu.gdb.or1k.group6", "debug"},
- {"drr" , GROUP6 + 21, "org.gnu.gdb.or1k.group6", "debug"},
-
- {"pccr0" , GROUP7 + 0, "org.gnu.gdb.or1k.group7", "perf"},
- {"pccr1" , GROUP7 + 1, "org.gnu.gdb.or1k.group7", "perf"},
- {"pccr2" , GROUP7 + 2, "org.gnu.gdb.or1k.group7", "perf"},
- {"pccr3" , GROUP7 + 3, "org.gnu.gdb.or1k.group7", "perf"},
- {"pccr4" , GROUP7 + 4, "org.gnu.gdb.or1k.group7", "perf"},
- {"pccr5" , GROUP7 + 5, "org.gnu.gdb.or1k.group7", "perf"},
- {"pccr6" , GROUP7 + 6, "org.gnu.gdb.or1k.group7", "perf"},
- {"pccr7" , GROUP7 + 7, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr0" , GROUP7 + 8, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr1" , GROUP7 + 9, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr2" , GROUP7 + 10, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr3" , GROUP7 + 11, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr4" , GROUP7 + 12, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr5" , GROUP7 + 13, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr6" , GROUP7 + 14, "org.gnu.gdb.or1k.group7", "perf"},
- {"pcmr7" , GROUP7 + 15, "org.gnu.gdb.or1k.group7", "perf"},
-
- {"pmr" , GROUP8 + 0, "org.gnu.gdb.or1k.group8", "power"},
-
- {"picmr" , GROUP9 + 0, "org.gnu.gdb.or1k.group9", "pic"},
- {"picsr" , GROUP9 + 2, "org.gnu.gdb.or1k.group9", "pic"},
-
- {"ttmr" , GROUP10 + 0, "org.gnu.gdb.or1k.group10", "timer"},
- {"ttcr" , GROUP10 + 1, "org.gnu.gdb.or1k.group10", "timer"},
-};
-
-static int or1k_add_reg(struct target *target, struct or1k_core_reg *new_reg)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- int reg_list_size = or1k->nb_regs * sizeof(struct or1k_core_reg);
-
- or1k_core_reg_list_arch_info = realloc(or1k_core_reg_list_arch_info,
- reg_list_size + sizeof(struct or1k_core_reg));
-
- memcpy(&or1k_core_reg_list_arch_info[or1k->nb_regs], new_reg,
- sizeof(struct or1k_core_reg));
-
- or1k_core_reg_list_arch_info[or1k->nb_regs].list_num = or1k->nb_regs;
-
- or1k->nb_regs++;
-
- return ERROR_OK;
-}
-
-static int or1k_create_reg_list(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
-
- LOG_DEBUG("-");
-
- or1k_core_reg_list_arch_info = malloc(ARRAY_SIZE(or1k_init_reg_list) *
- sizeof(struct or1k_core_reg));
-
- for (int i = 0; i < (int)ARRAY_SIZE(or1k_init_reg_list); i++) {
- or1k_core_reg_list_arch_info[i].name = or1k_init_reg_list[i].name;
- or1k_core_reg_list_arch_info[i].spr_num = or1k_init_reg_list[i].spr_num;
- or1k_core_reg_list_arch_info[i].group = or1k_init_reg_list[i].group;
- or1k_core_reg_list_arch_info[i].feature = or1k_init_reg_list[i].feature;
- or1k_core_reg_list_arch_info[i].list_num = i;
- or1k_core_reg_list_arch_info[i].target = NULL;
- or1k_core_reg_list_arch_info[i].or1k_common = NULL;
- }
-
- or1k->nb_regs = ARRAY_SIZE(or1k_init_reg_list);
-
- struct or1k_core_reg new_reg;
- new_reg.target = NULL;
- new_reg.or1k_common = NULL;
-
- char name[32];
- for (int way = 0; way < 4; way++) {
- for (int i = 0; i < 128; i++) {
-
- sprintf(name, "dtlbw%dmr%d", way, i);
- new_reg.name = strdup(name);
- new_reg.spr_num = GROUP1 + 512 + i + (way * 256);
- new_reg.feature = "org.gnu.gdb.or1k.group1";
- new_reg.group = "dmmu";
- or1k_add_reg(target, &new_reg);
-
- sprintf(name, "dtlbw%dtr%d", way, i);
- new_reg.name = strdup(name);
- new_reg.spr_num = GROUP1 + 640 + i + (way * 256);
- new_reg.feature = "org.gnu.gdb.or1k.group1";
- new_reg.group = "dmmu";
- or1k_add_reg(target, &new_reg);
-
-
- sprintf(name, "itlbw%dmr%d", way, i);
- new_reg.name = strdup(name);
- new_reg.spr_num = GROUP2 + 512 + i + (way * 256);
- new_reg.feature = "org.gnu.gdb.or1k.group2";
- new_reg.group = "immu";
- or1k_add_reg(target, &new_reg);
-
-
- sprintf(name, "itlbw%dtr%d", way, i);
- new_reg.name = strdup(name);
- new_reg.spr_num = GROUP2 + 640 + i + (way * 256);
- new_reg.feature = "org.gnu.gdb.or1k.group2";
- new_reg.group = "immu";
- or1k_add_reg(target, &new_reg);
-
- }
- }
-
- return ERROR_OK;
-}
-
-static int or1k_jtag_read_regs(struct or1k_common *or1k, uint32_t *regs)
-{
- struct or1k_du *du_core = or1k_jtag_to_du(&or1k->jtag);
-
- LOG_DEBUG("-");
-
- return du_core->or1k_jtag_read_cpu(&or1k->jtag,
- or1k->arch_info[OR1K_REG_R0].spr_num, OR1K_REG_R31 + 1,
- regs + OR1K_REG_R0);
-}
-
-static int or1k_jtag_write_regs(struct or1k_common *or1k, uint32_t *regs)
-{
- struct or1k_du *du_core = or1k_jtag_to_du(&or1k->jtag);
-
- LOG_DEBUG("-");
-
- return du_core->or1k_jtag_write_cpu(&or1k->jtag,
- or1k->arch_info[OR1K_REG_R0].spr_num, OR1K_REG_R31 + 1,
- &regs[OR1K_REG_R0]);
-}
-
-static int or1k_save_context(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- int regs_read = 0;
- int retval;
-
- LOG_DEBUG("-");
-
- for (int i = 0; i < OR1KNUMCOREREGS; i++) {
- if (!or1k->core_cache->reg_list[i].valid) {
- if (i == OR1K_REG_PPC || i == OR1K_REG_NPC || i == OR1K_REG_SR) {
- retval = du_core->or1k_jtag_read_cpu(&or1k->jtag,
- or1k->arch_info[i].spr_num, 1,
- &or1k->core_regs[i]);
- if (retval != ERROR_OK)
- return retval;
- } else if (!regs_read) {
- /* read gpr registers at once (but only one time in this loop) */
- retval = or1k_jtag_read_regs(or1k, or1k->core_regs);
- if (retval != ERROR_OK)
- return retval;
- /* prevent next reads in this loop */
- regs_read = 1;
- }
- /* We've just updated the core_reg[i], now update
- the core cache */
- or1k_read_core_reg(target, i);
- }
- }
-
- return ERROR_OK;
-}
-
-static int or1k_restore_context(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- int reg_write = 0;
- int retval;
-
- LOG_DEBUG("-");
-
- for (int i = 0; i < OR1KNUMCOREREGS; i++) {
- if (or1k->core_cache->reg_list[i].dirty) {
- or1k_write_core_reg(target, i);
-
- if (i == OR1K_REG_PPC || i == OR1K_REG_NPC || i == OR1K_REG_SR) {
- retval = du_core->or1k_jtag_write_cpu(&or1k->jtag,
- or1k->arch_info[i].spr_num, 1,
- &or1k->core_regs[i]);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while restoring context");
- return retval;
- }
- } else
- reg_write = 1;
- }
- }
-
- if (reg_write) {
- /* read gpr registers at once (but only one time in this loop) */
- retval = or1k_jtag_write_regs(or1k, or1k->core_regs);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while restoring context");
- return retval;
- }
- }
-
- return ERROR_OK;
-}
-
-static int or1k_read_core_reg(struct target *target, int num)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- uint32_t reg_value;
-
- LOG_DEBUG("-");
-
- if ((num < 0) || (num >= or1k->nb_regs))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if ((num >= 0) && (num < OR1KNUMCOREREGS)) {
- reg_value = or1k->core_regs[num];
- buf_set_u32(or1k->core_cache->reg_list[num].value, 0, 32, reg_value);
- LOG_DEBUG("Read core reg %i value 0x%08" PRIx32, num , reg_value);
- or1k->core_cache->reg_list[num].valid = 1;
- or1k->core_cache->reg_list[num].dirty = 0;
- } else {
- /* This is an spr, always read value from HW */
- int retval = du_core->or1k_jtag_read_cpu(&or1k->jtag,
- or1k->arch_info[num].spr_num, 1, &reg_value);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while reading spr 0x%08" PRIx32, or1k->arch_info[num].spr_num);
- return retval;
- }
- buf_set_u32(or1k->core_cache->reg_list[num].value, 0, 32, reg_value);
- LOG_DEBUG("Read spr reg %i value 0x%08" PRIx32, num , reg_value);
- }
-
- return ERROR_OK;
-}
-
-static int or1k_write_core_reg(struct target *target, int num)
-{
- struct or1k_common *or1k = target_to_or1k(target);
-
- LOG_DEBUG("-");
-
- if ((num < 0) || (num >= OR1KNUMCOREREGS))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t reg_value = buf_get_u32(or1k->core_cache->reg_list[num].value, 0, 32);
- or1k->core_regs[num] = reg_value;
- LOG_DEBUG("Write core reg %i value 0x%08" PRIx32, num , reg_value);
- or1k->core_cache->reg_list[num].valid = 1;
- or1k->core_cache->reg_list[num].dirty = 0;
-
- return ERROR_OK;
-}
-
-static int or1k_get_core_reg(struct reg *reg)
-{
- struct or1k_core_reg *or1k_reg = reg->arch_info;
- struct target *target = or1k_reg->target;
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- return or1k_read_core_reg(target, or1k_reg->list_num);
-}
-
-static int or1k_set_core_reg(struct reg *reg, uint8_t *buf)
-{
- struct or1k_core_reg *or1k_reg = reg->arch_info;
- struct target *target = or1k_reg->target;
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- uint32_t value = buf_get_u32(buf, 0, 32);
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED)
- return ERROR_TARGET_NOT_HALTED;
-
- if (or1k_reg->list_num < OR1KNUMCOREREGS) {
- buf_set_u32(reg->value, 0, 32, value);
- reg->dirty = 1;
- reg->valid = 1;
- } else {
- /* This is an spr, write it to the HW */
- int retval = du_core->or1k_jtag_write_cpu(&or1k->jtag,
- or1k_reg->spr_num, 1, &value);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while writing spr 0x%08" PRIx32, or1k_reg->spr_num);
- return retval;
- }
- }
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type or1k_reg_type = {
- .get = or1k_get_core_reg,
- .set = or1k_set_core_reg,
-};
-
-static struct reg_cache *or1k_build_reg_cache(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct reg_cache *cache = malloc(sizeof(struct reg_cache));
- struct reg *reg_list = calloc(or1k->nb_regs, sizeof(struct reg));
- struct or1k_core_reg *arch_info =
- malloc((or1k->nb_regs) * sizeof(struct or1k_core_reg));
- struct reg_feature *feature;
-
- LOG_DEBUG("-");
-
- /* Build the process context cache */
- cache->name = "OpenRISC 1000 registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = or1k->nb_regs;
- (*cache_p) = cache;
- or1k->core_cache = cache;
- or1k->arch_info = arch_info;
-
- for (int i = 0; i < or1k->nb_regs; i++) {
- arch_info[i] = or1k_core_reg_list_arch_info[i];
- arch_info[i].target = target;
- arch_info[i].or1k_common = or1k;
- reg_list[i].name = or1k_core_reg_list_arch_info[i].name;
-
- feature = malloc(sizeof(struct reg_feature));
- feature->name = or1k_core_reg_list_arch_info[i].feature;
- reg_list[i].feature = feature;
-
- reg_list[i].group = or1k_core_reg_list_arch_info[i].group;
- reg_list[i].size = 32;
- reg_list[i].value = calloc(1, 4);
- reg_list[i].dirty = 0;
- reg_list[i].valid = 0;
- reg_list[i].type = &or1k_reg_type;
- reg_list[i].arch_info = &arch_info[i];
- reg_list[i].number = i;
- reg_list[i].exist = true;
- }
-
- return cache;
-}
-
-static int or1k_debug_entry(struct target *target)
-{
- LOG_DEBUG("-");
-
- int retval = or1k_save_context(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_save_context");
- return retval;
- }
-
- struct or1k_common *or1k = target_to_or1k(target);
- uint32_t addr = or1k->core_regs[OR1K_REG_NPC];
-
- if (breakpoint_find(target, addr))
- /* Halted on a breakpoint, step back to permit executing the instruction there */
- retval = or1k_set_core_reg(&or1k->core_cache->reg_list[OR1K_REG_NPC],
- (uint8_t *)&addr);
-
- return retval;
-}
-
-static int or1k_halt(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("Target was already halted");
- return ERROR_OK;
- }
-
- if (target->state == TARGET_UNKNOWN)
- LOG_WARNING("Target was in unknown state when halt was requested");
-
- if (target->state == TARGET_RESET) {
- if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) &&
- jtag_get_srst()) {
- LOG_ERROR("Can't request a halt while in reset if nSRST pulls nTRST");
- return ERROR_TARGET_FAILURE;
- } else {
- target->debug_reason = DBG_REASON_DBGRQ;
- return ERROR_OK;
- }
- }
-
- int retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_STALL);
- if (retval != ERROR_OK) {
- LOG_ERROR("Impossible to stall the CPU");
- return retval;
- }
-
- target->debug_reason = DBG_REASON_DBGRQ;
-
- return ERROR_OK;
-}
-
-static int or1k_is_cpu_running(struct target *target, int *running)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- int retval;
- int tries = 0;
- const int RETRIES_MAX = 5;
-
- /* Have a retry loop to determine of the CPU is running.
- If target has been hard reset for any reason, it might take a couple
- of goes before it's ready again.
- */
- while (tries < RETRIES_MAX) {
-
- tries++;
-
- retval = du_core->or1k_is_cpu_running(&or1k->jtag, running);
- if (retval != ERROR_OK) {
- LOG_WARNING("Debug IF CPU control reg read failure.");
- /* Try once to restart the JTAG infrastructure -
- quite possibly the board has just been reset. */
- LOG_WARNING("Resetting JTAG TAP state and reconnectiong to debug IF.");
- du_core->or1k_jtag_init(&or1k->jtag);
-
- LOG_WARNING("...attempt %d of %d", tries, RETRIES_MAX);
-
- alive_sleep(2);
-
- continue;
- } else
- return ERROR_OK;
- }
-
- LOG_ERROR("Could not re-establish communication with target");
- return retval;
-}
-
-static int or1k_poll(struct target *target)
-{
- int retval;
- int running;
-
- retval = or1k_is_cpu_running(target, &running);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_is_cpu_running");
- return retval;
- }
-
- /* check for processor halted */
- if (!running) {
- /* It's actually stalled, so update our software's state */
- if ((target->state == TARGET_RUNNING) ||
- (target->state == TARGET_RESET)) {
-
- target->state = TARGET_HALTED;
-
- retval = or1k_debug_entry(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_debug_entry");
- return retval;
- }
-
- target_call_event_callbacks(target,
- TARGET_EVENT_HALTED);
- } else if (target->state == TARGET_DEBUG_RUNNING) {
- target->state = TARGET_HALTED;
-
- retval = or1k_debug_entry(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_debug_entry");
- return retval;
- }
-
- target_call_event_callbacks(target,
- TARGET_EVENT_DEBUG_HALTED);
- }
- } else { /* ... target is running */
-
- /* If target was supposed to be stalled, stall it again */
- if (target->state == TARGET_HALTED) {
-
- target->state = TARGET_RUNNING;
-
- retval = or1k_halt(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_halt");
- return retval;
- }
-
- retval = or1k_debug_entry(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_debug_entry");
- return retval;
- }
-
- target_call_event_callbacks(target,
- TARGET_EVENT_DEBUG_HALTED);
- }
-
- target->state = TARGET_RUNNING;
-
- }
-
- return ERROR_OK;
-}
-
-static int or1k_assert_reset(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- LOG_DEBUG("-");
-
- int retval = du_core->or1k_cpu_reset(&or1k->jtag, CPU_RESET);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while asserting RESET");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int or1k_deassert_reset(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- LOG_DEBUG("-");
-
- int retval = du_core->or1k_cpu_reset(&or1k->jtag, CPU_NOT_RESET);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while desasserting RESET");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int or1k_soft_reset_halt(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- LOG_DEBUG("-");
-
- int retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_STALL);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while stalling the CPU");
- return retval;
- }
-
- retval = or1k_assert_reset(target);
- if (retval != ERROR_OK)
- return retval;
-
- retval = or1k_deassert_reset(target);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static bool is_any_soft_breakpoint(struct target *target)
-{
- struct breakpoint *breakpoint = target->breakpoints;
-
- LOG_DEBUG("-");
-
- while (breakpoint)
- if (breakpoint->type == BKPT_SOFT)
- return true;
-
- return false;
-}
-
-static int or1k_resume_or_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints,
- int debug_execution, int step)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- struct breakpoint *breakpoint = NULL;
- uint32_t resume_pc;
- uint32_t debug_reg_list[OR1K_DEBUG_REG_NUM];
-
- LOG_DEBUG("Addr: 0x%" PRIx32 ", stepping: %s, handle breakpoints %s\n",
- address, step ? "yes" : "no", handle_breakpoints ? "yes" : "no");
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!debug_execution)
- target_free_all_working_areas(target);
-
- /* current ? continue on current pc : continue at <address> */
- if (!current)
- buf_set_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0,
- 32, address);
-
- int retval = or1k_restore_context(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_restore_context");
- return retval;
- }
-
- /* read debug registers (starting from DMR1 register) */
- retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD,
- OR1K_DEBUG_REG_NUM, debug_reg_list);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while reading debug registers");
- return retval;
- }
-
- /* Clear Debug Reason Register (DRR) */
- debug_reg_list[OR1K_DEBUG_REG_DRR] = 0;
-
- /* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) */
- debug_reg_list[OR1K_DEBUG_REG_DMR2] &= ~OR1K_DMR2_WGB;
- if (step)
- /* Set the single step trigger in Debug Mode Register 1 (DMR1) */
- debug_reg_list[OR1K_DEBUG_REG_DMR1] |= OR1K_DMR1_ST | OR1K_DMR1_BT;
- else
- /* Clear the single step trigger in Debug Mode Register 1 (DMR1) */
- debug_reg_list[OR1K_DEBUG_REG_DMR1] &= ~(OR1K_DMR1_ST | OR1K_DMR1_BT);
-
- /* Set traps to be handled by the debug unit in the Debug Stop
- Register (DSR). Check if we have any software breakpoints in
- place before setting this value - the kernel, for instance,
- relies on l.trap instructions not stalling the processor ! */
- if (is_any_soft_breakpoint(target) == true)
- debug_reg_list[OR1K_DEBUG_REG_DSR] |= OR1K_DSR_TE;
-
- /* Write debug registers (starting from DMR1 register) */
- retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD,
- OR1K_DEBUG_REG_NUM, debug_reg_list);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while writing back debug registers");
- return retval;
- }
-
- resume_pc = buf_get_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value,
- 0, 32);
-
- /* The front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- /* Single step past breakpoint at current address */
- breakpoint = breakpoint_find(target, resume_pc);
- if (breakpoint) {
- LOG_DEBUG("Unset breakpoint at 0x%08" PRIx32, breakpoint->address);
- retval = or1k_remove_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
- }
- }
-
- /* Unstall time */
- retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_UNSTALL);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while unstalling the CPU");
- return retval;
- }
-
- if (step)
- target->debug_reason = DBG_REASON_SINGLESTEP;
- else
- target->debug_reason = DBG_REASON_NOTHALTED;
-
- /* Registers are now invalid */
- register_cache_invalidate(or1k->core_cache);
-
- if (!debug_execution) {
- target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- LOG_DEBUG("Target resumed at 0x%08" PRIx32, resume_pc);
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- LOG_DEBUG("Target debug resumed at 0x%08" PRIx32, resume_pc);
- }
-
- return ERROR_OK;
-}
-
-static int or1k_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- return or1k_resume_or_step(target, current, address,
- handle_breakpoints,
- debug_execution,
- NO_SINGLE_STEP);
-}
-
-static int or1k_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- return or1k_resume_or_step(target, current, address,
- handle_breakpoints,
- 0,
- SINGLE_STEP);
-
-}
-
-static int or1k_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- uint8_t data;
-
- LOG_DEBUG("Adding breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32,
- breakpoint->address, breakpoint->length, breakpoint->type,
- breakpoint->set, breakpoint->unique_id);
-
- /* Only support SW breakpoints for now. */
- if (breakpoint->type == BKPT_HARD)
- LOG_ERROR("HW breakpoints not supported for now. Doing SW breakpoint.");
-
- /* Read and save the instruction */
- int retval = du_core->or1k_jtag_read_memory(&or1k->jtag,
- breakpoint->address,
- 4,
- 1,
- &data);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while reading the instruction at 0x%08" PRIx32,
- breakpoint->address);
- return retval;
- }
-
- if (breakpoint->orig_instr != NULL)
- free(breakpoint->orig_instr);
-
- breakpoint->orig_instr = malloc(breakpoint->length);
- memcpy(breakpoint->orig_instr, &data, breakpoint->length);
-
- /* Sub in the OR1K trap instruction */
- uint8_t or1k_trap_insn[4];
- target_buffer_set_u32(target, or1k_trap_insn, OR1K_TRAP_INSTR);
- retval = du_core->or1k_jtag_write_memory(&or1k->jtag,
- breakpoint->address,
- 4,
- 1,
- or1k_trap_insn);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while writing OR1K_TRAP_INSTR at 0x%08" PRIx32,
- breakpoint->address);
- return retval;
- }
-
- /* invalidate instruction cache */
- retval = du_core->or1k_jtag_write_cpu(&or1k->jtag,
- OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while invalidating the ICACHE");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int or1k_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- LOG_DEBUG("Removing breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32,
- breakpoint->address, breakpoint->length, breakpoint->type,
- breakpoint->set, breakpoint->unique_id);
-
- /* Only support SW breakpoints for now. */
- if (breakpoint->type == BKPT_HARD)
- LOG_ERROR("HW breakpoints not supported for now. Doing SW breakpoint.");
-
- /* Replace the removed instruction */
- int retval = du_core->or1k_jtag_write_memory(&or1k->jtag,
- breakpoint->address,
- 4,
- 1,
- breakpoint->orig_instr);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while writing back the instruction at 0x%08" PRIx32,
- breakpoint->address);
- return retval;
- }
-
- /* invalidate instruction cache */
- retval = du_core->or1k_jtag_write_cpu(&or1k->jtag,
- OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while invalidating the ICACHE");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int or1k_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- LOG_ERROR("%s: implement me", __func__);
- return ERROR_OK;
-}
-
-static int or1k_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- LOG_ERROR("%s: implement me", __func__);
- return ERROR_OK;
-}
-
-static int or1k_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- LOG_DEBUG("Read memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !buffer) {
- LOG_ERROR("Bad arguments");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) {
- LOG_ERROR("Can't handle unaligned memory access");
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- return du_core->or1k_jtag_read_memory(&or1k->jtag, address, size, count, buffer);
-}
-
-static int or1k_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- LOG_DEBUG("Write memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* Sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !buffer) {
- LOG_ERROR("Bad arguments");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) {
- LOG_ERROR("Can't handle unaligned memory access");
- return ERROR_TARGET_UNALIGNED_ACCESS;
- }
-
- return du_core->or1k_jtag_write_memory(&or1k->jtag, address, size, count, buffer);
-}
-
-static int or1k_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- struct or1k_jtag *jtag = &or1k->jtag;
-
- if (du_core == NULL) {
- LOG_ERROR("No debug unit selected");
- return ERROR_FAIL;
- }
-
- if (jtag->tap_ip == NULL) {
- LOG_ERROR("No tap selected");
- return ERROR_FAIL;
- }
-
- or1k->jtag.tap = target->tap;
- or1k->jtag.or1k_jtag_inited = 0;
- or1k->jtag.or1k_jtag_module_selected = -1;
- or1k->jtag.target = target;
-
- or1k_build_reg_cache(target);
-
- return ERROR_OK;
-}
-
-static int or1k_target_create(struct target *target, Jim_Interp *interp)
-{
- if (target->tap == NULL)
- return ERROR_FAIL;
-
- struct or1k_common *or1k = calloc(1, sizeof(struct or1k_common));
-
- target->arch_info = or1k;
-
- or1k_create_reg_list(target);
-
- or1k_tap_vjtag_register();
- or1k_tap_xilinx_bscan_register();
- or1k_tap_mohor_register();
-
- or1k_du_adv_register();
-
- return ERROR_OK;
-}
-
-static int or1k_examine(struct target *target)
-{
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
-
- if (!target_was_examined(target)) {
-
- target_set_examined(target);
-
- int running;
-
- int retval = du_core->or1k_is_cpu_running(&or1k->jtag, &running);
- if (retval != ERROR_OK) {
- LOG_ERROR("Couldn't read the CPU state");
- return retval;
- } else {
- if (running)
- target->state = TARGET_RUNNING;
- else {
- LOG_DEBUG("Target is halted");
-
- /* This is the first time we examine the target,
- * it is stalled and we don't know why. Let's
- * assume this is because of a debug reason.
- */
- if (target->state == TARGET_UNKNOWN)
- target->debug_reason = DBG_REASON_DBGRQ;
-
- target->state = TARGET_HALTED;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-static int or1k_arch_state(struct target *target)
-{
- return ERROR_OK;
-}
-
-static int or1k_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
- int *reg_list_size, enum target_register_class reg_class)
-{
- struct or1k_common *or1k = target_to_or1k(target);
-
- if (reg_class == REG_CLASS_GENERAL) {
- /* We will have this called whenever GDB connects. */
- int retval = or1k_save_context(target);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling or1k_save_context");
- return retval;
- }
- *reg_list_size = OR1KNUMCOREREGS;
- /* this is free()'d back in gdb_server.c's gdb_get_register_packet() */
- *reg_list = malloc((*reg_list_size) * sizeof(struct reg *));
-
- for (int i = 0; i < OR1KNUMCOREREGS; i++)
- (*reg_list)[i] = &or1k->core_cache->reg_list[i];
- } else {
- *reg_list_size = or1k->nb_regs;
- *reg_list = malloc((*reg_list_size) * sizeof(struct reg *));
-
- for (int i = 0; i < or1k->nb_regs; i++)
- (*reg_list)[i] = &or1k->core_cache->reg_list[i];
- }
-
- return ERROR_OK;
-
-}
-
-int or1k_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
-{
- return ERROR_FAIL;
-}
-
-static int or1k_checksum_memory(struct target *target, uint32_t address,
- uint32_t count, uint32_t *checksum) {
-
- return ERROR_FAIL;
-}
-
-static int or1k_profiling(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
-{
- struct timeval timeout, now;
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_du *du_core = or1k_to_du(or1k);
- int retval = ERROR_OK;
-
- gettimeofday(&timeout, NULL);
- timeval_add_time(&timeout, seconds, 0);
-
- LOG_INFO("Starting or1k profiling. Sampling npc as fast as we can...");
-
- /* Make sure the target is running */
- target_poll(target);
- if (target->state == TARGET_HALTED)
- retval = target_resume(target, 1, 0, 0, 0);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while resuming target");
- return retval;
- }
-
- uint32_t sample_count = 0;
-
- for (;;) {
- uint32_t reg_value;
- retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, GROUP0 + 16 /* NPC */, 1, &reg_value);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while reading NPC");
- return retval;
- }
-
- samples[sample_count++] = reg_value;
-
- gettimeofday(&now, NULL);
- if ((sample_count >= max_num_samples) ||
- ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) {
- LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
- break;
- }
- }
-
- *num_samples = sample_count;
- return retval;
-}
-
-COMMAND_HANDLER(or1k_tap_select_command_handler)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_jtag *jtag = &or1k->jtag;
- struct or1k_tap_ip *or1k_tap;
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- list_for_each_entry(or1k_tap, &tap_list, list) {
- if (or1k_tap->name) {
- if (!strcmp(CMD_ARGV[0], or1k_tap->name)) {
- jtag->tap_ip = or1k_tap;
- LOG_INFO("%s tap selected", or1k_tap->name);
- return ERROR_OK;
- }
- }
- }
-
- LOG_ERROR("%s unknown, no tap selected", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-COMMAND_HANDLER(or1k_tap_list_command_handler)
-{
- struct or1k_tap_ip *or1k_tap;
-
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- list_for_each_entry(or1k_tap, &tap_list, list) {
- if (or1k_tap->name)
- command_print(CMD_CTX, "%s", or1k_tap->name);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(or1k_du_select_command_handler)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct or1k_common *or1k = target_to_or1k(target);
- struct or1k_jtag *jtag = &or1k->jtag;
- struct or1k_du *or1k_du;
-
- if (CMD_ARGC > 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- list_for_each_entry(or1k_du, &du_list, list) {
- if (or1k_du->name) {
- if (!strcmp(CMD_ARGV[0], or1k_du->name)) {
- jtag->du_core = or1k_du;
- LOG_INFO("%s debug unit selected", or1k_du->name);
-
- if (CMD_ARGC == 2) {
- int options;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], options);
- or1k_du->options = options;
- LOG_INFO("Option %x is passed to %s debug unit"
- , options, or1k_du->name);
- }
-
- return ERROR_OK;
- }
- }
- }
-
- LOG_ERROR("%s unknown, no debug unit selected", CMD_ARGV[0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-COMMAND_HANDLER(or1k_du_list_command_handler)
-{
- struct or1k_du *or1k_du;
-
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- list_for_each_entry(or1k_du, &du_list, list) {
- if (or1k_du->name)
- command_print(CMD_CTX, "%s", or1k_du->name);
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(or1k_addreg_command_handler)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct or1k_core_reg new_reg;
-
- if (CMD_ARGC != 4)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- new_reg.target = NULL;
- new_reg.or1k_common = NULL;
-
- uint32_t addr;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
-
- new_reg.name = strdup(CMD_ARGV[0]);
- new_reg.spr_num = addr;
- new_reg.feature = strdup(CMD_ARGV[2]);
- new_reg.group = strdup(CMD_ARGV[3]);
-
- or1k_add_reg(target, &new_reg);
-
- LOG_DEBUG("Add reg \"%s\" @ 0x%08" PRIx32 ", group \"%s\", feature \"%s\"",
- new_reg.name, addr, new_reg.group, new_reg.feature);
-
- return ERROR_OK;
-}
-
-static const struct command_registration or1k_hw_ip_command_handlers[] = {
- {
- "tap_select",
- .handler = or1k_tap_select_command_handler,
- .mode = COMMAND_ANY,
- .usage = "tap_select name",
- .help = "Select the TAP core to use",
- },
- {
- "tap_list",
- .handler = or1k_tap_list_command_handler,
- .mode = COMMAND_ANY,
- .usage = "tap_list",
- .help = "Display available TAP core",
- },
- {
- "du_select",
- .handler = or1k_du_select_command_handler,
- .mode = COMMAND_ANY,
- .usage = "du_select name",
- .help = "Select the Debug Unit core to use",
- },
- {
- "du_list",
- .handler = or1k_du_list_command_handler,
- .mode = COMMAND_ANY,
- .usage = "select_tap name",
- .help = "Display available Debug Unit core",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration or1k_reg_command_handlers[] = {
- {
- "addreg",
- .handler = or1k_addreg_command_handler,
- .mode = COMMAND_ANY,
- .usage = "addreg name addr feature group",
- .help = "Add a register to the register list",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration or1k_command_handlers[] = {
- {
- .chain = or1k_reg_command_handlers,
- },
- {
- .chain = or1k_hw_ip_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-
-struct target_type or1k_target = {
- .name = "or1k",
-
- .poll = or1k_poll,
- .arch_state = or1k_arch_state,
-
- .target_request_data = NULL,
-
- .halt = or1k_halt,
- .resume = or1k_resume,
- .step = or1k_step,
-
- .assert_reset = or1k_assert_reset,
- .deassert_reset = or1k_deassert_reset,
- .soft_reset_halt = or1k_soft_reset_halt,
-
- .get_gdb_reg_list = or1k_get_gdb_reg_list,
-
- .read_memory = or1k_read_memory,
- .write_memory = or1k_write_memory,
- .checksum_memory = or1k_checksum_memory,
-
- .commands = or1k_command_handlers,
- .add_breakpoint = or1k_add_breakpoint,
- .remove_breakpoint = or1k_remove_breakpoint,
- .add_watchpoint = or1k_add_watchpoint,
- .remove_watchpoint = or1k_remove_watchpoint,
-
- .target_create = or1k_target_create,
- .init_target = or1k_init_target,
- .examine = or1k_examine,
-
- .get_gdb_fileio_info = or1k_get_gdb_fileio_info,
-
- .profiling = or1k_profiling,
-};
diff --git a/src/target/openrisc/or1k.h b/src/target/openrisc/or1k.h
deleted file mode 100644
index c456ccb..0000000
--- a/src/target/openrisc/or1k.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2011 by Julius Baxter *
- * julius@opencores.org *
- * *
- * Copyright (C) 2013 by Marek Czerski *
- * ma.czerski@gmail.com *
- * *
- * Copyright (C) 2013 by Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_OPENRISC_OR1K_H
-#define OPENOCD_TARGET_OPENRISC_OR1K_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <target/target.h>
-
-/* SPR groups start address */
-#define GROUP0 (0 << 11)
-#define GROUP1 (1 << 11)
-#define GROUP2 (2 << 11)
-#define GROUP3 (3 << 11)
-#define GROUP4 (4 << 11)
-#define GROUP5 (5 << 11)
-#define GROUP6 (6 << 11)
-#define GROUP7 (7 << 11)
-#define GROUP8 (8 << 11)
-#define GROUP9 (9 << 11)
-#define GROUP10 (10 << 11)
-
-/* OR1K registers */
-enum or1k_reg_nums {
- OR1K_REG_R0 = 0,
- OR1K_REG_R1,
- OR1K_REG_R2,
- OR1K_REG_R3,
- OR1K_REG_R4,
- OR1K_REG_R5,
- OR1K_REG_R6,
- OR1K_REG_R7,
- OR1K_REG_R8,
- OR1K_REG_R9,
- OR1K_REG_R10,
- OR1K_REG_R11,
- OR1K_REG_R12,
- OR1K_REG_R13,
- OR1K_REG_R14,
- OR1K_REG_R15,
- OR1K_REG_R16,
- OR1K_REG_R17,
- OR1K_REG_R18,
- OR1K_REG_R19,
- OR1K_REG_R20,
- OR1K_REG_R21,
- OR1K_REG_R22,
- OR1K_REG_R23,
- OR1K_REG_R24,
- OR1K_REG_R25,
- OR1K_REG_R26,
- OR1K_REG_R27,
- OR1K_REG_R28,
- OR1K_REG_R29,
- OR1K_REG_R30,
- OR1K_REG_R31,
- OR1K_REG_PPC,
- OR1K_REG_NPC,
- OR1K_REG_SR,
- OR1KNUMCOREREGS
-};
-
-struct or1k_jtag {
- struct jtag_tap *tap;
- int or1k_jtag_inited;
- int or1k_jtag_module_selected;
- uint8_t *current_reg_idx;
- struct or1k_tap_ip *tap_ip;
- struct or1k_du *du_core;
- struct target *target;
-};
-
-struct or1k_common {
- struct or1k_jtag jtag;
- struct reg_cache *core_cache;
- uint32_t core_regs[OR1KNUMCOREREGS];
- int nb_regs;
- struct or1k_core_reg *arch_info;
-};
-
-static inline struct or1k_common *
-target_to_or1k(struct target *target)
-{
- return (struct or1k_common *)target->arch_info;
-}
-
-struct or1k_core_reg {
- const char *name;
- uint32_t list_num; /* Index in register cache */
- uint32_t spr_num; /* Number in architecture's SPR space */
- struct target *target;
- struct or1k_common *or1k_common;
- const char *feature; /* feature name in XML tdesc file */
- const char *group; /* register group in XML tdesc file */
-};
-
-struct or1k_core_reg_init {
- const char *name;
- uint32_t spr_num; /* Number in architecture's SPR space */
- const char *feature; /* feature name in XML tdesc file */
- const char *group; /* register group in XML tdesc file */
-};
-
-/* ORBIS32 Trap instruction */
-#define OR1K_TRAP_INSTR 0x21000001
-
-enum or1k_debug_reg_nums {
- OR1K_DEBUG_REG_DMR1 = 0,
- OR1K_DEBUG_REG_DMR2,
- OR1K_DEBUG_REG_DCWR0,
- OR1K_DEBUG_REG_DCWR1,
- OR1K_DEBUG_REG_DSR,
- OR1K_DEBUG_REG_DRR,
- OR1K_DEBUG_REG_NUM
-};
-
-#define NO_SINGLE_STEP 0
-#define SINGLE_STEP 1
-
-/* OR1K Debug registers and bits needed for resuming */
-#define OR1K_DEBUG_REG_BASE GROUP6 /* Debug registers Base address */
-#define OR1K_DMR1_CPU_REG_ADD (OR1K_DEBUG_REG_BASE + 16) /* Debug Mode Register 1 0x3010 */
-#define OR1K_DMR1_ST 0x00400000 /* Single-step trace */
-#define OR1K_DMR1_BT 0x00800000 /* Branch trace */
-#define OR1K_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */
-#define OR1K_DSR_TE 0x00002000 /* Trap exception */
-
-/* OR1K Instruction cache registers needed for invalidating instruction
- * memory during adding and removing breakpoints.
- */
-#define OR1K_ICBIR_CPU_REG_ADD ((4 << 11) + 2) /* IC Block Invalidate Register 0x2002 */
-
-#endif /* OPENOCD_TARGET_OPENRISC_OR1K_H */
diff --git a/src/target/openrisc/or1k_du.h b/src/target/openrisc/or1k_du.h
deleted file mode 100644
index 9828b0d..0000000
--- a/src/target/openrisc/or1k_du.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_OPENRISC_OR1K_DU_H
-#define OPENOCD_TARGET_OPENRISC_OR1K_DU_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define CPU_STALL 0
-#define CPU_UNSTALL 1
-
-#define CPU_RESET 0
-#define CPU_NOT_RESET 1
-
-int or1k_du_adv_register(void);
-
-/* Linear list over all available or1k debug unit */
-extern struct list_head du_list;
-
-struct or1k_du {
- const char *name;
- struct list_head list;
- int options;
-
- int (*or1k_jtag_init)(struct or1k_jtag *jtag_info);
-
- int (*or1k_is_cpu_running)(struct or1k_jtag *jtag_info, int *running);
-
- int (*or1k_cpu_stall)(struct or1k_jtag *jtag_info, int action);
-
- int (*or1k_cpu_reset)(struct or1k_jtag *jtag_info, int action);
-
- int (*or1k_jtag_read_cpu)(struct or1k_jtag *jtag_info,
- uint32_t addr, int count, uint32_t *value);
-
- int (*or1k_jtag_write_cpu)(struct or1k_jtag *jtag_info,
- uint32_t addr, int count, const uint32_t *value);
-
- int (*or1k_jtag_read_memory)(struct or1k_jtag *jtag_info, uint32_t addr, uint32_t size,
- int count, uint8_t *buffer);
-
- int (*or1k_jtag_write_memory)(struct or1k_jtag *jtag_info, uint32_t addr, uint32_t size,
- int count, const uint8_t *buffer);
-};
-
-static inline struct or1k_du *or1k_jtag_to_du(struct or1k_jtag *jtag_info)
-{
- return (struct or1k_du *)jtag_info->du_core;
-}
-
-static inline struct or1k_du *or1k_to_du(struct or1k_common *or1k)
-{
- struct or1k_jtag *jtag = &or1k->jtag;
- return (struct or1k_du *)jtag->du_core;
-}
-
-int or1k_adv_jtag_jsp_xfer(struct or1k_jtag *jtag_info,
- int *out_len, unsigned char *out_buffer,
- int *in_len, unsigned char *in_buffer);
-
-#endif /* OPENOCD_TARGET_OPENRISC_OR1K_DU_H */
diff --git a/src/target/openrisc/or1k_du_adv.c b/src/target/openrisc/or1k_du_adv.c
deleted file mode 100644
index bdd6fc8..0000000
--- a/src/target/openrisc/or1k_du_adv.c
+++ /dev/null
@@ -1,1098 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013-2014 by Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * Inspired from adv_jtag_bridge which is: *
- * Copyright (C) 2008-2010 Nathan Yawn *
- * nyawn@opencores.net *
- * *
- * And the Mohor interface version of this file which is: *
- * Copyright (C) 2011 by Julius Baxter *
- * julius@opencores.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "or1k_tap.h"
-#include "or1k.h"
-#include "or1k_du.h"
-#include "jsp_server.h"
-
-#include <target/target.h>
-#include <jtag/jtag.h>
-
-#define JSP_BANNER "\n\r" \
- "******************************\n\r" \
- "** JTAG Serial Port **\n\r" \
- "******************************\n\r" \
- "\n\r"
-
-#define NO_OPTION 0
-
-/* This an option to the adv debug unit.
- * If this is defined, status bits will be skipped on burst
- * reads and writes to improve download speeds.
- * This option must match the RTL configured option.
- */
-#define ADBG_USE_HISPEED 1
-
-/* This an option to the adv debug unit.
- * If this is defined, the JTAG Serial Port Server is started.
- * This option must match the RTL configured option.
- */
-#define ENABLE_JSP_SERVER 2
-
-/* Define this if you intend to use the JSP in a system with multiple
- * devices on the JTAG chain
- */
-#define ENABLE_JSP_MULTI 4
-
-/* Definitions for the top-level debug unit. This really just consists
- * of a single register, used to select the active debug module ("chain").
- */
-#define DBG_MODULE_SELECT_REG_SIZE 2
-#define DBG_MAX_MODULES 4
-
-#define DC_NONE -1
-#define DC_WISHBONE 0
-#define DC_CPU0 1
-#define DC_CPU1 2
-#define DC_JSP 3
-
-/* CPU control register bits mask */
-#define DBG_CPU_CR_STALL 0x01
-#define DBG_CPU_CR_RESET 0x02
-
-/* Polynomial for the CRC calculation
- * Yes, it's backwards. Yes, this is on purpose.
- * The hardware is designed this way to save on logic and routing,
- * and it's really all the same to us here.
- */
-#define ADBG_CRC_POLY 0xedb88320
-
-/* These are for the internal registers in the Wishbone module
- * The first is the length of the index register,
- * the indexes of the various registers are defined after that.
- */
-#define DBG_WB_REG_SEL_LEN 1
-#define DBG_WB_REG_ERROR 0
-
-/* Opcode definitions for the Wishbone module. */
-#define DBG_WB_OPCODE_LEN 4
-#define DBG_WB_CMD_NOP 0x0
-#define DBG_WB_CMD_BWRITE8 0x1
-#define DBG_WB_CMD_BWRITE16 0x2
-#define DBG_WB_CMD_BWRITE32 0x3
-#define DBG_WB_CMD_BREAD8 0x5
-#define DBG_WB_CMD_BREAD16 0x6
-#define DBG_WB_CMD_BREAD32 0x7
-#define DBG_WB_CMD_IREG_WR 0x9
-#define DBG_WB_CMD_IREG_SEL 0xd
-
-/* Internal register definitions for the CPU0 module. */
-#define DBG_CPU0_REG_SEL_LEN 1
-#define DBG_CPU0_REG_STATUS 0
-
-/* Opcode definitions for the first CPU module. */
-#define DBG_CPU0_OPCODE_LEN 4
-#define DBG_CPU0_CMD_NOP 0x0
-#define DBG_CPU0_CMD_BWRITE32 0x3
-#define DBG_CPU0_CMD_BREAD32 0x7
-#define DBG_CPU0_CMD_IREG_WR 0x9
-#define DBG_CPU0_CMD_IREG_SEL 0xd
-
-/* Internal register definitions for the CPU1 module. */
-#define DBG_CPU1_REG_SEL_LEN 1
-#define DBG_CPU1_REG_STATUS 0
-
-/* Opcode definitions for the second CPU module. */
-#define DBG_CPU1_OPCODE_LEN 4
-#define DBG_CPU1_CMD_NOP 0x0
-#define DBG_CPU1_CMD_BWRITE32 0x3
-#define DBG_CPU1_CMD_BREAD32 0x7
-#define DBG_CPU1_CMD_IREG_WR 0x9
-#define DBG_CPU1_CMD_IREG_SEL 0xd
-
-#define MAX_READ_STATUS_WAIT 10
-#define MAX_READ_BUSY_RETRY 2
-#define MAX_READ_CRC_RETRY 2
-#define MAX_WRITE_CRC_RETRY 2
-#define BURST_READ_READY 1
-#define MAX_BUS_ERRORS 2
-
-#define MAX_BURST_SIZE (4 * 1024)
-
-#define STATUS_BYTES 1
-#define CRC_LEN 4
-
-static struct or1k_du or1k_du_adv;
-
-static const char * const chain_name[] = {"WISHBONE", "CPU0", "CPU1", "JSP"};
-
-static uint32_t adbg_compute_crc(uint32_t crc, uint32_t data_in,
- int length_bits)
-{
- for (int i = 0; i < length_bits; i++) {
- uint32_t d, c;
- d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
- c = (crc & 0x1) ? 0xffffffff : 0;
- crc = crc >> 1;
- crc = crc ^ ((d ^ c) & ADBG_CRC_POLY);
- }
-
- return crc;
-}
-
-static int find_status_bit(void *_buf, int len)
-{
- int i = 0;
- int count = 0;
- int ret = -1;
- uint8_t *buf = _buf;
-
- while (!(buf[i] & (1 << count++)) && (i < len)) {
- if (count == 8) {
- count = 0;
- i++;
- }
- }
-
- if (i < len)
- ret = (i * 8) + count;
-
- return ret;
-}
-
-static int or1k_adv_jtag_init(struct or1k_jtag *jtag_info)
-{
- struct or1k_tap_ip *tap_ip = jtag_info->tap_ip;
-
- int retval = tap_ip->init(jtag_info);
- if (retval != ERROR_OK) {
- LOG_ERROR("TAP initialization failed");
- return retval;
- }
-
- /* TAP is now configured to communicate with debug interface */
- jtag_info->or1k_jtag_inited = 1;
-
- /* TAP reset - not sure what state debug module chain is in now */
- jtag_info->or1k_jtag_module_selected = DC_NONE;
-
- jtag_info->current_reg_idx = malloc(DBG_MAX_MODULES * sizeof(uint8_t));
- memset(jtag_info->current_reg_idx, 0, DBG_MAX_MODULES * sizeof(uint8_t));
-
- if (or1k_du_adv.options & ADBG_USE_HISPEED)
- LOG_INFO("adv debug unit is configured with option ADBG_USE_HISPEED");
-
- if (or1k_du_adv.options & ENABLE_JSP_SERVER) {
- if (or1k_du_adv.options & ENABLE_JSP_MULTI)
- LOG_INFO("adv debug unit is configured with option ENABLE_JSP_MULTI");
- LOG_INFO("adv debug unit is configured with option ENABLE_JSP_SERVER");
- retval = jsp_init(jtag_info, JSP_BANNER);
- if (retval != ERROR_OK) {
- LOG_ERROR("Couldn't start the JSP server");
- return retval;
- }
- }
-
- LOG_DEBUG("Init done");
-
- return ERROR_OK;
-
-}
-
-/* Selects one of the modules in the debug unit
- * (e.g. wishbone unit, CPU0, etc.)
- */
-static int adbg_select_module(struct or1k_jtag *jtag_info, int chain)
-{
- if (jtag_info->or1k_jtag_module_selected == chain)
- return ERROR_OK;
-
- /* MSB of the data out must be set to 1, indicating a module
- * select command
- */
- uint8_t data = chain | (1 << DBG_MODULE_SELECT_REG_SIZE);
-
- LOG_DEBUG("Select module: %s", chain_name[chain]);
-
- struct scan_field field;
-
- field.num_bits = (DBG_MODULE_SELECT_REG_SIZE + 1);
- field.out_value = &data;
- field.in_value = NULL;
- jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- jtag_info->or1k_jtag_module_selected = chain;
-
- return ERROR_OK;
-}
-
-/* Set the index of the desired register in the currently selected module
- * 1 bit module select command
- * 4 bits opcode
- * n bits index
- */
-static int adbg_select_ctrl_reg(struct or1k_jtag *jtag_info, uint8_t regidx)
-{
- int index_len;
- uint32_t opcode;
- uint32_t opcode_len;
-
- /* If this reg is already selected, don't do a JTAG transaction */
- if (jtag_info->current_reg_idx[jtag_info->or1k_jtag_module_selected] == regidx)
- return ERROR_OK;
-
- switch (jtag_info->or1k_jtag_module_selected) {
- case DC_WISHBONE:
- index_len = DBG_WB_REG_SEL_LEN;
- opcode = DBG_WB_CMD_IREG_SEL;
- opcode_len = DBG_WB_OPCODE_LEN;
- break;
- case DC_CPU0:
- index_len = DBG_CPU0_REG_SEL_LEN;
- opcode = DBG_CPU0_CMD_IREG_SEL;
- opcode_len = DBG_CPU0_OPCODE_LEN;
- break;
- case DC_CPU1:
- index_len = DBG_CPU1_REG_SEL_LEN;
- opcode = DBG_CPU1_CMD_IREG_SEL;
- opcode_len = DBG_CPU1_OPCODE_LEN;
- break;
- default:
- LOG_ERROR("Illegal debug chain selected (%i) while selecting control register",
- jtag_info->or1k_jtag_module_selected);
- return ERROR_FAIL;
- }
-
- /* MSB must be 0 to access modules */
- uint32_t data = (opcode & ~(1 << opcode_len)) << index_len;
- data |= regidx;
-
- struct scan_field field;
-
- field.num_bits = (opcode_len + 1) + index_len;
- field.out_value = (uint8_t *)&data;
- field.in_value = NULL;
- jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- jtag_info->current_reg_idx[jtag_info->or1k_jtag_module_selected] = regidx;
-
- return ERROR_OK;
-}
-
-/* Write control register (internal to the debug unit) */
-static int adbg_ctrl_write(struct or1k_jtag *jtag_info, uint8_t regidx,
- uint32_t *cmd_data, int length_bits)
-{
- int index_len;
- uint32_t opcode;
- uint32_t opcode_len;
-
- LOG_DEBUG("Write control register %" PRId8 ": 0x%08" PRIx32, regidx, cmd_data[0]);
-
- int retval = adbg_select_ctrl_reg(jtag_info, regidx);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling adbg_select_ctrl_reg");
- return retval;
- }
-
- switch (jtag_info->or1k_jtag_module_selected) {
- case DC_WISHBONE:
- index_len = DBG_WB_REG_SEL_LEN;
- opcode = DBG_WB_CMD_IREG_WR;
- opcode_len = DBG_WB_OPCODE_LEN;
- break;
- case DC_CPU0:
- index_len = DBG_CPU0_REG_SEL_LEN;
- opcode = DBG_CPU0_CMD_IREG_WR;
- opcode_len = DBG_CPU0_OPCODE_LEN;
- break;
- case DC_CPU1:
- index_len = DBG_CPU1_REG_SEL_LEN;
- opcode = DBG_CPU1_CMD_IREG_WR;
- opcode_len = DBG_CPU1_OPCODE_LEN;
- break;
- default:
- LOG_ERROR("Illegal debug chain selected (%i) while doing control write",
- jtag_info->or1k_jtag_module_selected);
- return ERROR_FAIL;
- }
-
- struct scan_field field[2];
-
- /* MSB must be 0 to access modules */
- uint32_t data = (opcode & ~(1 << opcode_len)) << index_len;
- data |= regidx;
-
- field[0].num_bits = length_bits;
- field[0].out_value = (uint8_t *)cmd_data;
- field[0].in_value = NULL;
-
- field[1].num_bits = (opcode_len + 1) + index_len;
- field[1].out_value = (uint8_t *)&data;
- field[1].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 2, field, TAP_IDLE);
-
- return jtag_execute_queue();
-}
-
-/* Reads control register (internal to the debug unit) */
-static int adbg_ctrl_read(struct or1k_jtag *jtag_info, uint32_t regidx,
- uint32_t *data, int length_bits)
-{
-
- int retval = adbg_select_ctrl_reg(jtag_info, regidx);
- if (retval != ERROR_OK) {
- LOG_ERROR("Error while calling adbg_select_ctrl_reg");
- return retval;
- }
-
- int opcode_len;
- uint32_t opcode;
-
- /* There is no 'read' command, We write a NOP to read */
- switch (jtag_info->or1k_jtag_module_selected) {
- case DC_WISHBONE:
- opcode = DBG_WB_CMD_NOP;
- opcode_len = DBG_WB_OPCODE_LEN;
- break;
- case DC_CPU0:
- opcode = DBG_CPU0_CMD_NOP;
- opcode_len = DBG_CPU0_OPCODE_LEN;
- break;
- case DC_CPU1:
- opcode = DBG_CPU1_CMD_NOP;
- opcode_len = DBG_CPU1_OPCODE_LEN;
- break;
- default:
- LOG_ERROR("Illegal debug chain selected (%i) while doing control read",
- jtag_info->or1k_jtag_module_selected);
- return ERROR_FAIL;
- }
-
- /* Zero MSB = op for module, not top-level debug unit */
- uint32_t outdata = opcode & ~(0x1 << opcode_len);
-
- struct scan_field field[2];
-
- field[0].num_bits = length_bits;
- field[0].out_value = NULL;
- field[0].in_value = (uint8_t *)data;
-
- field[1].num_bits = opcode_len + 1;
- field[1].out_value = (uint8_t *)&outdata;
- field[1].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 2, field, TAP_IDLE);
-
- return jtag_execute_queue();
-}
-
-/* sends out a burst command to the selected module in the debug unit (MSB to LSB):
- * 1-bit module command
- * 4-bit opcode
- * 32-bit address
- * 16-bit length (of the burst, in words)
- */
-static int adbg_burst_command(struct or1k_jtag *jtag_info, uint32_t opcode,
- uint32_t address, uint16_t length_words)
-{
- uint32_t data[2];
-
- /* Set up the data */
- data[0] = length_words | (address << 16);
- /* MSB must be 0 to access modules */
- data[1] = ((address >> 16) | ((opcode & 0xf) << 16)) & ~(0x1 << 20);
-
- struct scan_field field;
-
- field.num_bits = 53;
- field.out_value = (uint8_t *)&data[0];
- field.in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
-
- return jtag_execute_queue();
-}
-
-static int adbg_wb_burst_read(struct or1k_jtag *jtag_info, int size,
- int count, uint32_t start_address, uint8_t *data)
-{
- int retry_full_crc = 0;
- int retry_full_busy = 0;
- int retval;
- uint8_t opcode;
-
- LOG_DEBUG("Doing burst read, word size %d, word count %d, start address 0x%08" PRIx32,
- size, count, start_address);
-
- /* Select the appropriate opcode */
- switch (jtag_info->or1k_jtag_module_selected) {
- case DC_WISHBONE:
- if (size == 1)
- opcode = DBG_WB_CMD_BREAD8;
- else if (size == 2)
- opcode = DBG_WB_CMD_BREAD16;
- else if (size == 4)
- opcode = DBG_WB_CMD_BREAD32;
- else {
- LOG_WARNING("Tried burst read with invalid word size (%d),"
- "defaulting to 4-byte words", size);
- opcode = DBG_WB_CMD_BREAD32;
- }
- break;
- case DC_CPU0:
- if (size == 4)
- opcode = DBG_CPU0_CMD_BREAD32;
- else {
- LOG_WARNING("Tried burst read with invalid word size (%d),"
- "defaulting to 4-byte words", size);
- opcode = DBG_CPU0_CMD_BREAD32;
- }
- break;
- case DC_CPU1:
- if (size == 4)
- opcode = DBG_CPU1_CMD_BREAD32;
- else {
- LOG_WARNING("Tried burst read with invalid word size (%d),"
- "defaulting to 4-byte words", size);
- opcode = DBG_CPU0_CMD_BREAD32;
- }
- break;
- default:
- LOG_ERROR("Illegal debug chain selected (%i) while doing burst read",
- jtag_info->or1k_jtag_module_selected);
- return ERROR_FAIL;
- }
-
- int total_size_bytes = count * size;
- struct scan_field field;
- uint8_t *in_buffer = malloc(total_size_bytes + CRC_LEN + STATUS_BYTES);
-
-retry_read_full:
-
- /* Send the BURST READ command, returns TAP to idle state */
- retval = adbg_burst_command(jtag_info, opcode, start_address, count);
- if (retval != ERROR_OK)
- goto out;
-
- field.num_bits = (total_size_bytes + CRC_LEN + STATUS_BYTES) * 8;
- field.out_value = NULL;
- field.in_value = in_buffer;
-
- jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- goto out;
-
- /* Look for the start bit in the first (STATUS_BYTES * 8) bits */
- int shift = find_status_bit(in_buffer, STATUS_BYTES);
-
- /* We expect the status bit to be in the first byte */
- if (shift < 0) {
- if (retry_full_busy++ < MAX_READ_BUSY_RETRY) {
- LOG_WARNING("Burst read timed out");
- goto retry_read_full;
- } else {
- LOG_ERROR("Burst read failed");
- retval = ERROR_FAIL;
- goto out;
- }
- }
-
- buffer_shr(in_buffer, total_size_bytes + CRC_LEN + STATUS_BYTES, shift);
-
- uint32_t crc_read;
- memcpy(data, in_buffer, total_size_bytes);
- memcpy(&crc_read, &in_buffer[total_size_bytes], 4);
-
- uint32_t crc_calc = 0xffffffff;
- for (int i = 0; i < total_size_bytes; i++)
- crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
-
- if (crc_calc != crc_read) {
- LOG_WARNING("CRC ERROR! Computed 0x%08" PRIx32 ", read CRC 0x%08" PRIx32, crc_calc, crc_read);
- if (retry_full_crc++ < MAX_READ_CRC_RETRY)
- goto retry_read_full;
- else {
- LOG_ERROR("Burst read failed");
- retval = ERROR_FAIL;
- goto out;
- }
- } else
- LOG_DEBUG("CRC OK!");
-
- /* Now, read the error register, and retry/recompute as necessary */
- if (jtag_info->or1k_jtag_module_selected == DC_WISHBONE &&
- !(or1k_du_adv.options & ADBG_USE_HISPEED)) {
-
- uint32_t err_data[2] = {0, 0};
- uint32_t addr;
- int bus_error_retries = 0;
-
- /* First, just get 1 bit...read address only if necessary */
- retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 1);
- if (retval != ERROR_OK)
- goto out;
-
- /* Then we have a problem */
- if (err_data[0] & 0x1) {
-
- retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 33);
- if (retval != ERROR_OK)
- goto out;
-
- addr = (err_data[0] >> 1) | (err_data[1] << 31);
- LOG_WARNING("WB bus error during burst read, address 0x%08" PRIx32 ", retrying!", addr);
-
- bus_error_retries++;
- if (bus_error_retries > MAX_BUS_ERRORS) {
- LOG_ERROR("Max WB bus errors reached during burst read");
- retval = ERROR_FAIL;
- goto out;
- }
-
- /* Don't call retry_do(), a JTAG reset won't help a WB bus error */
- /* Write 1 bit, to reset the error register */
- err_data[0] = 1;
- retval = adbg_ctrl_write(jtag_info, DBG_WB_REG_ERROR, err_data, 1);
- if (retval != ERROR_OK)
- goto out;
-
- goto retry_read_full;
- }
- }
-
-out:
- free(in_buffer);
-
- return retval;
-}
-
-/* Set up and execute a burst write to a contiguous set of addresses */
-static int adbg_wb_burst_write(struct or1k_jtag *jtag_info, const uint8_t *data, int size,
- int count, unsigned long start_address)
-{
- int retry_full_crc = 0;
- int retval;
- uint8_t opcode;
-
- LOG_DEBUG("Doing burst write, word size %d, word count %d,"
- "start address 0x%08lx", size, count, start_address);
-
- /* Select the appropriate opcode */
- switch (jtag_info->or1k_jtag_module_selected) {
- case DC_WISHBONE:
- if (size == 1)
- opcode = DBG_WB_CMD_BWRITE8;
- else if (size == 2)
- opcode = DBG_WB_CMD_BWRITE16;
- else if (size == 4)
- opcode = DBG_WB_CMD_BWRITE32;
- else {
- LOG_DEBUG("Tried WB burst write with invalid word size (%d),"
- "defaulting to 4-byte words", size);
- opcode = DBG_WB_CMD_BWRITE32;
- }
- break;
- case DC_CPU0:
- if (size == 4)
- opcode = DBG_CPU0_CMD_BWRITE32;
- else {
- LOG_DEBUG("Tried CPU0 burst write with invalid word size (%d),"
- "defaulting to 4-byte words", size);
- opcode = DBG_CPU0_CMD_BWRITE32;
- }
- break;
- case DC_CPU1:
- if (size == 4)
- opcode = DBG_CPU1_CMD_BWRITE32;
- else {
- LOG_DEBUG("Tried CPU1 burst write with invalid word size (%d),"
- "defaulting to 4-byte words", size);
- opcode = DBG_CPU0_CMD_BWRITE32;
- }
- break;
- default:
- LOG_ERROR("Illegal debug chain selected (%i) while doing burst write",
- jtag_info->or1k_jtag_module_selected);
- return ERROR_FAIL;
- }
-
-retry_full_write:
-
- /* Send the BURST WRITE command, returns TAP to idle state */
- retval = adbg_burst_command(jtag_info, opcode, start_address, count);
- if (retval != ERROR_OK)
- return retval;
-
- struct scan_field field[3];
-
- /* Write a start bit so it knows when to start counting */
- uint8_t value = 1;
- field[0].num_bits = 1;
- field[0].out_value = &value;
- field[0].in_value = NULL;
-
- uint32_t crc_calc = 0xffffffff;
- for (int i = 0; i < (count * size); i++)
- crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
-
- field[1].num_bits = count * size * 8;
- field[1].out_value = data;
- field[1].in_value = NULL;
-
- field[2].num_bits = 32;
- field[2].out_value = (uint8_t *)&crc_calc;
- field[2].in_value = NULL;
-
- jtag_add_dr_scan(jtag_info->tap, 3, field, TAP_DRSHIFT);
-
- /* Read the 'CRC match' bit, and go to idle */
- field[0].num_bits = 1;
- field[0].out_value = NULL;
- field[0].in_value = &value;
- jtag_add_dr_scan(jtag_info->tap, 1, field, TAP_IDLE);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- if (!value) {
- LOG_WARNING("CRC ERROR! match bit after write is %" PRIi8 " (computed CRC 0x%08" PRIx32 ")", value, crc_calc);
- if (retry_full_crc++ < MAX_WRITE_CRC_RETRY)
- goto retry_full_write;
- else
- return ERROR_FAIL;
- } else
- LOG_DEBUG("CRC OK!\n");
-
- /* Now, read the error register, and retry/recompute as necessary */
- if (jtag_info->or1k_jtag_module_selected == DC_WISHBONE &&
- !(or1k_du_adv.options & ADBG_USE_HISPEED)) {
- uint32_t addr;
- int bus_error_retries = 0;
- uint32_t err_data[2] = {0, 0};
-
- /* First, just get 1 bit...read address only if necessary */
- retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 1);
- if (retval != ERROR_OK)
- return retval;
-
- /* Then we have a problem */
- if (err_data[0] & 0x1) {
-
- retval = adbg_ctrl_read(jtag_info, DBG_WB_REG_ERROR, err_data, 33);
- if (retval != ERROR_OK)
- return retval;
-
- addr = (err_data[0] >> 1) | (err_data[1] << 31);
- LOG_WARNING("WB bus error during burst write, address 0x%08" PRIx32 ", retrying!", addr);
-
- bus_error_retries++;
- if (bus_error_retries > MAX_BUS_ERRORS) {
- LOG_ERROR("Max WB bus errors reached during burst read");
- retval = ERROR_FAIL;
- return retval;
- }
-
- /* Don't call retry_do(), a JTAG reset won't help a WB bus error */
- /* Write 1 bit, to reset the error register */
- err_data[0] = 1;
- retval = adbg_ctrl_write(jtag_info, DBG_WB_REG_ERROR, err_data, 1);
- if (retval != ERROR_OK)
- return retval;
-
- goto retry_full_write;
- }
- }
-
- return ERROR_OK;
-}
-
-/* Currently hard set in functions to 32-bits */
-static int or1k_adv_jtag_read_cpu(struct or1k_jtag *jtag_info,
- uint32_t addr, int count, uint32_t *value)
-{
- int retval;
- if (!jtag_info->or1k_jtag_inited) {
- retval = or1k_adv_jtag_init(jtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = adbg_select_module(jtag_info, DC_CPU0);
- if (retval != ERROR_OK)
- return retval;
-
- return adbg_wb_burst_read(jtag_info, 4, count, addr, (uint8_t *)value);
-}
-
-static int or1k_adv_jtag_write_cpu(struct or1k_jtag *jtag_info,
- uint32_t addr, int count, const uint32_t *value)
-{
- int retval;
- if (!jtag_info->or1k_jtag_inited) {
- retval = or1k_adv_jtag_init(jtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = adbg_select_module(jtag_info, DC_CPU0);
- if (retval != ERROR_OK)
- return retval;
-
- return adbg_wb_burst_write(jtag_info, (uint8_t *)value, 4, count, addr);
-}
-
-static int or1k_adv_cpu_stall(struct or1k_jtag *jtag_info, int action)
-{
- int retval;
- if (!jtag_info->or1k_jtag_inited) {
- retval = or1k_adv_jtag_init(jtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = adbg_select_module(jtag_info, DC_CPU0);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t cpu_cr;
- retval = adbg_ctrl_read(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2);
- if (retval != ERROR_OK)
- return retval;
-
- if (action == CPU_STALL)
- cpu_cr |= DBG_CPU_CR_STALL;
- else
- cpu_cr &= ~DBG_CPU_CR_STALL;
-
- retval = adbg_select_module(jtag_info, DC_CPU0);
- if (retval != ERROR_OK)
- return retval;
-
- return adbg_ctrl_write(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2);
-}
-
-static int or1k_adv_is_cpu_running(struct or1k_jtag *jtag_info, int *running)
-{
- int retval;
- if (!jtag_info->or1k_jtag_inited) {
- retval = or1k_adv_jtag_init(jtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- int current = jtag_info->or1k_jtag_module_selected;
-
- retval = adbg_select_module(jtag_info, DC_CPU0);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t cpu_cr = 0;
- retval = adbg_ctrl_read(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2);
- if (retval != ERROR_OK)
- return retval;
-
- if (cpu_cr & DBG_CPU_CR_STALL)
- *running = 0;
- else
- *running = 1;
-
- if (current != DC_NONE) {
- retval = adbg_select_module(jtag_info, current);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int or1k_adv_cpu_reset(struct or1k_jtag *jtag_info, int action)
-{
- int retval;
- if (!jtag_info->or1k_jtag_inited) {
- retval = or1k_adv_jtag_init(jtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = adbg_select_module(jtag_info, DC_CPU0);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t cpu_cr;
- retval = adbg_ctrl_read(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2);
- if (retval != ERROR_OK)
- return retval;
-
- if (action == CPU_RESET)
- cpu_cr |= DBG_CPU_CR_RESET;
- else
- cpu_cr &= ~DBG_CPU_CR_RESET;
-
- retval = adbg_select_module(jtag_info, DC_CPU0);
- if (retval != ERROR_OK)
- return retval;
-
- return adbg_ctrl_write(jtag_info, DBG_CPU0_REG_STATUS, &cpu_cr, 2);
-}
-
-static int or1k_adv_jtag_read_memory(struct or1k_jtag *jtag_info,
- uint32_t addr, uint32_t size, int count, uint8_t *buffer)
-{
- LOG_DEBUG("Reading WB%" PRId32 " at 0x%08" PRIx32, size * 8, addr);
-
- int retval;
- if (!jtag_info->or1k_jtag_inited) {
- retval = or1k_adv_jtag_init(jtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = adbg_select_module(jtag_info, DC_WISHBONE);
- if (retval != ERROR_OK)
- return retval;
-
- int block_count_left = count;
- uint32_t block_count_address = addr;
- uint8_t *block_count_buffer = buffer;
-
- while (block_count_left) {
-
- int blocks_this_round = (block_count_left > MAX_BURST_SIZE) ?
- MAX_BURST_SIZE : block_count_left;
-
- retval = adbg_wb_burst_read(jtag_info, size, blocks_this_round,
- block_count_address, block_count_buffer);
- if (retval != ERROR_OK)
- return retval;
-
- block_count_left -= blocks_this_round;
- block_count_address += size * MAX_BURST_SIZE;
- block_count_buffer += size * MAX_BURST_SIZE;
- }
-
- /* The adv_debug_if always return words and half words in
- * little-endian order no matter what the target endian is.
- * So if the target endian is big, change the order.
- */
-
- struct target *target = jtag_info->target;
- if ((target->endianness == TARGET_BIG_ENDIAN) && (size != 1)) {
- switch (size) {
- case 4:
- buf_bswap32(buffer, buffer, size * count);
- break;
- case 2:
- buf_bswap16(buffer, buffer, size * count);
- break;
- }
- }
-
- return ERROR_OK;
-}
-
-static int or1k_adv_jtag_write_memory(struct or1k_jtag *jtag_info,
- uint32_t addr, uint32_t size, int count, const uint8_t *buffer)
-{
- LOG_DEBUG("Writing WB%" PRId32 " at 0x%08" PRIx32, size * 8, addr);
-
- int retval;
- if (!jtag_info->or1k_jtag_inited) {
- retval = or1k_adv_jtag_init(jtag_info);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = adbg_select_module(jtag_info, DC_WISHBONE);
- if (retval != ERROR_OK)
- return retval;
-
- /* The adv_debug_if wants words and half words in little-endian
- * order no matter what the target endian is. So if the target
- * endian is big, change the order.
- */
-
- void *t = NULL;
- struct target *target = jtag_info->target;
- if ((target->endianness == TARGET_BIG_ENDIAN) && (size != 1)) {
- t = malloc(count * size * sizeof(uint8_t));
- if (t == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- switch (size) {
- case 4:
- buf_bswap32(t, buffer, size * count);
- break;
- case 2:
- buf_bswap16(t, buffer, size * count);
- break;
- }
- buffer = t;
- }
-
- int block_count_left = count;
- uint32_t block_count_address = addr;
- uint8_t *block_count_buffer = (uint8_t *)buffer;
-
- while (block_count_left) {
-
- int blocks_this_round = (block_count_left > MAX_BURST_SIZE) ?
- MAX_BURST_SIZE : block_count_left;
-
- retval = adbg_wb_burst_write(jtag_info, block_count_buffer,
- size, blocks_this_round,
- block_count_address);
- if (retval != ERROR_OK) {
- if (t != NULL)
- free(t);
- return retval;
- }
-
- block_count_left -= blocks_this_round;
- block_count_address += size * MAX_BURST_SIZE;
- block_count_buffer += size * MAX_BURST_SIZE;
- }
-
- if (t != NULL)
- free(t);
-
- return ERROR_OK;
-}
-
-int or1k_adv_jtag_jsp_xfer(struct or1k_jtag *jtag_info,
- int *out_len, unsigned char *out_buffer,
- int *in_len, unsigned char *in_buffer)
-{
- LOG_DEBUG("JSP transfert");
-
- int retval;
- if (!jtag_info->or1k_jtag_inited)
- return ERROR_OK;
-
- retval = adbg_select_module(jtag_info, DC_JSP);
- if (retval != ERROR_OK)
- return retval;
-
- /* return nb char xmit */
- int xmitsize;
- if (*out_len > 8)
- xmitsize = 8;
- else
- xmitsize = *out_len;
-
- uint8_t out_data[10];
- uint8_t in_data[10];
- struct scan_field field;
- int startbit, stopbit, wrapbit;
-
- memset(out_data, 0, 10);
-
- if (or1k_du_adv.options & ENABLE_JSP_MULTI) {
-
- startbit = 1;
- wrapbit = (xmitsize >> 3) & 0x1;
- out_data[0] = (xmitsize << 5) | 0x1; /* set the start bit */
-
- int i;
- /* don't copy off the end of the input array */
- for (i = 0; i < xmitsize; i++) {
- out_data[i + 1] = (out_buffer[i] << 1) | wrapbit;
- wrapbit = (out_buffer[i] >> 7) & 0x1;
- }
-
- if (i < 8)
- out_data[i + 1] = wrapbit;
- else
- out_data[9] = wrapbit;
-
- /* If the last data bit is a '1', then we need to append a '0' so the top-level module
- * won't treat the burst as a 'module select' command.
- */
- stopbit = !!(out_data[9] & 0x01);
-
- } else {
- startbit = 0;
- /* First byte out has write count in upper nibble */
- out_data[0] = 0x0 | (xmitsize << 4);
- if (xmitsize > 0)
- memcpy(&out_data[1], out_buffer, xmitsize);
-
- /* If the last data bit is a '1', then we need to append a '0' so the top-level module
- * won't treat the burst as a 'module select' command.
- */
- stopbit = !!(out_data[8] & 0x80);
- }
-
- field.num_bits = 72 + startbit + stopbit;
- field.out_value = out_data;
- field.in_value = in_data;
-
- jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- /* bytes available is in the upper nibble */
- *in_len = (in_data[0] >> 4) & 0xF;
- memcpy(in_buffer, &in_data[1], *in_len);
-
- int bytes_free = in_data[0] & 0x0F;
- *out_len = (bytes_free < xmitsize) ? bytes_free : xmitsize;
-
- return ERROR_OK;
-}
-
-static struct or1k_du or1k_du_adv = {
- .name = "adv",
- .options = NO_OPTION,
- .or1k_jtag_init = or1k_adv_jtag_init,
-
- .or1k_is_cpu_running = or1k_adv_is_cpu_running,
- .or1k_cpu_stall = or1k_adv_cpu_stall,
- .or1k_cpu_reset = or1k_adv_cpu_reset,
-
- .or1k_jtag_read_cpu = or1k_adv_jtag_read_cpu,
- .or1k_jtag_write_cpu = or1k_adv_jtag_write_cpu,
-
- .or1k_jtag_read_memory = or1k_adv_jtag_read_memory,
- .or1k_jtag_write_memory = or1k_adv_jtag_write_memory
-};
-
-int or1k_du_adv_register(void)
-{
- list_add_tail(&or1k_du_adv.list, &du_list);
- return 0;
-}
diff --git a/src/target/openrisc/or1k_tap.h b/src/target/openrisc/or1k_tap.h
deleted file mode 100644
index 2cf7da8..0000000
--- a/src/target/openrisc/or1k_tap.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2012 by Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_OPENRISC_OR1K_TAP_H
-#define OPENOCD_TARGET_OPENRISC_OR1K_TAP_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/list.h>
-#include "or1k.h"
-
-int or1k_tap_vjtag_register(void);
-int or1k_tap_xilinx_bscan_register(void);
-int or1k_tap_mohor_register(void);
-
-/* Linear list over all available or1k taps */
-extern struct list_head tap_list;
-
-struct or1k_tap_ip {
- struct list_head list;
- int (*init)(struct or1k_jtag *jtag_info);
- const char *name;
-};
-
-#endif /* OPENOCD_TARGET_OPENRISC_OR1K_TAP_H */
diff --git a/src/target/openrisc/or1k_tap_mohor.c b/src/target/openrisc/or1k_tap_mohor.c
deleted file mode 100644
index 1415e32..0000000
--- a/src/target/openrisc/or1k_tap_mohor.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "or1k_tap.h"
-#include "or1k.h"
-
-#include <jtag/jtag.h>
-
-#define OR1K_TAP_INST_DEBUG 0x8
-
-static int or1k_tap_mohor_init(struct or1k_jtag *jtag_info)
-{
- LOG_DEBUG("Initialising OpenCores JTAG TAP");
-
- /* Put TAP into state where it can talk to the debug interface
- * by shifting in correct value to IR.
- */
-
- /* Ensure TAP is reset - maybe not necessary*/
- jtag_add_tlr();
-
- struct jtag_tap *tap = jtag_info->tap;
- struct scan_field field;
- uint8_t ir_value = OR1K_TAP_INST_DEBUG;
-
- field.num_bits = tap->ir_length;
- field.out_value = &ir_value;
- field.in_value = NULL;
-
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- return jtag_execute_queue();
-}
-
-static struct or1k_tap_ip mohor_tap = {
- .name = "mohor",
- .init = or1k_tap_mohor_init,
-};
-
-int or1k_tap_mohor_register(void)
-{
- list_add_tail(&mohor_tap.list, &tap_list);
- return 0;
-}
diff --git a/src/target/openrisc/or1k_tap_vjtag.c b/src/target/openrisc/or1k_tap_vjtag.c
deleted file mode 100644
index 607451a..0000000
--- a/src/target/openrisc/or1k_tap_vjtag.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Franck Jullien *
- * elec4fun@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "or1k_tap.h"
-#include "or1k.h"
-
-#include <jtag/jtag.h>
-
-/* Contains constants relevant to the Altera Virtual JTAG
- * device, which are not included in the BSDL.
- * As of this writing, these are constant across every
- * device which supports virtual JTAG.
- */
-
-/* These are commands for the FPGA's IR. */
-#define ALTERA_CYCLONE_CMD_USER1 0x0E
-#define ALTERA_CYCLONE_CMD_USER0 0x0C
-
-/* These defines are for the virtual IR (not the FPGA's)
- * The virtual TAP was defined in hardware to match the OpenCores native
- * TAP in both IR size and DEBUG command.
- */
-#define ALT_VJTAG_IR_SIZE 4
-#define ALT_VJTAG_CMD_DEBUG 0x8
-
-/* SLD node ID. */
-#define JTAG_TO_AVALON_NODE_ID 0x84
-#define VJTAG_NODE_ID 0x08
-#define SIGNAL_TAP_NODE_ID 0x00
-#define SERIAL_FLASH_LOADER_NODE_ID 0x04
-
-#define VER(x) ((x >> 27) & 0x1f)
-#define NB_NODES(x) ((x >> 19) & 0xff)
-#define ID(x) ((x >> 19) & 0xff)
-#define MANUF(x) ((x >> 8) & 0x7ff)
-#define M_WIDTH(x) ((x >> 0) & 0xff)
-#define INST_ID(x) ((x >> 0) & 0xff)
-
-/* tap instructions - Mohor JTAG TAP */
-#define OR1K_TAP_INST_IDCODE 0x2
-#define OR1K_TAP_INST_DEBUG 0x8
-
-static const char *id_to_string(unsigned char id)
-{
- switch (id) {
- case VJTAG_NODE_ID:
- return "Virtual JTAG";
- case JTAG_TO_AVALON_NODE_ID:
- return "JTAG to avalon bridge";
- case SIGNAL_TAP_NODE_ID:
- return "Signal TAP";
- case SERIAL_FLASH_LOADER_NODE_ID:
- return "Serial Flash Loader";
- }
- return "unknown";
-}
-
-static unsigned char guess_addr_width(unsigned char number_of_nodes)
-{
- unsigned char width = 0;
-
- while (number_of_nodes) {
- number_of_nodes >>= 1;
- width++;
- }
-
- return width;
-}
-
-static int or1k_tap_vjtag_init(struct or1k_jtag *jtag_info)
-{
- LOG_DEBUG("Initialising Altera Virtual JTAG TAP");
-
- /* Put TAP into state where it can talk to the debug interface
- * by shifting in correct value to IR.
- */
-
- /* Ensure TAP is reset - maybe not necessary*/
- jtag_add_tlr();
-
- /* You can use a custom JTAG controller to discover transactions
- * necessary to enumerate all Virtual JTAG megafunction instances
- * from your design atruntime. All SLD nodes and the virtual JTAG
- * registers that they contain are targeted by two Instruction Register
- * values, USER0 and USER1.
- *
- * The USER1 instruction targets the virtual IR of either the sld_hub
- * or a SLD node. That is,when the USER1 instruction is issued to
- * the device, the subsequent DR scans target a specific virtual
- * IR chain based on an address field contained within the DR scan.
- * The table below shows how the virtual IR, the DR target of the
- * USER1 instruction is interpreted.
- *
- * The VIR_VALUE in the table below is the virtual IR value for the
- * target SLD node. The width of this field is m bits in length,
- * where m is the length of the largest VIR for all of the SLD nodes
- * in the design. All SLD nodes with VIR lengths of fewer than m
- * bits must pad VIR_VALUE with zeros up to a length of m.
- *
- * -------------------------------+-------------------------------
- * m + n - 1 m | m -1 0
- * -------------------------------+-------------------------------
- * ADDR [(n – 1)..0] | VIR_VALUE [(m – 1)..0]
- * -------------------------------+-------------------------------
- *
- * The ADDR bits act as address values to signal the active SLD node
- * that the virtual IR shift targets. ADDR is n bits in length, where
- * n bits must be long enough to encode all SLD nodes within the design,
- * as shown below.
- *
- * n = CEIL(log2(Number of SLD_nodes +1))
- *
- * The SLD hub is always 0 in the address map.
- *
- * Discovery and enumeration of the SLD instances within a design
- * requires interrogation of the sld_hub to determine the dimensions
- * of the USER1 DR (m and n) and associating each SLD instance, specifically
- * the Virtual JTAG megafunction instances, with an address value
- * contained within the ADDR bits of the USER1 DR.
- *
- * The SLD hub contains the HUB IP Configuration Register and SLD_NODE_INFO
- * register for each SLD node in the design. The HUB IP configuration register provides
- * information needed to determine the dimensions of the USER1 DR chain. The
- * SLD_NODE_INFO register is used to determine the address mapping for Virtual
- * JTAG instance in your design. This register set is shifted out by issuing the
- * HUB_INFO instruction. Both the ADDR bits for the SLD hub and the HUB_INFO
- * instruction is 0 × 0.
- * Because m and n are unknown at this point, the DR register
- * (ADDR bits + VIR_VALUE) must be filled with zeros. Shifting a sequence of 64 zeroes
- * into the USER1 DR is sufficient to cover the most conservative case for m and n.
- */
-
- uint8_t t[4];
- struct scan_field field;
- struct jtag_tap *tap = jtag_info->tap;
-
- /* Select VIR */
- buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER1);
- field.num_bits = tap->ir_length;
- field.out_value = t;
- field.in_value = NULL;
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- /* Select the SLD Hub */
- field.num_bits = 64;
- field.out_value = NULL;
- field.in_value = NULL;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- /* HUB IP Configuration Register
- *
- * When the USER1 and HUB_INFO instruction sequence is issued, the
- * USER0 instruction must be applied to enable the target register
- * of the HUB_INFO instruction. The HUB IP configuration register
- * is shifted out using eight four-bit nibble scans of the DR register.
- * Each four-bit scan must pass through the UPDATE_DR state before
- * the next four-bit scan. The 8 scans are assembled into a 32-bit
- * value with the definitions shown in the table below.
- *
- * --------------------------------------------------------------------------------
- * NIBBLE7 | NIBBLE6 | NIBBLE5 | NIBBLE4 | NIBBLE3 | NIBBLE2 | NIBBLE1 | NIBBLE0
- * ----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----
- * | | | | | | | | | | | | | | |
- * ----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----
- * HUB IP version| N | ALTERA_MFG_ID (0x06E) | SUM (m, n)
- * --------------+-------------------+------------------------+--------------------
- */
-
- /* Select VDR */
- buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER0);
- field.num_bits = tap->ir_length;
- field.out_value = t;
- field.in_value = NULL;
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
-
- uint8_t nibble;
- uint32_t hub_info = 0;
-
- for (int i = 0; i < 8; i++) {
- field.num_bits = 4;
- field.out_value = NULL;
- field.in_value = &nibble;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- hub_info = ((hub_info >> 4) | ((nibble & 0xf) << 28));
- }
-
- int nb_nodes = NB_NODES(hub_info);
- int m_width = M_WIDTH(hub_info);
-
- LOG_DEBUG("SLD HUB Configuration register");
- LOG_DEBUG("------------------------------");
- LOG_DEBUG("m_width = %d", m_width);
- LOG_DEBUG("manufacturer_id = 0x%02" PRIx32, MANUF(hub_info));
- LOG_DEBUG("nb_of_node = %d", nb_nodes);
- LOG_DEBUG("version = %" PRId32, VER(hub_info));
- LOG_DEBUG("VIR length = %d", guess_addr_width(nb_nodes) + m_width);
-
- /* Because the number of SLD nodes is now known, the Nodes on the hub can be
- * enumerated by repeating the 8 four-bit nibble scans, once for each Node,
- * to yield the SLD_NODE_INFO register of each Node. The DR nibble shifts
- * are a continuation of the HUB_INFO DR shift used to shift out the Hub IP
- * Configuration register.
- *
- * The order of the Nodes as they are shifted out determines the ADDR
- * values for the Nodes, beginning with, for the first Node SLD_NODE_INFO
- * shifted out, up to and including, for the last node on the hub. The
- * tables below show the SLD_NODE_INFO register and a their functional descriptions.
- *
- * --------------+-----------+---------------+----------------
- * 31 27 | 26 19 | 18 8 | 7 0
- * --------------+-----------+---------------+----------------
- * Node Version | NODE ID | NODE MFG_ID | NODE INST ID
- *
- */
-
- int vjtag_node_address = -1;
- int node_index;
- uint32_t node_info = 0;
- for (node_index = 0; node_index < nb_nodes; node_index++) {
-
- for (int i = 0; i < 8; i++) {
- field.num_bits = 4;
- field.out_value = NULL;
- field.in_value = &nibble;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
- retval = jtag_execute_queue();
- if (retval != ERROR_OK)
- return retval;
- node_info = ((node_info >> 4) | ((nibble & 0xf) << 28));
- }
-
- LOG_DEBUG("Node info register");
- LOG_DEBUG("--------------------");
- LOG_DEBUG("instance_id = %" PRId32, ID(node_info));
- LOG_DEBUG("manufacturer_id = 0x%02" PRIx32, MANUF(node_info));
- LOG_DEBUG("node_id = %" PRId32 " (%s)", ID(node_info),
- id_to_string(ID(node_info)));
- LOG_DEBUG("version = %" PRId32, VER(node_info));
-
- if (ID(node_info) == VJTAG_NODE_ID)
- vjtag_node_address = node_index + 1;
- }
-
- if (vjtag_node_address < 0) {
- LOG_ERROR("No VJTAG TAP instance found !");
- return ERROR_FAIL;
- }
-
- /* Select VIR */
- buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER1);
- field.num_bits = tap->ir_length;
- field.out_value = t;
- field.in_value = NULL;
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- /* Send the DEBUG command to the VJTAG IR */
- int dr_length = guess_addr_width(nb_nodes) + m_width;
- buf_set_u32(t, 0, dr_length, (vjtag_node_address << m_width) | ALT_VJTAG_CMD_DEBUG);
- field.num_bits = dr_length;
- field.out_value = t;
- field.in_value = NULL;
- jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
-
- /* Select the VJTAG DR */
- buf_set_u32(t, 0, tap->ir_length, ALTERA_CYCLONE_CMD_USER0);
- field.num_bits = tap->ir_length;
- field.out_value = t;
- field.in_value = NULL;
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- return jtag_execute_queue();
-}
-
-static struct or1k_tap_ip vjtag_tap = {
- .name = "vjtag",
- .init = or1k_tap_vjtag_init,
-};
-
-int or1k_tap_vjtag_register(void)
-{
- list_add_tail(&vjtag_tap.list, &tap_list);
- return 0;
-}
diff --git a/src/target/openrisc/or1k_tap_xilinx_bscan.c b/src/target/openrisc/or1k_tap_xilinx_bscan.c
deleted file mode 100644
index a77c65e..0000000
--- a/src/target/openrisc/or1k_tap_xilinx_bscan.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2013 by Sergio Chico *
- * sergio.chico@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "or1k_tap.h"
-#include "or1k.h"
-
-#include <jtag/jtag.h>
-
-#define OR1K_XILINX_TAP_INST_USER1 0x02
-
-static int or1k_tap_xilinx_bscan_init(struct or1k_jtag *jtag_info)
-{
- LOG_DEBUG("Initialising Xilinx Internal JTAG TAP");
-
- /* Put TAP into state where it can talk to the debug interface
- * by shifting in correct value to IR.
- */
-
- /* Ensure TAP is reset - maybe not necessary*/
- jtag_add_tlr();
-
- struct jtag_tap *tap = jtag_info->tap;
- struct scan_field field;
- uint8_t ir_value = OR1K_XILINX_TAP_INST_USER1;
-
- field.num_bits = tap->ir_length;
- field.out_value = &ir_value;
- field.in_value = NULL;
-
- jtag_add_ir_scan(tap, &field, TAP_IDLE);
-
- return jtag_execute_queue();
-}
-
-static struct or1k_tap_ip xilinx_bscan_tap = {
- .name = "xilinx_bscan",
- .init = or1k_tap_xilinx_bscan_init,
-};
-
-int or1k_tap_xilinx_bscan_register(void)
-{
- list_add_tail(&xilinx_bscan_tap.list, &tap_list);
- return 0;
-}
diff --git a/src/target/quark_d20xx.c b/src/target/quark_d20xx.c
deleted file mode 100644
index 42d3b8c..0000000
--- a/src/target/quark_d20xx.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright(c) 2015-2016 Intel Corporation.
- *
- * Jessica Gomez (jessica.gomez.hernandez@intel.com)
- * Ivan De Cesaris (ivan.de.cesaris@intel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Contact Information:
- * Intel Corporation
- */
-
-/*
- * @file
- * Debugger for Intel Quark D20xx
- * The CPU TAP (Lakemont TAP) is used for software debug and the CLTAP is
- * used for SoC level operations.
- *
- * Reference document:
- * Intel Quark microcontroller D2000 Debug Operations (web search for doc num 333241)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-
-#include "target.h"
-#include "target_type.h"
-#include "breakpoints.h"
-#include "lakemont.h"
-#include "x86_32_common.h"
-
-int quark_d20xx_target_create(struct target *t, Jim_Interp *interp)
-{
- struct x86_32_common *x86_32 = calloc(1, sizeof(struct x86_32_common));
- if (x86_32 == NULL) {
- LOG_ERROR("%s out of memory", __func__);
- return ERROR_FAIL;
- }
- x86_32_common_init_arch_info(t, x86_32);
- lakemont_init_arch_info(t, x86_32);
- x86_32->core_type = LMT3_5;
- return ERROR_OK;
-}
-
-int quark_d20xx_init_target(struct command_context *cmd_ctx, struct target *t)
-{
- return lakemont_init_target(cmd_ctx, t);
-}
-
-static int quark_d20xx_reset_deassert(struct target *t)
-{
- int retval;
-
- /* Can't detect if a warm reset happened while halted but we can make the
- * openocd and target state consistent here if in probe mode already
- */
- if (!check_not_halted(t)) {
- retval = lakemont_update_after_probemode_entry(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s core state update fail", __func__);
- return retval;
- }
- /* resume target if reset mode is run */
- if (!t->reset_halt) {
- retval = lakemont_resume(t, 1, 0, 0, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not resume target", __func__);
- return retval;
- }
- }
- }
-
- return ERROR_OK;
-}
-
-struct target_type quark_d20xx_target = {
- .name = "quark_d20xx",
- .target_create = quark_d20xx_target_create,
- .init_target = quark_d20xx_init_target,
- /* lakemont probemode specific code */
- .poll = lakemont_poll,
- .arch_state = lakemont_arch_state,
- .halt = lakemont_halt,
- .resume = lakemont_resume,
- .step = lakemont_step,
- .assert_reset = lakemont_reset_assert,
- .deassert_reset = quark_d20xx_reset_deassert,
- /* common x86 code */
- .commands = x86_32_command_handlers,
- .get_gdb_reg_list = x86_32_get_gdb_reg_list,
- .read_memory = x86_32_common_read_memory,
- .write_memory = x86_32_common_write_memory,
- .add_breakpoint = x86_32_common_add_breakpoint,
- .remove_breakpoint = x86_32_common_remove_breakpoint,
- .add_watchpoint = x86_32_common_add_watchpoint,
- .remove_watchpoint = x86_32_common_remove_watchpoint,
- .virt2phys = x86_32_common_virt2phys,
- .read_phys_memory = x86_32_common_read_phys_mem,
- .write_phys_memory = x86_32_common_write_phys_mem,
- .mmu = x86_32_common_mmu,
-};
diff --git a/src/target/quark_x10xx.c b/src/target/quark_x10xx.c
deleted file mode 100644
index 189f6cc..0000000
--- a/src/target/quark_x10xx.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright(c) 2013-2016 Intel Corporation.
- *
- * Adrian Burns (adrian.burns@intel.com)
- * Thomas Faust (thomas.faust@intel.com)
- * Ivan De Cesaris (ivan.de.cesaris@intel.com)
- * Julien Carreno (julien.carreno@intel.com)
- * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Contact Information:
- * Intel Corporation
- */
-
-/*
- * @file
- * Debugger for Intel Quark SoC X1000
- * Intel Quark X10xx is the first product in the Quark family of SoCs.
- * It is an IA-32 (Pentium x86 ISA) compatible SoC. The core CPU in the
- * X10xx is codenamed Lakemont. Lakemont version 1 (LMT1) is used in X10xx.
- * The CPU TAP (Lakemont TAP) is used for software debug and the CLTAP is
- * used for SoC level operations.
- * Useful docs are here: https://communities.intel.com/community/makers/documentation
- * Intel Quark SoC X1000 OpenOCD/GDB/Eclipse App Note (web search for doc num 330015)
- * Intel Quark SoC X1000 Debug Operations User Guide (web search for doc num 329866)
- * Intel Quark SoC X1000 Datasheet (web search for doc num 329676)
- *
- * This file implements any Quark SoC specific features such as resetbreak (TODO)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-
-#include "target.h"
-#include "target_type.h"
-#include "lakemont.h"
-#include "x86_32_common.h"
-
-int quark_x10xx_target_create(struct target *t, Jim_Interp *interp)
-{
- struct x86_32_common *x86_32 = calloc(1, sizeof(struct x86_32_common));
- if (x86_32 == NULL) {
- LOG_ERROR("%s out of memory", __func__);
- return ERROR_FAIL;
- }
- x86_32_common_init_arch_info(t, x86_32);
- lakemont_init_arch_info(t, x86_32);
- x86_32->core_type = LMT1;
- return ERROR_OK;
-}
-
-int quark_x10xx_init_target(struct command_context *cmd_ctx, struct target *t)
-{
- return lakemont_init_target(cmd_ctx, t);
-}
-
-struct target_type quark_x10xx_target = {
- .name = "quark_x10xx",
- /* Quark X1000 SoC */
- .target_create = quark_x10xx_target_create,
- .init_target = quark_x10xx_init_target,
- /* lakemont probemode specific code */
- .poll = lakemont_poll,
- .arch_state = lakemont_arch_state,
- .halt = lakemont_halt,
- .resume = lakemont_resume,
- .step = lakemont_step,
- .assert_reset = lakemont_reset_assert,
- .deassert_reset = lakemont_reset_deassert,
- /* common x86 code */
- .commands = x86_32_command_handlers,
- .get_gdb_reg_list = x86_32_get_gdb_reg_list,
- .read_memory = x86_32_common_read_memory,
- .write_memory = x86_32_common_write_memory,
- .add_breakpoint = x86_32_common_add_breakpoint,
- .remove_breakpoint = x86_32_common_remove_breakpoint,
- .add_watchpoint = x86_32_common_add_watchpoint,
- .remove_watchpoint = x86_32_common_remove_watchpoint,
- .virt2phys = x86_32_common_virt2phys,
- .read_phys_memory = x86_32_common_read_phys_mem,
- .write_phys_memory = x86_32_common_write_phys_mem,
- .mmu = x86_32_common_mmu,
-};
diff --git a/src/target/register.c b/src/target/register.c
deleted file mode 100644
index 1d63e12..0000000
--- a/src/target/register.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "register.h"
-#include <helper/log.h>
-
-/**
- * @file
- * Holds utilities to work with register caches.
- *
- * OpenOCD uses machine registers internally, and exposes them by name
- * to Tcl scripts. Sets of related registers are grouped into caches.
- * For example, a CPU core will expose a set of registers, and there
- * may be separate registers associated with debug or trace modules.
- */
-
-struct reg *register_get_by_name(struct reg_cache *first,
- const char *name, bool search_all)
-{
- unsigned i;
- struct reg_cache *cache = first;
-
- while (cache) {
- for (i = 0; i < cache->num_regs; i++) {
- if (strcmp(cache->reg_list[i].name, name) == 0)
- return &(cache->reg_list[i]);
- }
-
- if (search_all)
- cache = cache->next;
- else
- break;
- }
-
- return NULL;
-}
-
-struct reg_cache **register_get_last_cache_p(struct reg_cache **first)
-{
- struct reg_cache **cache_p = first;
-
- if (*cache_p)
- while (*cache_p)
- cache_p = &((*cache_p)->next);
- else
- return first;
-
- return cache_p;
-}
-
-void register_unlink_cache(struct reg_cache **cache_p, const struct reg_cache *cache)
-{
- while (*cache_p && *cache_p != cache)
- cache_p = &((*cache_p)->next);
- if (*cache_p)
- *cache_p = cache->next;
-}
-
-/** Marks the contents of the register cache as invalid (and clean). */
-void register_cache_invalidate(struct reg_cache *cache)
-{
- struct reg *reg = cache->reg_list;
-
- for (unsigned n = cache->num_regs; n != 0; n--, reg++) {
- reg->valid = 0;
- reg->dirty = 0;
- }
-}
-
-static int register_get_dummy_core_reg(struct reg *reg)
-{
- return ERROR_OK;
-}
-
-static int register_set_dummy_core_reg(struct reg *reg, uint8_t *buf)
-{
- reg->dirty = 1;
- reg->valid = 1;
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type dummy_type = {
- .get = register_get_dummy_core_reg,
- .set = register_set_dummy_core_reg,
-};
-
-void register_init_dummy(struct reg *reg)
-{
- reg->type = &dummy_type;
-}
diff --git a/src/target/register.h b/src/target/register.h
deleted file mode 100644
index d4c3281..0000000
--- a/src/target/register.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_REGISTER_H
-#define OPENOCD_TARGET_REGISTER_H
-
-struct target;
-
-enum reg_type {
- REG_TYPE_INT,
- REG_TYPE_INT8,
- REG_TYPE_INT16,
- REG_TYPE_INT32,
- REG_TYPE_INT64,
- REG_TYPE_INT128,
- REG_TYPE_UINT8,
- REG_TYPE_UINT16,
- REG_TYPE_UINT32,
- REG_TYPE_UINT64,
- REG_TYPE_UINT128,
- REG_TYPE_CODE_PTR,
- REG_TYPE_DATA_PTR,
- REG_TYPE_FLOAT,
- REG_TYPE_IEEE_SINGLE,
- REG_TYPE_IEEE_DOUBLE,
- REG_TYPE_ARCH_DEFINED,
-};
-
-struct reg_feature {
- const char *name;
-};
-
-struct reg_data_type_vector {
- struct reg_data_type *type;
- uint32_t count;
-};
-
-struct reg_data_type_union_field {
- const char *name;
- struct reg_data_type *type;
- struct reg_data_type_union_field *next;
-};
-
-struct reg_data_type_union {
- struct reg_data_type_union_field *fields;
-};
-
-struct reg_data_type_bitfield {
- uint32_t start;
- uint32_t end;
-};
-
-struct reg_data_type_struct_field {
- const char *name;
- bool use_bitfields;
- union {
- struct reg_data_type_bitfield *bitfield;
- struct reg_data_type *type;
- };
- struct reg_data_type_struct_field *next;
-};
-
-struct reg_data_type_struct {
- uint32_t size;
- struct reg_data_type_struct_field *fields;
-};
-
-struct reg_data_type_flags_field {
- const char *name;
- struct reg_data_type_bitfield *bitfield;
- struct reg_data_type_flags_field *next;
-};
-
-struct reg_data_type_flags {
- uint32_t size;
- struct reg_data_type_flags_field *fields;
-};
-
-enum reg_data_type_class {
- REG_TYPE_CLASS_VECTOR,
- REG_TYPE_CLASS_UNION,
- REG_TYPE_CLASS_STRUCT,
- REG_TYPE_CLASS_FLAGS,
-};
-
-struct reg_data_type {
- enum reg_type type;
- const char *id;
- enum reg_data_type_class type_class;
- union {
- struct reg_data_type_vector *reg_type_vector;
- struct reg_data_type_union *reg_type_union;
- struct reg_data_type_struct *reg_type_struct;
- struct reg_data_type_flags *reg_type_flags;
- };
-};
-
-struct reg {
- /** Canonical name of the register. */
- const char *name;
- /** Number that gdb uses to access this register. */
- uint32_t number;
- /* TODO. This should probably be const. */
- struct reg_feature *feature;
- /* TODO: When true, the caller will save this register before running any algorithm. */
- bool caller_save;
- /* Pointer to place where the value is stored, in the format understood by
- * the binarybuffer.h functions. */
- void *value;
- /* The stored value needs to be written to the target. */
- bool dirty;
- /* When true, value is valid. */
- bool valid;
- /* When false, the register doesn't actually exist in the target. */
- bool exist;
- /* Size of the register in bits. */
- uint32_t size;
- /* Used for generating XML description of registers. Can be set to NULL for
- * targets that don't use that. */
- struct reg_data_type *reg_data_type;
- /* Used for generating XML description of registers. Can be set to NULL for
- * targets that don't use that. */
- const char *group;
- /* Pointer to architecture-specific info for this register. */
- void *arch_info;
- const struct reg_arch_type *type;
-};
-
-struct reg_cache {
- const char *name;
- struct reg_cache *next;
- struct reg *reg_list;
- unsigned num_regs;
-};
-
-struct reg_arch_type {
- int (*get)(struct reg *reg);
- int (*set)(struct reg *reg, uint8_t *buf);
-};
-
-struct reg *register_get_by_name(struct reg_cache *first,
- const char *name, bool search_all);
-struct reg_cache **register_get_last_cache_p(struct reg_cache **first);
-void register_unlink_cache(struct reg_cache **cache_p, const struct reg_cache *cache);
-void register_cache_invalidate(struct reg_cache *cache);
-
-void register_init_dummy(struct reg *reg);
-
-#endif /* OPENOCD_TARGET_REGISTER_H */
diff --git a/src/target/riscv/asm.h b/src/target/riscv/asm.h
deleted file mode 100644
index 051e0f9..0000000
--- a/src/target/riscv/asm.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef TARGET__RISCV__ASM_H
-#define TARGET__RISCV__ASM_H
-
-#include "riscv.h"
-
-/*** Version-independent functions that we don't want in the main address space. ***/
-
-static uint32_t load(const struct target *target, unsigned int rd,
- unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t load(const struct target *target, unsigned int rd,
- unsigned int base, uint16_t offset)
-{
- switch (riscv_xlen(target)) {
- case 32:
- return lw(rd, base, offset);
- case 64:
- return ld(rd, base, offset);
- }
- assert(0);
-}
-
-static uint32_t store(const struct target *target, unsigned int src,
- unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t store(const struct target *target, unsigned int src,
- unsigned int base, uint16_t offset)
-{
- switch (riscv_xlen(target)) {
- case 32:
- return sw(src, base, offset);
- case 64:
- return sd(src, base, offset);
- }
- assert(0);
-}
-
-#endif
diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h
deleted file mode 100644
index ec535db..0000000
--- a/src/target/riscv/debug_defines.h
+++ /dev/null
@@ -1,1501 +0,0 @@
-#define DTM_IDCODE 0x01
-/*
-* Identifies the release version of this part.
- */
-#define DTM_IDCODE_VERSION_OFFSET 28
-#define DTM_IDCODE_VERSION_LENGTH 4
-#define DTM_IDCODE_VERSION (0xf << DTM_IDCODE_VERSION_OFFSET)
-/*
-* Identifies the designer's part number of this part.
- */
-#define DTM_IDCODE_PARTNUMBER_OFFSET 12
-#define DTM_IDCODE_PARTNUMBER_LENGTH 16
-#define DTM_IDCODE_PARTNUMBER (0xffff << DTM_IDCODE_PARTNUMBER_OFFSET)
-/*
-* Identifies the designer/manufacturer of this part. Bits 6:0 must be
-* bits 6:0 of the designer/manufacturer's Identification Code as
-* assigned by JEDEC Standard JEP106. Bits 10:7 contain the modulo-16
-* count of the number of continuation characters (0x7f) in that same
-* Identification Code.
- */
-#define DTM_IDCODE_MANUFID_OFFSET 1
-#define DTM_IDCODE_MANUFID_LENGTH 11
-#define DTM_IDCODE_MANUFID (0x7ff << DTM_IDCODE_MANUFID_OFFSET)
-#define DTM_IDCODE_1_OFFSET 0
-#define DTM_IDCODE_1_LENGTH 1
-#define DTM_IDCODE_1 (0x1 << DTM_IDCODE_1_OFFSET)
-#define DTM_DTMCS 0x10
-/*
-* Writing 1 to this bit resets the DMI controller, clearing any
-* sticky error state.
- */
-#define DTM_DTMCS_DMIRESET_OFFSET 16
-#define DTM_DTMCS_DMIRESET_LENGTH 1
-#define DTM_DTMCS_DMIRESET (0x1 << DTM_DTMCS_DMIRESET_OFFSET)
-/*
-* This is the minimum number of cycles a debugger should spend in
-* Run-Test/Idle after every DMI scan to avoid a 'busy'
-* return code (\Fdmistat of 3). A debugger must still
-* check \Fdmistat when necessary.
-*
-* 0: It is not necessary to enter Run-Test/Idle at all.
-*
-* 1: Enter Run-Test/Idle and leave it immediately.
-*
-* 2: Enter Run-Test/Idle and stay there for 1 cycle before leaving.
-*
-* And so on.
- */
-#define DTM_DTMCS_IDLE_OFFSET 12
-#define DTM_DTMCS_IDLE_LENGTH 3
-#define DTM_DTMCS_IDLE (0x7 << DTM_DTMCS_IDLE_OFFSET)
-/*
-* 0: No error.
-*
-* 1: Reserved. Interpret the same as 2.
-*
-* 2: An operation failed (resulted in \Fop of 2).
-*
-* 3: An operation was attempted while a DMI access was still in
-* progress (resulted in \Fop of 3).
- */
-#define DTM_DTMCS_DMISTAT_OFFSET 10
-#define DTM_DTMCS_DMISTAT_LENGTH 2
-#define DTM_DTMCS_DMISTAT (0x3 << DTM_DTMCS_DMISTAT_OFFSET)
-/*
-* The size of \Faddress in \Rdmi.
- */
-#define DTM_DTMCS_ABITS_OFFSET 4
-#define DTM_DTMCS_ABITS_LENGTH 6
-#define DTM_DTMCS_ABITS (0x3f << DTM_DTMCS_ABITS_OFFSET)
-/*
-* 0: Version described in spec version 0.11.
-*
-* 1: Version described in spec version 0.12 (and later?), which
-* reduces the DMI data width to 32 bits.
-*
-* Other values are reserved for future use.
- */
-#define DTM_DTMCS_VERSION_OFFSET 0
-#define DTM_DTMCS_VERSION_LENGTH 4
-#define DTM_DTMCS_VERSION (0xf << DTM_DTMCS_VERSION_OFFSET)
-#define DTM_DMI 0x11
-/*
-* Address used for DMI access. In Update-DR this value is used
-* to access the DM over the DMI.
- */
-#define DTM_DMI_ADDRESS_OFFSET 34
-#define DTM_DMI_ADDRESS_LENGTH abits
-#define DTM_DMI_ADDRESS (((1L<<abits)-1) << DTM_DMI_ADDRESS_OFFSET)
-/*
-* The data to send to the DM over the DMI during Update-DR, and
-* the data returned from the DM as a result of the previous operation.
- */
-#define DTM_DMI_DATA_OFFSET 2
-#define DTM_DMI_DATA_LENGTH 32
-#define DTM_DMI_DATA (0xffffffffL << DTM_DMI_DATA_OFFSET)
-/*
-* When the debugger writes this field, it has the following meaning:
-*
-* 0: Ignore \Fdata. (nop)
-*
-* 1: Read from \Faddress. (read)
-*
-* 2: Write \Fdata to \Faddress. (write)
-*
-* 3: Reserved.
-*
-* When the debugger reads this field, it means the following:
-*
-* 0: The previous operation completed successfully.
-*
-* 1: Reserved.
-*
-* 2: A previous operation failed. The data scanned into \Rdmi in
-* this access will be ignored. This status is sticky and can be
-* cleared by writing \Fdmireset in \Rdtmcs.
-*
-* This indicates that the DM itself responded with an error, e.g.
-* in the System Bus and Serial Port overflow/underflow cases.
-*
-* 3: An operation was attempted while a DMI request is still in
-* progress. The data scanned into \Rdmi in this access will be
-* ignored. This status is sticky and can be cleared by writing
-* \Fdmireset in \Rdtmcs. If a debugger sees this status, it
-* needs to give the target more TCK edges between Update-DR and
-* Capture-DR. The simplest way to do that is to add extra transitions
-* in Run-Test/Idle.
-*
-* (The DTM, DM, and/or component may be in different clock domains,
-* so synchronization may be required. Some relatively fixed number of
-* TCK ticks may be needed for the request to reach the DM, complete,
-* and for the response to be synchronized back into the TCK domain.)
- */
-#define DTM_DMI_OP_OFFSET 0
-#define DTM_DMI_OP_LENGTH 2
-#define DTM_DMI_OP (0x3L << DTM_DMI_OP_OFFSET)
-#define CSR_DCSR 0x7b0
-/*
-* 0: There is no external debug support.
-*
-* 1: External debug support exists as it is described in this document.
-*
-* Other values are reserved for future standards.
- */
-#define CSR_DCSR_XDEBUGVER_OFFSET 30
-#define CSR_DCSR_XDEBUGVER_LENGTH 2
-#define CSR_DCSR_XDEBUGVER (0x3 << CSR_DCSR_XDEBUGVER_OFFSET)
-/*
-* When 1, {\tt ebreak} instructions in Machine Mode enter Halt Mode.
- */
-#define CSR_DCSR_EBREAKM_OFFSET 15
-#define CSR_DCSR_EBREAKM_LENGTH 1
-#define CSR_DCSR_EBREAKM (0x1 << CSR_DCSR_EBREAKM_OFFSET)
-/*
-* When 1, {\tt ebreak} instructions in Hypervisor Mode enter Halt Mode.
- */
-#define CSR_DCSR_EBREAKH_OFFSET 14
-#define CSR_DCSR_EBREAKH_LENGTH 1
-#define CSR_DCSR_EBREAKH (0x1 << CSR_DCSR_EBREAKH_OFFSET)
-/*
-* When 1, {\tt ebreak} instructions in Supervisor Mode enter Halt Mode.
- */
-#define CSR_DCSR_EBREAKS_OFFSET 13
-#define CSR_DCSR_EBREAKS_LENGTH 1
-#define CSR_DCSR_EBREAKS (0x1 << CSR_DCSR_EBREAKS_OFFSET)
-/*
-* When 1, {\tt ebreak} instructions in User/Application Mode enter
-* Halt Mode.
- */
-#define CSR_DCSR_EBREAKU_OFFSET 12
-#define CSR_DCSR_EBREAKU_LENGTH 1
-#define CSR_DCSR_EBREAKU (0x1 << CSR_DCSR_EBREAKU_OFFSET)
-/*
-* 0: Increment counters as usual.
-*
-* 1: Don't increment any counters while in Halt Mode. This includes
-* the {\tt cycle} and {\tt instret} CSRs. This is preferred for most
-* debugging scenarios.
-*
-* An implementation may choose not to support writing to this bit.
-* The debugger must read back the value it writes to check whether
-* the feature is supported.
- */
-#define CSR_DCSR_STOPCOUNT_OFFSET 10
-#define CSR_DCSR_STOPCOUNT_LENGTH 1
-#define CSR_DCSR_STOPCOUNT (0x1 << CSR_DCSR_STOPCOUNT_OFFSET)
-/*
-* 0: Increment timers as usual.
-*
-* 1: Don't increment any hart-local timers while in Halt Mode.
-*
-* An implementation may choose not to support writing to this bit.
-* The debugger must read back the value it writes to check whether
-* the feature is supported.
- */
-#define CSR_DCSR_STOPTIME_OFFSET 9
-#define CSR_DCSR_STOPTIME_LENGTH 1
-#define CSR_DCSR_STOPTIME (0x1 << CSR_DCSR_STOPTIME_OFFSET)
-/*
-* Explains why Halt Mode was entered.
-*
-* When there are multiple reasons to enter Halt Mode in a single
-* cycle, the cause with the highest priority is the one written.
-*
-* 1: A software breakpoint was hit. (priority 3)
-*
-* 2: The Trigger Module caused a halt. (priority 4)
-*
-* 3: The debug interrupt was asserted by the Debug Module. (priority 2)
-*
-* 4: The hart single stepped because \Fstep was set. (priority 1)
-*
-* 5: \Fhaltreq was set. (priority 0)
-*
-* Other values are reserved for future use.
- */
-#define CSR_DCSR_CAUSE_OFFSET 6
-#define CSR_DCSR_CAUSE_LENGTH 3
-#define CSR_DCSR_CAUSE (0x7 << CSR_DCSR_CAUSE_OFFSET)
-/*
-* When set and not in Halt Mode, the hart will only execute a single
-* instruction, and then enter Halt Mode. Interrupts are disabled
-* when this bit is set.
- */
-#define CSR_DCSR_STEP_OFFSET 2
-#define CSR_DCSR_STEP_LENGTH 1
-#define CSR_DCSR_STEP (0x1 << CSR_DCSR_STEP_OFFSET)
-/*
-* Contains the privilege level the hart was operating in when Debug
-* Mode was entered. The encoding is describe in Table
-* \ref{tab:privlevel}. A debugger can change this value to change
-* the hart's privilege level when exiting Halt Mode.
-*
-* Not all privilege levels are supported on all harts. If the
-* encoding written is not supported or the debugger is not allowed to
-* change to it, the hart may change to any supported privilege level.
- */
-#define CSR_DCSR_PRV_OFFSET 0
-#define CSR_DCSR_PRV_LENGTH 2
-#define CSR_DCSR_PRV (0x3 << CSR_DCSR_PRV_OFFSET)
-#define CSR_DPC 0x7b1
-#define CSR_DPC_DPC_OFFSET 0
-#define CSR_DPC_DPC_LENGTH XLEN
-#define CSR_DPC_DPC (((1L<<XLEN)-1) << CSR_DPC_DPC_OFFSET)
-#define CSR_DSCRATCH0 0x7b2
-#define CSR_DSCRATCH1 0x7b3
-#define CSR_PRIV virtual
-/*
-* Contains the privilege level the hart was operating in when Debug
-* Mode was entered. The encoding is describe in Table
-* \ref{tab:privlevel}. A user can write this value to change the
-* hart's privilege level when exiting Halt Mode.
- */
-#define CSR_PRIV_PRV_OFFSET 0
-#define CSR_PRIV_PRV_LENGTH 2
-#define CSR_PRIV_PRV (0x3 << CSR_PRIV_PRV_OFFSET)
-#define CSR_TSELECT 0x7a0
-#define CSR_TSELECT_INDEX_OFFSET 0
-#define CSR_TSELECT_INDEX_LENGTH XLEN
-#define CSR_TSELECT_INDEX (((1L<<XLEN)-1) << CSR_TSELECT_INDEX_OFFSET)
-#define CSR_TDATA1 0x7a1
-/*
-* 0: There is no trigger at this \Rtselect.
-*
-* 1: The trigger is a legacy SiFive address match trigger. These
-* should not be implemented and aren't further documented here.
-*
-* 2: The trigger is an address/data match trigger. The remaining bits
-* in this register act as described in \Rmcontrol.
-*
-* 3: The trigger is an instruction count trigger. The remaining bits
-* in this register act as described in \Ricount.
-*
-* 15: This trigger exists (so enumeration shouldn't terminate), but
-* is not currently available.
-*
-* Other values are reserved for future use.
- */
-#define CSR_TDATA1_TYPE_OFFSET XLEN-4
-#define CSR_TDATA1_TYPE_LENGTH 4
-#define CSR_TDATA1_TYPE (0xfL << CSR_TDATA1_TYPE_OFFSET)
-/*
-* 0: Both Debug and M Mode can write the {\tt tdata} registers at the
-* selected \Rtselect.
-*
-* 1: Only Halt Mode can write the {\tt tdata} registers at the
-* selected \Rtselect. Writes from other modes are ignored.
-*
-* This bit is only writable from Halt Mode.
- */
-#define CSR_TDATA1_HMODE_OFFSET XLEN-5
-#define CSR_TDATA1_HMODE_LENGTH 1
-#define CSR_TDATA1_HMODE (0x1L << CSR_TDATA1_HMODE_OFFSET)
-/*
-* Trigger-specific data.
- */
-#define CSR_TDATA1_DATA_OFFSET 0
-#define CSR_TDATA1_DATA_LENGTH XLEN - 5
-#define CSR_TDATA1_DATA (((1L<<XLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET)
-#define CSR_TDATA2 0x7a2
-#define CSR_TDATA2_DATA_OFFSET 0
-#define CSR_TDATA2_DATA_LENGTH XLEN
-#define CSR_TDATA2_DATA (((1L<<XLEN)-1) << CSR_TDATA2_DATA_OFFSET)
-#define CSR_TDATA3 0x7a3
-#define CSR_TDATA3_DATA_OFFSET 0
-#define CSR_TDATA3_DATA_LENGTH XLEN
-#define CSR_TDATA3_DATA (((1L<<XLEN)-1) << CSR_TDATA3_DATA_OFFSET)
-#define CSR_MCONTROL 0x7a1
-#define CSR_MCONTROL_TYPE_OFFSET XLEN-4
-#define CSR_MCONTROL_TYPE_LENGTH 4
-#define CSR_MCONTROL_TYPE (0xfL << CSR_MCONTROL_TYPE_OFFSET)
-#define CSR_MCONTROL_DMODE_OFFSET XLEN-5
-#define CSR_MCONTROL_DMODE_LENGTH 1
-#define CSR_MCONTROL_DMODE (0x1L << CSR_MCONTROL_DMODE_OFFSET)
-/*
-* Specifies the largest naturally aligned powers-of-two (NAPOT) range
-* supported by the hardware. The value is the logarithm base 2 of the
-* number of bytes in that range. A value of 0 indicates that only
-* exact value matches are supported (one byte range). A value of 63
-* corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in
-* size.
- */
-#define CSR_MCONTROL_MASKMAX_OFFSET XLEN-11
-#define CSR_MCONTROL_MASKMAX_LENGTH 6
-#define CSR_MCONTROL_MASKMAX (0x3fL << CSR_MCONTROL_MASKMAX_OFFSET)
-/*
-* 0: Perform a match on the virtual address.
-*
-* 1: Perform a match on the data value loaded/stored, or the
-* instruction executed.
- */
-#define CSR_MCONTROL_SELECT_OFFSET 19
-#define CSR_MCONTROL_SELECT_LENGTH 1
-#define CSR_MCONTROL_SELECT (0x1L << CSR_MCONTROL_SELECT_OFFSET)
-/*
-* 0: The action for this trigger will be taken just before the
-* instruction that triggered it is executed, but after all preceding
-* instructions are are committed.
-*
-* 1: The action for this trigger will be taken after the instruction
-* that triggered it is executed. It should be taken before the next
-* instruction is executed, but it is better to implement triggers and
-* not implement that suggestion than to not implement them at all.
-*
-* Most hardware will only implement one timing or the other, possibly
-* dependent on \Fselect, \Fexecute, \Fload, and \Fstore. This bit
-* primarily exists for the hardware to communicate to the debugger
-* what will happen. Hardware may implement the bit fully writable, in
-* which case the debugger has a little more control.
-*
-* Data load triggers with \Ftiming of 0 will result in the same load
-* happening again when the debugger lets the core run. For data load
-* triggers, debuggers must first attempt to set the breakpoint with
-* \Ftiming of 1.
-*
-* A chain of triggers that don't all have the same \Ftiming value
-* will never fire (unless consecutive instructions match the
-* appropriate triggers).
- */
-#define CSR_MCONTROL_TIMING_OFFSET 18
-#define CSR_MCONTROL_TIMING_LENGTH 1
-#define CSR_MCONTROL_TIMING (0x1L << CSR_MCONTROL_TIMING_OFFSET)
-/*
-* Determines what happens when this trigger matches.
-*
-* 0: Raise a breakpoint exception. (Used when software wants to use
-* the trigger module without an external debugger attached.)
-*
-* 1: Enter Halt Mode. (Only supported when \Fhmode is 1.)
-*
-* 2: Start tracing.
-*
-* 3: Stop tracing.
-*
-* 4: Emit trace data for this match. If it is a data access match,
-* emit appropriate Load/Store Address/Data. If it is an instruction
-* execution, emit its PC.
-*
-* Other values are reserved for future use.
- */
-#define CSR_MCONTROL_ACTION_OFFSET 12
-#define CSR_MCONTROL_ACTION_LENGTH 6
-#define CSR_MCONTROL_ACTION (0x3fL << CSR_MCONTROL_ACTION_OFFSET)
-/*
-* 0: When this trigger matches, the configured action is taken.
-*
-* 1: While this trigger does not match, it prevents the trigger with
-* the next index from matching.
- */
-#define CSR_MCONTROL_CHAIN_OFFSET 11
-#define CSR_MCONTROL_CHAIN_LENGTH 1
-#define CSR_MCONTROL_CHAIN (0x1L << CSR_MCONTROL_CHAIN_OFFSET)
-/*
-* 0: Matches when the value equals \Rtdatatwo.
-*
-* 1: Matches when the top M bits of the value match the top M bits of
-* \Rtdatatwo. M is XLEN-1 minus the index of the least-significant
-* bit containing 0 in \Rtdatatwo.
-*
-* 2: Matches when the value is greater than or equal to \Rtdatatwo.
-*
-* 3: Matches when the value is less than \Rtdatatwo.
-*
-* 4: Matches when the lower half of the value equals the lower half
-* of \Rtdatatwo after the lower half of the value is ANDed with the
-* upper half of \Rtdatatwo.
-*
-* 5: Matches when the upper half of the value equals the lower half
-* of \Rtdatatwo after the upper half of the value is ANDed with the
-* upper half of \Rtdatatwo.
-*
-* Other values are reserved for future use.
- */
-#define CSR_MCONTROL_MATCH_OFFSET 7
-#define CSR_MCONTROL_MATCH_LENGTH 4
-#define CSR_MCONTROL_MATCH (0xfL << CSR_MCONTROL_MATCH_OFFSET)
-/*
-* When set, enable this trigger in M mode.
- */
-#define CSR_MCONTROL_M_OFFSET 6
-#define CSR_MCONTROL_M_LENGTH 1
-#define CSR_MCONTROL_M (0x1L << CSR_MCONTROL_M_OFFSET)
-/*
-* When set, enable this trigger in H mode.
- */
-#define CSR_MCONTROL_H_OFFSET 5
-#define CSR_MCONTROL_H_LENGTH 1
-#define CSR_MCONTROL_H (0x1L << CSR_MCONTROL_H_OFFSET)
-/*
-* When set, enable this trigger in S mode.
- */
-#define CSR_MCONTROL_S_OFFSET 4
-#define CSR_MCONTROL_S_LENGTH 1
-#define CSR_MCONTROL_S (0x1L << CSR_MCONTROL_S_OFFSET)
-/*
-* When set, enable this trigger in U mode.
- */
-#define CSR_MCONTROL_U_OFFSET 3
-#define CSR_MCONTROL_U_LENGTH 1
-#define CSR_MCONTROL_U (0x1L << CSR_MCONTROL_U_OFFSET)
-/*
-* When set, the trigger fires on the virtual address or opcode of an
-* instruction that is executed.
- */
-#define CSR_MCONTROL_EXECUTE_OFFSET 2
-#define CSR_MCONTROL_EXECUTE_LENGTH 1
-#define CSR_MCONTROL_EXECUTE (0x1L << CSR_MCONTROL_EXECUTE_OFFSET)
-/*
-* When set, the trigger fires on the virtual address or data of a store.
- */
-#define CSR_MCONTROL_STORE_OFFSET 1
-#define CSR_MCONTROL_STORE_LENGTH 1
-#define CSR_MCONTROL_STORE (0x1L << CSR_MCONTROL_STORE_OFFSET)
-/*
-* When set, the trigger fires on the virtual address or data of a load.
- */
-#define CSR_MCONTROL_LOAD_OFFSET 0
-#define CSR_MCONTROL_LOAD_LENGTH 1
-#define CSR_MCONTROL_LOAD (0x1L << CSR_MCONTROL_LOAD_OFFSET)
-#define CSR_ICOUNT 0x7a1
-#define CSR_ICOUNT_TYPE_OFFSET XLEN-4
-#define CSR_ICOUNT_TYPE_LENGTH 4
-#define CSR_ICOUNT_TYPE (0xfL << CSR_ICOUNT_TYPE_OFFSET)
-#define CSR_ICOUNT_DMODE_OFFSET XLEN-5
-#define CSR_ICOUNT_DMODE_LENGTH 1
-#define CSR_ICOUNT_DMODE (0x1L << CSR_ICOUNT_DMODE_OFFSET)
-/*
-* When count is decremented to 0, the trigger fires. Instead of
-* changing \Fcount from 1 to 0, it is also acceptable for hardware to
-* clear \Fm, \Fh, \Fs, and \Fu. This allows \Fcount to be hard-wired
-* to 1 if this register just exists for single step.
- */
-#define CSR_ICOUNT_COUNT_OFFSET 10
-#define CSR_ICOUNT_COUNT_LENGTH 14
-#define CSR_ICOUNT_COUNT (0x3fffL << CSR_ICOUNT_COUNT_OFFSET)
-/*
-* When set, every instruction completed in M mode decrements \Fcount
-* by 1.
- */
-#define CSR_ICOUNT_M_OFFSET 9
-#define CSR_ICOUNT_M_LENGTH 1
-#define CSR_ICOUNT_M (0x1L << CSR_ICOUNT_M_OFFSET)
-/*
-* When set, every instruction completed in H mode decrements \Fcount
-* by 1.
- */
-#define CSR_ICOUNT_H_OFFSET 8
-#define CSR_ICOUNT_H_LENGTH 1
-#define CSR_ICOUNT_H (0x1L << CSR_ICOUNT_H_OFFSET)
-/*
-* When set, every instruction completed in S mode decrements \Fcount
-* by 1.
- */
-#define CSR_ICOUNT_S_OFFSET 7
-#define CSR_ICOUNT_S_LENGTH 1
-#define CSR_ICOUNT_S (0x1L << CSR_ICOUNT_S_OFFSET)
-/*
-* When set, every instruction completed in U mode decrements \Fcount
-* by 1.
- */
-#define CSR_ICOUNT_U_OFFSET 6
-#define CSR_ICOUNT_U_LENGTH 1
-#define CSR_ICOUNT_U (0x1L << CSR_ICOUNT_U_OFFSET)
-/*
-* Determines what happens when this trigger matches.
-*
-* 0: Raise a debug exception. (Used when software wants to use the
-* trigger module without an external debugger attached.)
-*
-* 1: Enter Halt Mode. (Only supported when \Fhmode is 1.)
-*
-* 2: Start tracing.
-*
-* 3: Stop tracing.
-*
-* 4: Emit trace data for this match. If it is a data access match,
-* emit appropriate Load/Store Address/Data. If it is an instruction
-* execution, emit its PC.
-*
-* Other values are reserved for future use.
- */
-#define CSR_ICOUNT_ACTION_OFFSET 0
-#define CSR_ICOUNT_ACTION_LENGTH 6
-#define CSR_ICOUNT_ACTION (0x3fL << CSR_ICOUNT_ACTION_OFFSET)
-#define DMI_DMSTATUS 0x11
-/*
-* This field is 1 when all currently selected harts do not exist in this system.
- */
-#define DMI_DMSTATUS_ALLNONEXISTENT_OFFSET 15
-#define DMI_DMSTATUS_ALLNONEXISTENT_LENGTH 1
-#define DMI_DMSTATUS_ALLNONEXISTENT (0x1 << DMI_DMSTATUS_ALLNONEXISTENT_OFFSET)
-/*
-* This field is 1 when any currently selected hart does not exist in this system.
- */
-#define DMI_DMSTATUS_ANYNONEXISTENT_OFFSET 14
-#define DMI_DMSTATUS_ANYNONEXISTENT_LENGTH 1
-#define DMI_DMSTATUS_ANYNONEXISTENT (0x1 << DMI_DMSTATUS_ANYNONEXISTENT_OFFSET)
-/*
-* This field is 1 when all currently selected harts are unavailable.
- */
-#define DMI_DMSTATUS_ALLUNAVAIL_OFFSET 13
-#define DMI_DMSTATUS_ALLUNAVAIL_LENGTH 1
-#define DMI_DMSTATUS_ALLUNAVAIL (0x1 << DMI_DMSTATUS_ALLUNAVAIL_OFFSET)
-/*
-* This field is 1 when any currently selected hart is unavailable.
- */
-#define DMI_DMSTATUS_ANYUNAVAIL_OFFSET 12
-#define DMI_DMSTATUS_ANYUNAVAIL_LENGTH 1
-#define DMI_DMSTATUS_ANYUNAVAIL (0x1 << DMI_DMSTATUS_ANYUNAVAIL_OFFSET)
-/*
-* This field is 1 when all currently selected harts are running.
- */
-#define DMI_DMSTATUS_ALLRUNNING_OFFSET 11
-#define DMI_DMSTATUS_ALLRUNNING_LENGTH 1
-#define DMI_DMSTATUS_ALLRUNNING (0x1 << DMI_DMSTATUS_ALLRUNNING_OFFSET)
-/*
-* This field is 1 when any currently selected hart is running.
- */
-#define DMI_DMSTATUS_ANYRUNNING_OFFSET 10
-#define DMI_DMSTATUS_ANYRUNNING_LENGTH 1
-#define DMI_DMSTATUS_ANYRUNNING (0x1 << DMI_DMSTATUS_ANYRUNNING_OFFSET)
-/*
-* This field is 1 when all currently selected harts are halted.
- */
-#define DMI_DMSTATUS_ALLHALTED_OFFSET 9
-#define DMI_DMSTATUS_ALLHALTED_LENGTH 1
-#define DMI_DMSTATUS_ALLHALTED (0x1 << DMI_DMSTATUS_ALLHALTED_OFFSET)
-/*
-* This field is 1 when any currently selected hart is halted.
- */
-#define DMI_DMSTATUS_ANYHALTED_OFFSET 8
-#define DMI_DMSTATUS_ANYHALTED_LENGTH 1
-#define DMI_DMSTATUS_ANYHALTED (0x1 << DMI_DMSTATUS_ANYHALTED_OFFSET)
-/*
-* 0 when authentication is required before using the DM. 1 when the
-* authentication check has passed. On components that don't implement
-* authentication, this bit must be preset as 1.
- */
-#define DMI_DMSTATUS_AUTHENTICATED_OFFSET 7
-#define DMI_DMSTATUS_AUTHENTICATED_LENGTH 1
-#define DMI_DMSTATUS_AUTHENTICATED (0x1 << DMI_DMSTATUS_AUTHENTICATED_OFFSET)
-/*
-* 0: The authentication module is ready to process the next
-* read/write to \Rauthdata.
-*
-* 1: The authentication module is busy. Accessing \Rauthdata results
-* in unspecified behavior.
-*
-* \Fauthbusy only becomes set in immediate response to an access to
-* \Rauthdata.
- */
-#define DMI_DMSTATUS_AUTHBUSY_OFFSET 6
-#define DMI_DMSTATUS_AUTHBUSY_LENGTH 1
-#define DMI_DMSTATUS_AUTHBUSY (0x1 << DMI_DMSTATUS_AUTHBUSY_OFFSET)
-#define DMI_DMSTATUS_CFGSTRVALID_OFFSET 4
-#define DMI_DMSTATUS_CFGSTRVALID_LENGTH 1
-#define DMI_DMSTATUS_CFGSTRVALID (0x1 << DMI_DMSTATUS_CFGSTRVALID_OFFSET)
-/*
-* Reserved for future use. Reads as 0.
- */
-#define DMI_DMSTATUS_VERSIONHI_OFFSET 2
-#define DMI_DMSTATUS_VERSIONHI_LENGTH 2
-#define DMI_DMSTATUS_VERSIONHI (0x3 << DMI_DMSTATUS_VERSIONHI_OFFSET)
-/*
-* 00: There is no Debug Module present.
-*
-* 01: There is a Debug Module and it conforms to version 0.11 of this
-* specification.
-*
-* 10: There is a Debug Module and it conforms to version 0.13 of this
-* specification.
-*
-* 11: Reserved for future use.
- */
-#define DMI_DMSTATUS_VERSIONLO_OFFSET 0
-#define DMI_DMSTATUS_VERSIONLO_LENGTH 2
-#define DMI_DMSTATUS_VERSIONLO (0x3 << DMI_DMSTATUS_VERSIONLO_OFFSET)
-#define DMI_DMCONTROL 0x10
-/*
-* Halt request signal for all currently selected harts. When 1, the
-* hart will halt if it is not currently halted.
-* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_HALTREQ_OFFSET 31
-#define DMI_DMCONTROL_HALTREQ_LENGTH 1
-#define DMI_DMCONTROL_HALTREQ (0x1 << DMI_DMCONTROL_HALTREQ_OFFSET)
-/*
-* Resume request signal for all currently selected harts. When 1,
-* the hart will resume if it is currently halted.
-* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_RESUMEREQ_OFFSET 30
-#define DMI_DMCONTROL_RESUMEREQ_LENGTH 1
-#define DMI_DMCONTROL_RESUMEREQ (0x1 << DMI_DMCONTROL_RESUMEREQ_OFFSET)
-/*
-* This optional bit controls reset to all the currently selected harts.
-* To perform a reset the debugger writes 1, and then writes 0 to
-* deassert the reset signal.
-*
-* If this feature is not implemented, the bit always stays 0, so
-* after writing 1 the debugger can read the register back to see if
-* the feature is supported.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_HARTRESET_OFFSET 29
-#define DMI_DMCONTROL_HARTRESET_LENGTH 1
-#define DMI_DMCONTROL_HARTRESET (0x1 << DMI_DMCONTROL_HARTRESET_OFFSET)
-/*
-* Selects the definition of currently selected harts.
-*
-* 0: There is a single currently selected hart, that selected by \Fhartsel.
-*
-* 1: There may be multiple currently selected harts -- that selected by \Fhartsel,
-* plus those selected by the hart array mask register.
-*
-* An implementation which does not implement the hart array mask register
-* should tie this field to 0. A debugger which wishes to use the hart array
-* mask register feature should set this bit and read back to see if the functionality
-* is supported.
- */
-#define DMI_DMCONTROL_HASEL_OFFSET 26
-#define DMI_DMCONTROL_HASEL_LENGTH 1
-#define DMI_DMCONTROL_HASEL (0x1 << DMI_DMCONTROL_HASEL_OFFSET)
-/*
-* The DM-specific index of the hart to select. This hart is always part of the
-* currently selected harts.
- */
-#define DMI_DMCONTROL_HARTSEL_OFFSET 16
-#define DMI_DMCONTROL_HARTSEL_LENGTH 10
-#define DMI_DMCONTROL_HARTSEL (0x3ff << DMI_DMCONTROL_HARTSEL_OFFSET)
-/*
-* This bit controls the reset signal from the DM to the rest of the
-* system. To perform a reset the debugger writes 1, and then writes 0
-* to deassert the reset.
- */
-#define DMI_DMCONTROL_NDMRESET_OFFSET 1
-#define DMI_DMCONTROL_NDMRESET_LENGTH 1
-#define DMI_DMCONTROL_NDMRESET (0x1 << DMI_DMCONTROL_NDMRESET_OFFSET)
-/*
-* This bit serves as a reset signal for the Debug Module itself.
-*
-* 0: The module's state, including authentication mechanism,
-* takes its reset values (the \Fdmactive bit is the only bit which can
-* be written to something other than its reset value).
-*
-* 1: The module functions normally.
-*
-* No other mechanism should exist that may result in resetting the
-* Debug Module after power up, including the platform's system reset
-* or Debug Transport reset signals.
-*
-* A debugger should pulse this bit low to ensure that the Debug
-* Module is fully reset and ready to use.
-*
-* Implementations may use this bit to aid debugging, for example by
-* preventing the Debug Module from being power gated while debugging
-* is active.
- */
-#define DMI_DMCONTROL_DMACTIVE_OFFSET 0
-#define DMI_DMCONTROL_DMACTIVE_LENGTH 1
-#define DMI_DMCONTROL_DMACTIVE (0x1 << DMI_DMCONTROL_DMACTIVE_OFFSET)
-#define DMI_HARTINFO 0x12
-/*
-* Number of {\tt dscratch} registers available for the debugger
-* to use during program buffer execution, starting from \Rdscratchzero.
-* The debugger can make no assumptions about the contents of these
-* registers between commands.
- */
-#define DMI_HARTINFO_NSCRATCH_OFFSET 20
-#define DMI_HARTINFO_NSCRATCH_LENGTH 4
-#define DMI_HARTINFO_NSCRATCH (0xf << DMI_HARTINFO_NSCRATCH_OFFSET)
-/*
-* 0: The {\tt data} registers are shadowed in the hart by CSR
-* registers. Each CSR register is XLEN bits in size, and corresponds
-* to a single argument, per Table~\ref{tab:datareg}.
-*
-* 1: The {\tt data} registers are shadowed in the hart's memory map.
-* Each register takes up 4 bytes in the memory map.
- */
-#define DMI_HARTINFO_DATAACCESS_OFFSET 16
-#define DMI_HARTINFO_DATAACCESS_LENGTH 1
-#define DMI_HARTINFO_DATAACCESS (0x1 << DMI_HARTINFO_DATAACCESS_OFFSET)
-/*
-* If \Fdataaccess is 0: Number of CSR registers dedicated to
-* shadowing the {\tt data} registers.
-*
-* If \Fdataaccess is 1: Number of 32-bit words in the memory map
-* dedicated to shadowing the {\tt data} registers.
- */
-#define DMI_HARTINFO_DATASIZE_OFFSET 12
-#define DMI_HARTINFO_DATASIZE_LENGTH 4
-#define DMI_HARTINFO_DATASIZE (0xf << DMI_HARTINFO_DATASIZE_OFFSET)
-/*
-* If \Fdataaccess is 0: The number of the first CSR dedicated to
-* shadowing the {\tt data} registers.
-*
-* If \Fdataaccess is 1: Signed address of RAM where the {\tt data}
-* registers are shadowed.
- */
-#define DMI_HARTINFO_DATAADDR_OFFSET 0
-#define DMI_HARTINFO_DATAADDR_LENGTH 12
-#define DMI_HARTINFO_DATAADDR (0xfff << DMI_HARTINFO_DATAADDR_OFFSET)
-#define DMI_HALTSUM 0x13
-#define DMI_HALTSUM_HALT1023_992_OFFSET 31
-#define DMI_HALTSUM_HALT1023_992_LENGTH 1
-#define DMI_HALTSUM_HALT1023_992 (0x1 << DMI_HALTSUM_HALT1023_992_OFFSET)
-#define DMI_HALTSUM_HALT991_960_OFFSET 30
-#define DMI_HALTSUM_HALT991_960_LENGTH 1
-#define DMI_HALTSUM_HALT991_960 (0x1 << DMI_HALTSUM_HALT991_960_OFFSET)
-#define DMI_HALTSUM_HALT959_928_OFFSET 29
-#define DMI_HALTSUM_HALT959_928_LENGTH 1
-#define DMI_HALTSUM_HALT959_928 (0x1 << DMI_HALTSUM_HALT959_928_OFFSET)
-#define DMI_HALTSUM_HALT927_896_OFFSET 28
-#define DMI_HALTSUM_HALT927_896_LENGTH 1
-#define DMI_HALTSUM_HALT927_896 (0x1 << DMI_HALTSUM_HALT927_896_OFFSET)
-#define DMI_HALTSUM_HALT895_864_OFFSET 27
-#define DMI_HALTSUM_HALT895_864_LENGTH 1
-#define DMI_HALTSUM_HALT895_864 (0x1 << DMI_HALTSUM_HALT895_864_OFFSET)
-#define DMI_HALTSUM_HALT863_832_OFFSET 26
-#define DMI_HALTSUM_HALT863_832_LENGTH 1
-#define DMI_HALTSUM_HALT863_832 (0x1 << DMI_HALTSUM_HALT863_832_OFFSET)
-#define DMI_HALTSUM_HALT831_800_OFFSET 25
-#define DMI_HALTSUM_HALT831_800_LENGTH 1
-#define DMI_HALTSUM_HALT831_800 (0x1 << DMI_HALTSUM_HALT831_800_OFFSET)
-#define DMI_HALTSUM_HALT799_768_OFFSET 24
-#define DMI_HALTSUM_HALT799_768_LENGTH 1
-#define DMI_HALTSUM_HALT799_768 (0x1 << DMI_HALTSUM_HALT799_768_OFFSET)
-#define DMI_HALTSUM_HALT767_736_OFFSET 23
-#define DMI_HALTSUM_HALT767_736_LENGTH 1
-#define DMI_HALTSUM_HALT767_736 (0x1 << DMI_HALTSUM_HALT767_736_OFFSET)
-#define DMI_HALTSUM_HALT735_704_OFFSET 22
-#define DMI_HALTSUM_HALT735_704_LENGTH 1
-#define DMI_HALTSUM_HALT735_704 (0x1 << DMI_HALTSUM_HALT735_704_OFFSET)
-#define DMI_HALTSUM_HALT703_672_OFFSET 21
-#define DMI_HALTSUM_HALT703_672_LENGTH 1
-#define DMI_HALTSUM_HALT703_672 (0x1 << DMI_HALTSUM_HALT703_672_OFFSET)
-#define DMI_HALTSUM_HALT671_640_OFFSET 20
-#define DMI_HALTSUM_HALT671_640_LENGTH 1
-#define DMI_HALTSUM_HALT671_640 (0x1 << DMI_HALTSUM_HALT671_640_OFFSET)
-#define DMI_HALTSUM_HALT639_608_OFFSET 19
-#define DMI_HALTSUM_HALT639_608_LENGTH 1
-#define DMI_HALTSUM_HALT639_608 (0x1 << DMI_HALTSUM_HALT639_608_OFFSET)
-#define DMI_HALTSUM_HALT607_576_OFFSET 18
-#define DMI_HALTSUM_HALT607_576_LENGTH 1
-#define DMI_HALTSUM_HALT607_576 (0x1 << DMI_HALTSUM_HALT607_576_OFFSET)
-#define DMI_HALTSUM_HALT575_544_OFFSET 17
-#define DMI_HALTSUM_HALT575_544_LENGTH 1
-#define DMI_HALTSUM_HALT575_544 (0x1 << DMI_HALTSUM_HALT575_544_OFFSET)
-#define DMI_HALTSUM_HALT543_512_OFFSET 16
-#define DMI_HALTSUM_HALT543_512_LENGTH 1
-#define DMI_HALTSUM_HALT543_512 (0x1 << DMI_HALTSUM_HALT543_512_OFFSET)
-#define DMI_HALTSUM_HALT511_480_OFFSET 15
-#define DMI_HALTSUM_HALT511_480_LENGTH 1
-#define DMI_HALTSUM_HALT511_480 (0x1 << DMI_HALTSUM_HALT511_480_OFFSET)
-#define DMI_HALTSUM_HALT479_448_OFFSET 14
-#define DMI_HALTSUM_HALT479_448_LENGTH 1
-#define DMI_HALTSUM_HALT479_448 (0x1 << DMI_HALTSUM_HALT479_448_OFFSET)
-#define DMI_HALTSUM_HALT447_416_OFFSET 13
-#define DMI_HALTSUM_HALT447_416_LENGTH 1
-#define DMI_HALTSUM_HALT447_416 (0x1 << DMI_HALTSUM_HALT447_416_OFFSET)
-#define DMI_HALTSUM_HALT415_384_OFFSET 12
-#define DMI_HALTSUM_HALT415_384_LENGTH 1
-#define DMI_HALTSUM_HALT415_384 (0x1 << DMI_HALTSUM_HALT415_384_OFFSET)
-#define DMI_HALTSUM_HALT383_352_OFFSET 11
-#define DMI_HALTSUM_HALT383_352_LENGTH 1
-#define DMI_HALTSUM_HALT383_352 (0x1 << DMI_HALTSUM_HALT383_352_OFFSET)
-#define DMI_HALTSUM_HALT351_320_OFFSET 10
-#define DMI_HALTSUM_HALT351_320_LENGTH 1
-#define DMI_HALTSUM_HALT351_320 (0x1 << DMI_HALTSUM_HALT351_320_OFFSET)
-#define DMI_HALTSUM_HALT319_288_OFFSET 9
-#define DMI_HALTSUM_HALT319_288_LENGTH 1
-#define DMI_HALTSUM_HALT319_288 (0x1 << DMI_HALTSUM_HALT319_288_OFFSET)
-#define DMI_HALTSUM_HALT287_256_OFFSET 8
-#define DMI_HALTSUM_HALT287_256_LENGTH 1
-#define DMI_HALTSUM_HALT287_256 (0x1 << DMI_HALTSUM_HALT287_256_OFFSET)
-#define DMI_HALTSUM_HALT255_224_OFFSET 7
-#define DMI_HALTSUM_HALT255_224_LENGTH 1
-#define DMI_HALTSUM_HALT255_224 (0x1 << DMI_HALTSUM_HALT255_224_OFFSET)
-#define DMI_HALTSUM_HALT223_192_OFFSET 6
-#define DMI_HALTSUM_HALT223_192_LENGTH 1
-#define DMI_HALTSUM_HALT223_192 (0x1 << DMI_HALTSUM_HALT223_192_OFFSET)
-#define DMI_HALTSUM_HALT191_160_OFFSET 5
-#define DMI_HALTSUM_HALT191_160_LENGTH 1
-#define DMI_HALTSUM_HALT191_160 (0x1 << DMI_HALTSUM_HALT191_160_OFFSET)
-#define DMI_HALTSUM_HALT159_128_OFFSET 4
-#define DMI_HALTSUM_HALT159_128_LENGTH 1
-#define DMI_HALTSUM_HALT159_128 (0x1 << DMI_HALTSUM_HALT159_128_OFFSET)
-#define DMI_HALTSUM_HALT127_96_OFFSET 3
-#define DMI_HALTSUM_HALT127_96_LENGTH 1
-#define DMI_HALTSUM_HALT127_96 (0x1 << DMI_HALTSUM_HALT127_96_OFFSET)
-#define DMI_HALTSUM_HALT95_64_OFFSET 2
-#define DMI_HALTSUM_HALT95_64_LENGTH 1
-#define DMI_HALTSUM_HALT95_64 (0x1 << DMI_HALTSUM_HALT95_64_OFFSET)
-#define DMI_HALTSUM_HALT63_32_OFFSET 1
-#define DMI_HALTSUM_HALT63_32_LENGTH 1
-#define DMI_HALTSUM_HALT63_32 (0x1 << DMI_HALTSUM_HALT63_32_OFFSET)
-#define DMI_HALTSUM_HALT31_0_OFFSET 0
-#define DMI_HALTSUM_HALT31_0_LENGTH 1
-#define DMI_HALTSUM_HALT31_0 (0x1 << DMI_HALTSUM_HALT31_0_OFFSET)
-#define DMI_HAWINDOWSEL 0x14
-#define DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET 0
-#define DMI_HAWINDOWSEL_HAWINDOWSEL_LENGTH 5
-#define DMI_HAWINDOWSEL_HAWINDOWSEL (0x1f << DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET)
-#define DMI_HAWINDOW 0x15
-#define DMI_HAWINDOW_MASKDATA_OFFSET 0
-#define DMI_HAWINDOW_MASKDATA_LENGTH 32
-#define DMI_HAWINDOW_MASKDATA (0xffffffff << DMI_HAWINDOW_MASKDATA_OFFSET)
-#define DMI_ABSTRACTCS 0x16
-/*
-* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
-*
-* TODO: Explain what can be done with each size of the buffer, to suggest
-* why you would want more or less words.
- */
-#define DMI_ABSTRACTCS_PROGSIZE_OFFSET 24
-#define DMI_ABSTRACTCS_PROGSIZE_LENGTH 5
-#define DMI_ABSTRACTCS_PROGSIZE (0x1f << DMI_ABSTRACTCS_PROGSIZE_OFFSET)
-/*
-* 1: An abstract command is currently being executed.
-*
-* This bit is set as soon as \Rcommand is written, and is
-* not cleared until that command has completed.
- */
-#define DMI_ABSTRACTCS_BUSY_OFFSET 12
-#define DMI_ABSTRACTCS_BUSY_LENGTH 1
-#define DMI_ABSTRACTCS_BUSY (0x1 << DMI_ABSTRACTCS_BUSY_OFFSET)
-/*
-* Gets set if an abstract command fails. The bits in this field remain set until
-* they are cleared by writing 1 to them. No abstract command is
-* started until the value is reset to 0.
-*
-* 0 (none): No error.
-*
-* 1 (busy): An abstract command was executing while \Rcommand or one
-* of the {\tt data} registers was accessed.
-*
-* 2 (not supported): The requested command is not supported. A
-* command that is not supported while the hart is running may be
-* supported when it is halted.
-*
-* 3 (exception): An exception occurred while executing the command
-* (eg. while executing the Program Buffer).
-*
-* 4 (halt/resume): An abstract command couldn't execute because the
-* hart wasn't in the expected state (running/halted).
-*
-* 7 (other): The command failed for another reason.
- */
-#define DMI_ABSTRACTCS_CMDERR_OFFSET 8
-#define DMI_ABSTRACTCS_CMDERR_LENGTH 3
-#define DMI_ABSTRACTCS_CMDERR (0x7 << DMI_ABSTRACTCS_CMDERR_OFFSET)
-/*
-* Number of {\tt data} registers that are implemented as part of the
-* abstract command interface. Valid sizes are 0 - 8.
- */
-#define DMI_ABSTRACTCS_DATACOUNT_OFFSET 0
-#define DMI_ABSTRACTCS_DATACOUNT_LENGTH 5
-#define DMI_ABSTRACTCS_DATACOUNT (0x1f << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
-#define DMI_COMMAND 0x17
-/*
-* The type determines the overall functionality of this
-* abstract command.
- */
-#define DMI_COMMAND_CMDTYPE_OFFSET 24
-#define DMI_COMMAND_CMDTYPE_LENGTH 8
-#define DMI_COMMAND_CMDTYPE (0xff << DMI_COMMAND_CMDTYPE_OFFSET)
-/*
-* This field is interpreted in a command-specific manner,
-* described for each abstract command.
- */
-#define DMI_COMMAND_CONTROL_OFFSET 0
-#define DMI_COMMAND_CONTROL_LENGTH 24
-#define DMI_COMMAND_CONTROL (0xffffff << DMI_COMMAND_CONTROL_OFFSET)
-#define DMI_ABSTRACTAUTO 0x18
-/*
-* When a bit in this field is 1, read or write accesses the corresponding {\tt progbuf} word
-* cause the command in \Rcommand to be executed again.
- */
-#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16
-#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16
-#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF (0xffff << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET)
-/*
-* When a bit in this field is 1, read or write accesses the corresponding {\tt data} word
-* cause the command in \Rcommand to be executed again.
- */
-#define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0
-#define DMI_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 12
-#define DMI_ABSTRACTAUTO_AUTOEXECDATA (0xfff << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET)
-#define DMI_CFGSTRADDR0 0x19
-#define DMI_CFGSTRADDR0_ADDR_OFFSET 0
-#define DMI_CFGSTRADDR0_ADDR_LENGTH 32
-#define DMI_CFGSTRADDR0_ADDR (0xffffffff << DMI_CFGSTRADDR0_ADDR_OFFSET)
-#define DMI_CFGSTRADDR1 0x1a
-#define DMI_CFGSTRADDR2 0x1b
-#define DMI_CFGSTRADDR3 0x1c
-#define DMI_DATA0 0x04
-#define DMI_DATA0_DATA_OFFSET 0
-#define DMI_DATA0_DATA_LENGTH 32
-#define DMI_DATA0_DATA (0xffffffff << DMI_DATA0_DATA_OFFSET)
-#define DMI_DATA1 0x05
-#define DMI_DATA2 0x06
-#define DMI_DATA3 0x07
-#define DMI_DATA4 0x08
-#define DMI_DATA5 0x09
-#define DMI_DATA6 0x0a
-#define DMI_DATA7 0x0b
-#define DMI_DATA8 0x0c
-#define DMI_DATA9 0x0d
-#define DMI_DATA10 0x0e
-#define DMI_DATA11 0x0f
-#define DMI_PROGBUF0 0x20
-#define DMI_PROGBUF0_DATA_OFFSET 0
-#define DMI_PROGBUF0_DATA_LENGTH 32
-#define DMI_PROGBUF0_DATA (0xffffffff << DMI_PROGBUF0_DATA_OFFSET)
-#define DMI_PROGBUF1 0x21
-#define DMI_PROGBUF2 0x22
-#define DMI_PROGBUF3 0x23
-#define DMI_PROGBUF4 0x24
-#define DMI_PROGBUF5 0x25
-#define DMI_PROGBUF6 0x26
-#define DMI_PROGBUF7 0x27
-#define DMI_PROGBUF8 0x28
-#define DMI_PROGBUF9 0x29
-#define DMI_PROGBUF10 0x2a
-#define DMI_AUTHDATA 0x30
-#define DMI_AUTHDATA_DATA_OFFSET 0
-#define DMI_AUTHDATA_DATA_LENGTH 32
-#define DMI_AUTHDATA_DATA (0xffffffff << DMI_AUTHDATA_DATA_OFFSET)
-#define DMI_SERCS 0x34
-/*
-* Number of supported serial ports.
- */
-#define DMI_SERCS_SERIALCOUNT_OFFSET 28
-#define DMI_SERCS_SERIALCOUNT_LENGTH 4
-#define DMI_SERCS_SERIALCOUNT (0xf << DMI_SERCS_SERIALCOUNT_OFFSET)
-/*
-* Select which serial port is accessed by \Rserrx and \Rsertx.
- */
-#define DMI_SERCS_SERIAL_OFFSET 24
-#define DMI_SERCS_SERIAL_LENGTH 3
-#define DMI_SERCS_SERIAL (0x7 << DMI_SERCS_SERIAL_OFFSET)
-#define DMI_SERCS_ERROR7_OFFSET 23
-#define DMI_SERCS_ERROR7_LENGTH 1
-#define DMI_SERCS_ERROR7 (0x1 << DMI_SERCS_ERROR7_OFFSET)
-#define DMI_SERCS_VALID7_OFFSET 22
-#define DMI_SERCS_VALID7_LENGTH 1
-#define DMI_SERCS_VALID7 (0x1 << DMI_SERCS_VALID7_OFFSET)
-#define DMI_SERCS_FULL7_OFFSET 21
-#define DMI_SERCS_FULL7_LENGTH 1
-#define DMI_SERCS_FULL7 (0x1 << DMI_SERCS_FULL7_OFFSET)
-#define DMI_SERCS_ERROR6_OFFSET 20
-#define DMI_SERCS_ERROR6_LENGTH 1
-#define DMI_SERCS_ERROR6 (0x1 << DMI_SERCS_ERROR6_OFFSET)
-#define DMI_SERCS_VALID6_OFFSET 19
-#define DMI_SERCS_VALID6_LENGTH 1
-#define DMI_SERCS_VALID6 (0x1 << DMI_SERCS_VALID6_OFFSET)
-#define DMI_SERCS_FULL6_OFFSET 18
-#define DMI_SERCS_FULL6_LENGTH 1
-#define DMI_SERCS_FULL6 (0x1 << DMI_SERCS_FULL6_OFFSET)
-#define DMI_SERCS_ERROR5_OFFSET 17
-#define DMI_SERCS_ERROR5_LENGTH 1
-#define DMI_SERCS_ERROR5 (0x1 << DMI_SERCS_ERROR5_OFFSET)
-#define DMI_SERCS_VALID5_OFFSET 16
-#define DMI_SERCS_VALID5_LENGTH 1
-#define DMI_SERCS_VALID5 (0x1 << DMI_SERCS_VALID5_OFFSET)
-#define DMI_SERCS_FULL5_OFFSET 15
-#define DMI_SERCS_FULL5_LENGTH 1
-#define DMI_SERCS_FULL5 (0x1 << DMI_SERCS_FULL5_OFFSET)
-#define DMI_SERCS_ERROR4_OFFSET 14
-#define DMI_SERCS_ERROR4_LENGTH 1
-#define DMI_SERCS_ERROR4 (0x1 << DMI_SERCS_ERROR4_OFFSET)
-#define DMI_SERCS_VALID4_OFFSET 13
-#define DMI_SERCS_VALID4_LENGTH 1
-#define DMI_SERCS_VALID4 (0x1 << DMI_SERCS_VALID4_OFFSET)
-#define DMI_SERCS_FULL4_OFFSET 12
-#define DMI_SERCS_FULL4_LENGTH 1
-#define DMI_SERCS_FULL4 (0x1 << DMI_SERCS_FULL4_OFFSET)
-#define DMI_SERCS_ERROR3_OFFSET 11
-#define DMI_SERCS_ERROR3_LENGTH 1
-#define DMI_SERCS_ERROR3 (0x1 << DMI_SERCS_ERROR3_OFFSET)
-#define DMI_SERCS_VALID3_OFFSET 10
-#define DMI_SERCS_VALID3_LENGTH 1
-#define DMI_SERCS_VALID3 (0x1 << DMI_SERCS_VALID3_OFFSET)
-#define DMI_SERCS_FULL3_OFFSET 9
-#define DMI_SERCS_FULL3_LENGTH 1
-#define DMI_SERCS_FULL3 (0x1 << DMI_SERCS_FULL3_OFFSET)
-#define DMI_SERCS_ERROR2_OFFSET 8
-#define DMI_SERCS_ERROR2_LENGTH 1
-#define DMI_SERCS_ERROR2 (0x1 << DMI_SERCS_ERROR2_OFFSET)
-#define DMI_SERCS_VALID2_OFFSET 7
-#define DMI_SERCS_VALID2_LENGTH 1
-#define DMI_SERCS_VALID2 (0x1 << DMI_SERCS_VALID2_OFFSET)
-#define DMI_SERCS_FULL2_OFFSET 6
-#define DMI_SERCS_FULL2_LENGTH 1
-#define DMI_SERCS_FULL2 (0x1 << DMI_SERCS_FULL2_OFFSET)
-#define DMI_SERCS_ERROR1_OFFSET 5
-#define DMI_SERCS_ERROR1_LENGTH 1
-#define DMI_SERCS_ERROR1 (0x1 << DMI_SERCS_ERROR1_OFFSET)
-#define DMI_SERCS_VALID1_OFFSET 4
-#define DMI_SERCS_VALID1_LENGTH 1
-#define DMI_SERCS_VALID1 (0x1 << DMI_SERCS_VALID1_OFFSET)
-#define DMI_SERCS_FULL1_OFFSET 3
-#define DMI_SERCS_FULL1_LENGTH 1
-#define DMI_SERCS_FULL1 (0x1 << DMI_SERCS_FULL1_OFFSET)
-/*
-* 1 when the debugger-to-core queue for serial port 0 has
-* over or underflowed. This bit will remain set until it is reset by
-* writing 1 to this bit.
- */
-#define DMI_SERCS_ERROR0_OFFSET 2
-#define DMI_SERCS_ERROR0_LENGTH 1
-#define DMI_SERCS_ERROR0 (0x1 << DMI_SERCS_ERROR0_OFFSET)
-/*
-* 1 when the core-to-debugger queue for serial port 0 is not empty.
- */
-#define DMI_SERCS_VALID0_OFFSET 1
-#define DMI_SERCS_VALID0_LENGTH 1
-#define DMI_SERCS_VALID0 (0x1 << DMI_SERCS_VALID0_OFFSET)
-/*
-* 1 when the debugger-to-core queue for serial port 0 is full.
- */
-#define DMI_SERCS_FULL0_OFFSET 0
-#define DMI_SERCS_FULL0_LENGTH 1
-#define DMI_SERCS_FULL0 (0x1 << DMI_SERCS_FULL0_OFFSET)
-#define DMI_SERTX 0x35
-#define DMI_SERTX_DATA_OFFSET 0
-#define DMI_SERTX_DATA_LENGTH 32
-#define DMI_SERTX_DATA (0xffffffff << DMI_SERTX_DATA_OFFSET)
-#define DMI_SERRX 0x36
-#define DMI_SERRX_DATA_OFFSET 0
-#define DMI_SERRX_DATA_LENGTH 32
-#define DMI_SERRX_DATA (0xffffffff << DMI_SERRX_DATA_OFFSET)
-#define DMI_SBCS 0x38
-/*
-* When a 1 is written here, triggers a read at the address in {\tt
-* sbaddress} using the access size set by \Fsbaccess.
- */
-#define DMI_SBCS_SBSINGLEREAD_OFFSET 20
-#define DMI_SBCS_SBSINGLEREAD_LENGTH 1
-#define DMI_SBCS_SBSINGLEREAD (0x1 << DMI_SBCS_SBSINGLEREAD_OFFSET)
-/*
-* Select the access size to use for system bus accesses triggered by
-* writes to the {\tt sbaddress} registers or \Rsbdatazero.
-*
-* 0: 8-bit
-*
-* 1: 16-bit
-*
-* 2: 32-bit
-*
-* 3: 64-bit
-*
-* 4: 128-bit
-*
-* If an unsupported system bus access size is written here,
-* the DM may not perform the access, or may perform the access
-* with any access size.
- */
-#define DMI_SBCS_SBACCESS_OFFSET 17
-#define DMI_SBCS_SBACCESS_LENGTH 3
-#define DMI_SBCS_SBACCESS (0x7 << DMI_SBCS_SBACCESS_OFFSET)
-/*
-* When 1, the internal address value (used by the system bus master)
-* is incremented by the access size (in bytes) selected in \Fsbaccess
-* after every system bus access.
- */
-#define DMI_SBCS_SBAUTOINCREMENT_OFFSET 16
-#define DMI_SBCS_SBAUTOINCREMENT_LENGTH 1
-#define DMI_SBCS_SBAUTOINCREMENT (0x1 << DMI_SBCS_SBAUTOINCREMENT_OFFSET)
-/*
-* When 1, every read from \Rsbdatazero automatically triggers a system
-* bus read at the new address.
- */
-#define DMI_SBCS_SBAUTOREAD_OFFSET 15
-#define DMI_SBCS_SBAUTOREAD_LENGTH 1
-#define DMI_SBCS_SBAUTOREAD (0x1 << DMI_SBCS_SBAUTOREAD_OFFSET)
-/*
-* When the debug module's system bus
-* master causes a bus error, this field gets set. The bits in this
-* field remain set until they are cleared by writing 1 to them.
-* While this field is non-zero, no more system bus accesses can be
-* initiated by the debug module.
-*
-* 0: There was no bus error.
-*
-* 1: There was a timeout.
-*
-* 2: A bad address was accessed.
-*
-* 3: There was some other error (eg. alignment).
-*
-* 4: The system bus master was busy when a one of the
-* {\tt sbaddress} or {\tt sbdata} registers was written,
-* or the {\tt sbdata} register was read when it had
-* stale data.
- */
-#define DMI_SBCS_SBERROR_OFFSET 12
-#define DMI_SBCS_SBERROR_LENGTH 3
-#define DMI_SBCS_SBERROR (0x7 << DMI_SBCS_SBERROR_OFFSET)
-/*
-* Width of system bus addresses in bits. (0 indicates there is no bus
-* access support.)
- */
-#define DMI_SBCS_SBASIZE_OFFSET 5
-#define DMI_SBCS_SBASIZE_LENGTH 7
-#define DMI_SBCS_SBASIZE (0x7f << DMI_SBCS_SBASIZE_OFFSET)
-/*
-* 1 when 128-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS128_OFFSET 4
-#define DMI_SBCS_SBACCESS128_LENGTH 1
-#define DMI_SBCS_SBACCESS128 (0x1 << DMI_SBCS_SBACCESS128_OFFSET)
-/*
-* 1 when 64-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS64_OFFSET 3
-#define DMI_SBCS_SBACCESS64_LENGTH 1
-#define DMI_SBCS_SBACCESS64 (0x1 << DMI_SBCS_SBACCESS64_OFFSET)
-/*
-* 1 when 32-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS32_OFFSET 2
-#define DMI_SBCS_SBACCESS32_LENGTH 1
-#define DMI_SBCS_SBACCESS32 (0x1 << DMI_SBCS_SBACCESS32_OFFSET)
-/*
-* 1 when 16-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS16_OFFSET 1
-#define DMI_SBCS_SBACCESS16_LENGTH 1
-#define DMI_SBCS_SBACCESS16 (0x1 << DMI_SBCS_SBACCESS16_OFFSET)
-/*
-* 1 when 8-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS8_OFFSET 0
-#define DMI_SBCS_SBACCESS8_LENGTH 1
-#define DMI_SBCS_SBACCESS8 (0x1 << DMI_SBCS_SBACCESS8_OFFSET)
-#define DMI_SBADDRESS0 0x39
-/*
-* Accesses bits 31:0 of the internal address.
- */
-#define DMI_SBADDRESS0_ADDRESS_OFFSET 0
-#define DMI_SBADDRESS0_ADDRESS_LENGTH 32
-#define DMI_SBADDRESS0_ADDRESS (0xffffffff << DMI_SBADDRESS0_ADDRESS_OFFSET)
-#define DMI_SBADDRESS1 0x3a
-/*
-* Accesses bits 63:32 of the internal address (if the system address
-* bus is that wide).
- */
-#define DMI_SBADDRESS1_ADDRESS_OFFSET 0
-#define DMI_SBADDRESS1_ADDRESS_LENGTH 32
-#define DMI_SBADDRESS1_ADDRESS (0xffffffff << DMI_SBADDRESS1_ADDRESS_OFFSET)
-#define DMI_SBADDRESS2 0x3b
-/*
-* Accesses bits 95:64 of the internal address (if the system address
-* bus is that wide).
- */
-#define DMI_SBADDRESS2_ADDRESS_OFFSET 0
-#define DMI_SBADDRESS2_ADDRESS_LENGTH 32
-#define DMI_SBADDRESS2_ADDRESS (0xffffffff << DMI_SBADDRESS2_ADDRESS_OFFSET)
-#define DMI_SBDATA0 0x3c
-/*
-* Accesses bits 31:0 of the internal data.
- */
-#define DMI_SBDATA0_DATA_OFFSET 0
-#define DMI_SBDATA0_DATA_LENGTH 32
-#define DMI_SBDATA0_DATA (0xffffffff << DMI_SBDATA0_DATA_OFFSET)
-#define DMI_SBDATA1 0x3d
-/*
-* Accesses bits 63:32 of the internal data (if the system bus is
-* that wide).
- */
-#define DMI_SBDATA1_DATA_OFFSET 0
-#define DMI_SBDATA1_DATA_LENGTH 32
-#define DMI_SBDATA1_DATA (0xffffffff << DMI_SBDATA1_DATA_OFFSET)
-#define DMI_SBDATA2 0x3e
-/*
-* Accesses bits 95:64 of the internal data (if the system bus is
-* that wide).
- */
-#define DMI_SBDATA2_DATA_OFFSET 0
-#define DMI_SBDATA2_DATA_LENGTH 32
-#define DMI_SBDATA2_DATA (0xffffffff << DMI_SBDATA2_DATA_OFFSET)
-#define DMI_SBDATA3 0x3f
-/*
-* Accesses bits 127:96 of the internal data (if the system bus is
-* that wide).
- */
-#define DMI_SBDATA3_DATA_OFFSET 0
-#define DMI_SBDATA3_DATA_LENGTH 32
-#define DMI_SBDATA3_DATA (0xffffffff << DMI_SBDATA3_DATA_OFFSET)
-#define SERINFO 0x280
-/*
-* Like \Fserialzero.
- */
-#define SERINFO_SERIAL7_OFFSET 7
-#define SERINFO_SERIAL7_LENGTH 1
-#define SERINFO_SERIAL7 (0x1 << SERINFO_SERIAL7_OFFSET)
-/*
-* Like \Fserialzero.
- */
-#define SERINFO_SERIAL6_OFFSET 6
-#define SERINFO_SERIAL6_LENGTH 1
-#define SERINFO_SERIAL6 (0x1 << SERINFO_SERIAL6_OFFSET)
-/*
-* Like \Fserialzero.
- */
-#define SERINFO_SERIAL5_OFFSET 5
-#define SERINFO_SERIAL5_LENGTH 1
-#define SERINFO_SERIAL5 (0x1 << SERINFO_SERIAL5_OFFSET)
-/*
-* Like \Fserialzero.
- */
-#define SERINFO_SERIAL4_OFFSET 4
-#define SERINFO_SERIAL4_LENGTH 1
-#define SERINFO_SERIAL4 (0x1 << SERINFO_SERIAL4_OFFSET)
-/*
-* Like \Fserialzero.
- */
-#define SERINFO_SERIAL3_OFFSET 3
-#define SERINFO_SERIAL3_LENGTH 1
-#define SERINFO_SERIAL3 (0x1 << SERINFO_SERIAL3_OFFSET)
-/*
-* Like \Fserialzero.
- */
-#define SERINFO_SERIAL2_OFFSET 2
-#define SERINFO_SERIAL2_LENGTH 1
-#define SERINFO_SERIAL2 (0x1 << SERINFO_SERIAL2_OFFSET)
-/*
-* Like \Fserialzero.
- */
-#define SERINFO_SERIAL1_OFFSET 1
-#define SERINFO_SERIAL1_LENGTH 1
-#define SERINFO_SERIAL1 (0x1 << SERINFO_SERIAL1_OFFSET)
-/*
-* 1 means serial interface 0 is supported.
- */
-#define SERINFO_SERIAL0_OFFSET 0
-#define SERINFO_SERIAL0_LENGTH 1
-#define SERINFO_SERIAL0 (0x1 << SERINFO_SERIAL0_OFFSET)
-#define SERSEND0 0x200
-#define SERRECV0 0x204
-#define SERSTAT0 0x208
-/*
-* Send ready. 1 when the core-to-debugger queue is not full. 0
-* otherwise.
- */
-#define SERSTAT0_SENDR_OFFSET 1
-#define SERSTAT0_SENDR_LENGTH 1
-#define SERSTAT0_SENDR (0x1 << SERSTAT0_SENDR_OFFSET)
-/*
-* Receive ready. 1 when the debugger-to-core queue is not empty. 0
-* otherwise.
- */
-#define SERSTAT0_RECVR_OFFSET 0
-#define SERSTAT0_RECVR_LENGTH 1
-#define SERSTAT0_RECVR (0x1 << SERSTAT0_RECVR_OFFSET)
-#define SERSEND1 0x210
-#define SERRECV1 0x214
-#define SERSTAT1 0x218
-#define SERSEND2 0x220
-#define SERRECV2 0x224
-#define SERSTAT2 0x228
-#define SERSEND3 0x230
-#define SERRECV3 0x234
-#define SERSTAT3 0x238
-#define SERSEND4 0x240
-#define SERRECV4 0x244
-#define SERSTAT4 0x248
-#define SERSEND5 0x250
-#define SERRECV5 0x254
-#define SERSTAT5 0x258
-#define SERSEND6 0x260
-#define SERRECV6 0x264
-#define SERSTAT6 0x268
-#define SERSEND7 0x274
-#define SERRECV7 0x278
-#define SERSTAT7 0x27c
-#define TRACE 0x728
-/*
-* 1 if the trace buffer has wrapped since the last time \Fdiscard was
-* written. 0 otherwise.
- */
-#define TRACE_WRAPPED_OFFSET 24
-#define TRACE_WRAPPED_LENGTH 1
-#define TRACE_WRAPPED (0x1 << TRACE_WRAPPED_OFFSET)
-/*
-* Emit Timestamp trace sequences.
- */
-#define TRACE_EMITTIMESTAMP_OFFSET 23
-#define TRACE_EMITTIMESTAMP_LENGTH 1
-#define TRACE_EMITTIMESTAMP (0x1 << TRACE_EMITTIMESTAMP_OFFSET)
-/*
-* Emit Store Data trace sequences.
- */
-#define TRACE_EMITSTOREDATA_OFFSET 22
-#define TRACE_EMITSTOREDATA_LENGTH 1
-#define TRACE_EMITSTOREDATA (0x1 << TRACE_EMITSTOREDATA_OFFSET)
-/*
-* Emit Load Data trace sequences.
- */
-#define TRACE_EMITLOADDATA_OFFSET 21
-#define TRACE_EMITLOADDATA_LENGTH 1
-#define TRACE_EMITLOADDATA (0x1 << TRACE_EMITLOADDATA_OFFSET)
-/*
-* Emit Store Address trace sequences.
- */
-#define TRACE_EMITSTOREADDR_OFFSET 20
-#define TRACE_EMITSTOREADDR_LENGTH 1
-#define TRACE_EMITSTOREADDR (0x1 << TRACE_EMITSTOREADDR_OFFSET)
-/*
-* Emit Load Address trace sequences.
- */
-#define TRACE_EMITLOADADDR_OFFSET 19
-#define TRACE_EMITLOADADDR_LENGTH 1
-#define TRACE_EMITLOADADDR (0x1 << TRACE_EMITLOADADDR_OFFSET)
-/*
-* Emit Privilege Level trace sequences.
- */
-#define TRACE_EMITPRIV_OFFSET 18
-#define TRACE_EMITPRIV_LENGTH 1
-#define TRACE_EMITPRIV (0x1 << TRACE_EMITPRIV_OFFSET)
-/*
-* Emit Branch Taken and Branch Not Taken trace sequences.
- */
-#define TRACE_EMITBRANCH_OFFSET 17
-#define TRACE_EMITBRANCH_LENGTH 1
-#define TRACE_EMITBRANCH (0x1 << TRACE_EMITBRANCH_OFFSET)
-/*
-* Emit PC trace sequences.
- */
-#define TRACE_EMITPC_OFFSET 16
-#define TRACE_EMITPC_LENGTH 1
-#define TRACE_EMITPC (0x1 << TRACE_EMITPC_OFFSET)
-/*
-* Determine what happens when the trace buffer is full. 0 means wrap
-* and overwrite. 1 means turn off trace until \Fdiscard is written as 1.
-* 2 means cause a trace full exception. 3 is reserved for future use.
- */
-#define TRACE_FULLACTION_OFFSET 8
-#define TRACE_FULLACTION_LENGTH 2
-#define TRACE_FULLACTION (0x3 << TRACE_FULLACTION_OFFSET)
-/*
-* 0: Trace to a dedicated on-core RAM (which is not further defined in
-* this spec).
-*
-* 1: Trace to RAM on the system bus.
-*
-* 2: Send trace data to a dedicated off-chip interface (which is not
-* defined in this spec). This does not affect execution speed.
-*
-* 3: Reserved for future use.
-*
-* Options 0 and 1 slow down execution (eg. because of system bus
-* contention).
- */
-#define TRACE_DESTINATION_OFFSET 4
-#define TRACE_DESTINATION_LENGTH 2
-#define TRACE_DESTINATION (0x3 << TRACE_DESTINATION_OFFSET)
-/*
-* When 1, the trace logic may stall processor execution to ensure it
-* can emit all the trace sequences required. When 0 individual trace
-* sequences may be dropped.
- */
-#define TRACE_STALL_OFFSET 2
-#define TRACE_STALL_LENGTH 1
-#define TRACE_STALL (0x1 << TRACE_STALL_OFFSET)
-/*
-* Writing 1 to this bit tells the trace logic that any trace
-* collected is no longer required. When tracing to RAM, it resets the
-* trace write pointer to the start of the memory, as well as
-* \Fwrapped.
- */
-#define TRACE_DISCARD_OFFSET 1
-#define TRACE_DISCARD_LENGTH 1
-#define TRACE_DISCARD (0x1 << TRACE_DISCARD_OFFSET)
-#define TRACE_SUPPORTED_OFFSET 0
-#define TRACE_SUPPORTED_LENGTH 1
-#define TRACE_SUPPORTED (0x1 << TRACE_SUPPORTED_OFFSET)
-#define TBUFSTART 0x729
-#define TBUFEND 0x72a
-#define TBUFWRITE 0x72b
-#define SHORTNAME 0x123
-/*
-* Description of what this field is used for.
- */
-#define SHORTNAME_FIELD_OFFSET 0
-#define SHORTNAME_FIELD_LENGTH 8
-#define SHORTNAME_FIELD (0xff << SHORTNAME_FIELD_OFFSET)
-#define AC_ACCESS_REGISTER None
-/*
-* This is 0 to indicate Access Register Command.
- */
-#define AC_ACCESS_REGISTER_CMDTYPE_OFFSET 24
-#define AC_ACCESS_REGISTER_CMDTYPE_LENGTH 8
-#define AC_ACCESS_REGISTER_CMDTYPE (0xff << AC_ACCESS_REGISTER_CMDTYPE_OFFSET)
-/*
-* 2: Access the lowest 32 bits of the register.
-*
-* 3: Access the lowest 64 bits of the register.
-*
-* 4: Access the lowest 128 bits of the register.
-*
-* If \Fsize specifies a size larger than the register's actual size,
-* then the access must fail. If a register is accessible, then reads of \Fsize
-* less than or equal to the register's actual size must be supported.
- */
-#define AC_ACCESS_REGISTER_SIZE_OFFSET 20
-#define AC_ACCESS_REGISTER_SIZE_LENGTH 3
-#define AC_ACCESS_REGISTER_SIZE (0x7 << AC_ACCESS_REGISTER_SIZE_OFFSET)
-/*
-* When 1, execute the program in the Program Buffer exactly once
-* before performing the transfer.
-* \textbf{WARNING: preexec is considered for removal.}
- */
-#define AC_ACCESS_REGISTER_PREEXEC_OFFSET 19
-#define AC_ACCESS_REGISTER_PREEXEC_LENGTH 1
-#define AC_ACCESS_REGISTER_PREEXEC (0x1 << AC_ACCESS_REGISTER_PREEXEC_OFFSET)
-/*
-* When 1, execute the program in the Program Buffer exactly once
-* after performing the transfer, if any.
- */
-#define AC_ACCESS_REGISTER_POSTEXEC_OFFSET 18
-#define AC_ACCESS_REGISTER_POSTEXEC_LENGTH 1
-#define AC_ACCESS_REGISTER_POSTEXEC (0x1 << AC_ACCESS_REGISTER_POSTEXEC_OFFSET)
-/*
-* 0: Don't do the operation specified by \Fwrite.
-*
-* 1: Do the operation specified by \Fwrite.
- */
-#define AC_ACCESS_REGISTER_TRANSFER_OFFSET 17
-#define AC_ACCESS_REGISTER_TRANSFER_LENGTH 1
-#define AC_ACCESS_REGISTER_TRANSFER (0x1 << AC_ACCESS_REGISTER_TRANSFER_OFFSET)
-/*
-* When \Ftransfer is set:
-* 0: Copy data from the specified register into {\tt arg0} portion
-* of {\tt data}.
-*
-* 1: Copy data from {\tt arg0} portion of {\tt data} into the
-* specified register.
- */
-#define AC_ACCESS_REGISTER_WRITE_OFFSET 16
-#define AC_ACCESS_REGISTER_WRITE_LENGTH 1
-#define AC_ACCESS_REGISTER_WRITE (0x1 << AC_ACCESS_REGISTER_WRITE_OFFSET)
-/*
-* Number of the register to access, as described in Table~\ref{tab:regno}.
- */
-#define AC_ACCESS_REGISTER_REGNO_OFFSET 0
-#define AC_ACCESS_REGISTER_REGNO_LENGTH 16
-#define AC_ACCESS_REGISTER_REGNO (0xffff << AC_ACCESS_REGISTER_REGNO_OFFSET)
-#define AC_QUICK_ACCESS None
-/*
-* This is 1 to indicate Quick Access command.
- */
-#define AC_QUICK_ACCESS_CMDTYPE_OFFSET 24
-#define AC_QUICK_ACCESS_CMDTYPE_LENGTH 8
-#define AC_QUICK_ACCESS_CMDTYPE (0xff << AC_QUICK_ACCESS_CMDTYPE_OFFSET)
diff --git a/src/target/riscv/encoding.h b/src/target/riscv/encoding.h
deleted file mode 100644
index 35e0f9f..0000000
--- a/src/target/riscv/encoding.h
+++ /dev/null
@@ -1,1313 +0,0 @@
-// See LICENSE for license details.
-
-#ifndef RISCV_CSR_ENCODING_H
-#define RISCV_CSR_ENCODING_H
-
-#define MSTATUS_UIE 0x00000001
-#define MSTATUS_SIE 0x00000002
-#define MSTATUS_HIE 0x00000004
-#define MSTATUS_MIE 0x00000008
-#define MSTATUS_UPIE 0x00000010
-#define MSTATUS_SPIE 0x00000020
-#define MSTATUS_HPIE 0x00000040
-#define MSTATUS_MPIE 0x00000080
-#define MSTATUS_SPP 0x00000100
-#define MSTATUS_HPP 0x00000600
-#define MSTATUS_MPP 0x00001800
-#define MSTATUS_FS 0x00006000
-#define MSTATUS_XS 0x00018000
-#define MSTATUS_MPRV 0x00020000
-#define MSTATUS_PUM 0x00040000
-#define MSTATUS_MXR 0x00080000
-#define MSTATUS_VM 0x1F000000
-#define MSTATUS32_SD 0x80000000
-#define MSTATUS64_SD 0x8000000000000000
-
-#define SSTATUS_UIE 0x00000001
-#define SSTATUS_SIE 0x00000002
-#define SSTATUS_UPIE 0x00000010
-#define SSTATUS_SPIE 0x00000020
-#define SSTATUS_SPP 0x00000100
-#define SSTATUS_FS 0x00006000
-#define SSTATUS_XS 0x00018000
-#define SSTATUS_PUM 0x00040000
-#define SSTATUS32_SD 0x80000000
-#define SSTATUS64_SD 0x8000000000000000
-
-#define DCSR_XDEBUGVER (3U<<30)
-#define DCSR_NDRESET (1<<29)
-#define DCSR_FULLRESET (1<<28)
-#define DCSR_EBREAKM (1<<15)
-#define DCSR_EBREAKH (1<<14)
-#define DCSR_EBREAKS (1<<13)
-#define DCSR_EBREAKU (1<<12)
-#define DCSR_STOPCYCLE (1<<10)
-#define DCSR_STOPTIME (1<<9)
-#define DCSR_CAUSE (7<<6)
-#define DCSR_DEBUGINT (1<<5)
-#define DCSR_HALT (1<<3)
-#define DCSR_STEP (1<<2)
-#define DCSR_PRV (3<<0)
-
-#define DCSR_CAUSE_NONE 0
-#define DCSR_CAUSE_SWBP 1
-#define DCSR_CAUSE_HWBP 2
-#define DCSR_CAUSE_DEBUGINT 3
-#define DCSR_CAUSE_STEP 4
-#define DCSR_CAUSE_HALT 5
-
-#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
-#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
-#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
-
-#define MCONTROL_SELECT (1<<19)
-#define MCONTROL_TIMING (1<<18)
-#define MCONTROL_ACTION (0x3f<<12)
-#define MCONTROL_CHAIN (1<<11)
-#define MCONTROL_MATCH (0xf<<7)
-#define MCONTROL_M (1<<6)
-#define MCONTROL_H (1<<5)
-#define MCONTROL_S (1<<4)
-#define MCONTROL_U (1<<3)
-#define MCONTROL_EXECUTE (1<<2)
-#define MCONTROL_STORE (1<<1)
-#define MCONTROL_LOAD (1<<0)
-
-#define MCONTROL_TYPE_NONE 0
-#define MCONTROL_TYPE_MATCH 2
-
-#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
-#define MCONTROL_ACTION_DEBUG_MODE 1
-#define MCONTROL_ACTION_TRACE_START 2
-#define MCONTROL_ACTION_TRACE_STOP 3
-#define MCONTROL_ACTION_TRACE_EMIT 4
-
-#define MCONTROL_MATCH_EQUAL 0
-#define MCONTROL_MATCH_NAPOT 1
-#define MCONTROL_MATCH_GE 2
-#define MCONTROL_MATCH_LT 3
-#define MCONTROL_MATCH_MASK_LOW 4
-#define MCONTROL_MATCH_MASK_HIGH 5
-
-#define MIP_SSIP (1 << IRQ_S_SOFT)
-#define MIP_HSIP (1 << IRQ_H_SOFT)
-#define MIP_MSIP (1 << IRQ_M_SOFT)
-#define MIP_STIP (1 << IRQ_S_TIMER)
-#define MIP_HTIP (1 << IRQ_H_TIMER)
-#define MIP_MTIP (1 << IRQ_M_TIMER)
-#define MIP_SEIP (1 << IRQ_S_EXT)
-#define MIP_HEIP (1 << IRQ_H_EXT)
-#define MIP_MEIP (1 << IRQ_M_EXT)
-
-#define SIP_SSIP MIP_SSIP
-#define SIP_STIP MIP_STIP
-
-#define PRV_U 0
-#define PRV_S 1
-#define PRV_H 2
-#define PRV_M 3
-
-#define VM_MBARE 0
-#define VM_MBB 1
-#define VM_MBBID 2
-#define VM_SV32 8
-#define VM_SV39 9
-#define VM_SV48 10
-
-#define IRQ_S_SOFT 1
-#define IRQ_H_SOFT 2
-#define IRQ_M_SOFT 3
-#define IRQ_S_TIMER 5
-#define IRQ_H_TIMER 6
-#define IRQ_M_TIMER 7
-#define IRQ_S_EXT 9
-#define IRQ_H_EXT 10
-#define IRQ_M_EXT 11
-#define IRQ_COP 12
-#define IRQ_HOST 13
-
-#define DEFAULT_RSTVEC 0x00001000
-#define DEFAULT_NMIVEC 0x00001004
-#define DEFAULT_MTVEC 0x00001010
-#define CONFIG_STRING_ADDR 0x0000100C
-#define EXT_IO_BASE 0x40000000
-#define DRAM_BASE 0x80000000
-
-// page table entry (PTE) fields
-#define PTE_V 0x001 // Valid
-#define PTE_R 0x002 // Read
-#define PTE_W 0x004 // Write
-#define PTE_X 0x008 // Execute
-#define PTE_U 0x010 // User
-#define PTE_G 0x020 // Global
-#define PTE_A 0x040 // Accessed
-#define PTE_D 0x080 // Dirty
-#define PTE_SOFT 0x300 // Reserved for Software
-
-#define PTE_PPN_SHIFT 10
-
-#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
-
-#ifdef __riscv
-
-#ifdef __riscv64
-# define MSTATUS_SD MSTATUS64_SD
-# define SSTATUS_SD SSTATUS64_SD
-# define RISCV_PGLEVEL_BITS 9
-#else
-# define MSTATUS_SD MSTATUS32_SD
-# define SSTATUS_SD SSTATUS32_SD
-# define RISCV_PGLEVEL_BITS 10
-#endif
-#define RISCV_PGSHIFT 12
-#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
-
-#ifndef __ASSEMBLER__
-
-#ifdef __GNUC__
-
-#define read_csr(reg) ({ unsigned long __tmp; \
- asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
- __tmp; })
-
-#define write_csr(reg, val) ({ \
- if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
- asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
- else \
- asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
-
-#define swap_csr(reg, val) ({ unsigned long __tmp; \
- if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
- asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \
- else \
- asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
- __tmp; })
-
-#define set_csr(reg, bit) ({ unsigned long __tmp; \
- if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
- asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
- else \
- asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
- __tmp; })
-
-#define clear_csr(reg, bit) ({ unsigned long __tmp; \
- if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
- asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
- else \
- asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
- __tmp; })
-
-#define rdtime() read_csr(time)
-#define rdcycle() read_csr(cycle)
-#define rdinstret() read_csr(instret)
-
-#endif
-
-#endif
-
-#endif
-
-#endif
-/* Automatically generated by parse-opcodes */
-#ifndef RISCV_ENCODING_H
-#define RISCV_ENCODING_H
-#define MATCH_BEQ 0x63
-#define MASK_BEQ 0x707f
-#define MATCH_BNE 0x1063
-#define MASK_BNE 0x707f
-#define MATCH_BLT 0x4063
-#define MASK_BLT 0x707f
-#define MATCH_BGE 0x5063
-#define MASK_BGE 0x707f
-#define MATCH_BLTU 0x6063
-#define MASK_BLTU 0x707f
-#define MATCH_BGEU 0x7063
-#define MASK_BGEU 0x707f
-#define MATCH_JALR 0x67
-#define MASK_JALR 0x707f
-#define MATCH_JAL 0x6f
-#define MASK_JAL 0x7f
-#define MATCH_LUI 0x37
-#define MASK_LUI 0x7f
-#define MATCH_AUIPC 0x17
-#define MASK_AUIPC 0x7f
-#define MATCH_ADDI 0x13
-#define MASK_ADDI 0x707f
-#define MATCH_SLLI 0x1013
-#define MASK_SLLI 0xfc00707f
-#define MATCH_SLTI 0x2013
-#define MASK_SLTI 0x707f
-#define MATCH_SLTIU 0x3013
-#define MASK_SLTIU 0x707f
-#define MATCH_XORI 0x4013
-#define MASK_XORI 0x707f
-#define MATCH_SRLI 0x5013
-#define MASK_SRLI 0xfc00707f
-#define MATCH_SRAI 0x40005013
-#define MASK_SRAI 0xfc00707f
-#define MATCH_ORI 0x6013
-#define MASK_ORI 0x707f
-#define MATCH_ANDI 0x7013
-#define MASK_ANDI 0x707f
-#define MATCH_ADD 0x33
-#define MASK_ADD 0xfe00707f
-#define MATCH_SUB 0x40000033
-#define MASK_SUB 0xfe00707f
-#define MATCH_SLL 0x1033
-#define MASK_SLL 0xfe00707f
-#define MATCH_SLT 0x2033
-#define MASK_SLT 0xfe00707f
-#define MATCH_SLTU 0x3033
-#define MASK_SLTU 0xfe00707f
-#define MATCH_XOR 0x4033
-#define MASK_XOR 0xfe00707f
-#define MATCH_SRL 0x5033
-#define MASK_SRL 0xfe00707f
-#define MATCH_SRA 0x40005033
-#define MASK_SRA 0xfe00707f
-#define MATCH_OR 0x6033
-#define MASK_OR 0xfe00707f
-#define MATCH_AND 0x7033
-#define MASK_AND 0xfe00707f
-#define MATCH_ADDIW 0x1b
-#define MASK_ADDIW 0x707f
-#define MATCH_SLLIW 0x101b
-#define MASK_SLLIW 0xfe00707f
-#define MATCH_SRLIW 0x501b
-#define MASK_SRLIW 0xfe00707f
-#define MATCH_SRAIW 0x4000501b
-#define MASK_SRAIW 0xfe00707f
-#define MATCH_ADDW 0x3b
-#define MASK_ADDW 0xfe00707f
-#define MATCH_SUBW 0x4000003b
-#define MASK_SUBW 0xfe00707f
-#define MATCH_SLLW 0x103b
-#define MASK_SLLW 0xfe00707f
-#define MATCH_SRLW 0x503b
-#define MASK_SRLW 0xfe00707f
-#define MATCH_SRAW 0x4000503b
-#define MASK_SRAW 0xfe00707f
-#define MATCH_LB 0x3
-#define MASK_LB 0x707f
-#define MATCH_LH 0x1003
-#define MASK_LH 0x707f
-#define MATCH_LW 0x2003
-#define MASK_LW 0x707f
-#define MATCH_LD 0x3003
-#define MASK_LD 0x707f
-#define MATCH_LBU 0x4003
-#define MASK_LBU 0x707f
-#define MATCH_LHU 0x5003
-#define MASK_LHU 0x707f
-#define MATCH_LWU 0x6003
-#define MASK_LWU 0x707f
-#define MATCH_SB 0x23
-#define MASK_SB 0x707f
-#define MATCH_SH 0x1023
-#define MASK_SH 0x707f
-#define MATCH_SW 0x2023
-#define MASK_SW 0x707f
-#define MATCH_SD 0x3023
-#define MASK_SD 0x707f
-#define MATCH_FENCE 0xf
-#define MASK_FENCE 0x707f
-#define MATCH_FENCE_I 0x100f
-#define MASK_FENCE_I 0x707f
-#define MATCH_MUL 0x2000033
-#define MASK_MUL 0xfe00707f
-#define MATCH_MULH 0x2001033
-#define MASK_MULH 0xfe00707f
-#define MATCH_MULHSU 0x2002033
-#define MASK_MULHSU 0xfe00707f
-#define MATCH_MULHU 0x2003033
-#define MASK_MULHU 0xfe00707f
-#define MATCH_DIV 0x2004033
-#define MASK_DIV 0xfe00707f
-#define MATCH_DIVU 0x2005033
-#define MASK_DIVU 0xfe00707f
-#define MATCH_REM 0x2006033
-#define MASK_REM 0xfe00707f
-#define MATCH_REMU 0x2007033
-#define MASK_REMU 0xfe00707f
-#define MATCH_MULW 0x200003b
-#define MASK_MULW 0xfe00707f
-#define MATCH_DIVW 0x200403b
-#define MASK_DIVW 0xfe00707f
-#define MATCH_DIVUW 0x200503b
-#define MASK_DIVUW 0xfe00707f
-#define MATCH_REMW 0x200603b
-#define MASK_REMW 0xfe00707f
-#define MATCH_REMUW 0x200703b
-#define MASK_REMUW 0xfe00707f
-#define MATCH_AMOADD_W 0x202f
-#define MASK_AMOADD_W 0xf800707f
-#define MATCH_AMOXOR_W 0x2000202f
-#define MASK_AMOXOR_W 0xf800707f
-#define MATCH_AMOOR_W 0x4000202f
-#define MASK_AMOOR_W 0xf800707f
-#define MATCH_AMOAND_W 0x6000202f
-#define MASK_AMOAND_W 0xf800707f
-#define MATCH_AMOMIN_W 0x8000202f
-#define MASK_AMOMIN_W 0xf800707f
-#define MATCH_AMOMAX_W 0xa000202f
-#define MASK_AMOMAX_W 0xf800707f
-#define MATCH_AMOMINU_W 0xc000202f
-#define MASK_AMOMINU_W 0xf800707f
-#define MATCH_AMOMAXU_W 0xe000202f
-#define MASK_AMOMAXU_W 0xf800707f
-#define MATCH_AMOSWAP_W 0x800202f
-#define MASK_AMOSWAP_W 0xf800707f
-#define MATCH_LR_W 0x1000202f
-#define MASK_LR_W 0xf9f0707f
-#define MATCH_SC_W 0x1800202f
-#define MASK_SC_W 0xf800707f
-#define MATCH_AMOADD_D 0x302f
-#define MASK_AMOADD_D 0xf800707f
-#define MATCH_AMOXOR_D 0x2000302f
-#define MASK_AMOXOR_D 0xf800707f
-#define MATCH_AMOOR_D 0x4000302f
-#define MASK_AMOOR_D 0xf800707f
-#define MATCH_AMOAND_D 0x6000302f
-#define MASK_AMOAND_D 0xf800707f
-#define MATCH_AMOMIN_D 0x8000302f
-#define MASK_AMOMIN_D 0xf800707f
-#define MATCH_AMOMAX_D 0xa000302f
-#define MASK_AMOMAX_D 0xf800707f
-#define MATCH_AMOMINU_D 0xc000302f
-#define MASK_AMOMINU_D 0xf800707f
-#define MATCH_AMOMAXU_D 0xe000302f
-#define MASK_AMOMAXU_D 0xf800707f
-#define MATCH_AMOSWAP_D 0x800302f
-#define MASK_AMOSWAP_D 0xf800707f
-#define MATCH_LR_D 0x1000302f
-#define MASK_LR_D 0xf9f0707f
-#define MATCH_SC_D 0x1800302f
-#define MASK_SC_D 0xf800707f
-#define MATCH_ECALL 0x73
-#define MASK_ECALL 0xffffffff
-#define MATCH_EBREAK 0x100073
-#define MASK_EBREAK 0xffffffff
-#define MATCH_URET 0x200073
-#define MASK_URET 0xffffffff
-#define MATCH_SRET 0x10200073
-#define MASK_SRET 0xffffffff
-#define MATCH_HRET 0x20200073
-#define MASK_HRET 0xffffffff
-#define MATCH_MRET 0x30200073
-#define MASK_MRET 0xffffffff
-#define MATCH_DRET 0x7b200073
-#define MASK_DRET 0xffffffff
-#define MATCH_SFENCE_VM 0x10400073
-#define MASK_SFENCE_VM 0xfff07fff
-#define MATCH_WFI 0x10500073
-#define MASK_WFI 0xffffffff
-#define MATCH_CSRRW 0x1073
-#define MASK_CSRRW 0x707f
-#define MATCH_CSRRS 0x2073
-#define MASK_CSRRS 0x707f
-#define MATCH_CSRRC 0x3073
-#define MASK_CSRRC 0x707f
-#define MATCH_CSRRWI 0x5073
-#define MASK_CSRRWI 0x707f
-#define MATCH_CSRRSI 0x6073
-#define MASK_CSRRSI 0x707f
-#define MATCH_CSRRCI 0x7073
-#define MASK_CSRRCI 0x707f
-#define MATCH_FADD_S 0x53
-#define MASK_FADD_S 0xfe00007f
-#define MATCH_FSUB_S 0x8000053
-#define MASK_FSUB_S 0xfe00007f
-#define MATCH_FMUL_S 0x10000053
-#define MASK_FMUL_S 0xfe00007f
-#define MATCH_FDIV_S 0x18000053
-#define MASK_FDIV_S 0xfe00007f
-#define MATCH_FSGNJ_S 0x20000053
-#define MASK_FSGNJ_S 0xfe00707f
-#define MATCH_FSGNJN_S 0x20001053
-#define MASK_FSGNJN_S 0xfe00707f
-#define MATCH_FSGNJX_S 0x20002053
-#define MASK_FSGNJX_S 0xfe00707f
-#define MATCH_FMIN_S 0x28000053
-#define MASK_FMIN_S 0xfe00707f
-#define MATCH_FMAX_S 0x28001053
-#define MASK_FMAX_S 0xfe00707f
-#define MATCH_FSQRT_S 0x58000053
-#define MASK_FSQRT_S 0xfff0007f
-#define MATCH_FADD_D 0x2000053
-#define MASK_FADD_D 0xfe00007f
-#define MATCH_FSUB_D 0xa000053
-#define MASK_FSUB_D 0xfe00007f
-#define MATCH_FMUL_D 0x12000053
-#define MASK_FMUL_D 0xfe00007f
-#define MATCH_FDIV_D 0x1a000053
-#define MASK_FDIV_D 0xfe00007f
-#define MATCH_FSGNJ_D 0x22000053
-#define MASK_FSGNJ_D 0xfe00707f
-#define MATCH_FSGNJN_D 0x22001053
-#define MASK_FSGNJN_D 0xfe00707f
-#define MATCH_FSGNJX_D 0x22002053
-#define MASK_FSGNJX_D 0xfe00707f
-#define MATCH_FMIN_D 0x2a000053
-#define MASK_FMIN_D 0xfe00707f
-#define MATCH_FMAX_D 0x2a001053
-#define MASK_FMAX_D 0xfe00707f
-#define MATCH_FCVT_S_D 0x40100053
-#define MASK_FCVT_S_D 0xfff0007f
-#define MATCH_FCVT_D_S 0x42000053
-#define MASK_FCVT_D_S 0xfff0007f
-#define MATCH_FSQRT_D 0x5a000053
-#define MASK_FSQRT_D 0xfff0007f
-#define MATCH_FLE_S 0xa0000053
-#define MASK_FLE_S 0xfe00707f
-#define MATCH_FLT_S 0xa0001053
-#define MASK_FLT_S 0xfe00707f
-#define MATCH_FEQ_S 0xa0002053
-#define MASK_FEQ_S 0xfe00707f
-#define MATCH_FLE_D 0xa2000053
-#define MASK_FLE_D 0xfe00707f
-#define MATCH_FLT_D 0xa2001053
-#define MASK_FLT_D 0xfe00707f
-#define MATCH_FEQ_D 0xa2002053
-#define MASK_FEQ_D 0xfe00707f
-#define MATCH_FCVT_W_S 0xc0000053
-#define MASK_FCVT_W_S 0xfff0007f
-#define MATCH_FCVT_WU_S 0xc0100053
-#define MASK_FCVT_WU_S 0xfff0007f
-#define MATCH_FCVT_L_S 0xc0200053
-#define MASK_FCVT_L_S 0xfff0007f
-#define MATCH_FCVT_LU_S 0xc0300053
-#define MASK_FCVT_LU_S 0xfff0007f
-#define MATCH_FMV_X_S 0xe0000053
-#define MASK_FMV_X_S 0xfff0707f
-#define MATCH_FCLASS_S 0xe0001053
-#define MASK_FCLASS_S 0xfff0707f
-#define MATCH_FCVT_W_D 0xc2000053
-#define MASK_FCVT_W_D 0xfff0007f
-#define MATCH_FCVT_WU_D 0xc2100053
-#define MASK_FCVT_WU_D 0xfff0007f
-#define MATCH_FCVT_L_D 0xc2200053
-#define MASK_FCVT_L_D 0xfff0007f
-#define MATCH_FCVT_LU_D 0xc2300053
-#define MASK_FCVT_LU_D 0xfff0007f
-#define MATCH_FMV_X_D 0xe2000053
-#define MASK_FMV_X_D 0xfff0707f
-#define MATCH_FCLASS_D 0xe2001053
-#define MASK_FCLASS_D 0xfff0707f
-#define MATCH_FCVT_S_W 0xd0000053
-#define MASK_FCVT_S_W 0xfff0007f
-#define MATCH_FCVT_S_WU 0xd0100053
-#define MASK_FCVT_S_WU 0xfff0007f
-#define MATCH_FCVT_S_L 0xd0200053
-#define MASK_FCVT_S_L 0xfff0007f
-#define MATCH_FCVT_S_LU 0xd0300053
-#define MASK_FCVT_S_LU 0xfff0007f
-#define MATCH_FMV_S_X 0xf0000053
-#define MASK_FMV_S_X 0xfff0707f
-#define MATCH_FCVT_D_W 0xd2000053
-#define MASK_FCVT_D_W 0xfff0007f
-#define MATCH_FCVT_D_WU 0xd2100053
-#define MASK_FCVT_D_WU 0xfff0007f
-#define MATCH_FCVT_D_L 0xd2200053
-#define MASK_FCVT_D_L 0xfff0007f
-#define MATCH_FCVT_D_LU 0xd2300053
-#define MASK_FCVT_D_LU 0xfff0007f
-#define MATCH_FMV_D_X 0xf2000053
-#define MASK_FMV_D_X 0xfff0707f
-#define MATCH_FLW 0x2007
-#define MASK_FLW 0x707f
-#define MATCH_FLD 0x3007
-#define MASK_FLD 0x707f
-#define MATCH_FSW 0x2027
-#define MASK_FSW 0x707f
-#define MATCH_FSD 0x3027
-#define MASK_FSD 0x707f
-#define MATCH_FMADD_S 0x43
-#define MASK_FMADD_S 0x600007f
-#define MATCH_FMSUB_S 0x47
-#define MASK_FMSUB_S 0x600007f
-#define MATCH_FNMSUB_S 0x4b
-#define MASK_FNMSUB_S 0x600007f
-#define MATCH_FNMADD_S 0x4f
-#define MASK_FNMADD_S 0x600007f
-#define MATCH_FMADD_D 0x2000043
-#define MASK_FMADD_D 0x600007f
-#define MATCH_FMSUB_D 0x2000047
-#define MASK_FMSUB_D 0x600007f
-#define MATCH_FNMSUB_D 0x200004b
-#define MASK_FNMSUB_D 0x600007f
-#define MATCH_FNMADD_D 0x200004f
-#define MASK_FNMADD_D 0x600007f
-#define MATCH_C_NOP 0x1
-#define MASK_C_NOP 0xffff
-#define MATCH_C_ADDI16SP 0x6101
-#define MASK_C_ADDI16SP 0xef83
-#define MATCH_C_JR 0x8002
-#define MASK_C_JR 0xf07f
-#define MATCH_C_JALR 0x9002
-#define MASK_C_JALR 0xf07f
-#define MATCH_C_EBREAK 0x9002
-#define MASK_C_EBREAK 0xffff
-#define MATCH_C_LD 0x6000
-#define MASK_C_LD 0xe003
-#define MATCH_C_SD 0xe000
-#define MASK_C_SD 0xe003
-#define MATCH_C_ADDIW 0x2001
-#define MASK_C_ADDIW 0xe003
-#define MATCH_C_LDSP 0x6002
-#define MASK_C_LDSP 0xe003
-#define MATCH_C_SDSP 0xe002
-#define MASK_C_SDSP 0xe003
-#define MATCH_C_ADDI4SPN 0x0
-#define MASK_C_ADDI4SPN 0xe003
-#define MATCH_C_FLD 0x2000
-#define MASK_C_FLD 0xe003
-#define MATCH_C_LW 0x4000
-#define MASK_C_LW 0xe003
-#define MATCH_C_FLW 0x6000
-#define MASK_C_FLW 0xe003
-#define MATCH_C_FSD 0xa000
-#define MASK_C_FSD 0xe003
-#define MATCH_C_SW 0xc000
-#define MASK_C_SW 0xe003
-#define MATCH_C_FSW 0xe000
-#define MASK_C_FSW 0xe003
-#define MATCH_C_ADDI 0x1
-#define MASK_C_ADDI 0xe003
-#define MATCH_C_JAL 0x2001
-#define MASK_C_JAL 0xe003
-#define MATCH_C_LI 0x4001
-#define MASK_C_LI 0xe003
-#define MATCH_C_LUI 0x6001
-#define MASK_C_LUI 0xe003
-#define MATCH_C_SRLI 0x8001
-#define MASK_C_SRLI 0xec03
-#define MATCH_C_SRAI 0x8401
-#define MASK_C_SRAI 0xec03
-#define MATCH_C_ANDI 0x8801
-#define MASK_C_ANDI 0xec03
-#define MATCH_C_SUB 0x8c01
-#define MASK_C_SUB 0xfc63
-#define MATCH_C_XOR 0x8c21
-#define MASK_C_XOR 0xfc63
-#define MATCH_C_OR 0x8c41
-#define MASK_C_OR 0xfc63
-#define MATCH_C_AND 0x8c61
-#define MASK_C_AND 0xfc63
-#define MATCH_C_SUBW 0x9c01
-#define MASK_C_SUBW 0xfc63
-#define MATCH_C_ADDW 0x9c21
-#define MASK_C_ADDW 0xfc63
-#define MATCH_C_J 0xa001
-#define MASK_C_J 0xe003
-#define MATCH_C_BEQZ 0xc001
-#define MASK_C_BEQZ 0xe003
-#define MATCH_C_BNEZ 0xe001
-#define MASK_C_BNEZ 0xe003
-#define MATCH_C_SLLI 0x2
-#define MASK_C_SLLI 0xe003
-#define MATCH_C_FLDSP 0x2002
-#define MASK_C_FLDSP 0xe003
-#define MATCH_C_LWSP 0x4002
-#define MASK_C_LWSP 0xe003
-#define MATCH_C_FLWSP 0x6002
-#define MASK_C_FLWSP 0xe003
-#define MATCH_C_MV 0x8002
-#define MASK_C_MV 0xf003
-#define MATCH_C_ADD 0x9002
-#define MASK_C_ADD 0xf003
-#define MATCH_C_FSDSP 0xa002
-#define MASK_C_FSDSP 0xe003
-#define MATCH_C_SWSP 0xc002
-#define MASK_C_SWSP 0xe003
-#define MATCH_C_FSWSP 0xe002
-#define MASK_C_FSWSP 0xe003
-#define MATCH_CUSTOM0 0xb
-#define MASK_CUSTOM0 0x707f
-#define MATCH_CUSTOM0_RS1 0x200b
-#define MASK_CUSTOM0_RS1 0x707f
-#define MATCH_CUSTOM0_RS1_RS2 0x300b
-#define MASK_CUSTOM0_RS1_RS2 0x707f
-#define MATCH_CUSTOM0_RD 0x400b
-#define MASK_CUSTOM0_RD 0x707f
-#define MATCH_CUSTOM0_RD_RS1 0x600b
-#define MASK_CUSTOM0_RD_RS1 0x707f
-#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b
-#define MASK_CUSTOM0_RD_RS1_RS2 0x707f
-#define MATCH_CUSTOM1 0x2b
-#define MASK_CUSTOM1 0x707f
-#define MATCH_CUSTOM1_RS1 0x202b
-#define MASK_CUSTOM1_RS1 0x707f
-#define MATCH_CUSTOM1_RS1_RS2 0x302b
-#define MASK_CUSTOM1_RS1_RS2 0x707f
-#define MATCH_CUSTOM1_RD 0x402b
-#define MASK_CUSTOM1_RD 0x707f
-#define MATCH_CUSTOM1_RD_RS1 0x602b
-#define MASK_CUSTOM1_RD_RS1 0x707f
-#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b
-#define MASK_CUSTOM1_RD_RS1_RS2 0x707f
-#define MATCH_CUSTOM2 0x5b
-#define MASK_CUSTOM2 0x707f
-#define MATCH_CUSTOM2_RS1 0x205b
-#define MASK_CUSTOM2_RS1 0x707f
-#define MATCH_CUSTOM2_RS1_RS2 0x305b
-#define MASK_CUSTOM2_RS1_RS2 0x707f
-#define MATCH_CUSTOM2_RD 0x405b
-#define MASK_CUSTOM2_RD 0x707f
-#define MATCH_CUSTOM2_RD_RS1 0x605b
-#define MASK_CUSTOM2_RD_RS1 0x707f
-#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b
-#define MASK_CUSTOM2_RD_RS1_RS2 0x707f
-#define MATCH_CUSTOM3 0x7b
-#define MASK_CUSTOM3 0x707f
-#define MATCH_CUSTOM3_RS1 0x207b
-#define MASK_CUSTOM3_RS1 0x707f
-#define MATCH_CUSTOM3_RS1_RS2 0x307b
-#define MASK_CUSTOM3_RS1_RS2 0x707f
-#define MATCH_CUSTOM3_RD 0x407b
-#define MASK_CUSTOM3_RD 0x707f
-#define MATCH_CUSTOM3_RD_RS1 0x607b
-#define MASK_CUSTOM3_RD_RS1 0x707f
-#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b
-#define MASK_CUSTOM3_RD_RS1_RS2 0x707f
-#define CSR_FFLAGS 0x1
-#define CSR_FRM 0x2
-#define CSR_FCSR 0x3
-#define CSR_CYCLE 0xc00
-#define CSR_TIME 0xc01
-#define CSR_INSTRET 0xc02
-#define CSR_HPMCOUNTER3 0xc03
-#define CSR_HPMCOUNTER4 0xc04
-#define CSR_HPMCOUNTER5 0xc05
-#define CSR_HPMCOUNTER6 0xc06
-#define CSR_HPMCOUNTER7 0xc07
-#define CSR_HPMCOUNTER8 0xc08
-#define CSR_HPMCOUNTER9 0xc09
-#define CSR_HPMCOUNTER10 0xc0a
-#define CSR_HPMCOUNTER11 0xc0b
-#define CSR_HPMCOUNTER12 0xc0c
-#define CSR_HPMCOUNTER13 0xc0d
-#define CSR_HPMCOUNTER14 0xc0e
-#define CSR_HPMCOUNTER15 0xc0f
-#define CSR_HPMCOUNTER16 0xc10
-#define CSR_HPMCOUNTER17 0xc11
-#define CSR_HPMCOUNTER18 0xc12
-#define CSR_HPMCOUNTER19 0xc13
-#define CSR_HPMCOUNTER20 0xc14
-#define CSR_HPMCOUNTER21 0xc15
-#define CSR_HPMCOUNTER22 0xc16
-#define CSR_HPMCOUNTER23 0xc17
-#define CSR_HPMCOUNTER24 0xc18
-#define CSR_HPMCOUNTER25 0xc19
-#define CSR_HPMCOUNTER26 0xc1a
-#define CSR_HPMCOUNTER27 0xc1b
-#define CSR_HPMCOUNTER28 0xc1c
-#define CSR_HPMCOUNTER29 0xc1d
-#define CSR_HPMCOUNTER30 0xc1e
-#define CSR_HPMCOUNTER31 0xc1f
-#define CSR_SSTATUS 0x100
-#define CSR_SIE 0x104
-#define CSR_STVEC 0x105
-#define CSR_SSCRATCH 0x140
-#define CSR_SEPC 0x141
-#define CSR_SCAUSE 0x142
-#define CSR_SBADADDR 0x143
-#define CSR_SIP 0x144
-#define CSR_SPTBR 0x180
-#define CSR_MSTATUS 0x300
-#define CSR_MISA 0x301
-#define CSR_MEDELEG 0x302
-#define CSR_MIDELEG 0x303
-#define CSR_MIE 0x304
-#define CSR_MTVEC 0x305
-#define CSR_MSCRATCH 0x340
-#define CSR_MEPC 0x341
-#define CSR_MCAUSE 0x342
-#define CSR_MBADADDR 0x343
-#define CSR_MIP 0x344
-#define CSR_TSELECT 0x7a0
-#define CSR_TDATA1 0x7a1
-#define CSR_TDATA2 0x7a2
-#define CSR_TDATA3 0x7a3
-#define CSR_DCSR 0x7b0
-#define CSR_DPC 0x7b1
-#define CSR_DSCRATCH 0x7b2
-#define CSR_MCYCLE 0xb00
-#define CSR_MINSTRET 0xb02
-#define CSR_MHPMCOUNTER3 0xb03
-#define CSR_MHPMCOUNTER4 0xb04
-#define CSR_MHPMCOUNTER5 0xb05
-#define CSR_MHPMCOUNTER6 0xb06
-#define CSR_MHPMCOUNTER7 0xb07
-#define CSR_MHPMCOUNTER8 0xb08
-#define CSR_MHPMCOUNTER9 0xb09
-#define CSR_MHPMCOUNTER10 0xb0a
-#define CSR_MHPMCOUNTER11 0xb0b
-#define CSR_MHPMCOUNTER12 0xb0c
-#define CSR_MHPMCOUNTER13 0xb0d
-#define CSR_MHPMCOUNTER14 0xb0e
-#define CSR_MHPMCOUNTER15 0xb0f
-#define CSR_MHPMCOUNTER16 0xb10
-#define CSR_MHPMCOUNTER17 0xb11
-#define CSR_MHPMCOUNTER18 0xb12
-#define CSR_MHPMCOUNTER19 0xb13
-#define CSR_MHPMCOUNTER20 0xb14
-#define CSR_MHPMCOUNTER21 0xb15
-#define CSR_MHPMCOUNTER22 0xb16
-#define CSR_MHPMCOUNTER23 0xb17
-#define CSR_MHPMCOUNTER24 0xb18
-#define CSR_MHPMCOUNTER25 0xb19
-#define CSR_MHPMCOUNTER26 0xb1a
-#define CSR_MHPMCOUNTER27 0xb1b
-#define CSR_MHPMCOUNTER28 0xb1c
-#define CSR_MHPMCOUNTER29 0xb1d
-#define CSR_MHPMCOUNTER30 0xb1e
-#define CSR_MHPMCOUNTER31 0xb1f
-#define CSR_MUCOUNTEREN 0x320
-#define CSR_MSCOUNTEREN 0x321
-#define CSR_MHPMEVENT3 0x323
-#define CSR_MHPMEVENT4 0x324
-#define CSR_MHPMEVENT5 0x325
-#define CSR_MHPMEVENT6 0x326
-#define CSR_MHPMEVENT7 0x327
-#define CSR_MHPMEVENT8 0x328
-#define CSR_MHPMEVENT9 0x329
-#define CSR_MHPMEVENT10 0x32a
-#define CSR_MHPMEVENT11 0x32b
-#define CSR_MHPMEVENT12 0x32c
-#define CSR_MHPMEVENT13 0x32d
-#define CSR_MHPMEVENT14 0x32e
-#define CSR_MHPMEVENT15 0x32f
-#define CSR_MHPMEVENT16 0x330
-#define CSR_MHPMEVENT17 0x331
-#define CSR_MHPMEVENT18 0x332
-#define CSR_MHPMEVENT19 0x333
-#define CSR_MHPMEVENT20 0x334
-#define CSR_MHPMEVENT21 0x335
-#define CSR_MHPMEVENT22 0x336
-#define CSR_MHPMEVENT23 0x337
-#define CSR_MHPMEVENT24 0x338
-#define CSR_MHPMEVENT25 0x339
-#define CSR_MHPMEVENT26 0x33a
-#define CSR_MHPMEVENT27 0x33b
-#define CSR_MHPMEVENT28 0x33c
-#define CSR_MHPMEVENT29 0x33d
-#define CSR_MHPMEVENT30 0x33e
-#define CSR_MHPMEVENT31 0x33f
-#define CSR_MVENDORID 0xf11
-#define CSR_MARCHID 0xf12
-#define CSR_MIMPID 0xf13
-#define CSR_MHARTID 0xf14
-#define CSR_CYCLEH 0xc80
-#define CSR_TIMEH 0xc81
-#define CSR_INSTRETH 0xc82
-#define CSR_HPMCOUNTER3H 0xc83
-#define CSR_HPMCOUNTER4H 0xc84
-#define CSR_HPMCOUNTER5H 0xc85
-#define CSR_HPMCOUNTER6H 0xc86
-#define CSR_HPMCOUNTER7H 0xc87
-#define CSR_HPMCOUNTER8H 0xc88
-#define CSR_HPMCOUNTER9H 0xc89
-#define CSR_HPMCOUNTER10H 0xc8a
-#define CSR_HPMCOUNTER11H 0xc8b
-#define CSR_HPMCOUNTER12H 0xc8c
-#define CSR_HPMCOUNTER13H 0xc8d
-#define CSR_HPMCOUNTER14H 0xc8e
-#define CSR_HPMCOUNTER15H 0xc8f
-#define CSR_HPMCOUNTER16H 0xc90
-#define CSR_HPMCOUNTER17H 0xc91
-#define CSR_HPMCOUNTER18H 0xc92
-#define CSR_HPMCOUNTER19H 0xc93
-#define CSR_HPMCOUNTER20H 0xc94
-#define CSR_HPMCOUNTER21H 0xc95
-#define CSR_HPMCOUNTER22H 0xc96
-#define CSR_HPMCOUNTER23H 0xc97
-#define CSR_HPMCOUNTER24H 0xc98
-#define CSR_HPMCOUNTER25H 0xc99
-#define CSR_HPMCOUNTER26H 0xc9a
-#define CSR_HPMCOUNTER27H 0xc9b
-#define CSR_HPMCOUNTER28H 0xc9c
-#define CSR_HPMCOUNTER29H 0xc9d
-#define CSR_HPMCOUNTER30H 0xc9e
-#define CSR_HPMCOUNTER31H 0xc9f
-#define CSR_MCYCLEH 0xb80
-#define CSR_MINSTRETH 0xb82
-#define CSR_MHPMCOUNTER3H 0xb83
-#define CSR_MHPMCOUNTER4H 0xb84
-#define CSR_MHPMCOUNTER5H 0xb85
-#define CSR_MHPMCOUNTER6H 0xb86
-#define CSR_MHPMCOUNTER7H 0xb87
-#define CSR_MHPMCOUNTER8H 0xb88
-#define CSR_MHPMCOUNTER9H 0xb89
-#define CSR_MHPMCOUNTER10H 0xb8a
-#define CSR_MHPMCOUNTER11H 0xb8b
-#define CSR_MHPMCOUNTER12H 0xb8c
-#define CSR_MHPMCOUNTER13H 0xb8d
-#define CSR_MHPMCOUNTER14H 0xb8e
-#define CSR_MHPMCOUNTER15H 0xb8f
-#define CSR_MHPMCOUNTER16H 0xb90
-#define CSR_MHPMCOUNTER17H 0xb91
-#define CSR_MHPMCOUNTER18H 0xb92
-#define CSR_MHPMCOUNTER19H 0xb93
-#define CSR_MHPMCOUNTER20H 0xb94
-#define CSR_MHPMCOUNTER21H 0xb95
-#define CSR_MHPMCOUNTER22H 0xb96
-#define CSR_MHPMCOUNTER23H 0xb97
-#define CSR_MHPMCOUNTER24H 0xb98
-#define CSR_MHPMCOUNTER25H 0xb99
-#define CSR_MHPMCOUNTER26H 0xb9a
-#define CSR_MHPMCOUNTER27H 0xb9b
-#define CSR_MHPMCOUNTER28H 0xb9c
-#define CSR_MHPMCOUNTER29H 0xb9d
-#define CSR_MHPMCOUNTER30H 0xb9e
-#define CSR_MHPMCOUNTER31H 0xb9f
-#define CAUSE_MISALIGNED_FETCH 0x0
-#define CAUSE_FAULT_FETCH 0x1
-#define CAUSE_ILLEGAL_INSTRUCTION 0x2
-#define CAUSE_BREAKPOINT 0x3
-#define CAUSE_MISALIGNED_LOAD 0x4
-#define CAUSE_FAULT_LOAD 0x5
-#define CAUSE_MISALIGNED_STORE 0x6
-#define CAUSE_FAULT_STORE 0x7
-#define CAUSE_USER_ECALL 0x8
-#define CAUSE_SUPERVISOR_ECALL 0x9
-#define CAUSE_HYPERVISOR_ECALL 0xa
-#define CAUSE_MACHINE_ECALL 0xb
-#endif
-#ifdef DECLARE_INSN
-DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
-DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
-DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
-DECLARE_INSN(bge, MATCH_BGE, MASK_BGE)
-DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
-DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU)
-DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
-DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
-DECLARE_INSN(lui, MATCH_LUI, MASK_LUI)
-DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC)
-DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
-DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI)
-DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
-DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
-DECLARE_INSN(xori, MATCH_XORI, MASK_XORI)
-DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
-DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
-DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
-DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI)
-DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
-DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
-DECLARE_INSN(sll, MATCH_SLL, MASK_SLL)
-DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
-DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU)
-DECLARE_INSN(xor, MATCH_XOR, MASK_XOR)
-DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
-DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
-DECLARE_INSN(or, MATCH_OR, MASK_OR)
-DECLARE_INSN(and, MATCH_AND, MASK_AND)
-DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
-DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
-DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
-DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
-DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW)
-DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
-DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
-DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
-DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW)
-DECLARE_INSN(lb, MATCH_LB, MASK_LB)
-DECLARE_INSN(lh, MATCH_LH, MASK_LH)
-DECLARE_INSN(lw, MATCH_LW, MASK_LW)
-DECLARE_INSN(ld, MATCH_LD, MASK_LD)
-DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
-DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU)
-DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU)
-DECLARE_INSN(sb, MATCH_SB, MASK_SB)
-DECLARE_INSN(sh, MATCH_SH, MASK_SH)
-DECLARE_INSN(sw, MATCH_SW, MASK_SW)
-DECLARE_INSN(sd, MATCH_SD, MASK_SD)
-DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE)
-DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)
-DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
-DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
-DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
-DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
-DECLARE_INSN(div, MATCH_DIV, MASK_DIV)
-DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU)
-DECLARE_INSN(rem, MATCH_REM, MASK_REM)
-DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
-DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
-DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW)
-DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW)
-DECLARE_INSN(remw, MATCH_REMW, MASK_REMW)
-DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
-DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W)
-DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
-DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W)
-DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
-DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W)
-DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W)
-DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W)
-DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W)
-DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W)
-DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W)
-DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
-DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D)
-DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D)
-DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D)
-DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
-DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D)
-DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
-DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D)
-DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D)
-DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D)
-DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D)
-DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
-DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
-DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
-DECLARE_INSN(uret, MATCH_URET, MASK_URET)
-DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
-DECLARE_INSN(hret, MATCH_HRET, MASK_HRET)
-DECLARE_INSN(mret, MATCH_MRET, MASK_MRET)
-DECLARE_INSN(dret, MATCH_DRET, MASK_DRET)
-DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
-DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
-DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
-DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
-DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
-DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI)
-DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
-DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
-DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S)
-DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S)
-DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
-DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S)
-DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S)
-DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S)
-DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
-DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
-DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S)
-DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S)
-DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D)
-DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
-DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D)
-DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D)
-DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D)
-DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
-DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D)
-DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D)
-DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
-DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
-DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
-DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
-DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
-DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
-DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
-DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
-DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
-DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
-DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
-DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
-DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
-DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
-DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S)
-DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
-DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
-DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
-DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
-DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
-DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
-DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
-DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
-DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
-DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
-DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
-DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X)
-DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
-DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
-DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
-DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
-DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
-DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
-DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
-DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
-DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
-DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
-DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
-DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
-DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S)
-DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
-DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
-DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
-DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
-DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP)
-DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
-DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
-DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
-DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
-DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
-DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
-DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
-DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
-DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
-DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
-DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD)
-DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
-DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW)
-DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD)
-DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
-DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW)
-DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
-DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
-DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
-DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
-DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
-DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
-DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
-DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
-DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
-DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR)
-DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND)
-DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW)
-DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
-DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
-DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
-DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
-DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
-DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP)
-DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
-DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP)
-DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
-DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
-DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP)
-DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
-DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP)
-DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0)
-DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1)
-DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2)
-DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD)
-DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1)
-DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2)
-DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1)
-DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1)
-DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2)
-DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD)
-DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1)
-DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2)
-DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2)
-DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1)
-DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2)
-DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
-DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
-DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2)
-DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3)
-DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1)
-DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2)
-DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD)
-DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1)
-DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
-#endif
-#ifdef DECLARE_CSR
-DECLARE_CSR(fflags, CSR_FFLAGS)
-DECLARE_CSR(frm, CSR_FRM)
-DECLARE_CSR(fcsr, CSR_FCSR)
-DECLARE_CSR(cycle, CSR_CYCLE)
-DECLARE_CSR(time, CSR_TIME)
-DECLARE_CSR(instret, CSR_INSTRET)
-DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3)
-DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4)
-DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5)
-DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6)
-DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7)
-DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8)
-DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9)
-DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10)
-DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11)
-DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12)
-DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13)
-DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14)
-DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15)
-DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16)
-DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17)
-DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18)
-DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19)
-DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20)
-DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21)
-DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22)
-DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23)
-DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24)
-DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25)
-DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26)
-DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27)
-DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28)
-DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29)
-DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30)
-DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31)
-DECLARE_CSR(sstatus, CSR_SSTATUS)
-DECLARE_CSR(sie, CSR_SIE)
-DECLARE_CSR(stvec, CSR_STVEC)
-DECLARE_CSR(sscratch, CSR_SSCRATCH)
-DECLARE_CSR(sepc, CSR_SEPC)
-DECLARE_CSR(scause, CSR_SCAUSE)
-DECLARE_CSR(sbadaddr, CSR_SBADADDR)
-DECLARE_CSR(sip, CSR_SIP)
-DECLARE_CSR(sptbr, CSR_SPTBR)
-DECLARE_CSR(mstatus, CSR_MSTATUS)
-DECLARE_CSR(misa, CSR_MISA)
-DECLARE_CSR(medeleg, CSR_MEDELEG)
-DECLARE_CSR(mideleg, CSR_MIDELEG)
-DECLARE_CSR(mie, CSR_MIE)
-DECLARE_CSR(mtvec, CSR_MTVEC)
-DECLARE_CSR(mscratch, CSR_MSCRATCH)
-DECLARE_CSR(mepc, CSR_MEPC)
-DECLARE_CSR(mcause, CSR_MCAUSE)
-DECLARE_CSR(mbadaddr, CSR_MBADADDR)
-DECLARE_CSR(mip, CSR_MIP)
-DECLARE_CSR(tselect, CSR_TSELECT)
-DECLARE_CSR(tdata1, CSR_TDATA1)
-DECLARE_CSR(tdata2, CSR_TDATA2)
-DECLARE_CSR(tdata3, CSR_TDATA3)
-DECLARE_CSR(dcsr, CSR_DCSR)
-DECLARE_CSR(dpc, CSR_DPC)
-DECLARE_CSR(dscratch, CSR_DSCRATCH)
-DECLARE_CSR(mcycle, CSR_MCYCLE)
-DECLARE_CSR(minstret, CSR_MINSTRET)
-DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3)
-DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4)
-DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5)
-DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6)
-DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7)
-DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8)
-DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9)
-DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10)
-DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11)
-DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12)
-DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13)
-DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14)
-DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15)
-DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16)
-DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17)
-DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18)
-DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19)
-DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20)
-DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21)
-DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22)
-DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23)
-DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24)
-DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25)
-DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26)
-DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27)
-DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
-DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
-DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
-DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
-DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN)
-DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN)
-DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
-DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
-DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
-DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6)
-DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7)
-DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8)
-DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9)
-DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10)
-DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11)
-DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12)
-DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13)
-DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14)
-DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15)
-DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16)
-DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17)
-DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18)
-DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19)
-DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20)
-DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21)
-DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22)
-DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23)
-DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24)
-DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25)
-DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26)
-DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27)
-DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28)
-DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29)
-DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30)
-DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31)
-DECLARE_CSR(mvendorid, CSR_MVENDORID)
-DECLARE_CSR(marchid, CSR_MARCHID)
-DECLARE_CSR(mimpid, CSR_MIMPID)
-DECLARE_CSR(mhartid, CSR_MHARTID)
-DECLARE_CSR(cycleh, CSR_CYCLEH)
-DECLARE_CSR(timeh, CSR_TIMEH)
-DECLARE_CSR(instreth, CSR_INSTRETH)
-DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H)
-DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H)
-DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H)
-DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H)
-DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H)
-DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H)
-DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H)
-DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H)
-DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H)
-DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H)
-DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H)
-DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H)
-DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H)
-DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H)
-DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H)
-DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H)
-DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H)
-DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H)
-DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H)
-DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H)
-DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H)
-DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H)
-DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H)
-DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H)
-DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H)
-DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H)
-DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H)
-DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H)
-DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H)
-DECLARE_CSR(mcycleh, CSR_MCYCLEH)
-DECLARE_CSR(minstreth, CSR_MINSTRETH)
-DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H)
-DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H)
-DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H)
-DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H)
-DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H)
-DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H)
-DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H)
-DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H)
-DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H)
-DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H)
-DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H)
-DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H)
-DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H)
-DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H)
-DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H)
-DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H)
-DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H)
-DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H)
-DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H)
-DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H)
-DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H)
-DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H)
-DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H)
-DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H)
-DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H)
-DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H)
-DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H)
-DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H)
-DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H)
-#endif
-#ifdef DECLARE_CAUSE
-DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH)
-DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH)
-DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION)
-DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT)
-DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD)
-DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD)
-DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE)
-DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE)
-DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL)
-DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
-DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL)
-DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
-#endif
diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h
deleted file mode 100644
index a12c36f..0000000
--- a/src/target/riscv/gdb_regs.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef TARGET__RISCV__GDB_REGS_H
-#define TARGET__RISCV__GDB_REGS_H
-
-enum gdb_regno {
- GDB_REGNO_XPR0 = 0,
- GDB_REGNO_S0 = GDB_REGNO_XPR0 + 8,
- GDB_REGNO_S1 = GDB_REGNO_XPR0 + 9,
- GDB_REGNO_XPR31 = GDB_REGNO_XPR0 + 31,
- GDB_REGNO_PC = 32,
- GDB_REGNO_FPR0 = 33,
- GDB_REGNO_FPR31 = GDB_REGNO_FPR0 + 31,
- GDB_REGNO_CSR0 = 65,
- GDB_REGNO_TSELECT = CSR_TSELECT + GDB_REGNO_CSR0,
- GDB_REGNO_TDATA1 = CSR_TDATA1 + GDB_REGNO_CSR0,
- GDB_REGNO_TDATA2 = CSR_TDATA2 + GDB_REGNO_CSR0,
- GDB_REGNO_MISA = CSR_MISA + GDB_REGNO_CSR0,
- GDB_REGNO_DPC = CSR_DPC + GDB_REGNO_CSR0,
- GDB_REGNO_DCSR = CSR_DCSR + GDB_REGNO_CSR0,
- GDB_REGNO_MSTATUS = CSR_MSTATUS + GDB_REGNO_CSR0,
- GDB_REGNO_CSR4095 = GDB_REGNO_CSR0 + 4095,
- GDB_REGNO_PRIV = 4161,
- GDB_REGNO_COUNT
-};
-
-#endif
diff --git a/src/target/riscv/opcodes.h b/src/target/riscv/opcodes.h
deleted file mode 100644
index f5fac02..0000000
--- a/src/target/riscv/opcodes.h
+++ /dev/null
@@ -1,279 +0,0 @@
-#include "encoding.h"
-
-#define ZERO 0
-#define T0 5
-#define S0 8
-#define S1 9
-
-static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) {
- return (value >> lo) & ((1 << (hi+1-lo)) - 1);
-}
-
-static uint32_t bit(uint32_t value, unsigned int b) {
- return (value >> b) & 1;
-}
-
-static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused));
-static uint32_t jal(unsigned int rd, uint32_t imm) {
- return (bit(imm, 20) << 31) |
- (bits(imm, 10, 1) << 21) |
- (bit(imm, 11) << 20) |
- (bits(imm, 19, 12) << 12) |
- (rd << 7) |
- MATCH_JAL;
-}
-
-static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused));
-static uint32_t csrsi(unsigned int csr, uint16_t imm) {
- return (csr << 20) |
- (bits(imm, 4, 0) << 15) |
- MATCH_CSRRSI;
-}
-
-static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 5) << 25) |
- (src << 20) |
- (base << 15) |
- (bits(offset, 4, 0) << 7) |
- MATCH_SW;
-}
-
-static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 5) << 25) |
- (src << 20) |
- (base << 15) |
- (bits(offset, 4, 0) << 7) |
- MATCH_SD;
-}
-
-static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 5) << 25) |
- (src << 20) |
- (base << 15) |
- (bits(offset, 4, 0) << 7) |
- MATCH_SH;
-}
-
-static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 5) << 25) |
- (src << 20) |
- (base << 15) |
- (bits(offset, 4, 0) << 7) |
- MATCH_SB;
-}
-
-static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 0) << 20) |
- (base << 15) |
- (bits(rd, 4, 0) << 7) |
- MATCH_LD;
-}
-
-static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 0) << 20) |
- (base << 15) |
- (bits(rd, 4, 0) << 7) |
- MATCH_LW;
-}
-
-static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 0) << 20) |
- (base << 15) |
- (bits(rd, 4, 0) << 7) |
- MATCH_LH;
-}
-
-static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 0) << 20) |
- (base << 15) |
- (bits(rd, 4, 0) << 7) |
- MATCH_LB;
-}
-
-static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused));
-static uint32_t csrw(unsigned int source, unsigned int csr) {
- return (csr << 20) | (source << 15) | MATCH_CSRRW;
-}
-
-static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
-static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
-{
- return (bits(imm, 11, 0) << 20) |
- (src << 15) |
- (dest << 7) |
- MATCH_ADDI;
-}
-
-static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused));
-static uint32_t csrr(unsigned int rd, unsigned int csr) {
- return (csr << 20) | (rd << 7) | MATCH_CSRRS;
-}
-
-static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 5) << 25) |
- (bits(src, 4, 0) << 20) |
- (base << 15) |
- (bits(offset, 4, 0) << 7) |
- MATCH_FSW;
-}
-
-static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 5) << 25) |
- (bits(src, 4, 0) << 20) |
- (base << 15) |
- (bits(offset, 4, 0) << 7) |
- MATCH_FSD;
-}
-
-static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 0) << 20) |
- (base << 15) |
- (bits(dest, 4, 0) << 7) |
- MATCH_FLW;
-}
-
-static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 0) << 20) |
- (base << 15) |
- (bits(dest, 4, 0) << 7) |
- MATCH_FLD;
-}
-
-static uint32_t fmv_x_s(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_x_s(unsigned dest, unsigned src)
-{
- return src << 15 |
- dest << 7 |
- MATCH_FMV_X_S;
-}
-
-static uint32_t fmv_x_d(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_x_d(unsigned dest, unsigned src)
-{
- return src << 15 |
- dest << 7 |
- MATCH_FMV_X_D;
-}
-
-static uint32_t fmv_s_x(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_s_x(unsigned dest, unsigned src)
-{
- return src << 15 |
- dest << 7 |
- MATCH_FMV_S_X;
-}
-
-static uint32_t fmv_d_x(unsigned dest, unsigned src) __attribute__ ((unused));
-static uint32_t fmv_d_x(unsigned dest, unsigned src)
-{
- return src << 15 |
- dest << 7 |
- MATCH_FMV_D_X;
-}
-
-static uint32_t ebreak(void) __attribute__ ((unused));
-static uint32_t ebreak(void) { return MATCH_EBREAK; }
-static uint32_t ebreak_c(void) __attribute__ ((unused));
-static uint32_t ebreak_c(void) { return MATCH_C_EBREAK; }
-
-static uint32_t fence_i(void) __attribute__ ((unused));
-static uint32_t fence_i(void)
-{
- return MATCH_FENCE_I;
-}
-
-/*
-static uint32_t lui(unsigned int dest, uint32_t imm) __attribute__ ((unused));
-static uint32_t lui(unsigned int dest, uint32_t imm)
-{
- return (bits(imm, 19, 0) << 12) |
- (dest << 7) |
- MATCH_LUI;
-}
-
-static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused));
-static uint32_t csrci(unsigned int csr, uint16_t imm) {
- return (csr << 20) |
- (bits(imm, 4, 0) << 15) |
- MATCH_CSRRCI;
-}
-
-static uint32_t li(unsigned int dest, uint16_t imm) __attribute__ ((unused));
-static uint32_t li(unsigned int dest, uint16_t imm)
-{
- return addi(dest, 0, imm);
-}
-
-static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
-static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
-{
- return (bits(offset, 11, 5) << 25) |
- (bits(src, 4, 0) << 20) |
- (base << 15) |
- (bits(offset, 4, 0) << 7) |
- MATCH_FSD;
-}
-
-static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
-static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm)
-{
- return (bits(imm, 11, 0) << 20) |
- (src << 15) |
- (dest << 7) |
- MATCH_ORI;
-}
-
-static uint32_t nop(void) __attribute__ ((unused));
-static uint32_t nop(void)
-{
- return addi(0, 0, 0);
-}
-*/
-
-static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
-static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm)
-{
- return (bits(imm, 11, 0) << 20) |
- (src << 15) |
- (dest << 7) |
- MATCH_XORI;
-}
-
-static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) __attribute__ ((unused));
-static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt)
-{
- return (bits(shamt, 4, 0) << 20) |
- (src << 15) |
- (dest << 7) |
- MATCH_SRLI;
-}
-
-static uint32_t fence(void) __attribute__((unused));
-static uint32_t fence(void)
-{
- return MATCH_FENCE;
-}
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
deleted file mode 100644
index ed2a057..0000000
--- a/src/target/riscv/riscv-011.c
+++ /dev/null
@@ -1,2603 +0,0 @@
-/*
- * Support for RISC-V, debug version 0.11. This was never an officially adopted
- * spec, but SiFive made some silicon that uses it.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <time.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "target/algorithm.h"
-#include "target_type.h"
-#include "log.h"
-#include "jtag/jtag.h"
-#include "register.h"
-#include "breakpoints.h"
-#include "helper/time_support.h"
-#include "riscv.h"
-#include "asm.h"
-
-/**
- * Since almost everything can be accomplish by scanning the dbus register, all
- * functions here assume dbus is already selected. The exception are functions
- * called directly by OpenOCD, which can't assume anything about what's
- * currently in IR. They should set IR to dbus explicitly.
- */
-
-/**
- * Code structure
- *
- * At the bottom of the stack are the OpenOCD JTAG functions:
- * jtag_add_[id]r_scan
- * jtag_execute_query
- * jtag_add_runtest
- *
- * There are a few functions to just instantly shift a register and get its
- * value:
- * dtmcontrol_scan
- * idcode_scan
- * dbus_scan
- *
- * Because doing one scan and waiting for the result is slow, most functions
- * batch up a bunch of dbus writes and then execute them all at once. They use
- * the scans "class" for this:
- * scans_new
- * scans_delete
- * scans_execute
- * scans_add_...
- * Usually you new(), call a bunch of add functions, then execute() and look
- * at the results by calling scans_get...()
- *
- * Optimized functions will directly use the scans class above, but slightly
- * lazier code will use the cache functions that in turn use the scans
- * functions:
- * cache_get...
- * cache_set...
- * cache_write
- * cache_set... update a local structure, which is then synced to the target
- * with cache_write(). Only Debug RAM words that are actually changed are sent
- * to the target. Afterwards use cache_get... to read results.
- */
-
-#define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
-#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
-
-#define DIM(x) (sizeof(x)/sizeof(*x))
-
-// Constants for legacy SiFive hardware breakpoints.
-#define CSR_BPCONTROL_X (1<<0)
-#define CSR_BPCONTROL_W (1<<1)
-#define CSR_BPCONTROL_R (1<<2)
-#define CSR_BPCONTROL_U (1<<3)
-#define CSR_BPCONTROL_S (1<<4)
-#define CSR_BPCONTROL_H (1<<5)
-#define CSR_BPCONTROL_M (1<<6)
-#define CSR_BPCONTROL_BPMATCH (0xf<<7)
-#define CSR_BPCONTROL_BPACTION (0xff<<11)
-
-#define DEBUG_ROM_START 0x800
-#define DEBUG_ROM_RESUME (DEBUG_ROM_START + 4)
-#define DEBUG_ROM_EXCEPTION (DEBUG_ROM_START + 8)
-#define DEBUG_RAM_START 0x400
-
-#define SETHALTNOT 0x10c
-
-/*** JTAG registers. ***/
-
-#define DTMCONTROL 0x10
-#define DTMCONTROL_DBUS_RESET (1<<16)
-#define DTMCONTROL_IDLE (7<<10)
-#define DTMCONTROL_ADDRBITS (0xf<<4)
-#define DTMCONTROL_VERSION (0xf)
-
-#define DBUS 0x11
-#define DBUS_OP_START 0
-#define DBUS_OP_SIZE 2
-typedef enum {
- DBUS_OP_NOP = 0,
- DBUS_OP_READ = 1,
- DBUS_OP_WRITE = 2
-} dbus_op_t;
-typedef enum {
- DBUS_STATUS_SUCCESS = 0,
- DBUS_STATUS_FAILED = 2,
- DBUS_STATUS_BUSY = 3
-} dbus_status_t;
-#define DBUS_DATA_START 2
-#define DBUS_DATA_SIZE 34
-#define DBUS_ADDRESS_START 36
-
-typedef enum {
- RE_OK,
- RE_FAIL,
- RE_AGAIN
-} riscv_error_t;
-
-typedef enum slot {
- SLOT0,
- SLOT1,
- SLOT_LAST,
-} slot_t;
-
-/*** Debug Bus registers. ***/
-
-#define DMCONTROL 0x10
-#define DMCONTROL_INTERRUPT (((uint64_t)1)<<33)
-#define DMCONTROL_HALTNOT (((uint64_t)1)<<32)
-#define DMCONTROL_BUSERROR (7<<19)
-#define DMCONTROL_SERIAL (3<<16)
-#define DMCONTROL_AUTOINCREMENT (1<<15)
-#define DMCONTROL_ACCESS (7<<12)
-#define DMCONTROL_HARTID (0x3ff<<2)
-#define DMCONTROL_NDRESET (1<<1)
-#define DMCONTROL_FULLRESET 1
-
-#define DMINFO 0x11
-#define DMINFO_ABUSSIZE (0x7fU<<25)
-#define DMINFO_SERIALCOUNT (0xf<<21)
-#define DMINFO_ACCESS128 (1<<20)
-#define DMINFO_ACCESS64 (1<<19)
-#define DMINFO_ACCESS32 (1<<18)
-#define DMINFO_ACCESS16 (1<<17)
-#define DMINFO_ACCESS8 (1<<16)
-#define DMINFO_DRAMSIZE (0x3f<<10)
-#define DMINFO_AUTHENTICATED (1<<5)
-#define DMINFO_AUTHBUSY (1<<4)
-#define DMINFO_AUTHTYPE (3<<2)
-#define DMINFO_VERSION 3
-
-/*** Info about the core being debugged. ***/
-
-#define DBUS_ADDRESS_UNKNOWN 0xffff
-#define WALL_CLOCK_TIMEOUT 2
-
-// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
-// its source tree. We must interpret the numbers the same here.
-enum {
- REG_XPR0 = 0,
- REG_XPR31 = 31,
- REG_PC = 32,
- REG_FPR0 = 33,
- REG_FPR31 = 64,
- REG_CSR0 = 65,
- REG_MSTATUS = CSR_MSTATUS + REG_CSR0,
- REG_CSR4095 = 4160,
- REG_PRIV = 4161,
- REG_COUNT
-};
-
-#define MAX_HWBPS 16
-#define DRAM_CACHE_SIZE 16
-
-struct trigger {
- uint64_t address;
- uint32_t length;
- uint64_t mask;
- uint64_t value;
- bool read, write, execute;
- int unique_id;
-};
-
-struct memory_cache_line {
- uint32_t data;
- bool valid;
- bool dirty;
-};
-
-typedef struct {
- /* Number of address bits in the dbus register. */
- uint8_t addrbits;
- /* Number of words in Debug RAM. */
- unsigned int dramsize;
- uint64_t dcsr;
- uint64_t dpc;
- uint64_t misa;
- uint64_t tselect;
- bool tselect_dirty;
- /* The value that mstatus actually has on the target right now. This is not
- * the value we present to the user. That one may be stored in the
- * reg_cache. */
- uint64_t mstatus_actual;
-
- struct memory_cache_line dram_cache[DRAM_CACHE_SIZE];
-
- /* Single buffer that contains all register names, instead of calling
- * malloc for each register. Needs to be freed when reg_list is freed. */
- char *reg_names;
- /* Single buffer that contains all register values. */
- void *reg_values;
-
- // For each physical trigger, contains -1 if the hwbp is available, or the
- // unique_id of the breakpoint/watchpoint that is using it.
- int trigger_unique_id[MAX_HWBPS];
-
- unsigned int trigger_count;
-
- // Number of run-test/idle cycles the target requests we do after each dbus
- // access.
- unsigned int dtmcontrol_idle;
-
- // This value is incremented every time a dbus access comes back as "busy".
- // It's used to determine how many run-test/idle cycles to feed the target
- // in between accesses.
- unsigned int dbus_busy_delay;
-
- // This value is incremented every time we read the debug interrupt as
- // high. It's used to add extra run-test/idle cycles after setting debug
- // interrupt high, so ideally we never have to perform a whole extra scan
- // before the interrupt is cleared.
- unsigned int interrupt_high_delay;
-
- bool need_strict_step;
- bool never_halted;
-} riscv011_info_t;
-
-typedef struct {
- bool haltnot;
- bool interrupt;
-} bits_t;
-
-/*** Necessary prototypes. ***/
-
-static int poll_target(struct target *target, bool announce);
-static int riscv011_poll(struct target *target);
-static int register_get(struct reg *reg);
-
-/*** Utility functions. ***/
-
-#define DEBUG_LENGTH 264
-
-static riscv011_info_t *get_info(const struct target *target)
-{
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
- return (riscv011_info_t *) info->version_specific;
-}
-
-static unsigned int slot_offset(const struct target *target, slot_t slot)
-{
- riscv011_info_t *info = get_info(target);
- switch (riscv_xlen(target)) {
- case 32:
- switch (slot) {
- case SLOT0: return 4;
- case SLOT1: return 5;
- case SLOT_LAST: return info->dramsize-1;
- }
- case 64:
- switch (slot) {
- case SLOT0: return 4;
- case SLOT1: return 6;
- case SLOT_LAST: return info->dramsize-2;
- }
- }
- LOG_ERROR("slot_offset called with xlen=%d, slot=%d",
- riscv_xlen(target), slot);
- assert(0);
-}
-
-static uint32_t load_slot(const struct target *target, unsigned int dest,
- slot_t slot)
-{
- unsigned int offset = DEBUG_RAM_START + 4 * slot_offset(target, slot);
- return load(target, dest, ZERO, offset);
-}
-
-static uint32_t store_slot(const struct target *target, unsigned int src,
- slot_t slot)
-{
- unsigned int offset = DEBUG_RAM_START + 4 * slot_offset(target, slot);
- return store(target, src, ZERO, offset);
-}
-
-static uint16_t dram_address(unsigned int index)
-{
- if (index < 0x10)
- return index;
- else
- return 0x40 + index - 0x10;
-}
-
-static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
-{
- struct scan_field field;
- uint8_t in_value[4];
- uint8_t out_value[4];
-
- buf_set_u32(out_value, 0, 32, out);
-
- jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE);
-
- field.num_bits = 32;
- field.out_value = out_value;
- field.in_value = in_value;
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- /* Always return to dbus. */
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed jtag scan: %d", retval);
- return retval;
- }
-
- uint32_t in = buf_get_u32(field.in_value, 0, 32);
- LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in);
-
- return in;
-}
-
-static uint32_t idcode_scan(struct target *target)
-{
- struct scan_field field;
- uint8_t in_value[4];
-
- jtag_add_ir_scan(target->tap, &select_idcode, TAP_IDLE);
-
- field.num_bits = 32;
- field.out_value = NULL;
- field.in_value = in_value;
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed jtag scan: %d", retval);
- return retval;
- }
-
- /* Always return to dbus. */
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- uint32_t in = buf_get_u32(field.in_value, 0, 32);
- LOG_DEBUG("IDCODE: 0x0 -> 0x%x", in);
-
- return in;
-}
-
-static void increase_dbus_busy_delay(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
- info->dbus_busy_delay += info->dbus_busy_delay / 10 + 1;
- LOG_INFO("dtmcontrol_idle=%d, dbus_busy_delay=%d, interrupt_high_delay=%d",
- info->dtmcontrol_idle, info->dbus_busy_delay,
- info->interrupt_high_delay);
-
- dtmcontrol_scan(target, DTMCONTROL_DBUS_RESET);
-}
-
-static void increase_interrupt_high_delay(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
- info->interrupt_high_delay += info->interrupt_high_delay / 10 + 1;
- LOG_INFO("dtmcontrol_idle=%d, dbus_busy_delay=%d, interrupt_high_delay=%d",
- info->dtmcontrol_idle, info->dbus_busy_delay,
- info->interrupt_high_delay);
-}
-
-static void add_dbus_scan(const struct target *target, struct scan_field *field,
- uint8_t *out_value, uint8_t *in_value, dbus_op_t op,
- uint16_t address, uint64_t data)
-{
- riscv011_info_t *info = get_info(target);
-
- field->num_bits = info->addrbits + DBUS_OP_SIZE + DBUS_DATA_SIZE;
- field->in_value = in_value;
- field->out_value = out_value;
-
- buf_set_u64(out_value, DBUS_OP_START, DBUS_OP_SIZE, op);
- buf_set_u64(out_value, DBUS_DATA_START, DBUS_DATA_SIZE, data);
- buf_set_u64(out_value, DBUS_ADDRESS_START, info->addrbits, address);
-
- jtag_add_dr_scan(target->tap, 1, field, TAP_IDLE);
-
- int idle_count = info->dtmcontrol_idle + info->dbus_busy_delay;
- if (data & DMCONTROL_INTERRUPT) {
- idle_count += info->interrupt_high_delay;
- }
-
- if (idle_count) {
- jtag_add_runtest(idle_count, TAP_IDLE);
- }
-}
-
-static void dump_field(const struct scan_field *field)
-{
- static const char *op_string[] = {"nop", "r", "w", "?"};
- static const char *status_string[] = {"+", "?", "F", "b"};
-
- if (debug_level < LOG_LVL_DEBUG)
- return;
-
- uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits);
- unsigned int out_op = (out >> DBUS_OP_START) & ((1 << DBUS_OP_SIZE) - 1);
- char out_interrupt = ((out >> DBUS_DATA_START) & DMCONTROL_INTERRUPT) ? 'i' : '.';
- char out_haltnot = ((out >> DBUS_DATA_START) & DMCONTROL_HALTNOT) ? 'h' : '.';
- unsigned int out_data = out >> 2;
- unsigned int out_address = out >> DBUS_ADDRESS_START;
- uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
- unsigned int in_op = (in >> DBUS_OP_START) & ((1 << DBUS_OP_SIZE) - 1);
- char in_interrupt = ((in >> DBUS_DATA_START) & DMCONTROL_INTERRUPT) ? 'i' : '.';
- char in_haltnot = ((in >> DBUS_DATA_START) & DMCONTROL_HALTNOT) ? 'h' : '.';
- unsigned int in_data = in >> 2;
- unsigned int in_address = in >> DBUS_ADDRESS_START;
-
- log_printf_lf(LOG_LVL_DEBUG,
- __FILE__, __LINE__, "scan",
- "%db %s %c%c:%08x @%02x -> %s %c%c:%08x @%02x",
- field->num_bits,
- op_string[out_op], out_interrupt, out_haltnot, out_data,
- out_address,
- status_string[in_op], in_interrupt, in_haltnot, in_data,
- in_address);
-}
-
-static dbus_status_t dbus_scan(struct target *target, uint16_t *address_in,
- uint64_t *data_in, dbus_op_t op, uint16_t address_out, uint64_t data_out)
-{
- riscv011_info_t *info = get_info(target);
- uint8_t in[8] = {0};
- uint8_t out[8];
- struct scan_field field = {
- .num_bits = info->addrbits + DBUS_OP_SIZE + DBUS_DATA_SIZE,
- .out_value = out,
- .in_value = in
- };
-
- assert(info->addrbits != 0);
-
- buf_set_u64(out, DBUS_OP_START, DBUS_OP_SIZE, op);
- buf_set_u64(out, DBUS_DATA_START, DBUS_DATA_SIZE, data_out);
- buf_set_u64(out, DBUS_ADDRESS_START, info->addrbits, address_out);
-
- /* Assume dbus is already selected. */
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- int idle_count = info->dtmcontrol_idle + info->dbus_busy_delay;
-
- if (idle_count) {
- jtag_add_runtest(idle_count, TAP_IDLE);
- }
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("dbus_scan failed jtag scan");
- return retval;
- }
-
- if (data_in) {
- *data_in = buf_get_u64(in, DBUS_DATA_START, DBUS_DATA_SIZE);
- }
-
- if (address_in) {
- *address_in = buf_get_u32(in, DBUS_ADDRESS_START, info->addrbits);
- }
-
- dump_field(&field);
-
- return buf_get_u32(in, DBUS_OP_START, DBUS_OP_SIZE);
-}
-
-static uint64_t dbus_read(struct target *target, uint16_t address)
-{
- uint64_t value;
- dbus_status_t status;
- uint16_t address_in;
-
- unsigned i = 0;
- do {
- status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0);
- if (status == DBUS_STATUS_BUSY) {
- increase_dbus_busy_delay(target);
- }
- } while (((status == DBUS_STATUS_BUSY) || (address_in != address)) &&
- i++ < 256);
-
- if (status != DBUS_STATUS_SUCCESS) {
- LOG_ERROR("failed read from 0x%x; value=0x%" PRIx64 ", status=%d\n", address, value, status);
- }
-
- return value;
-}
-
-static void dbus_write(struct target *target, uint16_t address, uint64_t value)
-{
- dbus_status_t status = DBUS_STATUS_BUSY;
- unsigned i = 0;
- while (status == DBUS_STATUS_BUSY && i++ < 256) {
- status = dbus_scan(target, NULL, NULL, DBUS_OP_WRITE, address, value);
- if (status == DBUS_STATUS_BUSY) {
- increase_dbus_busy_delay(target);
- }
- }
- if (status != DBUS_STATUS_SUCCESS) {
- LOG_ERROR("failed to write 0x%" PRIx64 " to 0x%x; status=%d\n", value, address, status);
- }
-}
-
-/*** scans "class" ***/
-
-typedef struct {
- // Number of scans that space is reserved for.
- unsigned int scan_count;
- // Size reserved in memory for each scan, in bytes.
- unsigned int scan_size;
- unsigned int next_scan;
- uint8_t *in;
- uint8_t *out;
- struct scan_field *field;
- const struct target *target;
-} scans_t;
-
-static scans_t *scans_new(struct target *target, unsigned int scan_count)
-{
- scans_t *scans = malloc(sizeof(scans_t));
- scans->scan_count = scan_count;
- // This code also gets called before xlen is detected.
- if (riscv_xlen(target))
- scans->scan_size = 2 + riscv_xlen(target) / 8;
- else
- scans->scan_size = 2 + 128 / 8;
- scans->next_scan = 0;
- scans->in = calloc(scans->scan_size, scans->scan_count);
- scans->out = calloc(scans->scan_size, scans->scan_count);
- scans->field = calloc(scans->scan_count, sizeof(struct scan_field));
- scans->target = target;
- return scans;
-}
-
-static scans_t *scans_delete(scans_t *scans)
-{
- assert(scans);
- free(scans->field);
- free(scans->out);
- free(scans->in);
- free(scans);
- return NULL;
-}
-
-static void scans_reset(scans_t *scans)
-{
- scans->next_scan = 0;
-}
-
-static void scans_dump(scans_t *scans)
-{
- for (unsigned int i = 0; i < scans->next_scan; i++) {
- dump_field(&scans->field[i]);
- }
-}
-
-static int scans_execute(scans_t *scans)
-{
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed jtag scan: %d", retval);
- return retval;
- }
-
- scans_dump(scans);
-
- return ERROR_OK;
-}
-
-/** Add a 32-bit dbus write to the scans structure. */
-static void scans_add_write32(scans_t *scans, uint16_t address, uint32_t data,
- bool set_interrupt)
-{
- const unsigned int i = scans->next_scan;
- int data_offset = scans->scan_size * i;
- add_dbus_scan(scans->target, &scans->field[i], scans->out + data_offset,
- scans->in + data_offset, DBUS_OP_WRITE, address,
- (set_interrupt ? DMCONTROL_INTERRUPT : 0) | DMCONTROL_HALTNOT | data);
- scans->next_scan++;
- assert(scans->next_scan <= scans->scan_count);
-}
-
-/** Add a 32-bit dbus write for an instruction that jumps to the beginning of
- * debug RAM. */
-static void scans_add_write_jump(scans_t *scans, uint16_t address,
- bool set_interrupt)
-{
- scans_add_write32(scans, address,
- jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*address))),
- set_interrupt);
-}
-
-/** Add a 32-bit dbus write for an instruction that loads from the indicated
- * slot. */
-static void scans_add_write_load(scans_t *scans, uint16_t address,
- unsigned int reg, slot_t slot, bool set_interrupt)
-{
- scans_add_write32(scans, address, load_slot(scans->target, reg, slot),
- set_interrupt);
-}
-
-/** Add a 32-bit dbus write for an instruction that stores to the indicated
- * slot. */
-static void scans_add_write_store(scans_t *scans, uint16_t address,
- unsigned int reg, slot_t slot, bool set_interrupt)
-{
- scans_add_write32(scans, address, store_slot(scans->target, reg, slot),
- set_interrupt);
-}
-
-/** Add a 32-bit dbus read. */
-static void scans_add_read32(scans_t *scans, uint16_t address, bool set_interrupt)
-{
- assert(scans->next_scan < scans->scan_count);
- const unsigned int i = scans->next_scan;
- int data_offset = scans->scan_size * i;
- add_dbus_scan(scans->target, &scans->field[i], scans->out + data_offset,
- scans->in + data_offset, DBUS_OP_READ, address,
- (set_interrupt ? DMCONTROL_INTERRUPT : 0) | DMCONTROL_HALTNOT);
- scans->next_scan++;
-}
-
-/** Add one or more scans to read the indicated slot. */
-static void scans_add_read(scans_t *scans, slot_t slot, bool set_interrupt)
-{
- const struct target *target = scans->target;
- switch (riscv_xlen(target)) {
- case 32:
- scans_add_read32(scans, slot_offset(target, slot), set_interrupt);
- break;
- case 64:
- scans_add_read32(scans, slot_offset(target, slot), false);
- scans_add_read32(scans, slot_offset(target, slot) + 1, set_interrupt);
- break;
- }
-}
-
-static uint32_t scans_get_u32(scans_t *scans, unsigned int index,
- unsigned first, unsigned num)
-{
- return buf_get_u32(scans->in + scans->scan_size * index, first, num);
-}
-
-static uint64_t scans_get_u64(scans_t *scans, unsigned int index,
- unsigned first, unsigned num)
-{
- return buf_get_u64(scans->in + scans->scan_size * index, first, num);
-}
-
-/*** end of scans class ***/
-
-static uint32_t dram_read32(struct target *target, unsigned int index)
-{
- uint16_t address = dram_address(index);
- uint32_t value = dbus_read(target, address);
- return value;
-}
-
-static void dram_write32(struct target *target, unsigned int index, uint32_t value,
- bool set_interrupt)
-{
- uint64_t dbus_value = DMCONTROL_HALTNOT | value;
- if (set_interrupt)
- dbus_value |= DMCONTROL_INTERRUPT;
- dbus_write(target, dram_address(index), dbus_value);
-}
-
-/** Read the haltnot and interrupt bits. */
-static bits_t read_bits(struct target *target)
-{
- uint64_t value;
- dbus_status_t status;
- uint16_t address_in;
- riscv011_info_t *info = get_info(target);
-
- bits_t err_result = {
- .haltnot = 0,
- .interrupt = 0
- };
-
- do {
- unsigned i = 0;
- do {
- status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, 0, 0);
- if (status == DBUS_STATUS_BUSY) {
- if (address_in == (1<<info->addrbits) - 1 &&
- value == (1ULL<<DBUS_DATA_SIZE) - 1) {
- LOG_ERROR("TDO seems to be stuck high.");
- return err_result;
- }
- increase_dbus_busy_delay(target);
- }
- } while (status == DBUS_STATUS_BUSY && i++ < 256);
-
- if (i >= 256) {
- LOG_ERROR("Failed to read from 0x%x; status=%d", address_in, status);
- return err_result;
- }
- } while (address_in > 0x10 && address_in != DMCONTROL);
-
- bits_t result = {
- .haltnot = get_field(value, DMCONTROL_HALTNOT),
- .interrupt = get_field(value, DMCONTROL_INTERRUPT)
- };
- return result;
-}
-
-static int wait_for_debugint_clear(struct target *target, bool ignore_first)
-{
- time_t start = time(NULL);
- if (ignore_first) {
- // Throw away the results of the first read, since they'll contain the
- // result of the read that happened just before debugint was set.
- // (Assuming the last scan before calling this function was one that
- // sets debugint.)
- read_bits(target);
- }
- while (1) {
- bits_t bits = read_bits(target);
- if (!bits.interrupt) {
- return ERROR_OK;
- }
- if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
- LOG_ERROR("Timed out waiting for debug int to clear.");
- return ERROR_FAIL;
- }
- }
-}
-
-static int dram_check32(struct target *target, unsigned int index,
- uint32_t expected)
-{
- uint16_t address = dram_address(index);
- uint32_t actual = dbus_read(target, address);
- if (expected != actual) {
- LOG_ERROR("Wrote 0x%x to Debug RAM at %d, but read back 0x%x",
- expected, index, actual);
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static void cache_set32(struct target *target, unsigned int index, uint32_t data)
-{
- riscv011_info_t *info = get_info(target);
- if (info->dram_cache[index].valid &&
- info->dram_cache[index].data == data) {
- // This is already preset on the target.
- LOG_DEBUG("cache[0x%x] = 0x%x (hit)", index, data);
- return;
- }
- LOG_DEBUG("cache[0x%x] = 0x%x", index, data);
- info->dram_cache[index].data = data;
- info->dram_cache[index].valid = true;
- info->dram_cache[index].dirty = true;
-}
-
-static void cache_set(struct target *target, slot_t slot, uint64_t data)
-{
- unsigned int offset = slot_offset(target, slot);
- cache_set32(target, offset, data);
- if (riscv_xlen(target) > 32) {
- cache_set32(target, offset + 1, data >> 32);
- }
-}
-
-static void cache_set_jump(struct target *target, unsigned int index)
-{
- cache_set32(target, index,
- jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*index))));
-}
-
-static void cache_set_load(struct target *target, unsigned int index,
- unsigned int reg, slot_t slot)
-{
- uint16_t offset = DEBUG_RAM_START + 4 * slot_offset(target, slot);
- cache_set32(target, index, load(target, reg, ZERO, offset));
-}
-
-static void cache_set_store(struct target *target, unsigned int index,
- unsigned int reg, slot_t slot)
-{
- uint16_t offset = DEBUG_RAM_START + 4 * slot_offset(target, slot);
- cache_set32(target, index, store(target, reg, ZERO, offset));
-}
-
-static void dump_debug_ram(struct target *target)
-{
- for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) {
- uint32_t value = dram_read32(target, i);
- LOG_ERROR("Debug RAM 0x%x: 0x%08x", i, value);
- }
-}
-
-/* Call this if the code you just ran writes to debug RAM entries 0 through 3. */
-static void cache_invalidate(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
- for (unsigned int i = 0; i < info->dramsize; i++) {
- info->dram_cache[i].valid = false;
- info->dram_cache[i].dirty = false;
- }
-}
-
-/* Called by cache_write() after the program has run. Also call this if you're
- * running programs without calling cache_write(). */
-static void cache_clean(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
- for (unsigned int i = 0; i < info->dramsize; i++) {
- if (i >= 4) {
- info->dram_cache[i].valid = false;
- }
- info->dram_cache[i].dirty = false;
- }
-}
-
-static int cache_check(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
- int error = 0;
-
- for (unsigned int i = 0; i < info->dramsize; i++) {
- if (info->dram_cache[i].valid && !info->dram_cache[i].dirty) {
- if (dram_check32(target, i, info->dram_cache[i].data) != ERROR_OK) {
- error++;
- }
- }
- }
-
- if (error) {
- dump_debug_ram(target);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-/** Write cache to the target, and optionally run the program.
- * Then read the value at address into the cache, assuming address < 128. */
-#define CACHE_NO_READ 128
-static int cache_write(struct target *target, unsigned int address, bool run)
-{
- LOG_DEBUG("enter");
- riscv011_info_t *info = get_info(target);
- scans_t *scans = scans_new(target, info->dramsize + 2);
-
- unsigned int last = info->dramsize;
- for (unsigned int i = 0; i < info->dramsize; i++) {
- if (info->dram_cache[i].dirty) {
- last = i;
- }
- }
-
- if (last == info->dramsize) {
- // Nothing needs to be written to RAM.
- dbus_write(target, DMCONTROL, DMCONTROL_HALTNOT | DMCONTROL_INTERRUPT);
-
- } else {
- for (unsigned int i = 0; i < info->dramsize; i++) {
- if (info->dram_cache[i].dirty) {
- bool set_interrupt = (i == last && run);
- scans_add_write32(scans, i, info->dram_cache[i].data,
- set_interrupt);
- }
- }
- }
-
- if (run || address < CACHE_NO_READ) {
- // Throw away the results of the first read, since it'll contain the
- // result of the read that happened just before debugint was set.
- scans_add_read32(scans, address, false);
-
- // This scan contains the results of the read the caller requested, as
- // well as an interrupt bit worth looking at.
- scans_add_read32(scans, address, false);
- }
-
- int retval = scans_execute(scans);
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG execute failed.");
- return retval;
- }
-
- int errors = 0;
- for (unsigned int i = 0; i < scans->next_scan; i++) {
- dbus_status_t status = scans_get_u32(scans, i, DBUS_OP_START,
- DBUS_OP_SIZE);
- switch (status) {
- case DBUS_STATUS_SUCCESS:
- break;
- case DBUS_STATUS_FAILED:
- LOG_ERROR("Debug RAM write failed. Hardware error?");
- return ERROR_FAIL;
- case DBUS_STATUS_BUSY:
- errors++;
- break;
- default:
- LOG_ERROR("Got invalid bus access status: %d", status);
- return ERROR_FAIL;
- }
- }
-
- if (errors) {
- increase_dbus_busy_delay(target);
-
- // Try again, using the slow careful code.
- // Write all RAM, just to be extra cautious.
- for (unsigned int i = 0; i < info->dramsize; i++) {
- if (i == last && run) {
- dram_write32(target, last, info->dram_cache[last].data, true);
- } else {
- dram_write32(target, i, info->dram_cache[i].data, false);
- }
- info->dram_cache[i].dirty = false;
- }
- if (run) {
- cache_clean(target);
- }
-
- if (wait_for_debugint_clear(target, true) != ERROR_OK) {
- LOG_ERROR("Debug interrupt didn't clear.");
- dump_debug_ram(target);
- return ERROR_FAIL;
- }
-
- } else {
- if (run) {
- cache_clean(target);
- } else {
- for (unsigned int i = 0; i < info->dramsize; i++) {
- info->dram_cache[i].dirty = false;
- }
- }
-
- if (run || address < CACHE_NO_READ) {
- int interrupt = scans_get_u32(scans, scans->next_scan-1,
- DBUS_DATA_START + 33, 1);
- if (interrupt) {
- increase_interrupt_high_delay(target);
- // Slow path wait for it to clear.
- if (wait_for_debugint_clear(target, false) != ERROR_OK) {
- LOG_ERROR("Debug interrupt didn't clear.");
- dump_debug_ram(target);
- return ERROR_FAIL;
- }
- } else {
- // We read a useful value in that last scan.
- unsigned int read_addr = scans_get_u32(scans, scans->next_scan-1,
- DBUS_ADDRESS_START, info->addrbits);
- if (read_addr != address) {
- LOG_INFO("Got data from 0x%x but expected it from 0x%x",
- read_addr, address);
- }
- info->dram_cache[read_addr].data =
- scans_get_u32(scans, scans->next_scan-1, DBUS_DATA_START, 32);
- info->dram_cache[read_addr].valid = true;
- }
- }
- }
-
- scans_delete(scans);
- LOG_DEBUG("exit");
-
- return ERROR_OK;
-}
-
-static uint32_t cache_get32(struct target *target, unsigned int address)
-{
- riscv011_info_t *info = get_info(target);
- if (!info->dram_cache[address].valid) {
- info->dram_cache[address].data = dram_read32(target, address);
- info->dram_cache[address].valid = true;
- }
- return info->dram_cache[address].data;
-}
-
-static uint64_t cache_get(struct target *target, slot_t slot)
-{
- unsigned int offset = slot_offset(target, slot);
- uint64_t value = cache_get32(target, offset);
- if (riscv_xlen(target) > 32) {
- value |= ((uint64_t) cache_get32(target, offset + 1)) << 32;
- }
- return value;
-}
-
-/* Write instruction that jumps from the specified word in Debug RAM to resume
- * in Debug ROM. */
-static void dram_write_jump(struct target *target, unsigned int index,
- bool set_interrupt)
-{
- dram_write32(target, index,
- jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*index))),
- set_interrupt);
-}
-
-static int wait_for_state(struct target *target, enum target_state state)
-{
- time_t start = time(NULL);
- while (1) {
- int result = riscv011_poll(target);
- if (result != ERROR_OK) {
- return result;
- }
- if (target->state == state) {
- return ERROR_OK;
- }
- if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
- LOG_ERROR("Timed out waiting for state %d.", state);
- return ERROR_FAIL;
- }
- }
-}
-
-static int read_csr(struct target *target, uint64_t *value, uint32_t csr)
-{
- cache_set32(target, 0, csrr(S0, csr));
- cache_set_store(target, 1, S0, SLOT0);
- cache_set_jump(target, 2);
- if (cache_write(target, 4, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
- *value = cache_get(target, SLOT0);
- LOG_DEBUG("csr 0x%x = 0x%" PRIx64, csr, *value);
-
- return ERROR_OK;
-}
-
-static int write_csr(struct target *target, uint32_t csr, uint64_t value)
-{
- LOG_DEBUG("csr 0x%x <- 0x%" PRIx64, csr, value);
- cache_set_load(target, 0, S0, SLOT0);
- cache_set32(target, 1, csrw(S0, csr));
- cache_set_jump(target, 2);
- cache_set(target, SLOT0, value);
- if (cache_write(target, 4, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int write_gpr(struct target *target, unsigned int gpr, uint64_t value)
-{
- cache_set_load(target, 0, gpr, SLOT0);
- cache_set_jump(target, 1);
- cache_set(target, SLOT0, value);
- if (cache_write(target, 4, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
- return ERROR_OK;
-}
-
-static int maybe_read_tselect(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
-
- if (info->tselect_dirty) {
- int result = read_csr(target, &info->tselect, CSR_TSELECT);
- if (result != ERROR_OK)
- return result;
- info->tselect_dirty = false;
- }
-
- return ERROR_OK;
-}
-
-static int maybe_write_tselect(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
-
- if (!info->tselect_dirty) {
- int result = write_csr(target, CSR_TSELECT, info->tselect);
- if (result != ERROR_OK)
- return result;
- info->tselect_dirty = true;
- }
-
- return ERROR_OK;
-}
-
-static int execute_resume(struct target *target, bool step)
-{
- riscv011_info_t *info = get_info(target);
-
- LOG_DEBUG("step=%d", step);
-
- maybe_write_tselect(target);
-
- // TODO: check if dpc is dirty (which also is true if an exception was hit
- // at any time)
- cache_set_load(target, 0, S0, SLOT0);
- cache_set32(target, 1, csrw(S0, CSR_DPC));
- cache_set_jump(target, 2);
- cache_set(target, SLOT0, info->dpc);
- if (cache_write(target, 4, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS];
- if (mstatus_reg->valid) {
- uint64_t mstatus_user = buf_get_u64(mstatus_reg->value, 0, riscv_xlen(target));
- if (mstatus_user != info->mstatus_actual) {
- cache_set_load(target, 0, S0, SLOT0);
- cache_set32(target, 1, csrw(S0, CSR_MSTATUS));
- cache_set_jump(target, 2);
- cache_set(target, SLOT0, mstatus_user);
- if (cache_write(target, 4, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
- }
- }
-
- info->dcsr |= DCSR_EBREAKM | DCSR_EBREAKH | DCSR_EBREAKS | DCSR_EBREAKU;
- info->dcsr &= ~DCSR_HALT;
-
- if (step) {
- info->dcsr |= DCSR_STEP;
- } else {
- info->dcsr &= ~DCSR_STEP;
- }
-
- dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false);
- dram_write32(target, 1, csrw(S0, CSR_DCSR), false);
- dram_write32(target, 2, fence_i(), false);
- dram_write_jump(target, 3, false);
-
- // Write DCSR value, set interrupt and clear haltnot.
- uint64_t dbus_value = DMCONTROL_INTERRUPT | info->dcsr;
- dbus_write(target, dram_address(4), dbus_value);
-
- cache_invalidate(target);
-
- if (wait_for_debugint_clear(target, true) != ERROR_OK) {
- LOG_ERROR("Debug interrupt didn't clear.");
- return ERROR_FAIL;
- }
-
- target->state = TARGET_RUNNING;
- register_cache_invalidate(target->reg_cache);
-
- return ERROR_OK;
-}
-
-// Execute a step, and wait for reentry into Debug Mode.
-static int full_step(struct target *target, bool announce)
-{
- int result = execute_resume(target, true);
- if (result != ERROR_OK)
- return result;
- time_t start = time(NULL);
- while (1) {
- result = poll_target(target, announce);
- if (result != ERROR_OK)
- return result;
- if (target->state != TARGET_DEBUG_RUNNING)
- break;
- if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
- LOG_ERROR("Timed out waiting for step to complete.");
- return ERROR_FAIL;
- }
- }
- return ERROR_OK;
-}
-
-static int resume(struct target *target, int debug_execution, bool step)
-{
- if (debug_execution) {
- LOG_ERROR("TODO: debug_execution is true");
- return ERROR_FAIL;
- }
-
- return execute_resume(target, step);
-}
-
-/** Update register sizes based on xlen. */
-static void update_reg_list(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
- if (info->reg_values) {
- free(info->reg_values);
- }
- info->reg_values = malloc(REG_COUNT * riscv_xlen(target) / 4);
-
- for (unsigned int i = 0; i < REG_COUNT; i++) {
- struct reg *r = &target->reg_cache->reg_list[i];
- r->value = info->reg_values + i * riscv_xlen(target) / 4;
- if (r->dirty) {
- LOG_ERROR("Register %d was dirty. Its value is lost.", i);
- }
- if (i == REG_PRIV) {
- r->size = 8;
- } else {
- r->size = riscv_xlen(target);
- }
- r->valid = false;
- }
-}
-
-static uint64_t reg_cache_get(struct target *target, unsigned int number)
-{
- struct reg *r = &target->reg_cache->reg_list[number];
- if (!r->valid) {
- LOG_ERROR("Register cache entry for %d is invalid!", number);
- assert(r->valid);
- }
- uint64_t value = buf_get_u64(r->value, 0, r->size);
- LOG_DEBUG("%s = 0x%" PRIx64, r->name, value);
- return value;
-}
-
-static void reg_cache_set(struct target *target, unsigned int number,
- uint64_t value)
-{
- struct reg *r = &target->reg_cache->reg_list[number];
- LOG_DEBUG("%s <= 0x%" PRIx64, r->name, value);
- r->valid = true;
- buf_set_u64(r->value, 0, r->size, value);
-}
-
-static int update_mstatus_actual(struct target *target)
-{
- struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS];
- if (mstatus_reg->valid) {
- // We previously made it valid.
- return ERROR_OK;
- }
-
- // Force reading the register. In that process mstatus_actual will be
- // updated.
- return register_get(&target->reg_cache->reg_list[REG_MSTATUS]);
-}
-
-/*** OpenOCD target functions. ***/
-
-static int register_get(struct reg *reg)
-{
- struct target *target = (struct target *) reg->arch_info;
- riscv011_info_t *info = get_info(target);
-
- maybe_write_tselect(target);
-
- if (reg->number <= REG_XPR31) {
- buf_set_u64(reg->value, 0, riscv_xlen(target), reg_cache_get(target, reg->number));
- LOG_DEBUG("%s=0x%" PRIx64, reg->name, reg_cache_get(target, reg->number));
- return ERROR_OK;
- } else if (reg->number == REG_PC) {
- buf_set_u32(reg->value, 0, 32, info->dpc);
- reg->valid = true;
- LOG_DEBUG("%s=0x%" PRIx64 " (cached)", reg->name, info->dpc);
- return ERROR_OK;
- } else if (reg->number >= REG_FPR0 && reg->number <= REG_FPR31) {
- int result = update_mstatus_actual(target);
- if (result != ERROR_OK) {
- return result;
- }
- unsigned i = 0;
- if ((info->mstatus_actual & MSTATUS_FS) == 0) {
- info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1);
- cache_set_load(target, i++, S0, SLOT1);
- cache_set32(target, i++, csrw(S0, CSR_MSTATUS));
- cache_set(target, SLOT1, info->mstatus_actual);
- }
-
- if (riscv_xlen(target) == 32) {
- cache_set32(target, i++, fsw(reg->number - REG_FPR0, 0, DEBUG_RAM_START + 16));
- } else {
- cache_set32(target, i++, fsd(reg->number - REG_FPR0, 0, DEBUG_RAM_START + 16));
- }
- cache_set_jump(target, i++);
- } else if (reg->number >= REG_CSR0 && reg->number <= REG_CSR4095) {
- cache_set32(target, 0, csrr(S0, reg->number - REG_CSR0));
- cache_set_store(target, 1, S0, SLOT0);
- cache_set_jump(target, 2);
- } else if (reg->number == REG_PRIV) {
- buf_set_u64(reg->value, 0, 8, get_field(info->dcsr, DCSR_PRV));
- LOG_DEBUG("%s=%d (cached)", reg->name,
- (int) get_field(info->dcsr, DCSR_PRV));
- return ERROR_OK;
- } else {
- LOG_ERROR("Don't know how to read register %d (%s)", reg->number, reg->name);
- return ERROR_FAIL;
- }
-
- if (cache_write(target, 4, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- uint32_t exception = cache_get32(target, info->dramsize-1);
- if (exception) {
- LOG_ERROR("Got exception 0x%x when reading register %d", exception,
- reg->number);
- buf_set_u64(reg->value, 0, riscv_xlen(target), ~0);
- return ERROR_FAIL;
- }
-
- uint64_t value = cache_get(target, SLOT0);
- LOG_DEBUG("%s=0x%" PRIx64, reg->name, value);
- buf_set_u64(reg->value, 0, riscv_xlen(target), value);
-
- if (reg->number == REG_MSTATUS) {
- info->mstatus_actual = value;
- reg->valid = true;
- }
-
- return ERROR_OK;
-}
-
-static int register_write(struct target *target, unsigned int number,
- uint64_t value)
-{
- riscv011_info_t *info = get_info(target);
-
- maybe_write_tselect(target);
-
- if (number == S0) {
- cache_set_load(target, 0, S0, SLOT0);
- cache_set32(target, 1, csrw(S0, CSR_DSCRATCH));
- cache_set_jump(target, 2);
- } else if (number == S1) {
- cache_set_load(target, 0, S0, SLOT0);
- cache_set_store(target, 1, S0, SLOT_LAST);
- cache_set_jump(target, 2);
- } else if (number <= REG_XPR31) {
- cache_set_load(target, 0, number - REG_XPR0, SLOT0);
- cache_set_jump(target, 1);
- } else if (number == REG_PC) {
- info->dpc = value;
- return ERROR_OK;
- } else if (number >= REG_FPR0 && number <= REG_FPR31) {
- int result = update_mstatus_actual(target);
- if (result != ERROR_OK) {
- return result;
- }
- unsigned i = 0;
- if ((info->mstatus_actual & MSTATUS_FS) == 0) {
- info->mstatus_actual = set_field(info->mstatus_actual, MSTATUS_FS, 1);
- cache_set_load(target, i++, S0, SLOT1);
- cache_set32(target, i++, csrw(S0, CSR_MSTATUS));
- cache_set(target, SLOT1, info->mstatus_actual);
- }
-
- if (riscv_xlen(target) == 32) {
- cache_set32(target, i++, flw(number - REG_FPR0, 0, DEBUG_RAM_START + 16));
- } else {
- cache_set32(target, i++, fld(number - REG_FPR0, 0, DEBUG_RAM_START + 16));
- }
- cache_set_jump(target, i++);
- } else if (number >= REG_CSR0 && number <= REG_CSR4095) {
- cache_set_load(target, 0, S0, SLOT0);
- cache_set32(target, 1, csrw(S0, number - REG_CSR0));
- cache_set_jump(target, 2);
-
- if (number == REG_MSTATUS) {
- info->mstatus_actual = value;
- }
- } else if (number == REG_PRIV) {
- info->dcsr = set_field(info->dcsr, DCSR_PRV, value);
- return ERROR_OK;
- } else {
- LOG_ERROR("Don't know how to write register %d", number);
- return ERROR_FAIL;
- }
-
- cache_set(target, SLOT0, value);
- if (cache_write(target, info->dramsize - 1, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- uint32_t exception = cache_get32(target, info->dramsize-1);
- if (exception) {
- LOG_ERROR("Got exception 0x%x when writing register %d", exception,
- number);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int register_set(struct reg *reg, uint8_t *buf)
-{
- struct target *target = (struct target *) reg->arch_info;
-
- uint64_t value = buf_get_u64(buf, 0, riscv_xlen(target));
-
- LOG_DEBUG("write 0x%" PRIx64 " to %s", value, reg->name);
- struct reg *r = &target->reg_cache->reg_list[reg->number];
- r->valid = true;
- memcpy(r->value, buf, (r->size + 7) / 8);
-
- return register_write(target, reg->number, value);
-}
-
-static struct reg_arch_type riscv_reg_arch_type = {
- .get = register_get,
- .set = register_set
-};
-
-static int halt(struct target *target)
-{
- LOG_DEBUG("riscv_halt()");
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- cache_set32(target, 0, csrsi(CSR_DCSR, DCSR_HALT));
- cache_set32(target, 1, csrr(S0, CSR_MHARTID));
- cache_set32(target, 2, sw(S0, ZERO, SETHALTNOT));
- cache_set_jump(target, 3);
-
- if (cache_write(target, 4, true) != ERROR_OK) {
- LOG_ERROR("cache_write() failed.");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-static int init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- LOG_DEBUG("init");
- riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
- generic_info->get_register = NULL;
- generic_info->version_specific = calloc(1, sizeof(riscv011_info_t));
- if (!generic_info->version_specific)
- return ERROR_FAIL;
- riscv011_info_t *info = get_info(target);
-
- target->reg_cache = calloc(1, sizeof(*target->reg_cache));
- target->reg_cache->name = "RISC-V registers";
- target->reg_cache->num_regs = REG_COUNT;
-
- target->reg_cache->reg_list = calloc(REG_COUNT, sizeof(struct reg));
-
- const unsigned int max_reg_name_len = 12;
- info->reg_names = calloc(1, REG_COUNT * max_reg_name_len);
- char *reg_name = info->reg_names;
- info->reg_values = NULL;
-
- for (unsigned int i = 0; i < REG_COUNT; i++) {
- struct reg *r = &target->reg_cache->reg_list[i];
- r->number = i;
- r->caller_save = true;
- r->dirty = false;
- r->valid = false;
- r->exist = true;
- r->type = &riscv_reg_arch_type;
- r->arch_info = target;
- if (i <= REG_XPR31) {
- sprintf(reg_name, "x%d", i);
- } else if (i == REG_PC) {
- sprintf(reg_name, "pc");
- } else if (i >= REG_FPR0 && i <= REG_FPR31) {
- sprintf(reg_name, "f%d", i - REG_FPR0);
- } else if (i >= REG_CSR0 && i <= REG_CSR4095) {
- sprintf(reg_name, "csr%d", i - REG_CSR0);
- } else if (i == REG_PRIV) {
- sprintf(reg_name, "priv");
- }
- if (reg_name[0]) {
- r->name = reg_name;
- }
- reg_name += strlen(reg_name) + 1;
- assert(reg_name < info->reg_names + REG_COUNT * max_reg_name_len);
- }
- update_reg_list(target);
-
- memset(info->trigger_unique_id, 0xff, sizeof(info->trigger_unique_id));
-
- return ERROR_OK;
-}
-
-static void deinit_target(struct target *target)
-{
- LOG_DEBUG("riscv_deinit_target()");
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
- free(info->version_specific);
- info->version_specific = NULL;
-}
-
-static int add_trigger(struct target *target, struct trigger *trigger)
-{
- riscv011_info_t *info = get_info(target);
-
- maybe_read_tselect(target);
-
- unsigned int i;
- for (i = 0; i < info->trigger_count; i++) {
- if (info->trigger_unique_id[i] != -1) {
- continue;
- }
-
- write_csr(target, CSR_TSELECT, i);
-
- uint64_t tdata1;
- read_csr(target, &tdata1, CSR_TDATA1);
- int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
-
- if (type != 2) {
- continue;
- }
-
- if (tdata1 & (MCONTROL_EXECUTE | MCONTROL_STORE | MCONTROL_LOAD)) {
- // Trigger is already in use, presumably by user code.
- continue;
- }
-
- // address/data match trigger
- tdata1 |= MCONTROL_DMODE(riscv_xlen(target));
- tdata1 = set_field(tdata1, MCONTROL_ACTION,
- MCONTROL_ACTION_DEBUG_MODE);
- tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL);
- tdata1 |= MCONTROL_M;
- if (info->misa & (1 << ('H' - 'A')))
- tdata1 |= MCONTROL_H;
- if (info->misa & (1 << ('S' - 'A')))
- tdata1 |= MCONTROL_S;
- if (info->misa & (1 << ('U' - 'A')))
- tdata1 |= MCONTROL_U;
-
- if (trigger->execute)
- tdata1 |= MCONTROL_EXECUTE;
- if (trigger->read)
- tdata1 |= MCONTROL_LOAD;
- if (trigger->write)
- tdata1 |= MCONTROL_STORE;
-
- write_csr(target, CSR_TDATA1, tdata1);
-
- uint64_t tdata1_rb;
- read_csr(target, &tdata1_rb, CSR_TDATA1);
- LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
-
- if (tdata1 != tdata1_rb) {
- LOG_DEBUG("Trigger %d doesn't support what we need; After writing 0x%"
- PRIx64 " to tdata1 it contains 0x%" PRIx64,
- i, tdata1, tdata1_rb);
- write_csr(target, CSR_TDATA1, 0);
- continue;
- }
-
- write_csr(target, CSR_TDATA2, trigger->address);
-
- LOG_DEBUG("Using resource %d for bp %d", i,
- trigger->unique_id);
- info->trigger_unique_id[i] = trigger->unique_id;
- break;
- }
- if (i >= info->trigger_count) {
- LOG_ERROR("Couldn't find an available hardware trigger.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- return ERROR_OK;
-}
-
-static int remove_trigger(struct target *target, struct trigger *trigger)
-{
- riscv011_info_t *info = get_info(target);
-
- maybe_read_tselect(target);
-
- unsigned int i;
- for (i = 0; i < info->trigger_count; i++) {
- if (info->trigger_unique_id[i] == trigger->unique_id) {
- break;
- }
- }
- if (i >= info->trigger_count) {
- LOG_ERROR("Couldn't find the hardware resources used by hardware "
- "trigger.");
- return ERROR_FAIL;
- }
- LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id);
- write_csr(target, CSR_TSELECT, i);
- write_csr(target, CSR_TDATA1, 0);
- info->trigger_unique_id[i] = -1;
-
- return ERROR_OK;
-}
-
-static void trigger_from_breakpoint(struct trigger *trigger,
- const struct breakpoint *breakpoint)
-{
- trigger->address = breakpoint->address;
- trigger->length = breakpoint->length;
- trigger->mask = ~0LL;
- trigger->read = false;
- trigger->write = false;
- trigger->execute = true;
- // unique_id is unique across both breakpoints and watchpoints.
- trigger->unique_id = breakpoint->unique_id;
-}
-
-static void trigger_from_watchpoint(struct trigger *trigger,
- const struct watchpoint *watchpoint)
-{
- trigger->address = watchpoint->address;
- trigger->length = watchpoint->length;
- trigger->mask = watchpoint->mask;
- trigger->value = watchpoint->value;
- trigger->read = (watchpoint->rw == WPT_READ || watchpoint->rw == WPT_ACCESS);
- trigger->write = (watchpoint->rw == WPT_WRITE || watchpoint->rw == WPT_ACCESS);
- trigger->execute = false;
- // unique_id is unique across both breakpoints and watchpoints.
- trigger->unique_id = watchpoint->unique_id;
-}
-
-static int add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- if (breakpoint->type == BKPT_SOFT) {
- if (target_read_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr) != ERROR_OK) {
- LOG_ERROR("Failed to read original instruction at 0x%x",
- breakpoint->address);
- return ERROR_FAIL;
- }
-
- int retval;
- if (breakpoint->length == 4) {
- retval = target_write_u32(target, breakpoint->address, ebreak());
- } else {
- retval = target_write_u16(target, breakpoint->address, ebreak_c());
- }
- if (retval != ERROR_OK) {
- LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%x",
- breakpoint->length, breakpoint->address);
- return ERROR_FAIL;
- }
-
- } else if (breakpoint->type == BKPT_HARD) {
- struct trigger trigger;
- trigger_from_breakpoint(&trigger, breakpoint);
- int result = add_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
-
- } else {
- LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- breakpoint->set = true;
-
- return ERROR_OK;
-}
-
-static int remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- if (breakpoint->type == BKPT_SOFT) {
- if (target_write_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr) != ERROR_OK) {
- LOG_ERROR("Failed to restore instruction for %d-byte breakpoint at "
- "0x%x", breakpoint->length, breakpoint->address);
- return ERROR_FAIL;
- }
-
- } else if (breakpoint->type == BKPT_HARD) {
- struct trigger trigger;
- trigger_from_breakpoint(&trigger, breakpoint);
- int result = remove_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
-
- } else {
- LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- breakpoint->set = false;
-
- return ERROR_OK;
-}
-
-static int add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct trigger trigger;
- trigger_from_watchpoint(&trigger, watchpoint);
-
- int result = add_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
- watchpoint->set = true;
-
- return ERROR_OK;
-}
-
-static int remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct trigger trigger;
- trigger_from_watchpoint(&trigger, watchpoint);
-
- int result = remove_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
- watchpoint->set = false;
-
- return ERROR_OK;
-}
-
-static int strict_step(struct target *target, bool announce)
-{
- riscv011_info_t *info = get_info(target);
-
- LOG_DEBUG("enter");
-
- struct breakpoint *breakpoint = target->breakpoints;
- while (breakpoint) {
- remove_breakpoint(target, breakpoint);
- breakpoint = breakpoint->next;
- }
-
- struct watchpoint *watchpoint = target->watchpoints;
- while (watchpoint) {
- remove_watchpoint(target, watchpoint);
- watchpoint = watchpoint->next;
- }
-
- int result = full_step(target, announce);
- if (result != ERROR_OK)
- return result;
-
- breakpoint = target->breakpoints;
- while (breakpoint) {
- add_breakpoint(target, breakpoint);
- breakpoint = breakpoint->next;
- }
-
- watchpoint = target->watchpoints;
- while (watchpoint) {
- add_watchpoint(target, watchpoint);
- watchpoint = watchpoint->next;
- }
-
- info->need_strict_step = false;
-
- return ERROR_OK;
-}
-
-static int step(struct target *target, int current, uint32_t address,
- int handle_breakpoints)
-{
- riscv011_info_t *info = get_info(target);
-
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- if (!current) {
- if (riscv_xlen(target) > 32) {
- LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.",
- riscv_xlen(target));
- }
- int result = register_write(target, REG_PC, address);
- if (result != ERROR_OK)
- return result;
- }
-
- if (info->need_strict_step || handle_breakpoints) {
- int result = strict_step(target, true);
- if (result != ERROR_OK)
- return result;
- } else {
- return resume(target, 0, true);
- }
-
- return ERROR_OK;
-}
-
-static int examine(struct target *target)
-{
- // Don't need to select dbus, since the first thing we do is read dtmcontrol.
-
- uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
- LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
- LOG_DEBUG(" addrbits=%d", get_field(dtmcontrol, DTMCONTROL_ADDRBITS));
- LOG_DEBUG(" version=%d", get_field(dtmcontrol, DTMCONTROL_VERSION));
- LOG_DEBUG(" idle=%d", get_field(dtmcontrol, DTMCONTROL_IDLE));
- if (dtmcontrol == 0) {
- LOG_ERROR("dtmcontrol is 0. Check JTAG connectivity/board power.");
- return ERROR_FAIL;
- }
- if (get_field(dtmcontrol, DTMCONTROL_VERSION) != 0) {
- LOG_ERROR("Unsupported DTM version %d. (dtmcontrol=0x%x)",
- get_field(dtmcontrol, DTMCONTROL_VERSION), dtmcontrol);
- return ERROR_FAIL;
- }
-
- riscv011_info_t *info = get_info(target);
- info->addrbits = get_field(dtmcontrol, DTMCONTROL_ADDRBITS);
- info->dtmcontrol_idle = get_field(dtmcontrol, DTMCONTROL_IDLE);
- if (info->dtmcontrol_idle == 0) {
- // Some old SiFive cores don't set idle but need it to be 1.
- uint32_t idcode = idcode_scan(target);
- if (idcode == 0x10e31913)
- info->dtmcontrol_idle = 1;
- }
-
- uint32_t dminfo = dbus_read(target, DMINFO);
- LOG_DEBUG("dminfo: 0x%08x", dminfo);
- LOG_DEBUG(" abussize=0x%x", get_field(dminfo, DMINFO_ABUSSIZE));
- LOG_DEBUG(" serialcount=0x%x", get_field(dminfo, DMINFO_SERIALCOUNT));
- LOG_DEBUG(" access128=%d", get_field(dminfo, DMINFO_ACCESS128));
- LOG_DEBUG(" access64=%d", get_field(dminfo, DMINFO_ACCESS64));
- LOG_DEBUG(" access32=%d", get_field(dminfo, DMINFO_ACCESS32));
- LOG_DEBUG(" access16=%d", get_field(dminfo, DMINFO_ACCESS16));
- LOG_DEBUG(" access8=%d", get_field(dminfo, DMINFO_ACCESS8));
- LOG_DEBUG(" dramsize=0x%x", get_field(dminfo, DMINFO_DRAMSIZE));
- LOG_DEBUG(" authenticated=0x%x", get_field(dminfo, DMINFO_AUTHENTICATED));
- LOG_DEBUG(" authbusy=0x%x", get_field(dminfo, DMINFO_AUTHBUSY));
- LOG_DEBUG(" authtype=0x%x", get_field(dminfo, DMINFO_AUTHTYPE));
- LOG_DEBUG(" version=0x%x", get_field(dminfo, DMINFO_VERSION));
-
- if (get_field(dminfo, DMINFO_VERSION) != 1) {
- LOG_ERROR("OpenOCD only supports Debug Module version 1, not %d "
- "(dminfo=0x%x)", get_field(dminfo, DMINFO_VERSION), dminfo);
- return ERROR_FAIL;
- }
-
- info->dramsize = get_field(dminfo, DMINFO_DRAMSIZE) + 1;
-
- if (get_field(dminfo, DMINFO_AUTHTYPE) != 0) {
- LOG_ERROR("Authentication required by RISC-V core but not "
- "supported by OpenOCD. dminfo=0x%x", dminfo);
- return ERROR_FAIL;
- }
-
- // Figure out XLEN, and test writing all of Debug RAM while we're at it.
- cache_set32(target, 0, xori(S1, ZERO, -1));
- // 0xffffffff 0xffffffff:ffffffff 0xffffffff:ffffffff:ffffffff:ffffffff
- cache_set32(target, 1, srli(S1, S1, 31));
- // 0x00000001 0x00000001:ffffffff 0x00000001:ffffffff:ffffffff:ffffffff
- cache_set32(target, 2, sw(S1, ZERO, DEBUG_RAM_START));
- cache_set32(target, 3, srli(S1, S1, 31));
- // 0x00000000 0x00000000:00000003 0x00000000:00000003:ffffffff:ffffffff
- cache_set32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4));
- cache_set_jump(target, 5);
- for (unsigned i = 6; i < info->dramsize; i++) {
- cache_set32(target, i, i * 0x01020304);
- }
-
- cache_write(target, 0, false);
-
- // Check that we can actually read/write dram.
- if (cache_check(target) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- cache_write(target, 0, true);
- cache_invalidate(target);
-
- uint32_t word0 = cache_get32(target, 0);
- uint32_t word1 = cache_get32(target, 1);
- riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
- if (word0 == 1 && word1 == 0) {
- generic_info->xlen[0] = 32;
- } else if (word0 == 0xffffffff && word1 == 3) {
- generic_info->xlen[0] = 64;
- } else if (word0 == 0xffffffff && word1 == 0xffffffff) {
- generic_info->xlen[0] = 128;
- } else {
- uint32_t exception = cache_get32(target, info->dramsize-1);
- LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x, exception=0x%x",
- word0, word1, exception);
- dump_debug_ram(target);
- return ERROR_FAIL;
- }
- LOG_DEBUG("Discovered XLEN is %d", riscv_xlen(target));
-
- // Update register list to match discovered XLEN.
- update_reg_list(target);
-
- if (read_csr(target, &info->misa, CSR_MISA) != ERROR_OK) {
- LOG_ERROR("Failed to read misa.");
- return ERROR_FAIL;
- }
-
- info->never_halted = true;
-
- int result = riscv011_poll(target);
- if (result != ERROR_OK) {
- return result;
- }
-
- target_set_examined(target);
- LOG_INFO("Examined RISCV core; XLEN=%d, misa=0x%" PRIx64, riscv_xlen(target), info->misa);
-
- return ERROR_OK;
-}
-
-static riscv_error_t handle_halt_routine(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
-
- scans_t *scans = scans_new(target, 256);
-
- // Read all GPRs as fast as we can, because gdb is going to ask for them
- // anyway. Reading them one at a time is much slower.
-
- // Write the jump back to address 1.
- scans_add_write_jump(scans, 1, false);
- for (int reg = 1; reg < 32; reg++) {
- if (reg == S0 || reg == S1) {
- continue;
- }
-
- // Write store instruction.
- scans_add_write_store(scans, 0, reg, SLOT0, true);
-
- // Read value.
- scans_add_read(scans, SLOT0, false);
- }
-
- // Write store of s0 at index 1.
- scans_add_write_store(scans, 1, S0, SLOT0, false);
- // Write jump at index 2.
- scans_add_write_jump(scans, 2, false);
-
- // Read S1 from debug RAM
- scans_add_write_load(scans, 0, S0, SLOT_LAST, true);
- // Read value.
- scans_add_read(scans, SLOT0, false);
-
- // Read S0 from dscratch
- unsigned int csr[] = {CSR_DSCRATCH, CSR_DPC, CSR_DCSR};
- for (unsigned int i = 0; i < DIM(csr); i++) {
- scans_add_write32(scans, 0, csrr(S0, csr[i]), true);
- scans_add_read(scans, SLOT0, false);
- }
-
- // Final read to get the last value out.
- scans_add_read32(scans, 4, false);
-
- int retval = scans_execute(scans);
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG execute failed: %d", retval);
- goto error;
- }
-
- unsigned int dbus_busy = 0;
- unsigned int interrupt_set = 0;
- unsigned result = 0;
- uint64_t value = 0;
- reg_cache_set(target, 0, 0);
- // The first scan result is the result from something old we don't care
- // about.
- for (unsigned int i = 1; i < scans->next_scan && dbus_busy == 0; i++) {
- dbus_status_t status = scans_get_u32(scans, i, DBUS_OP_START,
- DBUS_OP_SIZE);
- uint64_t data = scans_get_u64(scans, i, DBUS_DATA_START, DBUS_DATA_SIZE);
- uint32_t address = scans_get_u32(scans, i, DBUS_ADDRESS_START,
- info->addrbits);
- switch (status) {
- case DBUS_STATUS_SUCCESS:
- break;
- case DBUS_STATUS_FAILED:
- LOG_ERROR("Debug access failed. Hardware error?");
- goto error;
- case DBUS_STATUS_BUSY:
- dbus_busy++;
- break;
- default:
- LOG_ERROR("Got invalid bus access status: %d", status);
- return ERROR_FAIL;
- }
- if (data & DMCONTROL_INTERRUPT) {
- interrupt_set++;
- break;
- }
- if (address == 4 || address == 5) {
- unsigned int reg;
- switch (result) {
- case 0: reg = 1; break;
- case 1: reg = 2; break;
- case 2: reg = 3; break;
- case 3: reg = 4; break;
- case 4: reg = 5; break;
- case 5: reg = 6; break;
- case 6: reg = 7; break;
- // S0
- // S1
- case 7: reg = 10; break;
- case 8: reg = 11; break;
- case 9: reg = 12; break;
- case 10: reg = 13; break;
- case 11: reg = 14; break;
- case 12: reg = 15; break;
- case 13: reg = 16; break;
- case 14: reg = 17; break;
- case 15: reg = 18; break;
- case 16: reg = 19; break;
- case 17: reg = 20; break;
- case 18: reg = 21; break;
- case 19: reg = 22; break;
- case 20: reg = 23; break;
- case 21: reg = 24; break;
- case 22: reg = 25; break;
- case 23: reg = 26; break;
- case 24: reg = 27; break;
- case 25: reg = 28; break;
- case 26: reg = 29; break;
- case 27: reg = 30; break;
- case 28: reg = 31; break;
- case 29: reg = S1; break;
- case 30: reg = S0; break;
- case 31: reg = CSR_DPC; break;
- case 32: reg = CSR_DCSR; break;
- default:
- assert(0);
- }
- if (riscv_xlen(target) == 32) {
- reg_cache_set(target, reg, data & 0xffffffff);
- result++;
- } else if (riscv_xlen(target) == 64) {
- if (address == 4) {
- value = data & 0xffffffff;
- } else if (address == 5) {
- reg_cache_set(target, reg, ((data & 0xffffffff) << 32) | value);
- value = 0;
- result++;
- }
- }
- }
- }
-
- if (dbus_busy) {
- increase_dbus_busy_delay(target);
- return RE_AGAIN;
- }
- if (interrupt_set) {
- increase_interrupt_high_delay(target);
- return RE_AGAIN;
- }
-
- // TODO: get rid of those 2 variables and talk to the cache directly.
- info->dpc = reg_cache_get(target, CSR_DPC);
- info->dcsr = reg_cache_get(target, CSR_DCSR);
-
- scans = scans_delete(scans);
-
- cache_invalidate(target);
-
- return RE_OK;
-
-error:
- scans = scans_delete(scans);
- return RE_FAIL;
-}
-
-static int handle_halt(struct target *target, bool announce)
-{
- riscv011_info_t *info = get_info(target);
- target->state = TARGET_HALTED;
-
- riscv_error_t re;
- do {
- re = handle_halt_routine(target);
- } while (re == RE_AGAIN);
- if (re != RE_OK) {
- LOG_ERROR("handle_halt_routine failed");
- return ERROR_FAIL;
- }
-
- int cause = get_field(info->dcsr, DCSR_CAUSE);
- switch (cause) {
- case DCSR_CAUSE_SWBP:
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case DCSR_CAUSE_HWBP:
- target->debug_reason = DBG_REASON_WPTANDBKPT;
- // If we halted because of a data trigger, gdb doesn't know to do
- // the disable-breakpoints-step-enable-breakpoints dance.
- info->need_strict_step = true;
- break;
- case DCSR_CAUSE_DEBUGINT:
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case DCSR_CAUSE_STEP:
- target->debug_reason = DBG_REASON_SINGLESTEP;
- break;
- case DCSR_CAUSE_HALT:
- default:
- LOG_ERROR("Invalid halt cause %d in DCSR (0x%" PRIx64 ")",
- cause, info->dcsr);
- }
-
- if (info->never_halted) {
- info->never_halted = false;
-
- // Disable any hardware triggers that have dmode set. We can't have set
- // them ourselves. Maybe they're left over from some killed debug
- // session.
- // Count the number of triggers while we're at it.
-
- int result = maybe_read_tselect(target);
- if (result != ERROR_OK)
- return result;
- for (info->trigger_count = 0; info->trigger_count < MAX_HWBPS; info->trigger_count++) {
- write_csr(target, CSR_TSELECT, info->trigger_count);
- uint64_t tselect_rb;
- read_csr(target, &tselect_rb, CSR_TSELECT);
- if (info->trigger_count != tselect_rb)
- break;
- uint64_t tdata1;
- read_csr(target, &tdata1, CSR_TDATA1);
- if ((tdata1 & MCONTROL_DMODE(riscv_xlen(target))) &&
- (tdata1 & (MCONTROL_EXECUTE | MCONTROL_STORE | MCONTROL_LOAD))) {
- write_csr(target, CSR_TDATA1, 0);
- }
- }
- }
-
- if (announce) {
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- }
-
- const char *cause_string[] = {
- "none",
- "software breakpoint",
- "hardware trigger",
- "debug interrupt",
- "step",
- "halt"
- };
- // This is logged to the user so that gdb will show it when a user types
- // 'monitor reset init'. At that time gdb appears to have the pc cached
- // still so if a user manually inspects the pc it will still have the old
- // value.
- LOG_USER("halted at 0x%" PRIx64 " due to %s", info->dpc, cause_string[cause]);
-
- return ERROR_OK;
-}
-
-static int poll_target(struct target *target, bool announce)
-{
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- // Inhibit debug logging during poll(), which isn't usually interesting and
- // just fills up the screen/logs with clutter.
- int old_debug_level = debug_level;
- if (debug_level >= LOG_LVL_DEBUG) {
- debug_level = LOG_LVL_INFO;
- }
- bits_t bits = read_bits(target);
- debug_level = old_debug_level;
-
- if (bits.haltnot && bits.interrupt) {
- target->state = TARGET_DEBUG_RUNNING;
- LOG_DEBUG("debug running");
- } else if (bits.haltnot && !bits.interrupt) {
- if (target->state != TARGET_HALTED) {
- return handle_halt(target, announce);
- }
- } else if (!bits.haltnot && bits.interrupt) {
- // Target is halting. There is no state for that, so don't change anything.
- LOG_DEBUG("halting");
- } else if (!bits.haltnot && !bits.interrupt) {
- target->state = TARGET_RUNNING;
- }
-
- return ERROR_OK;
-}
-
-static int riscv011_poll(struct target *target)
-{
- return poll_target(target, true);
-}
-
-static int riscv011_resume(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution)
-{
- riscv011_info_t *info = get_info(target);
-
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- if (!current) {
- if (riscv_xlen(target) > 32) {
- LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.",
- riscv_xlen(target));
- }
- int result = register_write(target, REG_PC, address);
- if (result != ERROR_OK)
- return result;
- }
-
- if (info->need_strict_step || handle_breakpoints) {
- int result = strict_step(target, false);
- if (result != ERROR_OK)
- return result;
- }
-
- return resume(target, debug_execution, false);
-}
-
-static int assert_reset(struct target *target)
-{
- riscv011_info_t *info = get_info(target);
- // TODO: Maybe what I implemented here is more like soft_reset_halt()?
-
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- // The only assumption we can make is that the TAP was reset.
- if (wait_for_debugint_clear(target, true) != ERROR_OK) {
- LOG_ERROR("Debug interrupt didn't clear.");
- return ERROR_FAIL;
- }
-
- // Not sure what we should do when there are multiple cores.
- // Here just reset the single hart we're talking to.
- info->dcsr |= DCSR_EBREAKM | DCSR_EBREAKH | DCSR_EBREAKS |
- DCSR_EBREAKU | DCSR_HALT;
- if (target->reset_halt) {
- info->dcsr |= DCSR_NDRESET;
- } else {
- info->dcsr |= DCSR_FULLRESET;
- }
- dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false);
- dram_write32(target, 1, csrw(S0, CSR_DCSR), false);
- // We shouldn't actually need the jump because a reset should happen.
- dram_write_jump(target, 2, false);
- dram_write32(target, 4, info->dcsr, true);
- cache_invalidate(target);
-
- target->state = TARGET_RESET;
-
- return ERROR_OK;
-}
-
-static int deassert_reset(struct target *target)
-{
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
- if (target->reset_halt) {
- return wait_for_state(target, TARGET_HALTED);
- } else {
- return wait_for_state(target, TARGET_RUNNING);
- }
-}
-
-static int read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- cache_set32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16));
- switch (size) {
- case 1:
- cache_set32(target, 1, lb(S1, S0, 0));
- cache_set32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16));
- break;
- case 2:
- cache_set32(target, 1, lh(S1, S0, 0));
- cache_set32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16));
- break;
- case 4:
- cache_set32(target, 1, lw(S1, S0, 0));
- cache_set32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16));
- break;
- default:
- LOG_ERROR("Unsupported size: %d", size);
- return ERROR_FAIL;
- }
- cache_set_jump(target, 3);
- cache_write(target, CACHE_NO_READ, false);
-
- riscv011_info_t *info = get_info(target);
- const int max_batch_size = 256;
- scans_t *scans = scans_new(target, max_batch_size);
-
- uint32_t result_value = 0x777;
- uint32_t i = 0;
- while (i < count + 3) {
- unsigned int batch_size = MIN(count + 3 - i, max_batch_size);
- scans_reset(scans);
-
- for (unsigned int j = 0; j < batch_size; j++) {
- if (i + j == count) {
- // Just insert a read so we can scan out the last value.
- scans_add_read32(scans, 4, false);
- } else if (i + j >= count + 1) {
- // And check for errors.
- scans_add_read32(scans, info->dramsize-1, false);
- } else {
- // Write the next address and set interrupt.
- uint32_t offset = size * (i + j);
- scans_add_write32(scans, 4, address + offset, true);
- }
- }
-
- int retval = scans_execute(scans);
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG execute failed: %d", retval);
- goto error;
- }
-
- int dbus_busy = 0;
- int execute_busy = 0;
- for (unsigned int j = 0; j < batch_size; j++) {
- dbus_status_t status = scans_get_u32(scans, j, DBUS_OP_START,
- DBUS_OP_SIZE);
- switch (status) {
- case DBUS_STATUS_SUCCESS:
- break;
- case DBUS_STATUS_FAILED:
- LOG_ERROR("Debug RAM write failed. Hardware error?");
- goto error;
- case DBUS_STATUS_BUSY:
- dbus_busy++;
- break;
- default:
- LOG_ERROR("Got invalid bus access status: %d", status);
- return ERROR_FAIL;
- }
- uint64_t data = scans_get_u64(scans, j, DBUS_DATA_START,
- DBUS_DATA_SIZE);
- if (data & DMCONTROL_INTERRUPT) {
- execute_busy++;
- }
- if (i + j == count + 2) {
- result_value = data;
- } else if (i + j > 1) {
- uint32_t offset = size * (i + j - 2);
- switch (size) {
- case 1:
- buffer[offset] = data;
- break;
- case 2:
- buffer[offset] = data;
- buffer[offset+1] = data >> 8;
- break;
- case 4:
- buffer[offset] = data;
- buffer[offset+1] = data >> 8;
- buffer[offset+2] = data >> 16;
- buffer[offset+3] = data >> 24;
- break;
- }
- }
- LOG_DEBUG("j=%d status=%d data=%09" PRIx64, j, status, data);
- }
- if (dbus_busy) {
- increase_dbus_busy_delay(target);
- }
- if (execute_busy) {
- increase_interrupt_high_delay(target);
- }
- if (dbus_busy || execute_busy) {
- wait_for_debugint_clear(target, false);
-
- // Retry.
- LOG_INFO("Retrying memory read starting from 0x%x with more delays",
- address + size * i);
- } else {
- i += batch_size;
- }
- }
-
- if (result_value != 0) {
- LOG_USER("Core got an exception (0x%x) while reading from 0x%x",
- result_value, address + size * (count-1));
- if (count > 1) {
- LOG_USER("(It may have failed between 0x%x and 0x%x as well, but we "
- "didn't check then.)",
- address, address + size * (count-2) + size - 1);
- }
- goto error;
- }
-
- scans_delete(scans);
- cache_clean(target);
- return ERROR_OK;
-
-error:
- scans_delete(scans);
- cache_clean(target);
- return ERROR_FAIL;
-}
-
-static int setup_write_memory(struct target *target, uint32_t size)
-{
- switch (size) {
- case 1:
- cache_set32(target, 0, lb(S0, ZERO, DEBUG_RAM_START + 16));
- cache_set32(target, 1, sb(S0, T0, 0));
- break;
- case 2:
- cache_set32(target, 0, lh(S0, ZERO, DEBUG_RAM_START + 16));
- cache_set32(target, 1, sh(S0, T0, 0));
- break;
- case 4:
- cache_set32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16));
- cache_set32(target, 1, sw(S0, T0, 0));
- break;
- default:
- LOG_ERROR("Unsupported size: %d", size);
- return ERROR_FAIL;
- }
- cache_set32(target, 2, addi(T0, T0, size));
- cache_set_jump(target, 3);
- cache_write(target, 4, false);
-
- return ERROR_OK;
-}
-
-static int write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- riscv011_info_t *info = get_info(target);
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- // Set up the address.
- cache_set_store(target, 0, T0, SLOT1);
- cache_set_load(target, 1, T0, SLOT0);
- cache_set_jump(target, 2);
- cache_set(target, SLOT0, address);
- if (cache_write(target, 5, true) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- uint64_t t0 = cache_get(target, SLOT1);
- LOG_DEBUG("t0 is 0x%" PRIx64, t0);
-
- if (setup_write_memory(target, size) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- const int max_batch_size = 256;
- scans_t *scans = scans_new(target, max_batch_size);
-
- uint32_t result_value = 0x777;
- uint32_t i = 0;
- while (i < count + 2) {
- unsigned int batch_size = MIN(count + 2 - i, max_batch_size);
- scans_reset(scans);
-
- for (unsigned int j = 0; j < batch_size; j++) {
- if (i + j >= count) {
- // Check for an exception.
- scans_add_read32(scans, info->dramsize-1, false);
- } else {
- // Write the next value and set interrupt.
- uint32_t value;
- uint32_t offset = size * (i + j);
- switch (size) {
- case 1:
- value = buffer[offset];
- break;
- case 2:
- value = buffer[offset] |
- (buffer[offset+1] << 8);
- break;
- case 4:
- value = buffer[offset] |
- ((uint32_t) buffer[offset+1] << 8) |
- ((uint32_t) buffer[offset+2] << 16) |
- ((uint32_t) buffer[offset+3] << 24);
- break;
- default:
- goto error;
- }
-
- scans_add_write32(scans, 4, value, true);
- }
- }
-
- int retval = scans_execute(scans);
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG execute failed: %d", retval);
- goto error;
- }
-
- int dbus_busy = 0;
- int execute_busy = 0;
- for (unsigned int j = 0; j < batch_size; j++) {
- dbus_status_t status = scans_get_u32(scans, j, DBUS_OP_START,
- DBUS_OP_SIZE);
- switch (status) {
- case DBUS_STATUS_SUCCESS:
- break;
- case DBUS_STATUS_FAILED:
- LOG_ERROR("Debug RAM write failed. Hardware error?");
- goto error;
- case DBUS_STATUS_BUSY:
- dbus_busy++;
- break;
- default:
- LOG_ERROR("Got invalid bus access status: %d", status);
- return ERROR_FAIL;
- }
- int interrupt = scans_get_u32(scans, j, DBUS_DATA_START + 33, 1);
- if (interrupt) {
- execute_busy++;
- }
- if (i + j == count + 1) {
- result_value = scans_get_u32(scans, j, DBUS_DATA_START, 32);
- }
- }
- if (dbus_busy) {
- increase_dbus_busy_delay(target);
- }
- if (execute_busy) {
- increase_interrupt_high_delay(target);
- }
- if (dbus_busy || execute_busy) {
- wait_for_debugint_clear(target, false);
-
- // Retry.
- // Set t0 back to what it should have been at the beginning of this
- // batch.
- LOG_INFO("Retrying memory write starting from 0x%x with more delays",
- address + size * i);
-
- cache_clean(target);
-
- if (write_gpr(target, T0, address + size * i) != ERROR_OK) {
- goto error;
- }
-
- if (setup_write_memory(target, size) != ERROR_OK) {
- goto error;
- }
- } else {
- i += batch_size;
- }
- }
-
- if (result_value != 0) {
- LOG_ERROR("Core got an exception (0x%x) while writing to 0x%x",
- result_value, address + size * (count-1));
- if (count > 1) {
- LOG_ERROR("(It may have failed between 0x%x and 0x%x as well, but we "
- "didn't check then.)",
- address, address + size * (count-2) + size - 1);
- }
- goto error;
- }
-
- cache_clean(target);
- return register_write(target, T0, t0);
-
-error:
- scans_delete(scans);
- cache_clean(target);
- return ERROR_FAIL;
-}
-
-static int arch_state(struct target *target)
-{
- return ERROR_OK;
-}
-
-struct target_type riscv011_target =
-{
- .name = "riscv",
-
- .init_target = init_target,
- .deinit_target = deinit_target,
- .examine = examine,
-
- /* poll current target status */
- .poll = riscv011_poll,
-
- .halt = halt,
- .resume = riscv011_resume,
- .step = step,
-
- .assert_reset = assert_reset,
- .deassert_reset = deassert_reset,
-
- .read_memory = read_memory,
- .write_memory = write_memory,
-
- .add_breakpoint = add_breakpoint,
- .remove_breakpoint = remove_breakpoint,
-
- .add_watchpoint = add_watchpoint,
- .remove_watchpoint = remove_watchpoint,
-
- .arch_state = arch_state,
-};
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
deleted file mode 100644
index 2eb28bf..0000000
--- a/src/target/riscv/riscv-013.c
+++ /dev/null
@@ -1,1634 +0,0 @@
-/*
- * Support for RISC-V, debug version 0.13, which is currently (2/4/17) the
- * latest draft.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <time.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "target/algorithm.h"
-#include "target_type.h"
-#include "log.h"
-#include "jtag/jtag.h"
-#include "register.h"
-#include "breakpoints.h"
-#include "helper/time_support.h"
-#include "riscv.h"
-#include "debug_defines.h"
-#include "rtos/rtos.h"
-
-static void riscv013_on_step_or_resume(struct target *target, bool step);
-static void riscv013_step_or_resume_current_hart(struct target *target, bool step);
-
-/* Implementations of the functions in riscv_info_t. */
-static riscv_reg_t riscv013_get_register(struct target *target, int hartid, int regid);
-static void riscv013_set_register(struct target *target, int hartid, int regid, uint64_t value);
-static void riscv013_select_current_hart(struct target *target);
-static void riscv013_halt_current_hart(struct target *target);
-static void riscv013_resume_current_hart(struct target *target);
-static void riscv013_step_current_hart(struct target *target);
-static void riscv013_on_halt(struct target *target);
-static void riscv013_on_step(struct target *target);
-static void riscv013_on_resume(struct target *target);
-static bool riscv013_is_halted(struct target *target);
-static enum riscv_halt_reason riscv013_halt_reason(struct target *target);
-
-/**
- * Since almost everything can be accomplish by scanning the dbus register, all
- * functions here assume dbus is already selected. The exception are functions
- * called directly by OpenOCD, which can't assume anything about what's
- * currently in IR. They should set IR to dbus explicitly.
- */
-
-#define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
-#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
-
-#define DIM(x) (sizeof(x)/sizeof(*x))
-
-#define CSR_DCSR_CAUSE_SWBP 1
-#define CSR_DCSR_CAUSE_TRIGGER 2
-#define CSR_DCSR_CAUSE_DEBUGINT 3
-#define CSR_DCSR_CAUSE_STEP 4
-#define CSR_DCSR_CAUSE_HALT 5
-
-/*** JTAG registers. ***/
-
-typedef enum {
- DMI_OP_NOP = 0,
- DMI_OP_READ = 1,
- DMI_OP_WRITE = 2
-} dmi_op_t;
-typedef enum {
- DMI_STATUS_SUCCESS = 0,
- DMI_STATUS_FAILED = 2,
- DMI_STATUS_BUSY = 3
-} dmi_status_t;
-
-typedef enum {
- RE_OK,
- RE_FAIL,
- RE_AGAIN
-} riscv_error_t;
-
-typedef enum slot {
- SLOT0,
- SLOT1,
- SLOT_LAST,
-} slot_t;
-
-/*** Debug Bus registers. ***/
-
-#define CMDERR_NONE 0
-#define CMDERR_BUSY 1
-#define CMDERR_NOT_SUPPORTED 2
-#define CMDERR_EXCEPTION 3
-#define CMDERR_HALT_RESUME 4
-#define CMDERR_OTHER 7
-
-/*** Info about the core being debugged. ***/
-
-#define WALL_CLOCK_TIMEOUT 2
-
-#define MAX_HWBPS 16
-
-struct trigger {
- uint64_t address;
- uint32_t length;
- uint64_t mask;
- uint64_t value;
- bool read, write, execute;
- int unique_id;
-};
-
-struct memory_cache_line {
- uint32_t data;
- bool valid;
- bool dirty;
-};
-
-typedef struct {
- /* Number of address bits in the dbus register. */
- unsigned abits;
- /* Number of abstract command data registers. */
- unsigned datacount;
- /* Number of words in the Program Buffer. */
- unsigned progsize;
- /* Number of Program Buffer registers. */
- /* Number of words in Debug RAM. */
- uint64_t misa;
- uint64_t tselect;
- bool tselect_dirty;
- /* The value that mstatus actually has on the target right now. This is not
- * the value we present to the user. That one may be stored in the
- * reg_cache. */
- uint64_t mstatus_actual;
-
- /* Single buffer that contains all register names, instead of calling
- * malloc for each register. Needs to be freed when reg_list is freed. */
- char *reg_names;
- /* Single buffer that contains all register values. */
- void *reg_values;
-
- // For each physical trigger, contains -1 if the hwbp is available, or the
- // unique_id of the breakpoint/watchpoint that is using it.
- int trigger_unique_id[MAX_HWBPS];
-
- unsigned int trigger_count;
-
- // Number of run-test/idle cycles the target requests we do after each dbus
- // access.
- unsigned int dtmcontrol_idle;
-
- // This value is incremented every time a dbus access comes back as "busy".
- // It's used to determine how many run-test/idle cycles to feed the target
- // in between accesses.
- unsigned int dmi_busy_delay;
-
- // This value is increased every time we tried to execute two commands
- // consecutively, and the second one failed because the previous hadn't
- // completed yet. It's used to add extra run-test/idle cycles after
- // starting a command, so we don't have to waste time checking for busy to
- // go low.
- unsigned int ac_busy_delay;
-
- bool need_strict_step;
-} riscv013_info_t;
-
-static void dump_field(const struct scan_field *field)
-{
- static const char *op_string[] = {"-", "r", "w", "?"};
- static const char *status_string[] = {"+", "?", "F", "b"};
-
- if (debug_level < LOG_LVL_DEBUG)
- return;
-
- uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits);
- unsigned int out_op = get_field(out, DTM_DMI_OP);
- unsigned int out_data = get_field(out, DTM_DMI_DATA);
- unsigned int out_address = out >> DTM_DMI_ADDRESS_OFFSET;
-
- if (field->in_value) {
- uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
- unsigned int in_op = get_field(in, DTM_DMI_OP);
- unsigned int in_data = get_field(in, DTM_DMI_DATA);
- unsigned int in_address = in >> DTM_DMI_ADDRESS_OFFSET;
-
- log_printf_lf(LOG_LVL_DEBUG,
- __FILE__, __LINE__, "scan",
- "%db %s %08x @%02x -> %s %08x @%02x",
- field->num_bits,
- op_string[out_op], out_data, out_address,
- status_string[in_op], in_data, in_address);
- } else {
- log_printf_lf(LOG_LVL_DEBUG,
- __FILE__, __LINE__, "scan", "%db %s %08x @%02x -> ?",
- field->num_bits, op_string[out_op], out_data, out_address);
- }
-}
-
-static riscv013_info_t *get_info(const struct target *target)
-{
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
- return (riscv013_info_t *) info->version_specific;
-}
-
-/*** Necessary prototypes. ***/
-
-static int register_get(struct reg *reg);
-
-/*** Utility functions. ***/
-
-bool supports_extension(struct target *target, char letter)
-{
- riscv013_info_t *info = get_info(target);
- unsigned num;
- if (letter >= 'a' && letter <= 'z') {
- num = letter - 'a';
- } else if (letter >= 'A' && letter <= 'Z') {
- num = letter - 'A';
- } else {
- return false;
- }
- return info->misa & (1 << num);
-}
-
-static void select_dmi(struct target *target)
-{
- static uint8_t ir_dmi[1] = {DTM_DMI};
- struct scan_field field = {
- .num_bits = target->tap->ir_length,
- .out_value = ir_dmi,
- .in_value = NULL,
- .check_value = NULL,
- .check_mask = NULL
- };
-
- jtag_add_ir_scan(target->tap, &field, TAP_IDLE);
-}
-
-static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
-{
- struct scan_field field;
- uint8_t in_value[4];
- uint8_t out_value[4];
-
- buf_set_u32(out_value, 0, 32, out);
-
- jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE);
-
- field.num_bits = 32;
- field.out_value = out_value;
- field.in_value = in_value;
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- /* Always return to dmi. */
- select_dmi(target);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed jtag scan: %d", retval);
- return retval;
- }
-
- uint32_t in = buf_get_u32(field.in_value, 0, 32);
- LOG_DEBUG("DTMCS: 0x%x -> 0x%x", out, in);
-
- return in;
-}
-
-static void increase_dmi_busy_delay(struct target *target)
-{
- riscv013_info_t *info = get_info(target);
- info->dmi_busy_delay += info->dmi_busy_delay / 10 + 1;
- LOG_INFO("dtmcontrol_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d",
- info->dtmcontrol_idle, info->dmi_busy_delay,
- info->ac_busy_delay);
-
- dtmcontrol_scan(target, DTM_DTMCS_DMIRESET);
-}
-
-/**
- * exec: If this is set, assume the scan results in an execution, so more
- * run-test/idle cycles may be required.
- */
-static dmi_status_t dmi_scan(struct target *target, uint16_t *address_in,
- uint64_t *data_in, dmi_op_t op, uint16_t address_out, uint64_t data_out,
- bool exec)
-{
- riscv013_info_t *info = get_info(target);
- uint8_t in[8] = {0};
- uint8_t out[8];
- struct scan_field field = {
- .num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH,
- .out_value = out,
- };
-
- if (address_in || data_in) {
- field.in_value = in;
- }
-
- assert(info->abits != 0);
-
- buf_set_u64(out, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH, op);
- buf_set_u64(out, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH, data_out);
- buf_set_u64(out, DTM_DMI_ADDRESS_OFFSET, info->abits, address_out);
-
- /* Assume dbus is already selected. */
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- int idle_count = info->dtmcontrol_idle + info->dmi_busy_delay;
- if (exec)
- idle_count += info->ac_busy_delay;
-
- if (idle_count) {
- jtag_add_runtest(idle_count, TAP_IDLE);
- }
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("dmi_scan failed jtag scan");
- return DMI_STATUS_FAILED;
- }
-
- if (data_in) {
- *data_in = buf_get_u64(in, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
- }
-
- if (address_in) {
- *address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits);
- }
-
- dump_field(&field);
-
- return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
-}
-
-static uint64_t dmi_read(struct target *target, uint16_t address)
-{
- select_dmi(target);
-
- uint64_t value;
- dmi_status_t status;
- uint16_t address_in;
-
- unsigned i = 0;
- for (i = 0; i < 256; i++) {
- status = dmi_scan(target, NULL, NULL, DMI_OP_READ, address, 0,
- false);
- if (status == DMI_STATUS_BUSY) {
- increase_dmi_busy_delay(target);
- } else {
- break;
- }
- }
-
- status = dmi_scan(target, &address_in, &value, DMI_OP_NOP, address, 0,
- false);
-
- if (status != DMI_STATUS_SUCCESS) {
- LOG_ERROR("failed read from 0x%x; value=0x%" PRIx64 ", status=%d\n",
- address, value, status);
- }
-
- return value;
-}
-
-static void dmi_write(struct target *target, uint16_t address, uint64_t value)
-{
- select_dmi(target);
- dmi_status_t status = DMI_STATUS_BUSY;
- unsigned i = 0;
- while (status == DMI_STATUS_BUSY && i++ < 256) {
- dmi_scan(target, NULL, NULL, DMI_OP_WRITE, address, value,
- address == DMI_COMMAND);
- status = dmi_scan(target, NULL, NULL, DMI_OP_NOP, 0, 0, false);
- if (status == DMI_STATUS_BUSY) {
- increase_dmi_busy_delay(target);
- }
- }
- if (status != DMI_STATUS_SUCCESS) {
- LOG_ERROR("failed to write 0x%" PRIx64 " to 0x%x; status=%d\n", value, address, status);
- }
-}
-
-/** Convert register number (internal OpenOCD number) to the number expected by
- * the abstract command interface. */
-static unsigned reg_number_to_no(unsigned reg_num)
-{
- if (reg_num <= GDB_REGNO_XPR31) {
- return reg_num + 0x1000 - GDB_REGNO_XPR0;
- } else if (reg_num >= GDB_REGNO_CSR0 && reg_num <= GDB_REGNO_CSR4095) {
- return reg_num - GDB_REGNO_CSR0;
- } else if (reg_num >= GDB_REGNO_FPR0 && reg_num <= GDB_REGNO_FPR31) {
- return reg_num + 0x1020 - GDB_REGNO_FPR0;
- } else {
- return ~0;
- }
-}
-
-uint32_t abstract_register_size(unsigned width)
-{
- switch (width) {
- case 32:
- return set_field(0, AC_ACCESS_REGISTER_SIZE, 2);
- case 64:
- return set_field(0, AC_ACCESS_REGISTER_SIZE, 3);
- break;
- case 128:
- return set_field(0, AC_ACCESS_REGISTER_SIZE, 4);
- break;
- default:
- LOG_ERROR("Unsupported register width: %d", width);
- return 0;
- }
-}
-
-static int wait_for_idle(struct target *target, uint32_t *abstractcs)
-{
- time_t start = time(NULL);
- while (1) {
- *abstractcs = dmi_read(target, DMI_ABSTRACTCS);
-
- if (get_field(*abstractcs, DMI_ABSTRACTCS_BUSY) == 0) {
- return ERROR_OK;
- }
-
- if (time(NULL) - start > WALL_CLOCK_TIMEOUT) {
- if (get_field(*abstractcs, DMI_ABSTRACTCS_CMDERR) != CMDERR_NONE) {
- const char *errors[8] = {
- "none",
- "busy",
- "not supported",
- "exception",
- "halt/resume",
- "reserved",
- "reserved",
- "other" };
-
- LOG_ERROR("Abstract command ended in error '%s' (abstractcs=0x%x)",
- errors[get_field(*abstractcs, DMI_ABSTRACTCS_CMDERR)],
- *abstractcs);
- }
-
- LOG_ERROR("Timed out waiting for busy to go low. (abstractcs=0x%x)",
- *abstractcs);
- return ERROR_FAIL;
- }
- }
-}
-
-static int execute_abstract_command(struct target *target, uint32_t command)
-{
- dmi_write(target, DMI_COMMAND, command);
-
- uint32_t abstractcs;
- if (wait_for_idle(target, &abstractcs) != ERROR_OK)
- return ERROR_FAIL;
-
- if (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR) != CMDERR_NONE) {
- const char *errors[8] = {
- "none",
- "busy",
- "not supported",
- "exception",
- "halt/resume",
- "reserved",
- "reserved",
- "other" };
- LOG_DEBUG("Abstract command 0x%x ended in error '%s' (abstractcs=0x%x)",
- command, errors[get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)],
- abstractcs);
- // Clear the error.
- dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-/*** program "class" ***/
-/* This class allows a debug program to be built up piecemeal, and then be
- * executed. If necessary, the program is split up to fit in the program
- * buffer. */
-
-typedef struct {
- uint8_t code[12 * 4];
- unsigned length;
- bool write;
- unsigned regno;
- uint64_t write_value;
-} program_t;
-
-static void program_add32(program_t *program, uint32_t instruction);
-
-static program_t *program_new(void)
-{
- program_t *program = malloc(sizeof(program_t));
- if (program) {
- program->length = 0;
- // Default to read zero.
- program->write = false;
- program->regno = 0x1000;
- }
- program_add32(program, fence_i());
- return program;
-}
-
-static void program_delete(program_t *program)
-{
- free(program);
-}
-
-static void program_add32(program_t *program, uint32_t instruction)
-{
- assert(program->length + 4 < sizeof(program->code));
- program->code[program->length++] = instruction & 0xff;
- program->code[program->length++] = (instruction >> 8) & 0xff;
- program->code[program->length++] = (instruction >> 16) & 0xff;
- program->code[program->length++] = (instruction >> 24) & 0xff;
-}
-
-static void program_set_read(program_t *program, unsigned reg_num)
-{
- program->write = false;
- program->regno = reg_number_to_no(reg_num);
-}
-
-static void program_set_write(program_t *program, unsigned reg_num, uint64_t value)
-{
- program->write = true;
- program->regno = reg_number_to_no(reg_num);
- program->write_value = value;
-}
-
-/*** end of program class ***/
-
-static void write_program(struct target *target, const program_t *program)
-{
- riscv013_info_t *info = get_info(target);
-
- assert(program->length <= info->progsize * 4);
- for (unsigned i = 0; i < program->length; i += 4) {
- uint32_t value =
- program->code[i] |
- ((uint32_t) program->code[i+1] << 8) |
- ((uint32_t) program->code[i+2] << 16) |
- ((uint32_t) program->code[i+3] << 24);
- dmi_write(target, DMI_PROGBUF0 + i / 4, value);
- }
-}
-
-static int execute_program(struct target *target, const program_t *program)
-{
- write_program(target, program);
-
- uint32_t command = 0;
- if (program->write) {
- if (get_field(command, AC_ACCESS_REGISTER_SIZE) > 2) {
- dmi_write(target, DMI_DATA1, program->write_value >> 32);
- }
- dmi_write(target, DMI_DATA0, program->write_value);
- command |= AC_ACCESS_REGISTER_WRITE | AC_ACCESS_REGISTER_POSTEXEC;
- } else {
- command |= AC_ACCESS_REGISTER_PREEXEC;
- }
- command |= abstract_register_size(riscv_xlen(target));
- command |= program->regno;
-
- return execute_abstract_command(target, command);
-}
-
-static int abstract_read_register(struct target *target,
- uint64_t *value,
- uint32_t reg_number,
- unsigned width)
-{
- uint32_t command = abstract_register_size(width);
-
- command |= reg_number_to_no(reg_number);
-
- int result = execute_abstract_command(target, command);
- if (result != ERROR_OK) {
- return result;
- }
-
- if (value) {
- *value = 0;
- switch (width) {
- case 128:
- LOG_ERROR("Ignoring top 64 bits from 128-bit register read.");
- case 64:
- *value |= ((uint64_t) dmi_read(target, DMI_DATA1)) << 32;
- case 32:
- *value |= dmi_read(target, DMI_DATA0);
- break;
- }
- }
-
- return ERROR_OK;
-}
-
-static int abstract_write_register(struct target *target,
- unsigned reg_number,
- unsigned width,
- uint64_t value)
-{
- uint32_t command = abstract_register_size(width);
-
- command |= reg_number_to_no(reg_number);
- command |= AC_ACCESS_REGISTER_WRITE;
-
- switch (width) {
- case 128:
- LOG_ERROR("Ignoring top 64 bits from 128-bit register write.");
- case 64:
- dmi_write(target, DMI_DATA1, value >> 32);
- case 32:
- dmi_write(target, DMI_DATA0, value);
- break;
- }
-
- int result = execute_abstract_command(target, command);
- if (result != ERROR_OK) {
- return result;
- }
-
- return ERROR_OK;
-}
-
-static int update_mstatus_actual(struct target *target)
-{
- struct reg *mstatus_reg = &target->reg_cache->reg_list[GDB_REGNO_MSTATUS];
- if (mstatus_reg->valid) {
- // We previously made it valid.
- return ERROR_OK;
- }
-
- LOG_DEBUG("Reading mstatus");
-
- // Force reading the register. In that process mstatus_actual will be
- // updated.
- return register_get(&target->reg_cache->reg_list[GDB_REGNO_MSTATUS]);
-}
-
-static int register_write_direct(struct target *target, unsigned number,
- uint64_t value)
-{
- riscv013_info_t *info = get_info(target);
- LOG_DEBUG("register 0x%x <- 0x%" PRIx64, number, value);
-
- if (number == GDB_REGNO_MSTATUS) {
- info->mstatus_actual = value;
- }
-
- int result = abstract_write_register(target, number, riscv_xlen(target), value);
- if (result == ERROR_OK)
- return result;
-
- // Fall back to program buffer.
- if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
- result = update_mstatus_actual(target);
- if (result != ERROR_OK) {
- return result;
- }
- if ((info->mstatus_actual & MSTATUS_FS) == 0) {
- result = register_write_direct(target, GDB_REGNO_MSTATUS,
- set_field(info->mstatus_actual, MSTATUS_FS, 1));
- if (result != ERROR_OK)
- return result;
- }
-
- program_t *program = program_new();
- // TODO: Fully support D extension on RV32.
- if (supports_extension(target, 'D') && riscv_xlen(target) >= 64) {
- program_add32(program, fmv_d_x(number - GDB_REGNO_FPR0, S0));
- } else {
- program_add32(program, fmv_s_x(number - GDB_REGNO_FPR0, S0));
- }
- program_add32(program, ebreak());
- program_set_write(program, S0, value);
- result = execute_program(target, program);
- program_delete(program);
- } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
- program_t *program = program_new();
- program_add32(program, csrw(S0, number - GDB_REGNO_CSR0));
- program_add32(program, ebreak());
- program_set_write(program, S0, value);
- result = execute_program(target, program);
- program_delete(program);
- } else {
- return result;
- }
-
- return result;
-}
-
-/** Actually read registers from the target right now. */
-static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
-{
- riscv013_info_t *info = get_info(target);
- int result = abstract_read_register(target, value, number, riscv_xlen(target));
- if (result == ERROR_OK)
- return result;
-
- // Fall back to program buffer.
- if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
- result = update_mstatus_actual(target);
- if (result != ERROR_OK) {
- return result;
- }
- if ((info->mstatus_actual & MSTATUS_FS) == 0) {
- result = register_write_direct(target, GDB_REGNO_MSTATUS,
- set_field(info->mstatus_actual, MSTATUS_FS, 1));
- if (result != ERROR_OK)
- return result;
- }
- LOG_DEBUG("mstatus_actual=0x%lx", info->mstatus_actual);
-
- program_t *program = program_new();
- if (supports_extension(target, 'D') && riscv_xlen(target) >= 64) {
- program_add32(program, fmv_x_d(S0, number - GDB_REGNO_FPR0));
- } else {
- program_add32(program, fmv_x_s(S0, number - GDB_REGNO_FPR0));
- }
- program_add32(program, ebreak());
- program_set_read(program, S0);
- result = execute_program(target, program);
- program_delete(program);
- } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
- program_t *program = program_new();
- program_add32(program, csrr(S0, number - GDB_REGNO_CSR0));
- program_add32(program, ebreak());
- program_set_read(program, S0);
- result = execute_program(target, program);
- program_delete(program);
- } else {
- return result;
- }
-
- if (result != ERROR_OK)
- return result;
-
- result = register_read_direct(target, value, S0);
- if (result != ERROR_OK)
- return result;
-
- LOG_DEBUG("register 0x%x = 0x%" PRIx64, number, *value);
-
- return ERROR_OK;
-}
-
-static int maybe_read_tselect(struct target *target)
-{
- riscv013_info_t *info = get_info(target);
-
- if (info->tselect_dirty) {
- int result = register_read_direct(target, &info->tselect, GDB_REGNO_TSELECT);
- if (result != ERROR_OK)
- return result;
- info->tselect_dirty = false;
- }
-
- return ERROR_OK;
-}
-
-static int maybe_write_tselect(struct target *target)
-{
- riscv013_info_t *info = get_info(target);
-
- if (!info->tselect_dirty) {
- int result = register_write_direct(target, GDB_REGNO_TSELECT, info->tselect);
- if (result != ERROR_OK)
- return result;
- info->tselect_dirty = true;
- }
-
- return ERROR_OK;
-}
-
-/*** OpenOCD target functions. ***/
-
-static int register_get(struct reg *reg)
-{
- struct target *target = (struct target *) reg->arch_info;
- riscv013_info_t *info = get_info(target);
-
- maybe_write_tselect(target);
-
- if (reg->number <= GDB_REGNO_XPR31) {
- register_read_direct(target, reg->value, reg->number);
- return ERROR_OK;
- } else if (reg->number == GDB_REGNO_PC) {
- buf_set_u32(reg->value, 0, 32, riscv_peek_register(target, GDB_REGNO_DPC));
- reg->valid = true;
- return ERROR_OK;
- } else if (reg->number == GDB_REGNO_PRIV) {
- uint64_t dcsr = riscv_peek_register(target, CSR_DCSR);
- buf_set_u64(reg->value, 0, 8, get_field(dcsr, CSR_DCSR_PRV));
- riscv_overwrite_register(target, CSR_DCSR, dcsr);
- return ERROR_OK;
- } else {
- uint64_t value;
- int result = register_read_direct(target, &value, reg->number);
- if (result != ERROR_OK) {
- return result;
- }
- LOG_DEBUG("%s=0x%" PRIx64, reg->name, value);
- buf_set_u64(reg->value, 0, riscv_xlen(target), value);
-
- if (reg->number == GDB_REGNO_MSTATUS) {
- info->mstatus_actual = value;
- reg->valid = true;
- }
- }
-
- return ERROR_OK;
-}
-
-static int register_write(struct target *target, unsigned int number,
- uint64_t value)
-{
- maybe_write_tselect(target);
-
- if (number == GDB_REGNO_PC) {
- riscv_overwrite_register(target, GDB_REGNO_DPC, value);
- } else if (number == GDB_REGNO_PRIV) {
- uint64_t dcsr = riscv_peek_register(target, CSR_DCSR);
- dcsr = set_field(dcsr, CSR_DCSR_PRV, value);
- riscv_overwrite_register(target, GDB_REGNO_DCSR, dcsr);
- } else {
- return register_write_direct(target, number, value);
- }
-
- return ERROR_OK;
-}
-
-static int register_set(struct reg *reg, uint8_t *buf)
-{
- struct target *target = (struct target *) reg->arch_info;
-
- uint64_t value = buf_get_u64(buf, 0, riscv_xlen(target));
-
- LOG_DEBUG("write 0x%" PRIx64 " to %s", value, reg->name);
- struct reg *r = &target->reg_cache->reg_list[reg->number];
- r->valid = true;
- memcpy(r->value, buf, (r->size + 7) / 8);
-
- return register_write(target, reg->number, value);
-}
-
-static struct reg_arch_type riscv_reg_arch_type = {
- .get = register_get,
- .set = register_set
-};
-
-static int init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- LOG_DEBUG("init");
- riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
-
- riscv_info_init(generic_info);
- generic_info->get_register = &riscv013_get_register;
- generic_info->set_register = &riscv013_set_register;
- generic_info->select_current_hart = &riscv013_select_current_hart;
- generic_info->is_halted = &riscv013_is_halted;
- generic_info->halt_current_hart = &riscv013_halt_current_hart;
- generic_info->resume_current_hart = &riscv013_resume_current_hart;
- generic_info->step_current_hart = &riscv013_step_current_hart;
- generic_info->on_halt = &riscv013_on_halt;
- generic_info->on_resume = &riscv013_on_resume;
- generic_info->on_step = &riscv013_on_step;
- generic_info->halt_reason = &riscv013_halt_reason;
-
- generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
- if (!generic_info->version_specific)
- return ERROR_FAIL;
- riscv013_info_t *info = get_info(target);
-
- target->reg_cache = calloc(1, sizeof(*target->reg_cache));
- target->reg_cache->name = "RISC-V registers";
- target->reg_cache->num_regs = GDB_REGNO_COUNT;
-
- target->reg_cache->reg_list = calloc(GDB_REGNO_COUNT, sizeof(struct reg));
-
- const unsigned int max_reg_name_len = 12;
- info->reg_names = calloc(1, GDB_REGNO_COUNT * max_reg_name_len);
- char *reg_name = info->reg_names;
- info->reg_values = NULL;
-
- for (unsigned int i = 0; i < GDB_REGNO_COUNT; i++) {
- struct reg *r = &target->reg_cache->reg_list[i];
- r->number = i;
- r->caller_save = true;
- r->dirty = false;
- r->valid = false;
- r->exist = true;
- r->type = &riscv_reg_arch_type;
- r->arch_info = target;
- if (i <= GDB_REGNO_XPR31) {
- sprintf(reg_name, "x%d", i);
- } else if (i == GDB_REGNO_PC) {
- sprintf(reg_name, "pc");
- } else if (i >= GDB_REGNO_FPR0 && i <= GDB_REGNO_FPR31) {
- sprintf(reg_name, "f%d", i - GDB_REGNO_FPR0);
- } else if (i >= GDB_REGNO_CSR0 && i <= GDB_REGNO_CSR4095) {
- sprintf(reg_name, "csr%d", i - GDB_REGNO_CSR0);
- } else if (i == GDB_REGNO_PRIV) {
- sprintf(reg_name, "priv");
- }
- if (reg_name[0]) {
- r->name = reg_name;
- }
- reg_name += strlen(reg_name) + 1;
- assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len);
- }
-#if 0
- update_reg_list(target);
-#endif
-
- memset(info->trigger_unique_id, 0xff, sizeof(info->trigger_unique_id));
-
- return ERROR_OK;
-}
-
-static void deinit_target(struct target *target)
-{
- LOG_DEBUG("riscv_deinit_target()");
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
- free(info->version_specific);
- info->version_specific = NULL;
-}
-
-static int add_trigger(struct target *target, struct trigger *trigger)
-{
- riscv013_info_t *info = get_info(target);
-
- maybe_read_tselect(target);
-
- unsigned int i;
- for (i = 0; i < info->trigger_count; i++) {
- if (info->trigger_unique_id[i] != -1) {
- continue;
- }
-
- register_write_direct(target, GDB_REGNO_TSELECT, i);
-
- uint64_t tdata1;
- register_read_direct(target, &tdata1, GDB_REGNO_TDATA1);
- int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
-
- if (type != 2) {
- continue;
- }
-
- if (tdata1 & (MCONTROL_EXECUTE | MCONTROL_STORE | MCONTROL_LOAD)) {
- // Trigger is already in use, presumably by user code.
- continue;
- }
-
- // address/data match trigger
- tdata1 |= MCONTROL_DMODE(riscv_xlen(target));
- tdata1 = set_field(tdata1, MCONTROL_ACTION,
- MCONTROL_ACTION_DEBUG_MODE);
- tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL);
- tdata1 |= MCONTROL_M;
- if (info->misa & (1 << ('H' - 'A')))
- tdata1 |= MCONTROL_H;
- if (info->misa & (1 << ('S' - 'A')))
- tdata1 |= MCONTROL_S;
- if (info->misa & (1 << ('U' - 'A')))
- tdata1 |= MCONTROL_U;
-
- if (trigger->execute)
- tdata1 |= MCONTROL_EXECUTE;
- if (trigger->read)
- tdata1 |= MCONTROL_LOAD;
- if (trigger->write)
- tdata1 |= MCONTROL_STORE;
-
- register_write_direct(target, GDB_REGNO_TDATA1, tdata1);
-
- uint64_t tdata1_rb;
- register_read_direct(target, &tdata1_rb, GDB_REGNO_TDATA1);
- LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
-
- if (tdata1 != tdata1_rb) {
- LOG_DEBUG("Trigger %d doesn't support what we need; After writing 0x%"
- PRIx64 " to tdata1 it contains 0x%" PRIx64,
- i, tdata1, tdata1_rb);
- register_write_direct(target, GDB_REGNO_TDATA1, 0);
- continue;
- }
-
- register_write_direct(target, GDB_REGNO_TDATA2, trigger->address);
-
- LOG_DEBUG("Using resource %d for bp %d", i,
- trigger->unique_id);
- info->trigger_unique_id[i] = trigger->unique_id;
- break;
- }
- if (i >= info->trigger_count) {
- LOG_ERROR("Couldn't find an available hardware trigger.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- return ERROR_OK;
-}
-
-static int remove_trigger(struct target *target, struct trigger *trigger)
-{
- riscv013_info_t *info = get_info(target);
-
- maybe_read_tselect(target);
-
- unsigned int i;
- for (i = 0; i < info->trigger_count; i++) {
- if (info->trigger_unique_id[i] == trigger->unique_id) {
- break;
- }
- }
- if (i >= info->trigger_count) {
- LOG_ERROR("Couldn't find the hardware resources used by hardware "
- "trigger.");
- return ERROR_FAIL;
- }
- LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id);
- register_write_direct(target, GDB_REGNO_TSELECT, i);
- register_write_direct(target, GDB_REGNO_TDATA1, 0);
- info->trigger_unique_id[i] = -1;
-
- return ERROR_OK;
-}
-
-static void trigger_from_breakpoint(struct trigger *trigger,
- const struct breakpoint *breakpoint)
-{
- trigger->address = breakpoint->address;
- trigger->length = breakpoint->length;
- trigger->mask = ~0LL;
- trigger->read = false;
- trigger->write = false;
- trigger->execute = true;
- // unique_id is unique across both breakpoints and watchpoints.
- trigger->unique_id = breakpoint->unique_id;
-}
-
-static void trigger_from_watchpoint(struct trigger *trigger,
- const struct watchpoint *watchpoint)
-{
- trigger->address = watchpoint->address;
- trigger->length = watchpoint->length;
- trigger->mask = watchpoint->mask;
- trigger->value = watchpoint->value;
- trigger->read = (watchpoint->rw == WPT_READ || watchpoint->rw == WPT_ACCESS);
- trigger->write = (watchpoint->rw == WPT_WRITE || watchpoint->rw == WPT_ACCESS);
- trigger->execute = false;
- // unique_id is unique across both breakpoints and watchpoints.
- trigger->unique_id = watchpoint->unique_id;
-}
-
-static int add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- if (breakpoint->type == BKPT_SOFT) {
- if (target_read_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr) != ERROR_OK) {
- LOG_ERROR("Failed to read original instruction at 0x%x",
- breakpoint->address);
- return ERROR_FAIL;
- }
-
- int retval;
- if (breakpoint->length == 4) {
- retval = target_write_u32(target, breakpoint->address, ebreak());
- } else {
- retval = target_write_u16(target, breakpoint->address, ebreak_c());
- }
- if (retval != ERROR_OK) {
- LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%x",
- breakpoint->length, breakpoint->address);
- return ERROR_FAIL;
- }
-
- } else if (breakpoint->type == BKPT_HARD) {
- struct trigger trigger;
- trigger_from_breakpoint(&trigger, breakpoint);
- int result = add_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
- } else {
- LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- breakpoint->set = true;
-
- return ERROR_OK;
-}
-
-static int remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- if (breakpoint->type == BKPT_SOFT) {
- if (target_write_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr) != ERROR_OK) {
- LOG_ERROR("Failed to restore instruction for %d-byte breakpoint at "
- "0x%x", breakpoint->length, breakpoint->address);
- return ERROR_FAIL;
- }
-
- } else if (breakpoint->type == BKPT_HARD) {
- struct trigger trigger;
- trigger_from_breakpoint(&trigger, breakpoint);
- int result = remove_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
- } else {
- LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- breakpoint->set = false;
-
- return ERROR_OK;
-}
-
-static int add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct trigger trigger;
- trigger_from_watchpoint(&trigger, watchpoint);
-
- int result = add_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
- watchpoint->set = true;
-
- return ERROR_OK;
-}
-
-static int remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct trigger trigger;
- trigger_from_watchpoint(&trigger, watchpoint);
-
- int result = remove_trigger(target, &trigger);
- if (result != ERROR_OK) {
- return result;
- }
- watchpoint->set = false;
-
- return ERROR_OK;
-}
-
-static int examine(struct target *target)
-{
- // Don't need to select dbus, since the first thing we do is read dtmcontrol.
-
- uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
- LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
- LOG_DEBUG(" dmireset=%d", get_field(dtmcontrol, DTM_DTMCS_DMIRESET));
- LOG_DEBUG(" idle=%d", get_field(dtmcontrol, DTM_DTMCS_IDLE));
- LOG_DEBUG(" dmistat=%d", get_field(dtmcontrol, DTM_DTMCS_DMISTAT));
- LOG_DEBUG(" abits=%d", get_field(dtmcontrol, DTM_DTMCS_ABITS));
- LOG_DEBUG(" version=%d", get_field(dtmcontrol, DTM_DTMCS_VERSION));
- if (dtmcontrol == 0) {
- LOG_ERROR("dtmcontrol is 0. Check JTAG connectivity/board power.");
- return ERROR_FAIL;
- }
- if (get_field(dtmcontrol, DTM_DTMCS_VERSION) != 1) {
- LOG_ERROR("Unsupported DTM version %d. (dtmcontrol=0x%x)",
- get_field(dtmcontrol, DTM_DTMCS_VERSION), dtmcontrol);
- return ERROR_FAIL;
- }
-
- riscv013_info_t *info = get_info(target);
- info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS);
- info->dtmcontrol_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE);
-
- uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
- uint32_t dmstatus = dmi_read(target, DMI_DMSTATUS);
- if (get_field(dmstatus, DMI_DMSTATUS_VERSIONLO) != 2) {
- LOG_ERROR("OpenOCD only supports Debug Module version 2, not %d "
- "(dmstatus=0x%x)", get_field(dmstatus, DMI_DMSTATUS_VERSIONLO), dmstatus);
- return ERROR_FAIL;
- }
-
- // Reset the Debug Module.
- dmi_write(target, DMI_DMCONTROL, 0);
- dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
- dmcontrol = dmi_read(target, DMI_DMCONTROL);
-
- LOG_DEBUG("dmcontrol: 0x%08x", dmcontrol);
- LOG_DEBUG("dmstatus: 0x%08x", dmstatus);
-
- if (!get_field(dmcontrol, DMI_DMCONTROL_DMACTIVE)) {
- LOG_ERROR("Debug Module did not become active. dmcontrol=0x%x",
- dmcontrol);
- return ERROR_FAIL;
- }
-
- if (!get_field(dmstatus, DMI_DMSTATUS_AUTHENTICATED)) {
- LOG_ERROR("Authentication required by RISC-V core but not "
- "supported by OpenOCD. dmcontrol=0x%x", dmcontrol);
- return ERROR_FAIL;
- }
-
- if (get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) {
- LOG_ERROR("The hart is unavailable.");
- return ERROR_FAIL;
- }
-
- if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT)) {
- LOG_ERROR("The hart doesn't exist.");
- return ERROR_FAIL;
- }
-
- // Check that abstract data registers are accessible.
- uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
- info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
- info->progsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGSIZE);
-
- /* Halt every hart so we can probe them. */
- riscv_halt_all_harts(target);
-
- /* Examines every hart, first checking XLEN. */
- for (int i = 0; i < riscv_count_harts(target); ++i) {
- RISCV_INFO(r);
- riscv_set_current_hartid(target, i);
-
- if (abstract_read_register(target, NULL, S0, 128) == ERROR_OK) {
- r->xlen[i] = 128;
- } else if (abstract_read_register(target, NULL, S0, 64) == ERROR_OK) {
- r->xlen[i] = 64;
- } else if (abstract_read_register(target, NULL, S0, 32) == ERROR_OK) {
- r->xlen[i] = 32;
- } else {
- LOG_ERROR("Failed to discover size using abstract register reads.");
- return ERROR_FAIL;
- }
- }
-
- /* FIXME: Are there 2 triggers? */
- info->trigger_count = 2;
-
- /* Resumes all the harts, so the debugger can later pause them. */
- riscv_resume_all_harts(target);
- target_set_examined(target);
- return ERROR_OK;
-}
-
-static int assert_reset(struct target *target)
-{
- return ERROR_FAIL;
-}
-
-static int deassert_reset(struct target *target)
-{
- return ERROR_FAIL;
-}
-
-/**
- * If there was a DMI error, clear that error and return 1.
- * Otherwise return 0.
- */
-static int check_dmi_error(struct target *target)
-{
- dmi_status_t status = dmi_scan(target, NULL, NULL, DMI_OP_NOP, 0, 0,
- false);
- if (status != DMI_STATUS_SUCCESS) {
- // Clear errors.
- dtmcontrol_scan(target, DTM_DTMCS_DMIRESET);
- increase_dmi_busy_delay(target);
- return 1;
- }
- return 0;
-}
-
-static int read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- select_dmi(target);
- riscv_set_current_hartid(target, 0);
-
- for (uint32_t i = 0; i < count; ++i) {
- uint32_t offset = i*size;
- uint32_t t_addr = address + offset;
- uint8_t *t_buffer = buffer + offset;
-
- abstract_write_register(target, S0, riscv_xlen(target), t_addr);
-
- program_t *program = program_new();
- switch (size) {
- case 1:
- program_add32(program, lb(S1, S0, 0));
- break;
- case 2:
- program_add32(program, lh(S1, S0, 0));
- break;
- case 4:
- program_add32(program, lw(S1, S0, 0));
- break;
- default:
- LOG_ERROR("Unsupported size: %d", size);
- return ERROR_FAIL;
- }
- program_add32(program, fence());
- program_add32(program, ebreak());
- program_set_read(program, S1);
- write_program(target, program);
- execute_program(target, program);
- uint32_t abstractcs;
- wait_for_idle(target, &abstractcs);
- program_delete(program);
-
- uint32_t value = dmi_read(target, DMI_DATA0);
- switch (size) {
- case 1:
- t_buffer[0] = value;
- break;
- case 2:
- t_buffer[0] = value;
- t_buffer[1] = value >> 8;
- break;
- case 4:
- t_buffer[0] = value;
- t_buffer[1] = value >> 8;
- t_buffer[2] = value >> 16;
- t_buffer[3] = value >> 24;
- break;
- default:
- return ERROR_FAIL;
- }
-
- LOG_INFO("read 0x%08x from 0x%08x", value, t_addr);
-
- if (check_dmi_error(target)) {
- LOG_ERROR("DMI error");
- return ERROR_FAIL;
- }
- }
-
- program_t *program = program_new();
- program_add32(program, ebreak());
- program_add32(program, ebreak());
- program_add32(program, ebreak());
- program_add32(program, ebreak());
- write_program(target, program);
- program_delete(program);
-
- return ERROR_OK;
-}
-
-static int write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- select_dmi(target);
- riscv_set_current_hartid(target, 0);
-
- for (uint32_t i = 0; i < count; ++i) {
- uint32_t offset = size*i;
- uint32_t t_addr = address + offset;
- const uint8_t *t_buffer = buffer + offset;
-
- abstract_write_register(target, S0, riscv_xlen(target), t_addr);
- program_t *program = program_new();
- switch (size) {
- case 1:
- program_add32(program, sb(S1, S0, 0));
- break;
- case 2:
- program_add32(program, sh(S1, S0, 0));
- break;
- case 4:
- program_add32(program, sw(S1, S0, 0));
- break;
- default:
- LOG_ERROR("Unsupported size: %d", size);
- return ERROR_FAIL;
- }
- program_add32(program, fence());
- program_add32(program, ebreak());
-
- uint32_t value;
- switch (size) {
- case 1:
- value = t_buffer[0];
- break;
- case 2:
- value = t_buffer[0] | ((uint32_t) t_buffer[1] << 8);
- break;
- case 4:
- value = t_buffer[0] |
- ((uint32_t) t_buffer[1] << 8) |
- ((uint32_t) t_buffer[2] << 16) |
- ((uint32_t) t_buffer[3] << 24);
- break;
- default:
- return ERROR_FAIL;
- }
- abstract_write_register(target, S1, riscv_xlen(target), value);
- program_set_write(program, S1, value);
-
- LOG_INFO("writing 0x%08x to 0x%08x", value, t_addr);
-
- write_program(target, program);
- execute_program(target, program);
- uint32_t abstractcs;
- wait_for_idle(target, &abstractcs);
- program_delete(program);
-
- if (check_dmi_error(target)) {
- LOG_ERROR("DMI error");
- return ERROR_FAIL;
- }
- }
-
- program_t *program = program_new();
- program_add32(program, ebreak());
- program_add32(program, ebreak());
- program_add32(program, ebreak());
- program_add32(program, ebreak());
- write_program(target, program);
- program_delete(program);
- return ERROR_OK;
-}
-
-static int arch_state(struct target *target)
-{
- return ERROR_OK;
-}
-
-struct target_type riscv013_target =
-{
- .name = "riscv",
-
- .init_target = init_target,
- .deinit_target = deinit_target,
- .examine = examine,
-
- .poll = &riscv_openocd_poll,
- .halt = &riscv_openocd_halt,
- .resume = &riscv_openocd_resume,
- .step = &riscv_openocd_step,
-
- .assert_reset = assert_reset,
- .deassert_reset = deassert_reset,
-
- .read_memory = read_memory,
- .write_memory = write_memory,
-
- .add_breakpoint = add_breakpoint,
- .remove_breakpoint = remove_breakpoint,
-
- .add_watchpoint = add_watchpoint,
- .remove_watchpoint = remove_watchpoint,
-
- .arch_state = arch_state,
-};
-
-/*** 0.13-specific implementations of various RISC-V hepler functions. ***/
-static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid)
-{
- riscv_set_current_hartid(target, hid);
-
- uint64_t out;
- register_read_direct(target, &out, rid);
- return out;
-}
-
-static void riscv013_set_register(struct target *target, int hid, int rid, uint64_t value)
-{
- riscv_set_current_hartid(target, hid);
-
- register_write_direct(target, rid, value);
-}
-
-static void riscv013_select_current_hart(struct target *target)
-{
- RISCV_INFO(r);
-
- uint64_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
- dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HARTSEL, r->current_hartid);
- dmi_write(target, DMI_DMCONTROL, dmcontrol);
-}
-
-static void riscv013_halt_current_hart(struct target *target)
-{
- RISCV_INFO(r);
- LOG_DEBUG("halting hart %d", r->current_hartid);
- assert(!riscv_is_halted(target));
-
- /* Issue the halt command, and then wait for the current hart to halt. */
- uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
- dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HALTREQ, 1);
- dmi_write(target, DMI_DMCONTROL, dmcontrol);
- for (size_t i = 0; i < 256; ++i)
- if (riscv_is_halted(target))
- break;
-
- if (!riscv_is_halted(target)) {
- uint32_t dmstatus = dmi_read(target, DMI_DMSTATUS);
- dmcontrol = dmi_read(target, DMI_DMCONTROL);
-
- LOG_ERROR("unable to halt hart %d", r->current_hartid);
- LOG_ERROR(" dmcontrol=0x%08x", dmcontrol);
- LOG_ERROR(" dmstatus =0x%08x", dmstatus);
- abort();
- }
-
- dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HALTREQ, 0);
- dmi_write(target, DMI_DMCONTROL, dmcontrol);
-}
-
-static void riscv013_resume_current_hart(struct target *target)
-{
- return riscv013_step_or_resume_current_hart(target, false);
-}
-
-static void riscv013_step_current_hart(struct target *target)
-{
- return riscv013_step_or_resume_current_hart(target, true);
-}
-
-static void riscv013_on_resume(struct target *target)
-{
- return riscv013_on_step_or_resume(target, false);
-}
-
-static void riscv013_on_step(struct target *target)
-{
- return riscv013_on_step_or_resume(target, true);
-}
-
-static void riscv013_on_halt(struct target *target)
-{
- RISCV_INFO(r);
- LOG_DEBUG("saving register state for hart %d", r->current_hartid);
- riscv_save_register(target, GDB_REGNO_S0);
- riscv_save_register(target, GDB_REGNO_S1);
- riscv_save_register(target, GDB_REGNO_DPC);
- riscv_save_register(target, GDB_REGNO_DCSR);
-}
-
-static bool riscv013_is_halted(struct target *target)
-{
- uint32_t dmstatus = dmi_read(target, DMI_DMSTATUS);
- return get_field(dmstatus, DMI_DMSTATUS_ALLHALTED);
-}
-
-static enum riscv_halt_reason riscv013_halt_reason(struct target *target)
-{
- uint64_t dcsr = riscv_peek_register(target, GDB_REGNO_DCSR);
- switch (get_field(dcsr, CSR_DCSR_CAUSE)) {
- case CSR_DCSR_CAUSE_SWBP:
- case CSR_DCSR_CAUSE_TRIGGER:
- return RISCV_HALT_BREAKPOINT;
- case CSR_DCSR_CAUSE_STEP:
- return RISCV_HALT_SINGLESTEP;
- case CSR_DCSR_CAUSE_DEBUGINT:
- case CSR_DCSR_CAUSE_HALT:
- return RISCV_HALT_INTERRUPT;
- }
-
- LOG_ERROR("Unknown DCSR cause field: %x", (int)get_field(dcsr, CSR_DCSR_CAUSE));
- abort();
-}
-
-/* Helper Functions. */
-static void riscv013_on_step_or_resume(struct target *target, bool step)
-{
- RISCV_INFO(r);
- LOG_DEBUG("restoring register state for hart %d", r->current_hartid);
-
- program_t *program = program_new();
- program_add32(program, fence_i());
- program_add32(program, ebreak());
- write_program(target, program);
- if (execute_program(target, program) != ERROR_OK) {
- LOG_ERROR("Unable to execute fence.i");
- }
- program_delete(program);
-
- /* We want to twiddle some bits in the debug CSR so debugging works. */
- uint64_t dcsr = riscv_peek_register(target, GDB_REGNO_DCSR);
- dcsr = set_field(dcsr, CSR_DCSR_STEP, step);
- dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, 1);
- dcsr = set_field(dcsr, CSR_DCSR_EBREAKH, 1);
- dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, 1);
- dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, 1);
- riscv_overwrite_register(target, GDB_REGNO_DCSR, dcsr);
-
- riscv_restore_register(target, GDB_REGNO_DCSR);
- riscv_restore_register(target, GDB_REGNO_DPC);
- riscv_restore_register(target, GDB_REGNO_S1);
- riscv_restore_register(target, GDB_REGNO_S0);
-}
-
-static void riscv013_step_or_resume_current_hart(struct target *target, bool step)
-{
- RISCV_INFO(r);
- LOG_DEBUG("resuming hart %d", r->current_hartid);
- assert(riscv_is_halted(target));
-
- /* Issue the halt command, and then wait for the current hart to halt. */
- uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
- dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 1);
- dmi_write(target, DMI_DMCONTROL, dmcontrol);
-
-#if 1
- /* FIXME: ... well, after a short time. */
- usleep(100);
-#else
- /* FIXME: there's a race condition in stepping now, so just return
- * right away... */
- for (size_t i = 0; i < 256; ++i) {
- if (!riscv_is_halted(target))
- break;
- }
-
- if (riscv_is_halted(target)) {
- uint32_t dmstatus = dmi_read(target, DMI_DMSTATUS);
- dmcontrol = dmi_read(target, DMI_DMCONTROL);
-
- LOG_ERROR("unable to resume hart %d", r->current_hartid);
- LOG_ERROR(" dmcontrol=0x%08x", dmcontrol);
- LOG_ERROR(" dmstatus =0x%08x", dmstatus);
- abort();
- }
-#endif
-
- dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 0);
- dmi_write(target, DMI_DMCONTROL, dmcontrol);
-}
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
deleted file mode 100644
index 13410bd..0000000
--- a/src/target/riscv/riscv.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <time.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "target.h"
-#include "target/algorithm.h"
-#include "target_type.h"
-#include "log.h"
-#include "jtag/jtag.h"
-#include "register.h"
-#include "breakpoints.h"
-#include "helper/time_support.h"
-#include "riscv.h"
-#include "gdb_regs.h"
-#include "rtos/rtos.h"
-
-/**
- * Since almost everything can be accomplish by scanning the dbus register, all
- * functions here assume dbus is already selected. The exception are functions
- * called directly by OpenOCD, which can't assume anything about what's
- * currently in IR. They should set IR to dbus explicitly.
- */
-
-/**
- * Code structure
- *
- * At the bottom of the stack are the OpenOCD JTAG functions:
- * jtag_add_[id]r_scan
- * jtag_execute_query
- * jtag_add_runtest
- *
- * There are a few functions to just instantly shift a register and get its
- * value:
- * dtmcontrol_scan
- * idcode_scan
- * dbus_scan
- *
- * Because doing one scan and waiting for the result is slow, most functions
- * batch up a bunch of dbus writes and then execute them all at once. They use
- * the scans "class" for this:
- * scans_new
- * scans_delete
- * scans_execute
- * scans_add_...
- * Usually you new(), call a bunch of add functions, then execute() and look
- * at the results by calling scans_get...()
- *
- * Optimized functions will directly use the scans class above, but slightly
- * lazier code will use the cache functions that in turn use the scans
- * functions:
- * cache_get...
- * cache_set...
- * cache_write
- * cache_set... update a local structure, which is then synced to the target
- * with cache_write(). Only Debug RAM words that are actually changed are sent
- * to the target. Afterwards use cache_get... to read results.
- */
-
-#define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
-#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
-
-#define DIM(x) (sizeof(x)/sizeof(*x))
-
-// Constants for legacy SiFive hardware breakpoints.
-#define CSR_BPCONTROL_X (1<<0)
-#define CSR_BPCONTROL_W (1<<1)
-#define CSR_BPCONTROL_R (1<<2)
-#define CSR_BPCONTROL_U (1<<3)
-#define CSR_BPCONTROL_S (1<<4)
-#define CSR_BPCONTROL_H (1<<5)
-#define CSR_BPCONTROL_M (1<<6)
-#define CSR_BPCONTROL_BPMATCH (0xf<<7)
-#define CSR_BPCONTROL_BPACTION (0xff<<11)
-
-#define DEBUG_ROM_START 0x800
-#define DEBUG_ROM_RESUME (DEBUG_ROM_START + 4)
-#define DEBUG_ROM_EXCEPTION (DEBUG_ROM_START + 8)
-#define DEBUG_RAM_START 0x400
-
-#define SETHALTNOT 0x10c
-
-/*** JTAG registers. ***/
-
-#define DTMCONTROL 0x10
-#define DTMCONTROL_DBUS_RESET (1<<16)
-#define DTMCONTROL_IDLE (7<<10)
-#define DTMCONTROL_ADDRBITS (0xf<<4)
-#define DTMCONTROL_VERSION (0xf)
-
-#define DBUS 0x11
-#define DBUS_OP_START 0
-#define DBUS_OP_SIZE 2
-typedef enum {
- DBUS_OP_NOP = 0,
- DBUS_OP_READ = 1,
- DBUS_OP_WRITE = 2
-} dbus_op_t;
-typedef enum {
- DBUS_STATUS_SUCCESS = 0,
- DBUS_STATUS_FAILED = 2,
- DBUS_STATUS_BUSY = 3
-} dbus_status_t;
-#define DBUS_DATA_START 2
-#define DBUS_DATA_SIZE 34
-#define DBUS_ADDRESS_START 36
-
-typedef enum {
- RE_OK,
- RE_FAIL,
- RE_AGAIN
-} riscv_error_t;
-
-typedef enum slot {
- SLOT0,
- SLOT1,
- SLOT_LAST,
-} slot_t;
-
-/*** Debug Bus registers. ***/
-
-#define DMCONTROL 0x10
-#define DMCONTROL_INTERRUPT (((uint64_t)1)<<33)
-#define DMCONTROL_HALTNOT (((uint64_t)1)<<32)
-#define DMCONTROL_BUSERROR (7<<19)
-#define DMCONTROL_SERIAL (3<<16)
-#define DMCONTROL_AUTOINCREMENT (1<<15)
-#define DMCONTROL_ACCESS (7<<12)
-#define DMCONTROL_HARTID (0x3ff<<2)
-#define DMCONTROL_NDRESET (1<<1)
-#define DMCONTROL_FULLRESET 1
-
-#define DMINFO 0x11
-#define DMINFO_ABUSSIZE (0x7fU<<25)
-#define DMINFO_SERIALCOUNT (0xf<<21)
-#define DMINFO_ACCESS128 (1<<20)
-#define DMINFO_ACCESS64 (1<<19)
-#define DMINFO_ACCESS32 (1<<18)
-#define DMINFO_ACCESS16 (1<<17)
-#define DMINFO_ACCESS8 (1<<16)
-#define DMINFO_DRAMSIZE (0x3f<<10)
-#define DMINFO_AUTHENTICATED (1<<5)
-#define DMINFO_AUTHBUSY (1<<4)
-#define DMINFO_AUTHTYPE (3<<2)
-#define DMINFO_VERSION 3
-
-/*** Info about the core being debugged. ***/
-
-#define DBUS_ADDRESS_UNKNOWN 0xffff
-#define WALL_CLOCK_TIMEOUT 2
-
-// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
-// its source tree. We must interpret the numbers the same here.
-enum {
- REG_XPR0 = 0,
- REG_XPR31 = 31,
- REG_PC = 32,
- REG_FPR0 = 33,
- REG_FPR31 = 64,
- REG_CSR0 = 65,
- REG_MSTATUS = CSR_MSTATUS + REG_CSR0,
- REG_CSR4095 = 4160,
- REG_PRIV = 4161,
- REG_COUNT
-};
-
-#define MAX_HWBPS 16
-#define DRAM_CACHE_SIZE 16
-
-uint8_t ir_dtmcontrol[1] = {DTMCONTROL};
-struct scan_field select_dtmcontrol = {
- .in_value = NULL,
- .out_value = ir_dtmcontrol
-};
-uint8_t ir_dbus[1] = {DBUS};
-struct scan_field select_dbus = {
- .in_value = NULL,
- .out_value = ir_dbus
-};
-uint8_t ir_idcode[1] = {0x1};
-struct scan_field select_idcode = {
- .in_value = NULL,
- .out_value = ir_idcode
-};
-
-struct trigger {
- uint64_t address;
- uint32_t length;
- uint64_t mask;
- uint64_t value;
- bool read, write, execute;
- int unique_id;
-};
-
-static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
-{
- struct scan_field field;
- uint8_t in_value[4];
- uint8_t out_value[4];
-
- buf_set_u32(out_value, 0, 32, out);
-
- jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE);
-
- field.num_bits = 32;
- field.out_value = out_value;
- field.in_value = in_value;
- jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
-
- /* Always return to dbus. */
- jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
-
- int retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("failed jtag scan: %d", retval);
- return retval;
- }
-
- uint32_t in = buf_get_u32(field.in_value, 0, 32);
- LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in);
-
- return in;
-}
-
-static struct target_type *get_target_type(struct target *target)
-{
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
-
- switch (info->dtm_version) {
- case 0:
- return &riscv011_target;
- case 1:
- return &riscv013_target;
- default:
- LOG_ERROR("Unsupported DTM version: %d", info->dtm_version);
- return NULL;
- }
-}
-
-static int riscv_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- LOG_DEBUG("riscv_init_target()");
- target->arch_info = calloc(1, sizeof(riscv_info_t));
- if (!target->arch_info)
- return ERROR_FAIL;
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
- info->cmd_ctx = cmd_ctx;
-
- select_dtmcontrol.num_bits = target->tap->ir_length;
- select_dbus.num_bits = target->tap->ir_length;
- select_idcode.num_bits = target->tap->ir_length;
-
- return ERROR_OK;
-}
-
-static void riscv_deinit_target(struct target *target)
-{
- LOG_DEBUG("riscv_deinit_target()");
- struct target_type *tt = get_target_type(target);
- tt->deinit_target(target);
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
- free(info);
- target->arch_info = NULL;
-}
-
-static int riscv_halt(struct target *target)
-{
- struct target_type *tt = get_target_type(target);
- return tt->halt(target);
-}
-
-static int riscv_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct target_type *tt = get_target_type(target);
- return tt->add_breakpoint(target, breakpoint);
-}
-
-static int riscv_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct target_type *tt = get_target_type(target);
- return tt->remove_breakpoint(target, breakpoint);
-}
-
-static int riscv_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct target_type *tt = get_target_type(target);
- return tt->add_watchpoint(target, watchpoint);
-}
-
-static int riscv_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct target_type *tt = get_target_type(target);
- return tt->remove_watchpoint(target, watchpoint);
-}
-
-static int riscv_step(struct target *target, int current, uint32_t address,
- int handle_breakpoints)
-{
- struct target_type *tt = get_target_type(target);
- return tt->step(target, current, address, handle_breakpoints);
-}
-
-static int riscv_examine(struct target *target)
-{
- LOG_DEBUG("riscv_examine()");
- if (target_was_examined(target)) {
- return ERROR_OK;
- }
-
- // Don't need to select dbus, since the first thing we do is read dtmcontrol.
-
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
- uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
- LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
- info->dtm_version = get_field(dtmcontrol, DTMCONTROL_VERSION);
- LOG_DEBUG(" version=0x%x", info->dtm_version);
-
- struct target_type *tt = get_target_type(target);
- if (tt == NULL)
- return ERROR_FAIL;
-
- int result = tt->init_target(info->cmd_ctx, target);
- if (result != ERROR_OK)
- return result;
-
- return tt->examine(target);
-}
-
-static int oldriscv_poll(struct target *target)
-{
- struct target_type *tt = get_target_type(target);
- return tt->poll(target);
-}
-
-static int riscv_resume(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution)
-{
- struct target_type *tt = get_target_type(target);
- return tt->resume(target, current, address, handle_breakpoints,
- debug_execution);
-}
-
-static int riscv_assert_reset(struct target *target)
-{
- struct target_type *tt = get_target_type(target);
- return tt->assert_reset(target);
-}
-
-static int riscv_deassert_reset(struct target *target)
-{
- struct target_type *tt = get_target_type(target);
- return tt->deassert_reset(target);
-}
-
-static int riscv_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct target_type *tt = get_target_type(target);
- return tt->read_memory(target, address, size, count, buffer);
-}
-
-static int riscv_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct target_type *tt = get_target_type(target);
- return tt->write_memory(target, address, size, count, buffer);
-}
-
-static int riscv_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class)
-{
- RISCV_INFO(r);
- LOG_DEBUG("reg_class=%d", reg_class);
- LOG_DEBUG("riscv_get_gdb_reg_list: rtos_hartid=%d current_hartid=%d", r->rtos_hartid, r->current_hartid);
- if (r->rtos_hartid != -1)
- riscv_set_current_hartid(target, r->rtos_hartid);
- else
- riscv_set_current_hartid(target, 0);
-
- switch (reg_class) {
- case REG_CLASS_GENERAL:
- *reg_list_size = 32;
- break;
- case REG_CLASS_ALL:
- *reg_list_size = REG_COUNT;
- break;
- default:
- LOG_ERROR("Unsupported reg_class: %d", reg_class);
- return ERROR_FAIL;
- }
-
- *reg_list = calloc(*reg_list_size, sizeof(struct reg *));
- if (!*reg_list) {
- return ERROR_FAIL;
- }
- for (int i = 0; i < *reg_list_size; i++) {
- assert(target->reg_cache->reg_list[i].size > 0);
- (*reg_list)[i] = &target->reg_cache->reg_list[i];
- }
-
- return ERROR_OK;
-}
-
-static int riscv_arch_state(struct target *target)
-{
- struct target_type *tt = get_target_type(target);
- return tt->arch_state(target);
-}
-
-// Algorithm must end with a software breakpoint instruction.
-static int riscv_run_algorithm(struct target *target, int num_mem_params,
- struct mem_param *mem_params, int num_reg_params,
- struct reg_param *reg_params, uint32_t entry_point,
- uint32_t exit_point, int timeout_ms, void *arch_info)
-{
- riscv_info_t *info = (riscv_info_t *) target->arch_info;
-
- if (num_mem_params > 0) {
- LOG_ERROR("Memory parameters are not supported for RISC-V algorithms.");
- return ERROR_FAIL;
- }
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /// Save registers
- struct reg *reg_pc = register_get_by_name(target->reg_cache, "pc", 1);
- if (!reg_pc || reg_pc->type->get(reg_pc) != ERROR_OK) {
- return ERROR_FAIL;
- }
- uint64_t saved_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
-
- uint64_t saved_regs[32];
- for (int i = 0; i < num_reg_params; i++) {
- LOG_DEBUG("save %s", reg_params[i].reg_name);
- struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
- if (!r) {
- LOG_ERROR("Couldn't find register named '%s'", reg_params[i].reg_name);
- return ERROR_FAIL;
- }
-
- if (r->size != reg_params[i].size) {
- LOG_ERROR("Register %s is %d bits instead of %d bits.",
- reg_params[i].reg_name, r->size, reg_params[i].size);
- return ERROR_FAIL;
- }
-
- if (r->number > REG_XPR31) {
- LOG_ERROR("Only GPRs can be use as argument registers.");
- return ERROR_FAIL;
- }
-
- if (r->type->get(r) != ERROR_OK) {
- return ERROR_FAIL;
- }
- saved_regs[r->number] = buf_get_u64(r->value, 0, r->size);
- if (r->type->set(r, reg_params[i].value) != ERROR_OK) {
- return ERROR_FAIL;
- }
- }
-
-
- // Disable Interrupts before attempting to run the algorithm.
- uint64_t current_mstatus;
- uint8_t mstatus_bytes[8];
-
- LOG_DEBUG("Disabling Interrupts");
- char mstatus_name[20];
- sprintf(mstatus_name, "csr%d", CSR_MSTATUS);
- struct reg *reg_mstatus = register_get_by_name(target->reg_cache,
- mstatus_name, 1);
- reg_mstatus->type->get(reg_mstatus);
- current_mstatus = buf_get_u64(reg_mstatus->value, 0, reg_mstatus->size);
- uint64_t ie_mask = MSTATUS_MIE | MSTATUS_HIE | MSTATUS_SIE | MSTATUS_UIE;
- buf_set_u64(mstatus_bytes, 0, info->xlen[0], set_field(current_mstatus,
- ie_mask, 0));
-
- reg_mstatus->type->set(reg_mstatus, mstatus_bytes);
-
- /// Run algorithm
- LOG_DEBUG("resume at 0x%x", entry_point);
- if (riscv_resume(target, 0, entry_point, 0, 0) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- int64_t start = timeval_ms();
- while (target->state != TARGET_HALTED) {
- LOG_DEBUG("poll()");
- int64_t now = timeval_ms();
- if (now - start > timeout_ms) {
- LOG_ERROR("Algorithm timed out after %d ms.", timeout_ms);
- riscv_halt(target);
- oldriscv_poll(target);
- return ERROR_TARGET_TIMEOUT;
- }
-
- int result = oldriscv_poll(target);
- if (result != ERROR_OK) {
- return result;
- }
- }
-
- if (reg_pc->type->get(reg_pc) != ERROR_OK) {
- return ERROR_FAIL;
- }
- uint64_t final_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
- if (final_pc != exit_point) {
- LOG_ERROR("PC ended up at 0x%" PRIx64 " instead of 0x%" PRIx32,
- final_pc, exit_point);
- return ERROR_FAIL;
- }
-
- // Restore Interrupts
- LOG_DEBUG("Restoring Interrupts");
- buf_set_u64(mstatus_bytes, 0, info->xlen[0], current_mstatus);
- reg_mstatus->type->set(reg_mstatus, mstatus_bytes);
-
- /// Restore registers
- uint8_t buf[8];
- buf_set_u64(buf, 0, info->xlen[0], saved_pc);
- if (reg_pc->type->set(reg_pc, buf) != ERROR_OK) {
- return ERROR_FAIL;
- }
-
- for (int i = 0; i < num_reg_params; i++) {
- LOG_DEBUG("restore %s", reg_params[i].reg_name);
- struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
- buf_set_u64(buf, 0, info->xlen[0], saved_regs[r->number]);
- if (r->type->set(r, buf) != ERROR_OK) {
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-/* Should run code on the target to perform CRC of
-memory. Not yet implemented.
-*/
-
-static int riscv_checksum_memory(struct target *target,
- uint32_t address, uint32_t count,
- uint32_t* checksum)
-{
- *checksum = 0xFFFFFFFF;
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-}
-
-/* Should run code on the target to check whether a memory
-block holds all-ones (because this is generally called on
-NOR flash which is 1 when "blank")
-Not yet implemented.
-*/
-int riscv_blank_check_memory(struct target * target,
- uint32_t address,
- uint32_t count,
- uint32_t * blank)
-{
- *blank = 0;
-
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-}
-
-struct target_type riscv_target =
-{
- .name = "riscv",
-
- .init_target = riscv_init_target,
- .deinit_target = riscv_deinit_target,
- .examine = riscv_examine,
-
- /* poll current target status */
- .poll = oldriscv_poll,
-
- .halt = riscv_halt,
- .resume = riscv_resume,
- .step = riscv_step,
-
- .assert_reset = riscv_assert_reset,
- .deassert_reset = riscv_deassert_reset,
-
- .read_memory = riscv_read_memory,
- .write_memory = riscv_write_memory,
-
- .blank_check_memory = riscv_blank_check_memory,
- .checksum_memory = riscv_checksum_memory,
-
- .get_gdb_reg_list = riscv_get_gdb_reg_list,
-
- .add_breakpoint = riscv_add_breakpoint,
- .remove_breakpoint = riscv_remove_breakpoint,
-
- .add_watchpoint = riscv_add_watchpoint,
- .remove_watchpoint = riscv_remove_watchpoint,
-
- .arch_state = riscv_arch_state,
-
- .run_algorithm = riscv_run_algorithm,
-};
-
-/*** OpenOCD Helper Functions ***/
-
-/* 0 means nothing happened, 1 means the hart's state changed (and thus the
- * poll should terminate), and -1 means there was an error. */
-static int riscv_poll_hart(struct target *target, int hartid)
-{
- RISCV_INFO(r);
- LOG_DEBUG("polling hart %d", hartid);
-
- /* If there's no new event then there's nothing to do. */
- riscv_set_current_hartid(target, hartid);
- assert((riscv_was_halted(target) && riscv_is_halted(target)) || !riscv_was_halted(target));
- if (riscv_was_halted(target) || !riscv_is_halted(target))
- return 0;
-
- /* If we got here then this must be the first poll during which this
- * hart halted. We need to synchronize the hart's state with the
- * debugger, and inform the outer polling loop that there's something
- * to do. */
- r->hart_state[hartid] = RISCV_HART_HALTED;
- r->on_halt(target);
- return 1;
-}
-
-/*** OpenOCD Interface ***/
-int riscv_openocd_poll(struct target *target)
-{
- LOG_DEBUG("polling all harts");
- if (riscv_rtos_enabled(target)) {
- /* Check every hart for an event. */
- int triggered_hart = -1;
- for (int i = 0; i < riscv_count_harts(target); ++i) {
- int out = riscv_poll_hart(target, i);
- switch (out) {
- case 0:
- continue;
- case 1:
- triggered_hart = i;
- break;
- case -1:
- return ERROR_FAIL;
- }
- }
- if (triggered_hart == -1) {
- LOG_DEBUG(" no harts halted");
- return ERROR_OK;
- }
- LOG_DEBUG(" hart %d halted", triggered_hart);
-
- /* If we're here then at least one hart triggered. That means
- * we want to go and halt _every_ hart in the system, as that's
- * the invariant we hold here. Some harts might have already
- * halted (as we're either in single-step mode or they also
- * triggered a breakpoint), so don't attempt to halt those
- * harts. */
- for (int i = 0; i < riscv_count_harts(target); ++i)
- riscv_halt_one_hart(target, i);
-
- target->state = TARGET_HALTED;
- switch (riscv_halt_reason(target, triggered_hart)) {
- case RISCV_HALT_BREAKPOINT:
- target->debug_reason = DBG_REASON_BREAKPOINT;
- break;
- case RISCV_HALT_INTERRUPT:
- target->debug_reason = DBG_REASON_DBGRQ;
- break;
- case RISCV_HALT_SINGLESTEP:
- target->debug_reason = DBG_REASON_SINGLESTEP;
- break;
- }
-
- target->rtos->current_threadid = triggered_hart + 1;
- target->rtos->current_thread = triggered_hart + 1;
-
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- return ERROR_OK;
- } else {
- return riscv_poll_hart(target, riscv_current_hartid(target));
- }
-}
-
-int riscv_openocd_halt(struct target *target)
-{
- int out = riscv_halt_all_harts(target);
- if (out != ERROR_OK)
- return out;
-
- target->state = TARGET_HALTED;
- return out;
-}
-
-int riscv_openocd_resume(
- struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints,
- int debug_execution
-) {
- if (!current) {
- LOG_ERROR("resume-at-pc unimplemented");
- return ERROR_FAIL;
- }
-
- int out = riscv_resume_all_harts(target);
- if (out != ERROR_OK)
- return out;
-
- target->state = TARGET_RUNNING;
- return out;
-}
-
-int riscv_openocd_step(
- struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints
-) {
- if (!current) {
- LOG_ERROR("step-at-pc unimplemented");
- return ERROR_FAIL;
- }
-
- int out = riscv_step_rtos_hart(target);
- if (out != ERROR_OK)
- return out;
-
- target->state = TARGET_RUNNING;
- return out;
-}
-
-/*** RISC-V Interface ***/
-
-void riscv_info_init(riscv_info_t *r)
-{
- memset(r, 0, sizeof(*r));
- r->dtm_version = 1;
-
- /* FIXME: The RTOS gets enabled before the target gets initialized. */
- r->rtos_enabled = true;
-
- for (size_t h = 0; h < RISCV_MAX_HARTS; ++h) {
- /* FIXME: I need to rip out Tim's probing sequence, as it
- * disrupts the running code. For now, I'm just hard-coding
- * XLEN to 64 for all cores at reset. */
- r->xlen[h] = 64;
- r->hart_state[h] = RISCV_HART_UNKNOWN;
-
- for (size_t e = 0; e < RISCV_MAX_REGISTERS; ++e)
- r->valid_saved_registers[h][e] = false;
- }
-}
-
-void riscv_save_register(struct target *target, int regno)
-{
- RISCV_INFO(r);
- int hartno = r->current_hartid;
- LOG_DEBUG("riscv_save_register(%d, %d)", hartno, regno);
- assert(r->valid_saved_registers[hartno][regno] == false);
- r->valid_saved_registers[hartno][regno] = true;
- r->saved_registers[hartno][regno] = riscv_get_register(target, hartno, regno);
-}
-
-uint64_t riscv_peek_register(struct target *target, int regno)
-{
- RISCV_INFO(r);
- int hartno = r->current_hartid;
- LOG_DEBUG("riscv_peek_register(%d, %d)", hartno, regno);
- assert(r->valid_saved_registers[hartno][regno] == true);
- return r->saved_registers[hartno][regno];
-}
-
-void riscv_overwrite_register(struct target *target, int regno, uint64_t newval)
-{
- RISCV_INFO(r);
- int hartno = r->current_hartid;
- LOG_DEBUG("riscv_overwrite_register(%d, %d)", hartno, regno);
- assert(r->valid_saved_registers[hartno][regno] == true);
- r->saved_registers[hartno][regno] = newval;
-}
-
-void riscv_restore_register(struct target *target, int regno)
-{
- RISCV_INFO(r);
- int hartno = r->current_hartid;
- LOG_DEBUG("riscv_restore_register(%d, %d)", hartno, regno);
- assert(r->valid_saved_registers[hartno][regno] == true);
- r->valid_saved_registers[hartno][regno] = false;
- riscv_set_register(target, hartno, regno, r->saved_registers[hartno][regno]);
-}
-
-int riscv_halt_all_harts(struct target *target)
-{
- if (riscv_rtos_enabled(target)) {
- for (int i = 0; i < riscv_count_harts(target); ++i)
- riscv_halt_one_hart(target, i);
- } else {
- riscv_halt_one_hart(target, riscv_current_hartid(target));
- }
-
- return ERROR_OK;
-}
-
-int riscv_halt_one_hart(struct target *target, int hartid)
-{
- RISCV_INFO(r);
- LOG_DEBUG("halting hart %d", hartid);
- riscv_set_current_hartid(target, hartid);
-
- if (r->hart_state[hartid] == RISCV_HART_UNKNOWN) {
- r->hart_state[hartid] = riscv_is_halted(target) ? RISCV_HART_HALTED : RISCV_HART_RUNNING;
- if (riscv_was_halted(target)) {
- LOG_WARNING("Connected to hart %d, which was halted. s0, s1, and pc were overwritten by your previous debugger session and cannot be restored.", hartid);
- r->on_halt(target);
- }
- }
-
- if (riscv_was_halted(target)) {
- LOG_DEBUG(" hart %d requested halt, but was already halted", hartid);
- return ERROR_OK;
- }
-
- r->halt_current_hart(target);
- return ERROR_OK;
-}
-
-int riscv_resume_all_harts(struct target *target)
-{
- if (riscv_rtos_enabled(target)) {
- for (int i = 0; i < riscv_count_harts(target); ++i)
- riscv_resume_one_hart(target, i);
- } else {
- riscv_resume_one_hart(target, riscv_current_hartid(target));
- }
-
- return ERROR_OK;
-}
-
-int riscv_resume_one_hart(struct target *target, int hartid)
-{
- RISCV_INFO(r);
- LOG_DEBUG("resuming hart %d", hartid);
- riscv_set_current_hartid(target, hartid);
-
- if (r->hart_state[hartid] == RISCV_HART_UNKNOWN) {
- r->hart_state[hartid] = riscv_is_halted(target) ? RISCV_HART_HALTED : RISCV_HART_RUNNING;
- if (!riscv_was_halted(target)) {
- LOG_ERROR("Asked to resume hart %d, which was in an unknown state", hartid);
- r->on_resume(target);
- }
- }
-
- if (!riscv_was_halted(target)) {
- LOG_DEBUG(" hart %d requested resume, but was already resumed", hartid);
- return ERROR_OK;
- }
-
- r->on_resume(target);
- r->resume_current_hart(target);
- r->hart_state[hartid] = RISCV_HART_RUNNING;
- return ERROR_OK;
-}
-
-int riscv_step_rtos_hart(struct target *target)
-{
- RISCV_INFO(r);
- int hartid = r->current_hartid;
- if (riscv_rtos_enabled(target)) {
- hartid = r->rtos_hartid;
- if (hartid == -1) {
- LOG_USER("GDB has asked me to step \"any\" thread, so I'm stepping hart 0.");
- hartid = 0;
- }
- }
- riscv_set_current_hartid(target, hartid);
- LOG_DEBUG("stepping hart %d", hartid);
-
- assert(r->hart_state[hartid] == RISCV_HART_HALTED);
- r->on_step(target);
- r->step_current_hart(target);
- /* FIXME: There's a race condition with step. */
- r->hart_state[hartid] = RISCV_HART_RUNNING;
- return ERROR_OK;
-}
-
-int riscv_xlen(const struct target *target)
-{
- return riscv_xlen_of_hart(target, riscv_current_hartid(target));
-}
-
-int riscv_xlen_of_hart(const struct target *target, int hartid)
-{
- RISCV_INFO(r);
- assert(r->xlen[hartid] != -1);
- return r->xlen[hartid];
-}
-
-void riscv_enable_rtos(struct target *target)
-{
- RISCV_INFO(r);
- r->rtos_enabled = true;
-}
-
-bool riscv_rtos_enabled(const struct target *target)
-{
- RISCV_INFO(r);
- return r->rtos_enabled;
-}
-
-void riscv_set_current_hartid(struct target *target, int hartid)
-{
- RISCV_INFO(r);
- register_cache_invalidate(target->reg_cache);
- r->current_hartid = hartid;
- r->select_current_hart(target);
-
- /* Update the register list's widths. */
- for (size_t i = 0; i < GDB_REGNO_COUNT; ++i) {
- struct reg *reg = &target->reg_cache->reg_list[i];
-
- reg->value = &r->reg_cache_values[i];
- reg->valid = false;
-
- switch (i) {
- case GDB_REGNO_PRIV:
- reg->size = 8;
- break;
- default:
- reg->size = riscv_xlen(target);
- break;
- }
- }
-}
-
-int riscv_current_hartid(const struct target *target)
-{
- RISCV_INFO(r);
- assert(riscv_rtos_enabled(target) || target->coreid == r->current_hartid);
- return r->current_hartid;
-}
-
-void riscv_set_all_rtos_harts(struct target *target)
-{
- RISCV_INFO(r);
- r->rtos_hartid = -1;
-}
-
-void riscv_set_rtos_hartid(struct target *target, int hartid)
-{
- RISCV_INFO(r);
- r->rtos_hartid = hartid;
-}
-
-int riscv_count_harts(struct target *target)
-{
- return 3;
-}
-
-bool riscv_has_register(struct target *target, int hartid, int regid)
-{
- return 1;
-}
-
-void riscv_set_register(struct target *target, int hartid, enum gdb_regno regid, uint64_t value)
-{
- RISCV_INFO(r);
- LOG_DEBUG("writing register %d on hart %d", regid, hartid);
- return r->set_register(target, hartid, regid, value);
-}
-
-uint64_t riscv_get_register(struct target *target, int hartid, enum gdb_regno regid)
-{
- RISCV_INFO(r);
- LOG_DEBUG("reading register %d on hart %d", regid, hartid);
- return r->get_register(target, hartid, regid);
-}
-
-bool riscv_is_halted(struct target *target)
-{
- RISCV_INFO(r);
- return r->is_halted(target);
-}
-
-bool riscv_was_halted(struct target *target)
-{
- RISCV_INFO(r);
- assert(r->hart_state[r->current_hartid] != RISCV_HART_UNKNOWN);
- return r->hart_state[r->current_hartid] == RISCV_HART_HALTED;
-}
-
-enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid)
-{
- RISCV_INFO(r);
- riscv_set_current_hartid(target, hartid);
- assert(riscv_is_halted(target));
- return r->halt_reason(target);
-}
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
deleted file mode 100644
index 7ce2622..0000000
--- a/src/target/riscv/riscv.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef RISCV_H
-#define RISCV_H
-
-#include "opcodes.h"
-#include "gdb_regs.h"
-
-/* The register cache is staticly allocated. */
-#define RISCV_MAX_HARTS 32
-#define RISCV_MAX_REGISTERS 5000
-
-extern struct target_type riscv011_target;
-extern struct target_type riscv013_target;
-
-/*
- * Definitions shared by code supporting all RISC-V versions.
- */
-typedef uint64_t riscv_reg_t;
-
-enum riscv_hart_state {
- RISCV_HART_UNKNOWN,
- RISCV_HART_HALTED,
- RISCV_HART_RUNNING,
-};
-
-enum riscv_halt_reason {
- RISCV_HALT_INTERRUPT,
- RISCV_HALT_BREAKPOINT,
- RISCV_HALT_SINGLESTEP,
-};
-
-typedef struct {
- unsigned dtm_version;
- struct command_context *cmd_ctx;
- void *version_specific;
-
- /* When the RTOS is enabled this target is expected to handle all the
- * harts in the system. When it's disabled this just uses the regular
- * multi-target mode. */
- bool rtos_enabled;
-
- /* The hart that the RTOS thinks is currently being debugged. */
- int rtos_hartid;
-
- /* The hart that is currently being debugged. Note that this is
- * different than the hartid that the RTOS is expected to use. This
- * one will change all the time, it's more of a global argument to
- * every function than an actual */
- int current_hartid;
-
- /* Enough space to store all the registers we might need to save. */
- /* FIXME: This should probably be a bunch of register caches. */
- uint64_t saved_registers[RISCV_MAX_HARTS][RISCV_MAX_REGISTERS];
- bool valid_saved_registers[RISCV_MAX_HARTS][RISCV_MAX_REGISTERS];
-
- /* The register cache points into here. */
- uint64_t reg_cache_values[RISCV_MAX_REGISTERS];
-
- /* It's possible that each core has a different supported ISA set. */
- int xlen[RISCV_MAX_HARTS];
-
- /* The state of every hart. */
- enum riscv_hart_state hart_state[RISCV_MAX_HARTS];
-
- /* Helper functions that target the various RISC-V debug spec
- * implementations. */
- riscv_reg_t (*get_register)(struct target *, int, int);
- void (*set_register)(struct target *, int, int, uint64_t);
- void (*select_current_hart)(struct target *);
- bool (*is_halted)(struct target *target);
- void (*halt_current_hart)(struct target *);
- void (*resume_current_hart)(struct target *target);
- void (*step_current_hart)(struct target *target);
- void (*on_halt)(struct target *target);
- void (*on_resume)(struct target *target);
- void (*on_step)(struct target *target);
- enum riscv_halt_reason (*halt_reason)(struct target *target);
-} riscv_info_t;
-
-/* Everything needs the RISC-V specific info structure, so here's a nice macro
- * that provides that. */
-static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused));
-static inline riscv_info_t *riscv_info(const struct target *target)
-{ return target->arch_info; }
-#define RISCV_INFO(R) riscv_info_t *R = riscv_info(target);
-
-extern uint8_t ir_dtmcontrol[1];
-extern struct scan_field select_dtmcontrol;
-extern uint8_t ir_dbus[1];
-extern struct scan_field select_dbus;
-extern uint8_t ir_idcode[1];
-extern struct scan_field select_idcode;
-
-/*** OpenOCD Interface */
-int riscv_openocd_poll(struct target *target);
-
-int riscv_openocd_halt(struct target *target);
-
-int riscv_openocd_resume(
- struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints,
- int debug_execution
-);
-
-int riscv_openocd_step(
- struct target *target,
- int current,
- uint32_t address,
- int handle_breakpoints
-);
-
-/*** RISC-V Interface ***/
-
-/* Initializes the shared RISC-V structure. */
-void riscv_info_init(riscv_info_t *r);
-
-/* Functions that save and restore registers. */
-void riscv_save_register(struct target *target, int regno);
-uint64_t riscv_peek_register(struct target *target, int regno);
-void riscv_overwrite_register(struct target *target, int regno, uint64_t newval);
-void riscv_restore_register(struct target *target, int regno);
-
-/* Run control, possibly for multiple harts. The _all_harts versions resume
- * all the enabled harts, which when running in RTOS mode is all the harts on
- * the system. */
-int riscv_halt_all_harts(struct target *target);
-int riscv_halt_one_hart(struct target *target, int hartid);
-int riscv_resume_all_harts(struct target *target);
-int riscv_resume_one_hart(struct target *target, int hartid);
-
-/* Steps the hart that's currently selected in the RTOS, or if there is no RTOS
- * then the only hart. */
-int riscv_step_rtos_hart(struct target *target);
-
-/* Returns XLEN for the given (or current) hart. */
-int riscv_xlen(const struct target *target);
-int riscv_xlen_of_hart(const struct target *target, int hartid);
-
-/* Enables RISC-V RTOS support for this target. This causes the coreid field
- * of the generic target struct to be ignored, and instead for operations to
- * apply to all the harts in the system. */
-void riscv_enable_rtos(struct target *target);
-bool riscv_rtos_enabled(const struct target *target);
-
-/* Sets the current hart, which is the hart that will actually be used when
- * issuing debug commands. */
-void riscv_set_current_hartid(struct target *target, int hartid);
-int riscv_current_hartid(const struct target *target);
-
-/*** Support functions for the RISC-V 'RTOS', which provides multihart support
- * without requiring multiple targets. */
-
-/* When using the RTOS to debug, this selects the hart that is currently being
- * debugged. This doesn't propogate to the hardware. */
-void riscv_set_all_rtos_harts(struct target *target);
-void riscv_set_rtos_hartid(struct target *target, int hartid);
-
-/* Lists the number of harts in the system, which are assumed to be
- * concecutive and start with mhartid=0. */
-int riscv_count_harts(struct target *target);
-
-/* Returns TRUE if the target has the given register on the given hart. */
-bool riscv_has_register(struct target *target, int hartid, int regid);
-
-/* Returns the value of the given register on the given hart. 32-bit registers
- * are zero extended to 64 bits. */
-void riscv_set_register(struct target *target, int hid, enum gdb_regno rid, uint64_t v);
-riscv_reg_t riscv_get_register(struct target *target, int hid, enum gdb_regno rid);
-
-/* Checks the state of the current hart -- "is_halted" checks the actual
- * on-device register, while "was_halted" checks the machine's state. */
-bool riscv_is_halted(struct target *target);
-bool riscv_was_halted(struct target *target);
-enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid);
-
-#endif
diff --git a/src/target/smp.c b/src/target/smp.c
deleted file mode 100644
index 3dc6f6d..0000000
--- a/src/target/smp.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/***************************************************************************
- * *
- * Copyright (C) ST-Ericsson SA 2011 *
- * Author: Michel Jaouen <michel.jaouen@stericsson.com> for ST-Ericsson. *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "server/server.h"
-
-#include "target/target.h"
-
-#include "server/gdb_server.h"
-#include "smp.h"
-#include "helper/binarybuffer.h"
-
-/* implementation of new packet in gdb interface for smp feature */
-/* */
-/* j : smp status request */
-/* J : smp set request */
-/* */
-/* jc :read core id displayed by gdb connection */
-/* reply XXXXXXXX core id is int32_t , 8 hex digits */
-/* */
-/* Reply ENN error not supported (target not smp) */
-/* */
-/* JcXX set core id displayed at next gdb continue */
-/* maximum 8 bytes described core id int32_t (8 hex digits) */
-/* (core id -1 , reserved for returning to normal continue mode) */
-/* Reply ENN error not supported(target not smp,core id out of range) */
-/* Reply OK : for success */
-/* */
-/* handling of this packet within gdb can be done by the creation */
-/* internal variable by mean of function allocate_computed_value */
-/* set $_core 1 => Jc01 packet is sent */
-/* print $_core => jc packet is sent and result is affected in $ */
-/* Another way to test this packet is the usage of maintenance packet */
-/* maint packet Jc01 */
-/* maint packet jc */
-
-/* packet j :smp status request */
-int gdb_read_smp_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- int retval = ERROR_OK;
- if (target->smp) {
- if (strncmp(packet, "jc", 2) == 0) {
- const uint32_t len = sizeof(target->gdb_service->core[0]);
- char hex_buffer[len * 2 + 1];
- uint8_t buffer[len];
- buf_set_u32(buffer, 0, len * 8, target->gdb_service->core[0]);
- int pkt_len = hexify(hex_buffer, (char *)buffer, sizeof(buffer), sizeof(hex_buffer));
-
- retval = gdb_put_packet(connection, hex_buffer, pkt_len);
- }
- } else
- retval = gdb_put_packet(connection, "E01", 3);
- return retval;
-}
-
-/* J : smp set request */
-int gdb_write_smp_packet(struct connection *connection,
- char const *packet, int packet_size)
-{
- struct target *target = get_target_from_connection(connection);
- char *separator;
- int coreid = 0;
- int retval = ERROR_OK;
-
- /* skip command character */
- if (target->smp) {
- if (strncmp(packet, "Jc", 2) == 0) {
- packet += 2;
- coreid = strtoul(packet, &separator, 16);
- target->gdb_service->core[1] = coreid;
- retval = gdb_put_packet(connection, "OK", 2);
- }
- } else
- retval = gdb_put_packet(connection, "E01", 3);
-
- return retval;
-}
diff --git a/src/target/smp.h b/src/target/smp.h
deleted file mode 100644
index c3e6c6c..0000000
--- a/src/target/smp.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/***************************************************************************
- * *
- * Copyright (C) ST-Ericsson SA 2011 *
- * Author: Michel Jaouen <michel.jaouen@stericsson.com> for ST-Ericsson. *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_SMP_H
-#define OPENOCD_TARGET_SMP_H
-
-#include "server/server.h"
-
-int gdb_read_smp_packet(struct connection *connection,
- char const *packet, int packet_size);
-int gdb_write_smp_packet(struct connection *connection,
- char const *packet, int packet_size);
-
-#endif /* OPENOCD_TARGET_SMP_H */
diff --git a/src/target/startup.tcl b/src/target/startup.tcl
deleted file mode 100644
index cf2813b..0000000
--- a/src/target/startup.tcl
+++ /dev/null
@@ -1,210 +0,0 @@
-# Defines basic Tcl procs for OpenOCD target module
-
-proc new_target_name { } {
- return [target number [expr [target count] - 1 ]]
-}
-
-global in_process_reset
-set in_process_reset 0
-
-# Catch reset recursion
-proc ocd_process_reset { MODE } {
- global in_process_reset
- if {$in_process_reset} {
- set in_process_reset 0
- return -code error "'reset' can not be invoked recursively"
- }
-
- set in_process_reset 1
- set success [expr [catch {ocd_process_reset_inner $MODE} result]==0]
- set in_process_reset 0
-
- if {$success} {
- return $result
- } else {
- return -code error $result
- }
-}
-
-proc ocd_process_reset_inner { MODE } {
- set targets [target names]
-
- # If this target must be halted...
- set halt -1
- if { 0 == [string compare $MODE halt] } {
- set halt 1
- }
- if { 0 == [string compare $MODE init] } {
- set halt 1;
- }
- if { 0 == [string compare $MODE run ] } {
- set halt 0;
- }
- if { $halt < 0 } {
- return -code error "Invalid mode: $MODE, must be one of: halt, init, or run";
- }
-
- # Target event handlers *might* change which TAPs are enabled
- # or disabled, so we fire all of them. But don't issue any
- # target "arp_*" commands, which may issue JTAG transactions,
- # unless we know the underlying TAP is active.
- #
- # NOTE: ARP == "Advanced Reset Process" ... "advanced" is
- # relative to a previous restrictive scheme
-
- foreach t $targets {
- # New event script.
- $t invoke-event reset-start
- }
-
- # Use TRST or TMS/TCK operations to reset all the tap controllers.
- # TAP reset events get reported; they might enable some taps.
- init_reset $MODE
-
- # Examine all targets on enabled taps.
- foreach t $targets {
- if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} {
- $t invoke-event examine-start
- set err [catch "$t arp_examine"]
- if { $err == 0 } {
- $t invoke-event examine-end
- }
- }
- }
-
- # Assert SRST, and report the pre/post events.
- # Note: no target sees SRST before "pre" or after "post".
- foreach t $targets {
- $t invoke-event reset-assert-pre
- }
- foreach t $targets {
- # C code needs to know if we expect to 'halt'
- if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} {
- $t arp_reset assert $halt
- }
- }
- foreach t $targets {
- $t invoke-event reset-assert-post
- }
-
- # Now de-assert SRST, and report the pre/post events.
- # Note: no target sees !SRST before "pre" or after "post".
- foreach t $targets {
- $t invoke-event reset-deassert-pre
- }
- foreach t $targets {
- # Again, de-assert code needs to know if we 'halt'
- if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} {
- $t arp_reset deassert $halt
- }
- }
- foreach t $targets {
- $t invoke-event reset-deassert-post
- }
-
- # Pass 1 - Now wait for any halt (requested as part of reset
- # assert/deassert) to happen. Ideally it takes effect without
- # first executing any instructions.
- if { $halt } {
- foreach t $targets {
- if {[using_jtag] && ![jtag tapisenabled [$t cget -chain-position]]} {
- continue
- }
-
- # Wait upto 1 second for target to halt. Why 1sec? Cause
- # the JTAG tap reset signal might be hooked to a slow
- # resistor/capacitor circuit - and it might take a while
- # to charge
-
- # Catch, but ignore any errors.
- catch { $t arp_waitstate halted 1000 }
-
- # Did we succeed?
- set s [$t curstate]
-
- if { 0 != [string compare $s "halted" ] } {
- return -code error [format "TARGET: %s - Not halted" $t]
- }
- }
- }
-
- #Pass 2 - if needed "init"
- if { 0 == [string compare init $MODE] } {
- foreach t $targets {
- if {[using_jtag] && ![jtag tapisenabled [$t cget -chain-position]]} {
- continue
- }
-
- set err [catch "$t arp_waitstate halted 5000"]
- # Did it halt?
- if { $err == 0 } {
- $t invoke-event reset-init
- }
- }
- }
-
- foreach t $targets {
- $t invoke-event reset-end
- }
-}
-
-proc using_jtag {} {
- set _TRANSPORT [ transport select ]
- expr { [ string first "jtag" $_TRANSPORT ] != -1 }
-}
-
-proc using_swd {} {
- set _TRANSPORT [ transport select ]
- expr { [ string first "swd" $_TRANSPORT ] != -1 }
-}
-
-proc using_hla {} {
- set _TRANSPORT [ transport select ]
- expr { [ string first "hla" $_TRANSPORT ] != -1 }
-}
-
-#########
-
-# Temporary migration aid. May be removed starting in January 2011.
-proc armv4_5 params {
- echo "DEPRECATED! use 'arm $params' not 'armv4_5 $params'"
- arm $params
-}
-
-# Target/chain configuration scripts can either execute commands directly
-# or define a procedure which is executed once all configuration
-# scripts have completed.
-#
-# By default(classic) the config scripts will set up the target configuration
-proc init_targets {} {
-}
-
-proc set_default_target_event {t e s} {
- if {[$t cget -event $e] == ""} {
- $t configure -event $e $s
- }
-}
-
-proc init_target_events {} {
- set targets [target names]
-
- foreach t $targets {
- set_default_target_event $t gdb-flash-erase-start "reset init"
- set_default_target_event $t gdb-flash-write-end "reset halt"
- }
-}
-
-# Additionally board config scripts can define a procedure init_board that will be executed after init and init_targets
-proc init_board {} {
-}
-
-# deprecated target name cmds
-proc cortex_m3 args {
- echo "DEPRECATED! use 'cortex_m' not 'cortex_m3'"
- eval cortex_m $args
-}
-
-proc cortex_a8 args {
- echo "DEPRECATED! use 'cortex_a' not 'cortex_a8'"
- eval cortex_a $args
-}
diff --git a/src/target/target.c b/src/target/target.c
deleted file mode 100644
index 42a8cac..0000000
--- a/src/target/target.c
+++ /dev/null
@@ -1,6228 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008, Duane Ellis *
- * openocd@duaneeellis.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2008 by Rick Altherr *
- * kc8apf@kc8apf.net> *
- * *
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * Copyright (C) ST-Ericsson SA 2011 *
- * michel.jaouen@stericsson.com : smp minimum support *
- * *
- * Copyright (C) 2011 Andreas Fritiofson *
- * andreas.fritiofson@gmail.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/time_support.h>
-#include <jtag/jtag.h>
-#include <flash/nor/core.h>
-
-#include "target.h"
-#include "target_type.h"
-#include "target_request.h"
-#include "breakpoints.h"
-#include "register.h"
-#include "trace.h"
-#include "image.h"
-#include "rtos/rtos.h"
-#include "transport/transport.h"
-
-/* default halt wait timeout (ms) */
-#define DEFAULT_HALT_TIMEOUT 5000
-
-static int target_read_buffer_default(struct target *target, uint32_t address,
- uint32_t count, uint8_t *buffer);
-static int target_write_buffer_default(struct target *target, uint32_t address,
- uint32_t count, const uint8_t *buffer);
-static int target_array2mem(Jim_Interp *interp, struct target *target,
- int argc, Jim_Obj * const *argv);
-static int target_mem2array(Jim_Interp *interp, struct target *target,
- int argc, Jim_Obj * const *argv);
-static int target_register_user_commands(struct command_context *cmd_ctx);
-static int target_get_gdb_fileio_info_default(struct target *target,
- struct gdb_fileio_info *fileio_info);
-static int target_gdb_fileio_end_default(struct target *target, int retcode,
- int fileio_errno, bool ctrl_c);
-static int target_profiling_default(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
-
-/* targets */
-extern struct target_type arm7tdmi_target;
-extern struct target_type arm720t_target;
-extern struct target_type arm9tdmi_target;
-extern struct target_type arm920t_target;
-extern struct target_type arm966e_target;
-extern struct target_type arm946e_target;
-extern struct target_type arm926ejs_target;
-extern struct target_type fa526_target;
-extern struct target_type feroceon_target;
-extern struct target_type dragonite_target;
-extern struct target_type xscale_target;
-extern struct target_type cortexm_target;
-extern struct target_type cortexa_target;
-extern struct target_type cortexr4_target;
-extern struct target_type arm11_target;
-extern struct target_type ls1_sap_target;
-extern struct target_type mips_m4k_target;
-extern struct target_type avr_target;
-extern struct target_type dsp563xx_target;
-extern struct target_type dsp5680xx_target;
-extern struct target_type testee_target;
-extern struct target_type avr32_ap7k_target;
-extern struct target_type hla_target;
-extern struct target_type nds32_v2_target;
-extern struct target_type nds32_v3_target;
-extern struct target_type nds32_v3m_target;
-extern struct target_type or1k_target;
-extern struct target_type quark_x10xx_target;
-extern struct target_type quark_d20xx_target;
-extern struct target_type riscv_target;
-
-static struct target_type *target_types[] = {
- &arm7tdmi_target,
- &arm9tdmi_target,
- &arm920t_target,
- &arm720t_target,
- &arm966e_target,
- &arm946e_target,
- &arm926ejs_target,
- &fa526_target,
- &feroceon_target,
- &dragonite_target,
- &xscale_target,
- &cortexm_target,
- &cortexa_target,
- &cortexr4_target,
- &arm11_target,
- &ls1_sap_target,
- &mips_m4k_target,
- &avr_target,
- &dsp563xx_target,
- &dsp5680xx_target,
- &testee_target,
- &avr32_ap7k_target,
- &hla_target,
- &nds32_v2_target,
- &nds32_v3_target,
- &nds32_v3m_target,
- &or1k_target,
- &quark_x10xx_target,
- &quark_d20xx_target,
- &riscv_target,
- NULL,
-};
-
-struct target *all_targets;
-static struct target_event_callback *target_event_callbacks;
-static struct target_timer_callback *target_timer_callbacks;
-LIST_HEAD(target_reset_callback_list);
-LIST_HEAD(target_trace_callback_list);
-static const int polling_interval = 100;
-
-static const Jim_Nvp nvp_assert[] = {
- { .name = "assert", NVP_ASSERT },
- { .name = "deassert", NVP_DEASSERT },
- { .name = "T", NVP_ASSERT },
- { .name = "F", NVP_DEASSERT },
- { .name = "t", NVP_ASSERT },
- { .name = "f", NVP_DEASSERT },
- { .name = NULL, .value = -1 }
-};
-
-static const Jim_Nvp nvp_error_target[] = {
- { .value = ERROR_TARGET_INVALID, .name = "err-invalid" },
- { .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" },
- { .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" },
- { .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" },
- { .value = ERROR_TARGET_FAILURE, .name = "err-failure" },
- { .value = ERROR_TARGET_UNALIGNED_ACCESS , .name = "err-unaligned-access" },
- { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" },
- { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" },
- { .value = ERROR_TARGET_TRANSLATION_FAULT , .name = "err-translation-fault" },
- { .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" },
- { .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" },
- { .value = -1, .name = NULL }
-};
-
-static const char *target_strerror_safe(int err)
-{
- const Jim_Nvp *n;
-
- n = Jim_Nvp_value2name_simple(nvp_error_target, err);
- if (n->name == NULL)
- return "unknown";
- else
- return n->name;
-}
-
-static const Jim_Nvp nvp_target_event[] = {
-
- { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
- { .value = TARGET_EVENT_HALTED, .name = "halted" },
- { .value = TARGET_EVENT_RESUMED, .name = "resumed" },
- { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
- { .value = TARGET_EVENT_RESUME_END, .name = "resume-end" },
-
- { .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
- { .name = "gdb-end", .value = TARGET_EVENT_GDB_END },
-
- { .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
- { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" },
- { .value = TARGET_EVENT_RESET_ASSERT, .name = "reset-assert" },
- { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" },
- { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" },
- { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
- { .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" },
- { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" },
- { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" },
- { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" },
- { .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" },
- { .value = TARGET_EVENT_RESET_END, .name = "reset-end" },
-
- { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
- { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
-
- { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" },
- { .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" },
-
- { .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" },
- { .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" },
-
- { .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" },
- { .value = TARGET_EVENT_GDB_FLASH_WRITE_END , .name = "gdb-flash-write-end" },
-
- { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
- { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" },
-
- { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" },
-
- { .name = NULL, .value = -1 }
-};
-
-static const Jim_Nvp nvp_target_state[] = {
- { .name = "unknown", .value = TARGET_UNKNOWN },
- { .name = "running", .value = TARGET_RUNNING },
- { .name = "halted", .value = TARGET_HALTED },
- { .name = "reset", .value = TARGET_RESET },
- { .name = "debug-running", .value = TARGET_DEBUG_RUNNING },
- { .name = NULL, .value = -1 },
-};
-
-static const Jim_Nvp nvp_target_debug_reason[] = {
- { .name = "debug-request" , .value = DBG_REASON_DBGRQ },
- { .name = "breakpoint" , .value = DBG_REASON_BREAKPOINT },
- { .name = "watchpoint" , .value = DBG_REASON_WATCHPOINT },
- { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT },
- { .name = "single-step" , .value = DBG_REASON_SINGLESTEP },
- { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED },
- { .name = "program-exit" , .value = DBG_REASON_EXIT },
- { .name = "undefined" , .value = DBG_REASON_UNDEFINED },
- { .name = NULL, .value = -1 },
-};
-
-static const Jim_Nvp nvp_target_endian[] = {
- { .name = "big", .value = TARGET_BIG_ENDIAN },
- { .name = "little", .value = TARGET_LITTLE_ENDIAN },
- { .name = "be", .value = TARGET_BIG_ENDIAN },
- { .name = "le", .value = TARGET_LITTLE_ENDIAN },
- { .name = NULL, .value = -1 },
-};
-
-static const Jim_Nvp nvp_reset_modes[] = {
- { .name = "unknown", .value = RESET_UNKNOWN },
- { .name = "run" , .value = RESET_RUN },
- { .name = "halt" , .value = RESET_HALT },
- { .name = "init" , .value = RESET_INIT },
- { .name = NULL , .value = -1 },
-};
-
-const char *debug_reason_name(struct target *t)
-{
- const char *cp;
-
- cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason,
- t->debug_reason)->name;
- if (!cp) {
- LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason));
- cp = "(*BUG*unknown*BUG*)";
- }
- return cp;
-}
-
-const char *target_state_name(struct target *t)
-{
- const char *cp;
- cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name;
- if (!cp) {
- LOG_ERROR("Invalid target state: %d", (int)(t->state));
- cp = "(*BUG*unknown*BUG*)";
- }
- return cp;
-}
-
-const char *target_event_name(enum target_event event)
-{
- const char *cp;
- cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name;
- if (!cp) {
- LOG_ERROR("Invalid target event: %d", (int)(event));
- cp = "(*BUG*unknown*BUG*)";
- }
- return cp;
-}
-
-const char *target_reset_mode_name(enum target_reset_mode reset_mode)
-{
- const char *cp;
- cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name;
- if (!cp) {
- LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode));
- cp = "(*BUG*unknown*BUG*)";
- }
- return cp;
-}
-
-/* determine the number of the new target */
-static int new_target_number(void)
-{
- struct target *t;
- int x;
-
- /* number is 0 based */
- x = -1;
- t = all_targets;
- while (t) {
- if (x < t->target_number)
- x = t->target_number;
- t = t->next;
- }
- return x + 1;
-}
-
-/* read a uint64_t from a buffer in target memory endianness */
-uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- return le_to_h_u64(buffer);
- else
- return be_to_h_u64(buffer);
-}
-
-/* read a uint32_t from a buffer in target memory endianness */
-uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- return le_to_h_u32(buffer);
- else
- return be_to_h_u32(buffer);
-}
-
-/* read a uint24_t from a buffer in target memory endianness */
-uint32_t target_buffer_get_u24(struct target *target, const uint8_t *buffer)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- return le_to_h_u24(buffer);
- else
- return be_to_h_u24(buffer);
-}
-
-/* read a uint16_t from a buffer in target memory endianness */
-uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- return le_to_h_u16(buffer);
- else
- return be_to_h_u16(buffer);
-}
-
-/* read a uint8_t from a buffer in target memory endianness */
-static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer)
-{
- return *buffer & 0x0ff;
-}
-
-/* write a uint64_t to a buffer in target memory endianness */
-void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- h_u64_to_le(buffer, value);
- else
- h_u64_to_be(buffer, value);
-}
-
-/* write a uint32_t to a buffer in target memory endianness */
-void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- h_u32_to_le(buffer, value);
- else
- h_u32_to_be(buffer, value);
-}
-
-/* write a uint24_t to a buffer in target memory endianness */
-void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- h_u24_to_le(buffer, value);
- else
- h_u24_to_be(buffer, value);
-}
-
-/* write a uint16_t to a buffer in target memory endianness */
-void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value)
-{
- if (target->endianness == TARGET_LITTLE_ENDIAN)
- h_u16_to_le(buffer, value);
- else
- h_u16_to_be(buffer, value);
-}
-
-/* write a uint8_t to a buffer in target memory endianness */
-static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value)
-{
- *buffer = value;
-}
-
-/* write a uint64_t array to a buffer in target memory endianness */
-void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, uint32_t count, uint64_t *dstbuf)
-{
- uint32_t i;
- for (i = 0; i < count; i++)
- dstbuf[i] = target_buffer_get_u64(target, &buffer[i * 8]);
-}
-
-/* write a uint32_t array to a buffer in target memory endianness */
-void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf)
-{
- uint32_t i;
- for (i = 0; i < count; i++)
- dstbuf[i] = target_buffer_get_u32(target, &buffer[i * 4]);
-}
-
-/* write a uint16_t array to a buffer in target memory endianness */
-void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf)
-{
- uint32_t i;
- for (i = 0; i < count; i++)
- dstbuf[i] = target_buffer_get_u16(target, &buffer[i * 2]);
-}
-
-/* write a uint64_t array to a buffer in target memory endianness */
-void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_t count, const uint64_t *srcbuf)
-{
- uint32_t i;
- for (i = 0; i < count; i++)
- target_buffer_set_u64(target, &buffer[i * 8], srcbuf[i]);
-}
-
-/* write a uint32_t array to a buffer in target memory endianness */
-void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf)
-{
- uint32_t i;
- for (i = 0; i < count; i++)
- target_buffer_set_u32(target, &buffer[i * 4], srcbuf[i]);
-}
-
-/* write a uint16_t array to a buffer in target memory endianness */
-void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf)
-{
- uint32_t i;
- for (i = 0; i < count; i++)
- target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]);
-}
-
-/* return a pointer to a configured target; id is name or number */
-struct target *get_target(const char *id)
-{
- struct target *target;
-
- /* try as tcltarget name */
- for (target = all_targets; target; target = target->next) {
- if (target_name(target) == NULL)
- continue;
- if (strcmp(id, target_name(target)) == 0)
- return target;
- }
-
- /* It's OK to remove this fallback sometime after August 2010 or so */
-
- /* no match, try as number */
- unsigned num;
- if (parse_uint(id, &num) != ERROR_OK)
- return NULL;
-
- for (target = all_targets; target; target = target->next) {
- if (target->target_number == (int)num) {
- LOG_WARNING("use '%s' as target identifier, not '%u'",
- target_name(target), num);
- return target;
- }
- }
-
- return NULL;
-}
-
-/* returns a pointer to the n-th configured target */
-struct target *get_target_by_num(int num)
-{
- struct target *target = all_targets;
-
- while (target) {
- if (target->target_number == num)
- return target;
- target = target->next;
- }
-
- return NULL;
-}
-
-struct target *get_current_target(struct command_context *cmd_ctx)
-{
- struct target *target = get_target_by_num(cmd_ctx->current_target);
-
- if (target == NULL) {
- LOG_ERROR("BUG: current_target out of bounds");
- exit(-1);
- }
-
- return target;
-}
-
-int target_poll(struct target *target)
-{
- int retval;
-
- /* We can't poll until after examine */
- if (!target_was_examined(target)) {
- /* Fail silently lest we pollute the log */
- return ERROR_FAIL;
- }
-
- retval = target->type->poll(target);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->halt_issued) {
- if (target->state == TARGET_HALTED)
- target->halt_issued = false;
- else {
- int64_t t = timeval_ms() - target->halt_issued_time;
- if (t > DEFAULT_HALT_TIMEOUT) {
- target->halt_issued = false;
- LOG_INFO("Halt timed out, wake up GDB.");
- target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
- }
- }
- }
-
- return ERROR_OK;
-}
-
-int target_halt(struct target *target)
-{
- int retval;
- /* We can't poll until after examine */
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- retval = target->type->halt(target);
- if (retval != ERROR_OK)
- return retval;
-
- target->halt_issued = true;
- target->halt_issued_time = timeval_ms();
-
- return ERROR_OK;
-}
-
-/**
- * Make the target (re)start executing using its saved execution
- * context (possibly with some modifications).
- *
- * @param target Which target should start executing.
- * @param current True to use the target's saved program counter instead
- * of the address parameter
- * @param address Optionally used as the program counter.
- * @param handle_breakpoints True iff breakpoints at the resumption PC
- * should be skipped. (For example, maybe execution was stopped by
- * such a breakpoint, in which case it would be counterprodutive to
- * let it re-trigger.
- * @param debug_execution False if all working areas allocated by OpenOCD
- * should be released and/or restored to their original contents.
- * (This would for example be true to run some downloaded "helper"
- * algorithm code, which resides in one such working buffer and uses
- * another for data storage.)
- *
- * @todo Resolve the ambiguity about what the "debug_execution" flag
- * signifies. For example, Target implementations don't agree on how
- * it relates to invalidation of the register cache, or to whether
- * breakpoints and watchpoints should be enabled. (It would seem wrong
- * to enable breakpoints when running downloaded "helper" algorithms
- * (debug_execution true), since the breakpoints would be set to match
- * target firmware being debugged, not the helper algorithm.... and
- * enabling them could cause such helpers to malfunction (for example,
- * by overwriting data with a breakpoint instruction. On the other
- * hand the infrastructure for running such helpers might use this
- * procedure but rely on hardware breakpoint to detect termination.)
- */
-int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
-{
- int retval;
-
- /* We can't poll until after examine */
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- target_call_event_callbacks(target, TARGET_EVENT_RESUME_START);
-
- /* note that resume *must* be asynchronous. The CPU can halt before
- * we poll. The CPU can even halt at the current PC as a result of
- * a software breakpoint being inserted by (a bug?) the application.
- */
- retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution);
- if (retval != ERROR_OK)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_RESUME_END);
-
- return retval;
-}
-
-static int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode)
-{
- char buf[100];
- int retval;
- Jim_Nvp *n;
- n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode);
- if (n->name == NULL) {
- LOG_ERROR("invalid reset mode");
- return ERROR_FAIL;
- }
-
- struct target *target;
- for (target = all_targets; target; target = target->next)
- target_call_reset_callbacks(target, reset_mode);
-
- /* disable polling during reset to make reset event scripts
- * more predictable, i.e. dr/irscan & pathmove in events will
- * not have JTAG operations injected into the middle of a sequence.
- */
- bool save_poll = jtag_poll_get_enabled();
-
- jtag_poll_set_enabled(false);
-
- sprintf(buf, "ocd_process_reset %s", n->name);
- retval = Jim_Eval(cmd_ctx->interp, buf);
-
- jtag_poll_set_enabled(save_poll);
-
- if (retval != JIM_OK) {
- Jim_MakeErrorMessage(cmd_ctx->interp);
- command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL));
- return ERROR_FAIL;
- }
-
- /* We want any events to be processed before the prompt */
- retval = target_call_timer_callbacks_now();
-
- for (target = all_targets; target; target = target->next) {
- target->type->check_reset(target);
- target->running_alg = false;
- }
-
- return retval;
-}
-
-static int identity_virt2phys(struct target *target,
- uint32_t virtual, uint32_t *physical)
-{
- *physical = virtual;
- return ERROR_OK;
-}
-
-static int no_mmu(struct target *target, int *enabled)
-{
- *enabled = 0;
- return ERROR_OK;
-}
-
-static int default_examine(struct target *target)
-{
- target_set_examined(target);
- return ERROR_OK;
-}
-
-/* no check by default */
-static int default_check_reset(struct target *target)
-{
- return ERROR_OK;
-}
-
-int target_examine_one(struct target *target)
-{
- target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
-
- int retval = target->type->examine(target);
- if (retval != ERROR_OK)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
-
- return ERROR_OK;
-}
-
-static int jtag_enable_callback(enum jtag_event event, void *priv)
-{
- struct target *target = priv;
-
- if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled)
- return ERROR_OK;
-
- jtag_unregister_event_callback(jtag_enable_callback, target);
-
- return target_examine_one(target);
-}
-
-/* Targets that correctly implement init + examine, i.e.
- * no communication with target during init:
- *
- * XScale
- */
-int target_examine(void)
-{
- int retval = ERROR_OK;
- struct target *target;
-
- for (target = all_targets; target; target = target->next) {
- /* defer examination, but don't skip it */
- if (!target->tap->enabled) {
- jtag_register_event_callback(jtag_enable_callback,
- target);
- continue;
- }
-
- retval = target_examine_one(target);
- if (retval != ERROR_OK)
- return retval;
- }
- return retval;
-}
-
-const char *target_type_name(struct target *target)
-{
- return target->type->name;
-}
-
-static int target_soft_reset_halt(struct target *target)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
- if (!target->type->soft_reset_halt) {
- LOG_ERROR("Target %s does not support soft_reset_halt",
- target_name(target));
- return ERROR_FAIL;
- }
- return target->type->soft_reset_halt(target);
-}
-
-/**
- * Downloads a target-specific native code algorithm to the target,
- * and executes it. * Note that some targets may need to set up, enable,
- * and tear down a breakpoint (hard or * soft) to detect algorithm
- * termination, while others may support lower overhead schemes where
- * soft breakpoints embedded in the algorithm automatically terminate the
- * algorithm.
- *
- * @param target used to run the algorithm
- * @param arch_info target-specific description of the algorithm.
- */
-int target_run_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_param,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info)
-{
- int retval = ERROR_FAIL;
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- goto done;
- }
- if (!target->type->run_algorithm) {
- LOG_ERROR("Target type '%s' does not support %s",
- target_type_name(target), __func__);
- goto done;
- }
-
- target->running_alg = true;
- retval = target->type->run_algorithm(target,
- num_mem_params, mem_params,
- num_reg_params, reg_param,
- entry_point, exit_point, timeout_ms, arch_info);
- target->running_alg = false;
-
-done:
- return retval;
-}
-
-/**
- * Downloads a target-specific native code algorithm to the target,
- * executes and leaves it running.
- *
- * @param target used to run the algorithm
- * @param arch_info target-specific description of the algorithm.
- */
-int target_start_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- void *arch_info)
-{
- int retval = ERROR_FAIL;
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- goto done;
- }
- if (!target->type->start_algorithm) {
- LOG_ERROR("Target type '%s' does not support %s",
- target_type_name(target), __func__);
- goto done;
- }
- if (target->running_alg) {
- LOG_ERROR("Target is already running an algorithm");
- goto done;
- }
-
- target->running_alg = true;
- retval = target->type->start_algorithm(target,
- num_mem_params, mem_params,
- num_reg_params, reg_params,
- entry_point, exit_point, arch_info);
-
-done:
- return retval;
-}
-
-/**
- * Waits for an algorithm started with target_start_algorithm() to complete.
- *
- * @param target used to run the algorithm
- * @param arch_info target-specific description of the algorithm.
- */
-int target_wait_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t exit_point, int timeout_ms,
- void *arch_info)
-{
- int retval = ERROR_FAIL;
-
- if (!target->type->wait_algorithm) {
- LOG_ERROR("Target type '%s' does not support %s",
- target_type_name(target), __func__);
- goto done;
- }
- if (!target->running_alg) {
- LOG_ERROR("Target is not running an algorithm");
- goto done;
- }
-
- retval = target->type->wait_algorithm(target,
- num_mem_params, mem_params,
- num_reg_params, reg_params,
- exit_point, timeout_ms, arch_info);
- if (retval != ERROR_TARGET_TIMEOUT)
- target->running_alg = false;
-
-done:
- return retval;
-}
-
-/**
- * Executes a target-specific native code algorithm in the target.
- * It differs from target_run_algorithm in that the algorithm is asynchronous.
- * Because of this it requires an compliant algorithm:
- * see contrib/loaders/flash/stm32f1x.S for example.
- *
- * @param target used to run the algorithm
- */
-
-int target_run_flash_async_algorithm(struct target *target,
- const uint8_t *buffer, uint32_t count, int block_size,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t buffer_start, uint32_t buffer_size,
- uint32_t entry_point, uint32_t exit_point, void *arch_info)
-{
- int retval;
- int timeout = 0;
-
- const uint8_t *buffer_orig = buffer;
-
- /* Set up working area. First word is write pointer, second word is read pointer,
- * rest is fifo data area. */
- uint32_t wp_addr = buffer_start;
- uint32_t rp_addr = buffer_start + 4;
- uint32_t fifo_start_addr = buffer_start + 8;
- uint32_t fifo_end_addr = buffer_start + buffer_size;
-
- uint32_t wp = fifo_start_addr;
- uint32_t rp = fifo_start_addr;
-
- /* validate block_size is 2^n */
- assert(!block_size || !(block_size & (block_size - 1)));
-
- retval = target_write_u32(target, wp_addr, wp);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, rp_addr, rp);
- if (retval != ERROR_OK)
- return retval;
-
- /* Start up algorithm on target and let it idle while writing the first chunk */
- retval = target_start_algorithm(target, num_mem_params, mem_params,
- num_reg_params, reg_params,
- entry_point,
- exit_point,
- arch_info);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("error starting target flash write algorithm");
- return retval;
- }
-
- while (count > 0) {
-
- retval = target_read_u32(target, rp_addr, &rp);
- if (retval != ERROR_OK) {
- LOG_ERROR("failed to get read pointer");
- break;
- }
-
- LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32,
- (size_t) (buffer - buffer_orig), count, wp, rp);
-
- if (rp == 0) {
- LOG_ERROR("flash write algorithm aborted by target");
- retval = ERROR_FLASH_OPERATION_FAILED;
- break;
- }
-
- if (((rp - fifo_start_addr) & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) {
- LOG_ERROR("corrupted fifo read pointer 0x%" PRIx32, rp);
- break;
- }
-
- /* Count the number of bytes available in the fifo without
- * crossing the wrap around. Make sure to not fill it completely,
- * because that would make wp == rp and that's the empty condition. */
- uint32_t thisrun_bytes;
- if (rp > wp)
- thisrun_bytes = rp - wp - block_size;
- else if (rp > fifo_start_addr)
- thisrun_bytes = fifo_end_addr - wp;
- else
- thisrun_bytes = fifo_end_addr - wp - block_size;
-
- if (thisrun_bytes == 0) {
- /* Throttle polling a bit if transfer is (much) faster than flash
- * programming. The exact delay shouldn't matter as long as it's
- * less than buffer size / flash speed. This is very unlikely to
- * run when using high latency connections such as USB. */
- alive_sleep(10);
-
- /* to stop an infinite loop on some targets check and increment a timeout
- * this issue was observed on a stellaris using the new ICDI interface */
- if (timeout++ >= 500) {
- LOG_ERROR("timeout waiting for algorithm, a target reset is recommended");
- return ERROR_FLASH_OPERATION_FAILED;
- }
- continue;
- }
-
- /* reset our timeout */
- timeout = 0;
-
- /* Limit to the amount of data we actually want to write */
- if (thisrun_bytes > count * block_size)
- thisrun_bytes = count * block_size;
-
- /* Write data to fifo */
- retval = target_write_buffer(target, wp, thisrun_bytes, buffer);
- if (retval != ERROR_OK)
- break;
-
- /* Update counters and wrap write pointer */
- buffer += thisrun_bytes;
- count -= thisrun_bytes / block_size;
- wp += thisrun_bytes;
- if (wp >= fifo_end_addr)
- wp = fifo_start_addr;
-
- /* Store updated write pointer to target */
- retval = target_write_u32(target, wp_addr, wp);
- if (retval != ERROR_OK)
- break;
- }
-
- if (retval != ERROR_OK) {
- /* abort flash write algorithm on target */
- target_write_u32(target, wp_addr, 0);
- }
-
- int retval2 = target_wait_algorithm(target, num_mem_params, mem_params,
- num_reg_params, reg_params,
- exit_point,
- 10000,
- arch_info);
-
- if (retval2 != ERROR_OK) {
- LOG_ERROR("error waiting for target flash write algorithm");
- retval = retval2;
- }
-
- if (retval == ERROR_OK) {
- /* check if algorithm set rp = 0 after fifo writer loop finished */
- retval = target_read_u32(target, rp_addr, &rp);
- if (retval == ERROR_OK && rp == 0) {
- LOG_ERROR("flash write algorithm aborted by target");
- retval = ERROR_FLASH_OPERATION_FAILED;
- }
- }
-
- return retval;
-}
-
-int target_read_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
- if (!target->type->read_memory) {
- LOG_ERROR("Target %s doesn't support read_memory", target_name(target));
- return ERROR_FAIL;
- }
- return target->type->read_memory(target, address, size, count, buffer);
-}
-
-int target_read_phys_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
- if (!target->type->read_phys_memory) {
- LOG_ERROR("Target %s doesn't support read_phys_memory", target_name(target));
- return ERROR_FAIL;
- }
- return target->type->read_phys_memory(target, address, size, count, buffer);
-}
-
-int target_write_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
- if (!target->type->write_memory) {
- LOG_ERROR("Target %s doesn't support write_memory", target_name(target));
- return ERROR_FAIL;
- }
- return target->type->write_memory(target, address, size, count, buffer);
-}
-
-int target_write_phys_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
- if (!target->type->write_phys_memory) {
- LOG_ERROR("Target %s doesn't support write_phys_memory", target_name(target));
- return ERROR_FAIL;
- }
- return target->type->write_phys_memory(target, address, size, count, buffer);
-}
-
-int target_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) {
- LOG_WARNING("target %s is not halted", target_name(target));
- return ERROR_TARGET_NOT_HALTED;
- }
- return target->type->add_breakpoint(target, breakpoint);
-}
-
-int target_add_context_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target_name(target));
- return ERROR_TARGET_NOT_HALTED;
- }
- return target->type->add_context_breakpoint(target, breakpoint);
-}
-
-int target_add_hybrid_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target_name(target));
- return ERROR_TARGET_NOT_HALTED;
- }
- return target->type->add_hybrid_breakpoint(target, breakpoint);
-}
-
-int target_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- return target->type->remove_breakpoint(target, breakpoint);
-}
-
-int target_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target_name(target));
- return ERROR_TARGET_NOT_HALTED;
- }
- return target->type->add_watchpoint(target, watchpoint);
-}
-int target_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- return target->type->remove_watchpoint(target, watchpoint);
-}
-int target_hit_watchpoint(struct target *target,
- struct watchpoint **hit_watchpoint)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (target->type->hit_watchpoint == NULL) {
- /* For backward compatible, if hit_watchpoint is not implemented,
- * return ERROR_FAIL such that gdb_server will not take the nonsense
- * information. */
- return ERROR_FAIL;
- }
-
- return target->type->hit_watchpoint(target, hit_watchpoint);
-}
-
-int target_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class)
-{
- return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class);
-}
-int target_step(struct target *target,
- int current, uint32_t address, int handle_breakpoints)
-{
- return target->type->step(target, current, address, handle_breakpoints);
-}
-
-int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
- return ERROR_TARGET_NOT_HALTED;
- }
- return target->type->get_gdb_fileio_info(target, fileio_info);
-}
-
-int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
- return ERROR_TARGET_NOT_HALTED;
- }
- return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c);
-}
-
-int target_profiling(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
-{
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target %s is not halted", target->cmd_name);
- return ERROR_TARGET_NOT_HALTED;
- }
- return target->type->profiling(target, samples, max_num_samples,
- num_samples, seconds);
-}
-
-/**
- * Reset the @c examined flag for the given target.
- * Pure paranoia -- targets are zeroed on allocation.
- */
-static void target_reset_examined(struct target *target)
-{
- target->examined = false;
-}
-
-static int handle_target(void *priv);
-
-static int target_init_one(struct command_context *cmd_ctx,
- struct target *target)
-{
- target_reset_examined(target);
-
- struct target_type *type = target->type;
- if (type->examine == NULL)
- type->examine = default_examine;
-
- if (type->check_reset == NULL)
- type->check_reset = default_check_reset;
-
- assert(type->init_target != NULL);
-
- int retval = type->init_target(cmd_ctx, target);
- if (ERROR_OK != retval) {
- LOG_ERROR("target '%s' init failed", target_name(target));
- return retval;
- }
-
- /* Sanity-check MMU support ... stub in what we must, to help
- * implement it in stages, but warn if we need to do so.
- */
- if (type->mmu) {
- if (type->virt2phys == NULL) {
- LOG_ERROR("type '%s' is missing virt2phys", type->name);
- type->virt2phys = identity_virt2phys;
- }
- } else {
- /* Make sure no-MMU targets all behave the same: make no
- * distinction between physical and virtual addresses, and
- * ensure that virt2phys() is always an identity mapping.
- */
- if (type->write_phys_memory || type->read_phys_memory || type->virt2phys)
- LOG_WARNING("type '%s' has bad MMU hooks", type->name);
-
- type->mmu = no_mmu;
- type->write_phys_memory = type->write_memory;
- type->read_phys_memory = type->read_memory;
- type->virt2phys = identity_virt2phys;
- }
-
- if (target->type->read_buffer == NULL)
- target->type->read_buffer = target_read_buffer_default;
-
- if (target->type->write_buffer == NULL)
- target->type->write_buffer = target_write_buffer_default;
-
- if (target->type->get_gdb_fileio_info == NULL)
- target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default;
-
- if (target->type->gdb_fileio_end == NULL)
- target->type->gdb_fileio_end = target_gdb_fileio_end_default;
-
- if (target->type->profiling == NULL)
- target->type->profiling = target_profiling_default;
-
- return ERROR_OK;
-}
-
-static int target_init(struct command_context *cmd_ctx)
-{
- struct target *target;
- int retval;
-
- for (target = all_targets; target; target = target->next) {
- retval = target_init_one(cmd_ctx, target);
- if (ERROR_OK != retval)
- return retval;
- }
-
- if (!all_targets)
- return ERROR_OK;
-
- retval = target_register_user_commands(cmd_ctx);
- if (ERROR_OK != retval)
- return retval;
-
- retval = target_register_timer_callback(&handle_target,
- polling_interval, 1, cmd_ctx->interp);
- if (ERROR_OK != retval)
- return retval;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_target_init_command)
-{
- int retval;
-
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- static bool target_initialized;
- if (target_initialized) {
- LOG_INFO("'target init' has already been called");
- return ERROR_OK;
- }
- target_initialized = true;
-
- retval = command_run_line(CMD_CTX, "init_targets");
- if (ERROR_OK != retval)
- return retval;
-
- retval = command_run_line(CMD_CTX, "init_target_events");
- if (ERROR_OK != retval)
- return retval;
-
- retval = command_run_line(CMD_CTX, "init_board");
- if (ERROR_OK != retval)
- return retval;
-
- LOG_DEBUG("Initializing targets...");
- return target_init(CMD_CTX);
-}
-
-int target_register_event_callback(int (*callback)(struct target *target,
- enum target_event event, void *priv), void *priv)
-{
- struct target_event_callback **callbacks_p = &target_event_callbacks;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (*callbacks_p) {
- while ((*callbacks_p)->next)
- callbacks_p = &((*callbacks_p)->next);
- callbacks_p = &((*callbacks_p)->next);
- }
-
- (*callbacks_p) = malloc(sizeof(struct target_event_callback));
- (*callbacks_p)->callback = callback;
- (*callbacks_p)->priv = priv;
- (*callbacks_p)->next = NULL;
-
- return ERROR_OK;
-}
-
-int target_register_reset_callback(int (*callback)(struct target *target,
- enum target_reset_mode reset_mode, void *priv), void *priv)
-{
- struct target_reset_callback *entry;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- entry = malloc(sizeof(struct target_reset_callback));
- if (entry == NULL) {
- LOG_ERROR("error allocating buffer for reset callback entry");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- entry->callback = callback;
- entry->priv = priv;
- list_add(&entry->list, &target_reset_callback_list);
-
-
- return ERROR_OK;
-}
-
-int target_register_trace_callback(int (*callback)(struct target *target,
- size_t len, uint8_t *data, void *priv), void *priv)
-{
- struct target_trace_callback *entry;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- entry = malloc(sizeof(struct target_trace_callback));
- if (entry == NULL) {
- LOG_ERROR("error allocating buffer for trace callback entry");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- entry->callback = callback;
- entry->priv = priv;
- list_add(&entry->list, &target_trace_callback_list);
-
-
- return ERROR_OK;
-}
-
-int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
-{
- struct target_timer_callback **callbacks_p = &target_timer_callbacks;
- struct timeval now;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (*callbacks_p) {
- while ((*callbacks_p)->next)
- callbacks_p = &((*callbacks_p)->next);
- callbacks_p = &((*callbacks_p)->next);
- }
-
- (*callbacks_p) = malloc(sizeof(struct target_timer_callback));
- (*callbacks_p)->callback = callback;
- (*callbacks_p)->periodic = periodic;
- (*callbacks_p)->time_ms = time_ms;
- (*callbacks_p)->removed = false;
-
- gettimeofday(&now, NULL);
- (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
- time_ms -= (time_ms % 1000);
- (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
- if ((*callbacks_p)->when.tv_usec > 1000000) {
- (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
- (*callbacks_p)->when.tv_sec += 1;
- }
-
- (*callbacks_p)->priv = priv;
- (*callbacks_p)->next = NULL;
-
- return ERROR_OK;
-}
-
-int target_unregister_event_callback(int (*callback)(struct target *target,
- enum target_event event, void *priv), void *priv)
-{
- struct target_event_callback **p = &target_event_callbacks;
- struct target_event_callback *c = target_event_callbacks;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- while (c) {
- struct target_event_callback *next = c->next;
- if ((c->callback == callback) && (c->priv == priv)) {
- *p = next;
- free(c);
- return ERROR_OK;
- } else
- p = &(c->next);
- c = next;
- }
-
- return ERROR_OK;
-}
-
-int target_unregister_reset_callback(int (*callback)(struct target *target,
- enum target_reset_mode reset_mode, void *priv), void *priv)
-{
- struct target_reset_callback *entry;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- list_for_each_entry(entry, &target_reset_callback_list, list) {
- if (entry->callback == callback && entry->priv == priv) {
- list_del(&entry->list);
- free(entry);
- break;
- }
- }
-
- return ERROR_OK;
-}
-
-int target_unregister_trace_callback(int (*callback)(struct target *target,
- size_t len, uint8_t *data, void *priv), void *priv)
-{
- struct target_trace_callback *entry;
-
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- list_for_each_entry(entry, &target_trace_callback_list, list) {
- if (entry->callback == callback && entry->priv == priv) {
- list_del(&entry->list);
- free(entry);
- break;
- }
- }
-
- return ERROR_OK;
-}
-
-int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
-{
- if (callback == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- for (struct target_timer_callback *c = target_timer_callbacks;
- c; c = c->next) {
- if ((c->callback == callback) && (c->priv == priv)) {
- c->removed = true;
- return ERROR_OK;
- }
- }
-
- return ERROR_FAIL;
-}
-
-int target_call_event_callbacks(struct target *target, enum target_event event)
-{
- struct target_event_callback *callback = target_event_callbacks;
- struct target_event_callback *next_callback;
-
- if (event == TARGET_EVENT_HALTED) {
- /* execute early halted first */
- target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
- }
-
- LOG_DEBUG("target event %i (%s)", event,
- Jim_Nvp_value2name_simple(nvp_target_event, event)->name);
-
- target_handle_event(target, event);
-
- while (callback) {
- next_callback = callback->next;
- callback->callback(target, event, callback->priv);
- callback = next_callback;
- }
-
- return ERROR_OK;
-}
-
-int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode)
-{
- struct target_reset_callback *callback;
-
- LOG_DEBUG("target reset %i (%s)", reset_mode,
- Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name);
-
- list_for_each_entry(callback, &target_reset_callback_list, list)
- callback->callback(target, reset_mode, callback->priv);
-
- return ERROR_OK;
-}
-
-int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data)
-{
- struct target_trace_callback *callback;
-
- list_for_each_entry(callback, &target_trace_callback_list, list)
- callback->callback(target, len, data, callback->priv);
-
- return ERROR_OK;
-}
-
-static int target_timer_callback_periodic_restart(
- struct target_timer_callback *cb, struct timeval *now)
-{
- int time_ms = cb->time_ms;
- cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000;
- time_ms -= (time_ms % 1000);
- cb->when.tv_sec = now->tv_sec + time_ms / 1000;
- if (cb->when.tv_usec > 1000000) {
- cb->when.tv_usec = cb->when.tv_usec - 1000000;
- cb->when.tv_sec += 1;
- }
- return ERROR_OK;
-}
-
-static int target_call_timer_callback(struct target_timer_callback *cb,
- struct timeval *now)
-{
- cb->callback(cb->priv);
-
- if (cb->periodic)
- return target_timer_callback_periodic_restart(cb, now);
-
- return target_unregister_timer_callback(cb->callback, cb->priv);
-}
-
-static int target_call_timer_callbacks_check_time(int checktime)
-{
- static bool callback_processing;
-
- /* Do not allow nesting */
- if (callback_processing)
- return ERROR_OK;
-
- callback_processing = true;
-
- keep_alive();
-
- struct timeval now;
- gettimeofday(&now, NULL);
-
- /* Store an address of the place containing a pointer to the
- * next item; initially, that's a standalone "root of the
- * list" variable. */
- struct target_timer_callback **callback = &target_timer_callbacks;
- while (*callback) {
- if ((*callback)->removed) {
- struct target_timer_callback *p = *callback;
- *callback = (*callback)->next;
- free(p);
- continue;
- }
-
- bool call_it = (*callback)->callback &&
- ((!checktime && (*callback)->periodic) ||
- now.tv_sec > (*callback)->when.tv_sec ||
- (now.tv_sec == (*callback)->when.tv_sec &&
- now.tv_usec >= (*callback)->when.tv_usec));
-
- if (call_it)
- target_call_timer_callback(*callback, &now);
-
- callback = &(*callback)->next;
- }
-
- callback_processing = false;
- return ERROR_OK;
-}
-
-int target_call_timer_callbacks(void)
-{
- return target_call_timer_callbacks_check_time(1);
-}
-
-/* invoke periodic callbacks immediately */
-int target_call_timer_callbacks_now(void)
-{
- return target_call_timer_callbacks_check_time(0);
-}
-
-/* Prints the working area layout for debug purposes */
-static void print_wa_layout(struct target *target)
-{
- struct working_area *c = target->working_areas;
-
- while (c) {
- LOG_DEBUG("%c%c 0x%08"PRIx32"-0x%08"PRIx32" (%"PRIu32" bytes)",
- c->backup ? 'b' : ' ', c->free ? ' ' : '*',
- c->address, c->address + c->size - 1, c->size);
- c = c->next;
- }
-}
-
-/* Reduce area to size bytes, create a new free area from the remaining bytes, if any. */
-static void target_split_working_area(struct working_area *area, uint32_t size)
-{
- assert(area->free); /* Shouldn't split an allocated area */
- assert(size <= area->size); /* Caller should guarantee this */
-
- /* Split only if not already the right size */
- if (size < area->size) {
- struct working_area *new_wa = malloc(sizeof(*new_wa));
-
- if (new_wa == NULL)
- return;
-
- new_wa->next = area->next;
- new_wa->size = area->size - size;
- new_wa->address = area->address + size;
- new_wa->backup = NULL;
- new_wa->user = NULL;
- new_wa->free = true;
-
- area->next = new_wa;
- area->size = size;
-
- /* If backup memory was allocated to this area, it has the wrong size
- * now so free it and it will be reallocated if/when needed */
- if (area->backup) {
- free(area->backup);
- area->backup = NULL;
- }
- }
-}
-
-/* Merge all adjacent free areas into one */
-static void target_merge_working_areas(struct target *target)
-{
- struct working_area *c = target->working_areas;
-
- while (c && c->next) {
- assert(c->next->address == c->address + c->size); /* This is an invariant */
-
- /* Find two adjacent free areas */
- if (c->free && c->next->free) {
- /* Merge the last into the first */
- c->size += c->next->size;
-
- /* Remove the last */
- struct working_area *to_be_freed = c->next;
- c->next = c->next->next;
- if (to_be_freed->backup)
- free(to_be_freed->backup);
- free(to_be_freed);
-
- /* If backup memory was allocated to the remaining area, it's has
- * the wrong size now */
- if (c->backup) {
- free(c->backup);
- c->backup = NULL;
- }
- } else {
- c = c->next;
- }
- }
-}
-
-int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area)
-{
- /* Reevaluate working area address based on MMU state*/
- if (target->working_areas == NULL) {
- int retval;
- int enabled;
-
- retval = target->type->mmu(target, &enabled);
- if (retval != ERROR_OK)
- return retval;
-
- if (!enabled) {
- if (target->working_area_phys_spec) {
- LOG_DEBUG("MMU disabled, using physical "
- "address for working memory 0x%08"PRIx32,
- target->working_area_phys);
- target->working_area = target->working_area_phys;
- } else {
- LOG_ERROR("No working memory available. "
- "Specify -work-area-phys to target.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- } else {
- if (target->working_area_virt_spec) {
- LOG_DEBUG("MMU enabled, using virtual "
- "address for working memory 0x%08"PRIx32,
- target->working_area_virt);
- target->working_area = target->working_area_virt;
- } else {
- LOG_ERROR("No working memory available. "
- "Specify -work-area-virt to target.");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- }
-
- /* Set up initial working area on first call */
- struct working_area *new_wa = malloc(sizeof(*new_wa));
- if (new_wa) {
- new_wa->next = NULL;
- new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */
- new_wa->address = target->working_area;
- new_wa->backup = NULL;
- new_wa->user = NULL;
- new_wa->free = true;
- }
-
- target->working_areas = new_wa;
- }
-
- /* only allocate multiples of 4 byte */
- if (size % 4)
- size = (size + 3) & (~3UL);
-
- struct working_area *c = target->working_areas;
-
- /* Find the first large enough working area */
- while (c) {
- if (c->free && c->size >= size)
- break;
- c = c->next;
- }
-
- if (c == NULL)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- /* Split the working area into the requested size */
- target_split_working_area(c, size);
-
- LOG_DEBUG("allocated new working area of %"PRIu32" bytes at address 0x%08"PRIx32, size, c->address);
-
- if (target->backup_working_area) {
- if (c->backup == NULL) {
- c->backup = malloc(c->size);
- if (c->backup == NULL)
- return ERROR_FAIL;
- }
-
- int retval = target_read_memory(target, c->address, 4, c->size / 4, c->backup);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* mark as used, and return the new (reused) area */
- c->free = false;
- *area = c;
-
- /* user pointer */
- c->user = area;
-
- print_wa_layout(target);
-
- return ERROR_OK;
-}
-
-int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area)
-{
- int retval;
-
- retval = target_alloc_working_area_try(target, size, area);
- if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
- LOG_WARNING("not enough working area available(requested %"PRIu32")", size);
- return retval;
-
-}
-
-static int target_restore_working_area(struct target *target, struct working_area *area)
-{
- int retval = ERROR_OK;
-
- if (target->backup_working_area && area->backup != NULL) {
- retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup);
- if (retval != ERROR_OK)
- LOG_ERROR("failed to restore %"PRIu32" bytes of working area at address 0x%08"PRIx32,
- area->size, area->address);
- }
-
- return retval;
-}
-
-/* Restore the area's backup memory, if any, and return the area to the allocation pool */
-static int target_free_working_area_restore(struct target *target, struct working_area *area, int restore)
-{
- int retval = ERROR_OK;
-
- if (area->free)
- return retval;
-
- if (restore) {
- retval = target_restore_working_area(target, area);
- /* REVISIT: Perhaps the area should be freed even if restoring fails. */
- if (retval != ERROR_OK)
- return retval;
- }
-
- area->free = true;
-
- LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32,
- area->size, area->address);
-
- /* mark user pointer invalid */
- /* TODO: Is this really safe? It points to some previous caller's memory.
- * How could we know that the area pointer is still in that place and not
- * some other vital data? What's the purpose of this, anyway? */
- *area->user = NULL;
- area->user = NULL;
-
- target_merge_working_areas(target);
-
- print_wa_layout(target);
-
- return retval;
-}
-
-int target_free_working_area(struct target *target, struct working_area *area)
-{
- return target_free_working_area_restore(target, area, 1);
-}
-
-void target_quit(void)
-{
- struct target_event_callback *pe = target_event_callbacks;
- while (pe) {
- struct target_event_callback *t = pe->next;
- free(pe);
- pe = t;
- }
- target_event_callbacks = NULL;
-
- struct target_timer_callback *pt = target_timer_callbacks;
- while (pt) {
- struct target_timer_callback *t = pt->next;
- free(pt);
- pt = t;
- }
- target_timer_callbacks = NULL;
-
- for (struct target *target = all_targets;
- target; target = target->next) {
- if (target->type->deinit_target)
- target->type->deinit_target(target);
- }
-}
-
-/* free resources and restore memory, if restoring memory fails,
- * free up resources anyway
- */
-static void target_free_all_working_areas_restore(struct target *target, int restore)
-{
- struct working_area *c = target->working_areas;
-
- LOG_DEBUG("freeing all working areas");
-
- /* Loop through all areas, restoring the allocated ones and marking them as free */
- while (c) {
- if (!c->free) {
- if (restore)
- target_restore_working_area(target, c);
- c->free = true;
- *c->user = NULL; /* Same as above */
- c->user = NULL;
- }
- c = c->next;
- }
-
- /* Run a merge pass to combine all areas into one */
- target_merge_working_areas(target);
-
- print_wa_layout(target);
-}
-
-void target_free_all_working_areas(struct target *target)
-{
- target_free_all_working_areas_restore(target, 1);
-}
-
-/* Find the largest number of bytes that can be allocated */
-uint32_t target_get_working_area_avail(struct target *target)
-{
- struct working_area *c = target->working_areas;
- uint32_t max_size = 0;
-
- if (c == NULL)
- return target->working_area_size;
-
- while (c) {
- if (c->free && max_size < c->size)
- max_size = c->size;
-
- c = c->next;
- }
-
- return max_size;
-}
-
-int target_arch_state(struct target *target)
-{
- int retval;
- if (target == NULL) {
- LOG_USER("No target has been configured");
- return ERROR_OK;
- }
-
- LOG_USER("%s: target state: %s", target_name(target),
- target_state_name(target));
-
- if (target->state != TARGET_HALTED)
- return ERROR_OK;
-
- retval = target->type->arch_state(target);
- return retval;
-}
-
-static int target_get_gdb_fileio_info_default(struct target *target,
- struct gdb_fileio_info *fileio_info)
-{
- /* If target does not support semi-hosting function, target
- has no need to provide .get_gdb_fileio_info callback.
- It just return ERROR_FAIL and gdb_server will return "Txx"
- as target halted every time. */
- return ERROR_FAIL;
-}
-
-static int target_gdb_fileio_end_default(struct target *target,
- int retcode, int fileio_errno, bool ctrl_c)
-{
- return ERROR_OK;
-}
-
-static int target_profiling_default(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
-{
- struct timeval timeout, now;
-
- gettimeofday(&timeout, NULL);
- timeval_add_time(&timeout, seconds, 0);
-
- LOG_INFO("Starting profiling. Halting and resuming the"
- " target as often as we can...");
-
- uint32_t sample_count = 0;
- /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */
- struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1);
-
- int retval = ERROR_OK;
- for (;;) {
- target_poll(target);
- if (target->state == TARGET_HALTED) {
- uint32_t t = buf_get_u32(reg->value, 0, 32);
- samples[sample_count++] = t;
- /* current pc, addr = 0, do not handle breakpoints, not debugging */
- retval = target_resume(target, 1, 0, 0, 0);
- target_poll(target);
- alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
- } else if (target->state == TARGET_RUNNING) {
- /* We want to quickly sample the PC. */
- retval = target_halt(target);
- } else {
- LOG_INFO("Target not halted or running");
- retval = ERROR_OK;
- break;
- }
-
- if (retval != ERROR_OK)
- break;
-
- gettimeofday(&now, NULL);
- if ((sample_count >= max_num_samples) ||
- ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) {
- LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
- break;
- }
- }
-
- *num_samples = sample_count;
- return retval;
-}
-
-/* Single aligned words are guaranteed to use 16 or 32 bit access
- * mode respectively, otherwise data is handled as quickly as
- * possible
- */
-int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer)
-{
- LOG_DEBUG("writing buffer of %i byte at 0x%8.8x",
- (int)size, (unsigned)address);
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- if (size == 0)
- return ERROR_OK;
-
- if ((address + size - 1) < address) {
- /* GDB can request this when e.g. PC is 0xfffffffc*/
- LOG_ERROR("address + size wrapped(0x%08x, 0x%08x)",
- (unsigned)address,
- (unsigned)size);
- return ERROR_FAIL;
- }
-
- return target->type->write_buffer(target, address, size, buffer);
-}
-
-static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer)
-{
- uint32_t size;
-
- /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
- * will have something to do with the size we leave to it. */
- for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
- if (address & size) {
- int retval = target_write_memory(target, address, size, 1, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += size;
- count -= size;
- buffer += size;
- }
- }
-
- /* Write the data with as large access size as possible. */
- for (; size > 0; size /= 2) {
- uint32_t aligned = count - count % size;
- if (aligned > 0) {
- int retval = target_write_memory(target, address, size, aligned / size, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += aligned;
- count -= aligned;
- buffer += aligned;
- }
- }
-
- return ERROR_OK;
-}
-
-/* Single aligned words are guaranteed to use 16 or 32 bit access
- * mode respectively, otherwise data is handled as quickly as
- * possible
- */
-int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
-{
- LOG_DEBUG("reading buffer of %i byte at 0x%8.8x",
- (int)size, (unsigned)address);
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- if (size == 0)
- return ERROR_OK;
-
- if ((address + size - 1) < address) {
- /* GDB can request this when e.g. PC is 0xfffffffc*/
- LOG_ERROR("address + size wrapped(0x%08" PRIx32 ", 0x%08" PRIx32 ")",
- address,
- size);
- return ERROR_FAIL;
- }
-
- return target->type->read_buffer(target, address, size, buffer);
-}
-
-static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer)
-{
- uint32_t size;
-
- /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
- * will have something to do with the size we leave to it. */
- for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
- if (address & size) {
- int retval = target_read_memory(target, address, size, 1, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += size;
- count -= size;
- buffer += size;
- }
- }
-
- /* Read the data with as large access size as possible. */
- for (; size > 0; size /= 2) {
- uint32_t aligned = count - count % size;
- if (aligned > 0) {
- int retval = target_read_memory(target, address, size, aligned / size, buffer);
- if (retval != ERROR_OK)
- return retval;
- address += aligned;
- count -= aligned;
- buffer += aligned;
- }
- }
-
- return ERROR_OK;
-}
-
-int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc)
-{
- uint8_t *buffer;
- int retval;
- uint32_t i;
- uint32_t checksum = 0;
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- retval = target->type->checksum_memory(target, address, size, &checksum);
- if (retval != ERROR_OK) {
- buffer = malloc(size);
- if (buffer == NULL) {
- LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- retval = target_read_buffer(target, address, size, buffer);
- if (retval != ERROR_OK) {
- free(buffer);
- return retval;
- }
-
- /* convert to target endianness */
- for (i = 0; i < (size/sizeof(uint32_t)); i++) {
- uint32_t target_data;
- target_data = target_buffer_get_u32(target, &buffer[i*sizeof(uint32_t)]);
- target_buffer_set_u32(target, &buffer[i*sizeof(uint32_t)], target_data);
- }
-
- retval = image_calculate_checksum(buffer, size, &checksum);
- free(buffer);
- }
-
- *crc = checksum;
-
- return retval;
-}
-
-int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank)
-{
- int retval;
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- if (target->type->blank_check_memory == 0)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- retval = target->type->blank_check_memory(target, address, size, blank);
-
- return retval;
-}
-
-int target_read_u64(struct target *target, uint64_t address, uint64_t *value)
-{
- uint8_t value_buf[8];
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- int retval = target_read_memory(target, address, 8, 1, value_buf);
-
- if (retval == ERROR_OK) {
- *value = target_buffer_get_u64(target, value_buf);
- LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "",
- address,
- *value);
- } else {
- *value = 0x0;
- LOG_DEBUG("address: 0x%" PRIx64 " failed",
- address);
- }
-
- return retval;
-}
-
-int target_read_u32(struct target *target, uint32_t address, uint32_t *value)
-{
- uint8_t value_buf[4];
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- int retval = target_read_memory(target, address, 4, 1, value_buf);
-
- if (retval == ERROR_OK) {
- *value = target_buffer_get_u32(target, value_buf);
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
- address,
- *value);
- } else {
- *value = 0x0;
- LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
- address);
- }
-
- return retval;
-}
-
-int target_read_u16(struct target *target, uint32_t address, uint16_t *value)
-{
- uint8_t value_buf[2];
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- int retval = target_read_memory(target, address, 2, 1, value_buf);
-
- if (retval == ERROR_OK) {
- *value = target_buffer_get_u16(target, value_buf);
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4x",
- address,
- *value);
- } else {
- *value = 0x0;
- LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
- address);
- }
-
- return retval;
-}
-
-int target_read_u8(struct target *target, uint32_t address, uint8_t *value)
-{
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- int retval = target_read_memory(target, address, 1, 1, value);
-
- if (retval == ERROR_OK) {
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x",
- address,
- *value);
- } else {
- *value = 0x0;
- LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
- address);
- }
-
- return retval;
-}
-
-int target_write_u64(struct target *target, uint64_t address, uint64_t value)
-{
- int retval;
- uint8_t value_buf[8];
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "",
- address,
- value);
-
- target_buffer_set_u64(target, value_buf, value);
- retval = target_write_memory(target, address, 8, 1, value_buf);
- if (retval != ERROR_OK)
- LOG_DEBUG("failed: %i", retval);
-
- return retval;
-}
-
-int target_write_u32(struct target *target, uint32_t address, uint32_t value)
-{
- int retval;
- uint8_t value_buf[4];
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
- address,
- value);
-
- target_buffer_set_u32(target, value_buf, value);
- retval = target_write_memory(target, address, 4, 1, value_buf);
- if (retval != ERROR_OK)
- LOG_DEBUG("failed: %i", retval);
-
- return retval;
-}
-
-int target_write_u16(struct target *target, uint32_t address, uint16_t value)
-{
- int retval;
- uint8_t value_buf[2];
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8x",
- address,
- value);
-
- target_buffer_set_u16(target, value_buf, value);
- retval = target_write_memory(target, address, 2, 1, value_buf);
- if (retval != ERROR_OK)
- LOG_DEBUG("failed: %i", retval);
-
- return retval;
-}
-
-int target_write_u8(struct target *target, uint32_t address, uint8_t value)
-{
- int retval;
- if (!target_was_examined(target)) {
- LOG_ERROR("Target not examined yet");
- return ERROR_FAIL;
- }
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x",
- address, value);
-
- retval = target_write_memory(target, address, 1, 1, &value);
- if (retval != ERROR_OK)
- LOG_DEBUG("failed: %i", retval);
-
- return retval;
-}
-
-static int find_target(struct command_context *cmd_ctx, const char *name)
-{
- struct target *target = get_target(name);
- if (target == NULL) {
- LOG_ERROR("Target: %s is unknown, try one of:\n", name);
- return ERROR_FAIL;
- }
- if (!target->tap->enabled) {
- LOG_USER("Target: TAP %s is disabled, "
- "can't be the current target\n",
- target->tap->dotted_name);
- return ERROR_FAIL;
- }
-
- cmd_ctx->current_target = target->target_number;
- return ERROR_OK;
-}
-
-
-COMMAND_HANDLER(handle_targets_command)
-{
- int retval = ERROR_OK;
- if (CMD_ARGC == 1) {
- retval = find_target(CMD_CTX, CMD_ARGV[0]);
- if (retval == ERROR_OK) {
- /* we're done! */
- return retval;
- }
- }
-
- struct target *target = all_targets;
- command_print(CMD_CTX, " TargetName Type Endian TapName State ");
- command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------");
- while (target) {
- const char *state;
- char marker = ' ';
-
- if (target->tap->enabled)
- state = target_state_name(target);
- else
- state = "tap-disabled";
-
- if (CMD_CTX->current_target == target->target_number)
- marker = '*';
-
- /* keep columns lined up to match the headers above */
- command_print(CMD_CTX,
- "%2d%c %-18s %-10s %-6s %-18s %s",
- target->target_number,
- marker,
- target_name(target),
- target_type_name(target),
- Jim_Nvp_value2name_simple(nvp_target_endian,
- target->endianness)->name,
- target->tap->dotted_name,
- state);
- target = target->next;
- }
-
- return retval;
-}
-
-/* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */
-
-static int powerDropout;
-static int srstAsserted;
-
-static int runPowerRestore;
-static int runPowerDropout;
-static int runSrstAsserted;
-static int runSrstDeasserted;
-
-static int sense_handler(void)
-{
- static int prevSrstAsserted;
- static int prevPowerdropout;
-
- int retval = jtag_power_dropout(&powerDropout);
- if (retval != ERROR_OK)
- return retval;
-
- int powerRestored;
- powerRestored = prevPowerdropout && !powerDropout;
- if (powerRestored)
- runPowerRestore = 1;
-
- int64_t current = timeval_ms();
- static int64_t lastPower;
- bool waitMore = lastPower + 2000 > current;
- if (powerDropout && !waitMore) {
- runPowerDropout = 1;
- lastPower = current;
- }
-
- retval = jtag_srst_asserted(&srstAsserted);
- if (retval != ERROR_OK)
- return retval;
-
- int srstDeasserted;
- srstDeasserted = prevSrstAsserted && !srstAsserted;
-
- static int64_t lastSrst;
- waitMore = lastSrst + 2000 > current;
- if (srstDeasserted && !waitMore) {
- runSrstDeasserted = 1;
- lastSrst = current;
- }
-
- if (!prevSrstAsserted && srstAsserted)
- runSrstAsserted = 1;
-
- prevSrstAsserted = srstAsserted;
- prevPowerdropout = powerDropout;
-
- if (srstDeasserted || powerRestored) {
- /* Other than logging the event we can't do anything here.
- * Issuing a reset is a particularly bad idea as we might
- * be inside a reset already.
- */
- }
-
- return ERROR_OK;
-}
-
-/* process target state changes */
-static int handle_target(void *priv)
-{
- Jim_Interp *interp = (Jim_Interp *)priv;
- int retval = ERROR_OK;
-
- if (!is_jtag_poll_safe()) {
- /* polling is disabled currently */
- return ERROR_OK;
- }
-
- /* we do not want to recurse here... */
- static int recursive;
- if (!recursive) {
- recursive = 1;
- sense_handler();
- /* danger! running these procedures can trigger srst assertions and power dropouts.
- * We need to avoid an infinite loop/recursion here and we do that by
- * clearing the flags after running these events.
- */
- int did_something = 0;
- if (runSrstAsserted) {
- LOG_INFO("srst asserted detected, running srst_asserted proc.");
- Jim_Eval(interp, "srst_asserted");
- did_something = 1;
- }
- if (runSrstDeasserted) {
- Jim_Eval(interp, "srst_deasserted");
- did_something = 1;
- }
- if (runPowerDropout) {
- LOG_INFO("Power dropout detected, running power_dropout proc.");
- Jim_Eval(interp, "power_dropout");
- did_something = 1;
- }
- if (runPowerRestore) {
- Jim_Eval(interp, "power_restore");
- did_something = 1;
- }
-
- if (did_something) {
- /* clear detect flags */
- sense_handler();
- }
-
- /* clear action flags */
-
- runSrstAsserted = 0;
- runSrstDeasserted = 0;
- runPowerRestore = 0;
- runPowerDropout = 0;
-
- recursive = 0;
- }
-
- /* Poll targets for state changes unless that's globally disabled.
- * Skip targets that are currently disabled.
- */
- for (struct target *target = all_targets;
- is_jtag_poll_safe() && target;
- target = target->next) {
-
- if (!target_was_examined(target))
- continue;
-
- if (!target->tap->enabled)
- continue;
-
- if (target->backoff.times > target->backoff.count) {
- /* do not poll this time as we failed previously */
- target->backoff.count++;
- continue;
- }
- target->backoff.count = 0;
-
- /* only poll target if we've got power and srst isn't asserted */
- if (!powerDropout && !srstAsserted) {
- /* polling may fail silently until the target has been examined */
- retval = target_poll(target);
- if (retval != ERROR_OK) {
- /* 100ms polling interval. Increase interval between polling up to 5000ms */
- if (target->backoff.times * polling_interval < 5000) {
- target->backoff.times *= 2;
- target->backoff.times++;
- }
-
- /* Tell GDB to halt the debugger. This allows the user to
- * run monitor commands to handle the situation.
- */
- target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
- }
- if (target->backoff.times > 0) {
- LOG_USER("Polling target %s failed, trying to reexamine", target_name(target));
- target_reset_examined(target);
- retval = target_examine_one(target);
- /* Target examination could have failed due to unstable connection,
- * but we set the examined flag anyway to repoll it later */
- if (retval != ERROR_OK) {
- target->examined = true;
- LOG_USER("Examination failed, GDB will be halted. Polling again in %dms",
- target->backoff.times * polling_interval);
- return retval;
- }
- }
-
- /* Since we succeeded, we reset backoff count */
- target->backoff.times = 0;
- }
- }
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_reg_command)
-{
- struct target *target;
- struct reg *reg = NULL;
- unsigned count = 0;
- char *value;
- int retval;
-
- LOG_DEBUG("-");
-
- target = get_current_target(CMD_CTX);
-
- /* list all available registers for the current target */
- if (CMD_ARGC == 0) {
- struct reg_cache *cache = target->reg_cache;
-
- count = 0;
- while (cache) {
- unsigned i;
-
- command_print(CMD_CTX, "===== %s", cache->name);
-
- for (i = 0, reg = cache->reg_list;
- i < cache->num_regs;
- i++, reg++, count++) {
- /* only print cached values if they are valid */
- if (reg->valid) {
- value = buf_to_str(reg->value,
- reg->size, 16);
- command_print(CMD_CTX,
- "(%i) %s (/%" PRIu32 "): 0x%s%s",
- count, reg->name,
- reg->size, value,
- reg->dirty
- ? " (dirty)"
- : "");
- free(value);
- } else {
- command_print(CMD_CTX, "(%i) %s (/%" PRIu32 ")",
- count, reg->name,
- reg->size) ;
- }
- }
- cache = cache->next;
- }
-
- return ERROR_OK;
- }
-
- /* access a single register by its ordinal number */
- if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) {
- unsigned num;
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
-
- struct reg_cache *cache = target->reg_cache;
- count = 0;
- while (cache) {
- unsigned i;
- for (i = 0; i < cache->num_regs; i++) {
- if (count++ == num) {
- reg = &cache->reg_list[i];
- break;
- }
- }
- if (reg)
- break;
- cache = cache->next;
- }
-
- if (!reg) {
- command_print(CMD_CTX, "%i is out of bounds, the current target "
- "has only %i registers (0 - %i)", num, count, count - 1);
- return ERROR_OK;
- }
- } else {
- /* access a single register by its name */
- reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1);
-
- if (!reg) {
- command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
- return ERROR_OK;
- }
- }
-
- assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */
-
- /* display a register */
- if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
- && (CMD_ARGV[1][0] <= '9')))) {
- if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
- reg->valid = 0;
-
- if (reg->valid == 0) {
- retval = reg->type->get(reg);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Couldn't get register %s.", reg->name);
- return retval;
- }
- }
- value = buf_to_str(reg->value, reg->size, 16);
- command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
- free(value);
- return ERROR_OK;
- }
-
- /* set register value */
- if (CMD_ARGC == 2) {
- uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8));
- if (buf == NULL)
- return ERROR_FAIL;
- str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0);
-
- retval = reg->type->set(reg, buf);
- if (retval != ERROR_OK) {
- LOG_DEBUG("Couldn't set register %s.", reg->name);
- free (buf);
- return retval;
- }
-
- value = buf_to_str(reg->value, reg->size, 16);
- command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
- free(value);
-
- free(buf);
-
- return ERROR_OK;
- }
-
- return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-COMMAND_HANDLER(handle_poll_command)
-{
- int retval = ERROR_OK;
- struct target *target = get_current_target(CMD_CTX);
-
- if (CMD_ARGC == 0) {
- command_print(CMD_CTX, "background polling: %s",
- jtag_poll_get_enabled() ? "on" : "off");
- command_print(CMD_CTX, "TAP: %s (%s)",
- target->tap->dotted_name,
- target->tap->enabled ? "enabled" : "disabled");
- if (!target->tap->enabled)
- return ERROR_OK;
- retval = target_poll(target);
- if (retval != ERROR_OK)
- return retval;
- retval = target_arch_state(target);
- if (retval != ERROR_OK)
- return retval;
- } else if (CMD_ARGC == 1) {
- bool enable;
- COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
- jtag_poll_set_enabled(enable);
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_wait_halt_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned ms = DEFAULT_HALT_TIMEOUT;
- if (1 == CMD_ARGC) {
- int retval = parse_uint(CMD_ARGV[0], &ms);
- if (ERROR_OK != retval)
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- struct target *target = get_current_target(CMD_CTX);
- return target_wait_state(target, TARGET_HALTED, ms);
-}
-
-/* wait for target state to change. The trick here is to have a low
- * latency for short waits and not to suck up all the CPU time
- * on longer waits.
- *
- * After 500ms, keep_alive() is invoked
- */
-int target_wait_state(struct target *target, enum target_state state, int ms)
-{
- int retval;
- int64_t then = 0, cur;
- bool once = true;
-
- for (;;) {
- retval = target_poll(target);
- if (retval != ERROR_OK)
- return retval;
- if (target->state == state)
- break;
- cur = timeval_ms();
- if (once) {
- once = false;
- then = timeval_ms();
- LOG_DEBUG("waiting for target %s...",
- Jim_Nvp_value2name_simple(nvp_target_state, state)->name);
- }
-
- if (cur-then > 500)
- keep_alive();
-
- if ((cur-then) > ms) {
- LOG_ERROR("timed out while waiting for target %s",
- Jim_Nvp_value2name_simple(nvp_target_state, state)->name);
- return ERROR_FAIL;
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_halt_command)
-{
- LOG_DEBUG("-");
-
- struct target *target = get_current_target(CMD_CTX);
- int retval = target_halt(target);
- if (ERROR_OK != retval)
- return retval;
-
- if (CMD_ARGC == 1) {
- unsigned wait_local;
- retval = parse_uint(CMD_ARGV[0], &wait_local);
- if (ERROR_OK != retval)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (!wait_local)
- return ERROR_OK;
- }
-
- return CALL_COMMAND_HANDLER(handle_wait_halt_command);
-}
-
-COMMAND_HANDLER(handle_soft_reset_halt_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- LOG_USER("requesting target halt and executing a soft reset");
-
- target_soft_reset_halt(target);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_reset_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- enum target_reset_mode reset_mode = RESET_RUN;
- if (CMD_ARGC == 1) {
- const Jim_Nvp *n;
- n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]);
- if ((n->name == NULL) || (n->value == RESET_UNKNOWN))
- return ERROR_COMMAND_SYNTAX_ERROR;
- reset_mode = n->value;
- }
-
- /* reset *all* targets */
- return target_process_reset(CMD_CTX, reset_mode);
-}
-
-
-COMMAND_HANDLER(handle_resume_command)
-{
- int current = 1;
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct target *target = get_current_target(CMD_CTX);
-
- /* with no CMD_ARGV, resume from current pc, addr = 0,
- * with one arguments, addr = CMD_ARGV[0],
- * handle breakpoints, not debugging */
- uint32_t addr = 0;
- if (CMD_ARGC == 1) {
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
- current = 0;
- }
-
- return target_resume(target, current, addr, 1, 0);
-}
-
-COMMAND_HANDLER(handle_step_command)
-{
- if (CMD_ARGC > 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- LOG_DEBUG("-");
-
- /* with no CMD_ARGV, step from current pc, addr = 0,
- * with one argument addr = CMD_ARGV[0],
- * handle breakpoints, debugging */
- uint32_t addr = 0;
- int current_pc = 1;
- if (CMD_ARGC == 1) {
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
- current_pc = 0;
- }
-
- struct target *target = get_current_target(CMD_CTX);
-
- return target->type->step(target, current_pc, addr, 1);
-}
-
-static void handle_md_output(struct command_context *cmd_ctx,
- struct target *target, uint32_t address, unsigned size,
- unsigned count, const uint8_t *buffer)
-{
- const unsigned line_bytecnt = 32;
- unsigned line_modulo = line_bytecnt / size;
-
- char output[line_bytecnt * 4 + 1];
- unsigned output_len = 0;
-
- const char *value_fmt;
- switch (size) {
- case 4:
- value_fmt = "%8.8x ";
- break;
- case 2:
- value_fmt = "%4.4x ";
- break;
- case 1:
- value_fmt = "%2.2x ";
- break;
- default:
- /* "can't happen", caller checked */
- LOG_ERROR("invalid memory read size: %u", size);
- return;
- }
-
- for (unsigned i = 0; i < count; i++) {
- if (i % line_modulo == 0) {
- output_len += snprintf(output + output_len,
- sizeof(output) - output_len,
- "0x%8.8x: ",
- (unsigned)(address + (i*size)));
- }
-
- uint32_t value = 0;
- const uint8_t *value_ptr = buffer + i * size;
- switch (size) {
- case 4:
- value = target_buffer_get_u32(target, value_ptr);
- break;
- case 2:
- value = target_buffer_get_u16(target, value_ptr);
- break;
- case 1:
- value = *value_ptr;
- }
- output_len += snprintf(output + output_len,
- sizeof(output) - output_len,
- value_fmt, value);
-
- if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) {
- command_print(cmd_ctx, "%s", output);
- output_len = 0;
- }
- }
-}
-
-COMMAND_HANDLER(handle_md_command)
-{
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- unsigned size = 0;
- switch (CMD_NAME[2]) {
- case 'w':
- size = 4;
- break;
- case 'h':
- size = 2;
- break;
- case 'b':
- size = 1;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- bool physical = strcmp(CMD_ARGV[0], "phys") == 0;
- int (*fn)(struct target *target,
- uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer);
- if (physical) {
- CMD_ARGC--;
- CMD_ARGV++;
- fn = target_read_phys_memory;
- } else
- fn = target_read_memory;
- if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
-
- unsigned count = 1;
- if (CMD_ARGC == 2)
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
-
- uint8_t *buffer = calloc(count, size);
-
- struct target *target = get_current_target(CMD_CTX);
- int retval = fn(target, address, size, count, buffer);
- if (ERROR_OK == retval)
- handle_md_output(CMD_CTX, target, address, size, count, buffer);
-
- free(buffer);
-
- return retval;
-}
-
-typedef int (*target_write_fn)(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-
-static int target_fill_mem(struct target *target,
- uint32_t address,
- target_write_fn fn,
- unsigned data_size,
- /* value */
- uint32_t b,
- /* count */
- unsigned c)
-{
- /* We have to write in reasonably large chunks to be able
- * to fill large memory areas with any sane speed */
- const unsigned chunk_size = 16384;
- uint8_t *target_buf = malloc(chunk_size * data_size);
- if (target_buf == NULL) {
- LOG_ERROR("Out of memory");
- return ERROR_FAIL;
- }
-
- for (unsigned i = 0; i < chunk_size; i++) {
- switch (data_size) {
- case 4:
- target_buffer_set_u32(target, target_buf + i * data_size, b);
- break;
- case 2:
- target_buffer_set_u16(target, target_buf + i * data_size, b);
- break;
- case 1:
- target_buffer_set_u8(target, target_buf + i * data_size, b);
- break;
- default:
- exit(-1);
- }
- }
-
- int retval = ERROR_OK;
-
- for (unsigned x = 0; x < c; x += chunk_size) {
- unsigned current;
- current = c - x;
- if (current > chunk_size)
- current = chunk_size;
- retval = fn(target, address + x * data_size, data_size, current, target_buf);
- if (retval != ERROR_OK)
- break;
- /* avoid GDB timeouts */
- keep_alive();
- }
- free(target_buf);
-
- return retval;
-}
-
-
-COMMAND_HANDLER(handle_mw_command)
-{
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- bool physical = strcmp(CMD_ARGV[0], "phys") == 0;
- target_write_fn fn;
- if (physical) {
- CMD_ARGC--;
- CMD_ARGV++;
- fn = target_write_phys_memory;
- } else
- fn = target_write_memory;
- if ((CMD_ARGC < 2) || (CMD_ARGC > 3))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
-
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
-
- unsigned count = 1;
- if (CMD_ARGC == 3)
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count);
-
- struct target *target = get_current_target(CMD_CTX);
- unsigned wordsize;
- switch (CMD_NAME[2]) {
- case 'w':
- wordsize = 4;
- break;
- case 'h':
- wordsize = 2;
- break;
- case 'b':
- wordsize = 1;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- return target_fill_mem(target, address, fn, wordsize, value, count);
-}
-
-static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
- uint32_t *min_address, uint32_t *max_address)
-{
- if (CMD_ARGC < 1 || CMD_ARGC > 5)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* a base address isn't always necessary,
- * default to 0x0 (i.e. don't relocate) */
- if (CMD_ARGC >= 2) {
- uint32_t addr;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
- image->base_address = addr;
- image->base_address_set = 1;
- } else
- image->base_address_set = 0;
-
- image->start_address_set = 0;
-
- if (CMD_ARGC >= 4)
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
- if (CMD_ARGC == 5) {
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
- /* use size (given) to find max (required) */
- *max_address += *min_address;
- }
-
- if (*min_address > *max_address)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_load_image_command)
-{
- uint8_t *buffer;
- size_t buf_cnt;
- uint32_t image_size;
- uint32_t min_address = 0;
- uint32_t max_address = 0xffffffff;
- int i;
- struct image image;
-
- int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
- &image, &min_address, &max_address);
- if (ERROR_OK != retval)
- return retval;
-
- struct target *target = get_current_target(CMD_CTX);
-
- struct duration bench;
- duration_start(&bench);
-
- if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
- return ERROR_OK;
-
- image_size = 0x0;
- retval = ERROR_OK;
- for (i = 0; i < image.num_sections; i++) {
- buffer = malloc(image.sections[i].size);
- if (buffer == NULL) {
- command_print(CMD_CTX,
- "error allocating buffer for section (%d bytes)",
- (int)(image.sections[i].size));
- break;
- }
-
- retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
- if (retval != ERROR_OK) {
- free(buffer);
- break;
- }
-
- uint32_t offset = 0;
- uint32_t length = buf_cnt;
-
- /* DANGER!!! beware of unsigned comparision here!!! */
-
- if ((image.sections[i].base_address + buf_cnt >= min_address) &&
- (image.sections[i].base_address < max_address)) {
-
- if (image.sections[i].base_address < min_address) {
- /* clip addresses below */
- offset += min_address-image.sections[i].base_address;
- length -= offset;
- }
-
- if (image.sections[i].base_address + buf_cnt > max_address)
- length -= (image.sections[i].base_address + buf_cnt)-max_address;
-
- retval = target_write_buffer(target,
- image.sections[i].base_address + offset, length, buffer + offset);
- if (retval != ERROR_OK) {
- free(buffer);
- break;
- }
- image_size += length;
- command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
- (unsigned int)length,
- image.sections[i].base_address + offset);
- }
-
- free(buffer);
- }
-
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "downloaded %" PRIu32 " bytes "
- "in %fs (%0.3f KiB/s)", image_size,
- duration_elapsed(&bench), duration_kbps(&bench, image_size));
- }
-
- image_close(&image);
-
- return retval;
-
-}
-
-COMMAND_HANDLER(handle_dump_image_command)
-{
- struct fileio *fileio;
- uint8_t *buffer;
- int retval, retvaltemp;
- uint32_t address, size;
- struct duration bench;
- struct target *target = get_current_target(CMD_CTX);
-
- if (CMD_ARGC != 3)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size);
-
- uint32_t buf_size = (size > 4096) ? 4096 : size;
- buffer = malloc(buf_size);
- if (!buffer)
- return ERROR_FAIL;
-
- retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY);
- if (retval != ERROR_OK) {
- free(buffer);
- return retval;
- }
-
- duration_start(&bench);
-
- while (size > 0) {
- size_t size_written;
- uint32_t this_run_size = (size > buf_size) ? buf_size : size;
- retval = target_read_buffer(target, address, this_run_size, buffer);
- if (retval != ERROR_OK)
- break;
-
- retval = fileio_write(fileio, this_run_size, buffer, &size_written);
- if (retval != ERROR_OK)
- break;
-
- size -= this_run_size;
- address += this_run_size;
- }
-
- free(buffer);
-
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- size_t filesize;
- retval = fileio_size(fileio, &filesize);
- if (retval != ERROR_OK)
- return retval;
- command_print(CMD_CTX,
- "dumped %zu bytes in %fs (%0.3f KiB/s)", filesize,
- duration_elapsed(&bench), duration_kbps(&bench, filesize));
- }
-
- retvaltemp = fileio_close(fileio);
- if (retvaltemp != ERROR_OK)
- return retvaltemp;
-
- return retval;
-}
-
-static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
-{
- uint8_t *buffer;
- size_t buf_cnt;
- uint32_t image_size;
- int i;
- int retval;
- uint32_t checksum = 0;
- uint32_t mem_checksum = 0;
-
- struct image image;
-
- struct target *target = get_current_target(CMD_CTX);
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (!target) {
- LOG_ERROR("no target selected");
- return ERROR_FAIL;
- }
-
- struct duration bench;
- duration_start(&bench);
-
- if (CMD_ARGC >= 2) {
- uint32_t addr;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
- image.base_address = addr;
- image.base_address_set = 1;
- } else {
- image.base_address_set = 0;
- image.base_address = 0x0;
- }
-
- image.start_address_set = 0;
-
- retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
- if (retval != ERROR_OK)
- return retval;
-
- image_size = 0x0;
- int diffs = 0;
- retval = ERROR_OK;
- for (i = 0; i < image.num_sections; i++) {
- buffer = malloc(image.sections[i].size);
- if (buffer == NULL) {
- command_print(CMD_CTX,
- "error allocating buffer for section (%d bytes)",
- (int)(image.sections[i].size));
- break;
- }
- retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
- if (retval != ERROR_OK) {
- free(buffer);
- break;
- }
-
- if (verify) {
- /* calculate checksum of image */
- retval = image_calculate_checksum(buffer, buf_cnt, &checksum);
- if (retval != ERROR_OK) {
- free(buffer);
- break;
- }
-
- retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
- if (retval != ERROR_OK) {
- free(buffer);
- break;
- }
-
- if (checksum != mem_checksum) {
- /* failed crc checksum, fall back to a binary compare */
- uint8_t *data;
-
- if (diffs == 0)
- LOG_ERROR("checksum mismatch - attempting binary compare");
-
- data = malloc(buf_cnt);
-
- /* Can we use 32bit word accesses? */
- int size = 1;
- int count = buf_cnt;
- if ((count % 4) == 0) {
- size *= 4;
- count /= 4;
- }
- retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
- if (retval == ERROR_OK) {
- uint32_t t;
- for (t = 0; t < buf_cnt; t++) {
- if (data[t] != buffer[t]) {
- command_print(CMD_CTX,
- "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x",
- diffs,
- (unsigned)(t + image.sections[i].base_address),
- data[t],
- buffer[t]);
- if (diffs++ >= 127) {
- command_print(CMD_CTX, "More than 128 errors, the rest are not printed.");
- free(data);
- free(buffer);
- goto done;
- }
- }
- keep_alive();
- }
- }
- free(data);
- }
- } else {
- command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx",
- image.sections[i].base_address,
- buf_cnt);
- }
-
- free(buffer);
- image_size += buf_cnt;
- }
- if (diffs > 0)
- command_print(CMD_CTX, "No more differences found.");
-done:
- if (diffs > 0)
- retval = ERROR_FAIL;
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "verified %" PRIu32 " bytes "
- "in %fs (%0.3f KiB/s)", image_size,
- duration_elapsed(&bench), duration_kbps(&bench, image_size));
- }
-
- image_close(&image);
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_verify_image_command)
-{
- return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1);
-}
-
-COMMAND_HANDLER(handle_test_image_command)
-{
- return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0);
-}
-
-static int handle_bp_command_list(struct command_context *cmd_ctx)
-{
- struct target *target = get_current_target(cmd_ctx);
- struct breakpoint *breakpoint = target->breakpoints;
- while (breakpoint) {
- if (breakpoint->type == BKPT_SOFT) {
- char *buf = buf_to_str(breakpoint->orig_instr,
- breakpoint->length, 16);
- command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s",
- breakpoint->address,
- breakpoint->length,
- breakpoint->set, buf);
- free(buf);
- } else {
- if ((breakpoint->address == 0) && (breakpoint->asid != 0))
- command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i",
- breakpoint->asid,
- breakpoint->length, breakpoint->set);
- else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
- command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
- breakpoint->address,
- breakpoint->length, breakpoint->set);
- command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
- breakpoint->asid);
- } else
- command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
- breakpoint->address,
- breakpoint->length, breakpoint->set);
- }
-
- breakpoint = breakpoint->next;
- }
- return ERROR_OK;
-}
-
-static int handle_bp_command_set(struct command_context *cmd_ctx,
- uint32_t addr, uint32_t asid, uint32_t length, int hw)
-{
- struct target *target = get_current_target(cmd_ctx);
- int retval;
-
- if (asid == 0) {
- retval = breakpoint_add(target, addr, length, hw);
- if (ERROR_OK == retval)
- command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
- else {
- LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used");
- return retval;
- }
- } else if (addr == 0) {
- if (target->type->add_context_breakpoint == NULL) {
- LOG_WARNING("Context breakpoint not available");
- return ERROR_OK;
- }
- retval = context_breakpoint_add(target, asid, length, hw);
- if (ERROR_OK == retval)
- command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid);
- else {
- LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used");
- return retval;
- }
- } else {
- if (target->type->add_hybrid_breakpoint == NULL) {
- LOG_WARNING("Hybrid breakpoint not available");
- return ERROR_OK;
- }
- retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
- if (ERROR_OK == retval)
- command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid);
- else {
- LOG_ERROR("Failure setting breakpoint, the same address is already used");
- return retval;
- }
- }
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_bp_command)
-{
- uint32_t addr;
- uint32_t asid;
- uint32_t length;
- int hw = BKPT_SOFT;
-
- switch (CMD_ARGC) {
- case 0:
- return handle_bp_command_list(CMD_CTX);
-
- case 2:
- asid = 0;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
- return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
-
- case 3:
- if (strcmp(CMD_ARGV[2], "hw") == 0) {
- hw = BKPT_HARD;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
-
- asid = 0;
- return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
- } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) {
- hw = BKPT_HARD;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
- addr = 0;
- return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
- }
-
- case 4:
- hw = BKPT_HARD;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length);
- return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-}
-
-COMMAND_HANDLER(handle_rbp_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t addr;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
-
- struct target *target = get_current_target(CMD_CTX);
- breakpoint_remove(target, addr);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_wp_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- if (CMD_ARGC == 0) {
- struct watchpoint *watchpoint = target->watchpoints;
-
- while (watchpoint) {
- command_print(CMD_CTX, "address: 0x%8.8" PRIx32
- ", len: 0x%8.8" PRIx32
- ", r/w/a: %i, value: 0x%8.8" PRIx32
- ", mask: 0x%8.8" PRIx32,
- watchpoint->address,
- watchpoint->length,
- (int)watchpoint->rw,
- watchpoint->value,
- watchpoint->mask);
- watchpoint = watchpoint->next;
- }
- return ERROR_OK;
- }
-
- enum watchpoint_rw type = WPT_ACCESS;
- uint32_t addr = 0;
- uint32_t length = 0;
- uint32_t data_value = 0x0;
- uint32_t data_mask = 0xffffffff;
-
- switch (CMD_ARGC) {
- case 5:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], data_mask);
- /* fall through */
- case 4:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], data_value);
- /* fall through */
- case 3:
- switch (CMD_ARGV[2][0]) {
- case 'r':
- type = WPT_READ;
- break;
- case 'w':
- type = WPT_WRITE;
- break;
- case 'a':
- type = WPT_ACCESS;
- break;
- default:
- LOG_ERROR("invalid watchpoint mode ('%c')", CMD_ARGV[2][0]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- /* fall through */
- case 2:
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
- break;
-
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- int retval = watchpoint_add(target, addr, length, type,
- data_value, data_mask);
- if (ERROR_OK != retval)
- LOG_ERROR("Failure setting watchpoints");
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_rwp_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t addr;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
-
- struct target *target = get_current_target(CMD_CTX);
- watchpoint_remove(target, addr);
-
- return ERROR_OK;
-}
-
-/**
- * Translate a virtual address to a physical address.
- *
- * The low-level target implementation must have logged a detailed error
- * which is forwarded to telnet/GDB session.
- */
-COMMAND_HANDLER(handle_virt2phys_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t va;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], va);
- uint32_t pa;
-
- struct target *target = get_current_target(CMD_CTX);
- int retval = target->type->virt2phys(target, va, &pa);
- if (retval == ERROR_OK)
- command_print(CMD_CTX, "Physical address 0x%08" PRIx32 "", pa);
-
- return retval;
-}
-
-static void writeData(FILE *f, const void *data, size_t len)
-{
- size_t written = fwrite(data, 1, len, f);
- if (written != len)
- LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno));
-}
-
-static void writeLong(FILE *f, int l, struct target *target)
-{
- uint8_t val[4];
-
- target_buffer_set_u32(target, val, l);
- writeData(f, val, 4);
-}
-
-static void writeString(FILE *f, char *s)
-{
- writeData(f, s, strlen(s));
-}
-
-typedef unsigned char UNIT[2]; /* unit of profiling */
-
-/* Dump a gmon.out histogram file. */
-static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range,
- uint32_t start_address, uint32_t end_address, struct target *target)
-{
- uint32_t i;
- FILE *f = fopen(filename, "w");
- if (f == NULL)
- return;
- writeString(f, "gmon");
- writeLong(f, 0x00000001, target); /* Version */
- writeLong(f, 0, target); /* padding */
- writeLong(f, 0, target); /* padding */
- writeLong(f, 0, target); /* padding */
-
- uint8_t zero = 0; /* GMON_TAG_TIME_HIST */
- writeData(f, &zero, 1);
-
- /* figure out bucket size */
- uint32_t min;
- uint32_t max;
- if (with_range) {
- min = start_address;
- max = end_address;
- } else {
- min = samples[0];
- max = samples[0];
- for (i = 0; i < sampleNum; i++) {
- if (min > samples[i])
- min = samples[i];
- if (max < samples[i])
- max = samples[i];
- }
-
- /* max should be (largest sample + 1)
- * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */
- max++;
- }
-
- int addressSpace = max - min;
- assert(addressSpace >= 2);
-
- /* FIXME: What is the reasonable number of buckets?
- * The profiling result will be more accurate if there are enough buckets. */
- static const uint32_t maxBuckets = 128 * 1024; /* maximum buckets. */
- uint32_t numBuckets = addressSpace / sizeof(UNIT);
- if (numBuckets > maxBuckets)
- numBuckets = maxBuckets;
- int *buckets = malloc(sizeof(int) * numBuckets);
- if (buckets == NULL) {
- fclose(f);
- return;
- }
- memset(buckets, 0, sizeof(int) * numBuckets);
- for (i = 0; i < sampleNum; i++) {
- uint32_t address = samples[i];
-
- if ((address < min) || (max <= address))
- continue;
-
- long long a = address - min;
- long long b = numBuckets;
- long long c = addressSpace;
- int index_t = (a * b) / c; /* danger!!!! int32 overflows */
- buckets[index_t]++;
- }
-
- /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
- writeLong(f, min, target); /* low_pc */
- writeLong(f, max, target); /* high_pc */
- writeLong(f, numBuckets, target); /* # of buckets */
- writeLong(f, 100, target); /* KLUDGE! We lie, ca. 100Hz best case. */
- writeString(f, "seconds");
- for (i = 0; i < (15-strlen("seconds")); i++)
- writeData(f, &zero, 1);
- writeString(f, "s");
-
- /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */
-
- char *data = malloc(2 * numBuckets);
- if (data != NULL) {
- for (i = 0; i < numBuckets; i++) {
- int val;
- val = buckets[i];
- if (val > 65535)
- val = 65535;
- data[i * 2] = val&0xff;
- data[i * 2 + 1] = (val >> 8) & 0xff;
- }
- free(buckets);
- writeData(f, data, numBuckets * 2);
- free(data);
- } else
- free(buckets);
-
- fclose(f);
-}
-
-/* profiling samples the CPU PC as quickly as OpenOCD is able,
- * which will be used as a random sampling of PC */
-COMMAND_HANDLER(handle_profile_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- if ((CMD_ARGC != 2) && (CMD_ARGC != 4))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000;
- uint32_t offset;
- uint32_t num_of_samples;
- int retval = ERROR_OK;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset);
-
- uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM);
- if (samples == NULL) {
- LOG_ERROR("No memory to store samples.");
- return ERROR_FAIL;
- }
-
- /**
- * Some cores let us sample the PC without the
- * annoying halt/resume step; for example, ARMv7 PCSR.
- * Provide a way to use that more efficient mechanism.
- */
- retval = target_profiling(target, samples, MAX_PROFILE_SAMPLE_NUM,
- &num_of_samples, offset);
- if (retval != ERROR_OK) {
- free(samples);
- return retval;
- }
-
- assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM);
-
- retval = target_poll(target);
- if (retval != ERROR_OK) {
- free(samples);
- return retval;
- }
- if (target->state == TARGET_RUNNING) {
- retval = target_halt(target);
- if (retval != ERROR_OK) {
- free(samples);
- return retval;
- }
- }
-
- retval = target_poll(target);
- if (retval != ERROR_OK) {
- free(samples);
- return retval;
- }
-
- uint32_t start_address = 0;
- uint32_t end_address = 0;
- bool with_range = false;
- if (CMD_ARGC == 4) {
- with_range = true;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], start_address);
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address);
- }
-
- write_gmon(samples, num_of_samples, CMD_ARGV[1],
- with_range, start_address, end_address, target);
- command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]);
-
- free(samples);
- return retval;
-}
-
-static int new_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t val)
-{
- char *namebuf;
- Jim_Obj *nameObjPtr, *valObjPtr;
- int result;
-
- namebuf = alloc_printf("%s(%d)", varname, idx);
- if (!namebuf)
- return JIM_ERR;
-
- nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
- valObjPtr = Jim_NewIntObj(interp, val);
- if (!nameObjPtr || !valObjPtr) {
- free(namebuf);
- return JIM_ERR;
- }
-
- Jim_IncrRefCount(nameObjPtr);
- Jim_IncrRefCount(valObjPtr);
- result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
- Jim_DecrRefCount(interp, nameObjPtr);
- Jim_DecrRefCount(interp, valObjPtr);
- free(namebuf);
- /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
- return result;
-}
-
-static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- struct command_context *context;
- struct target *target;
-
- context = current_command_context(interp);
- assert(context != NULL);
-
- target = get_current_target(context);
- if (target == NULL) {
- LOG_ERROR("mem2array: no current target");
- return JIM_ERR;
- }
-
- return target_mem2array(interp, target, argc - 1, argv + 1);
-}
-
-static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv)
-{
- long l;
- uint32_t width;
- int len;
- uint32_t addr;
- uint32_t count;
- uint32_t v;
- const char *varname;
- const char *phys;
- bool is_phys;
- int n, e, retval;
- uint32_t i;
-
- /* argv[1] = name of array to receive the data
- * argv[2] = desired width
- * argv[3] = memory address
- * argv[4] = count of times to read
- */
- if (argc < 4 || argc > 5) {
- Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems [phys]");
- return JIM_ERR;
- }
- varname = Jim_GetString(argv[0], &len);
- /* given "foo" get space for worse case "foo(%d)" .. add 20 */
-
- e = Jim_GetLong(interp, argv[1], &l);
- width = l;
- if (e != JIM_OK)
- return e;
-
- e = Jim_GetLong(interp, argv[2], &l);
- addr = l;
- if (e != JIM_OK)
- return e;
- e = Jim_GetLong(interp, argv[3], &l);
- len = l;
- if (e != JIM_OK)
- return e;
- is_phys = false;
- if (argc > 4) {
- phys = Jim_GetString(argv[4], &n);
- if (!strncmp(phys, "phys", n))
- is_phys = true;
- else
- return JIM_ERR;
- }
- switch (width) {
- case 8:
- width = 1;
- break;
- case 16:
- width = 2;
- break;
- case 32:
- width = 4;
- break;
- default:
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL);
- return JIM_ERR;
- }
- if (len == 0) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
- return JIM_ERR;
- }
- if ((addr + (len * width)) < addr) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
- return JIM_ERR;
- }
- /* absurd transfer size? */
- if (len > 65536) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
- return JIM_ERR;
- }
-
- if ((width == 1) ||
- ((width == 2) && ((addr & 1) == 0)) ||
- ((width == 4) && ((addr & 3) == 0))) {
- /* all is well */
- } else {
- char buf[100];
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads",
- addr,
- width);
- Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
- return JIM_ERR;
- }
-
- /* Transfer loop */
-
- /* index counter */
- n = 0;
-
- size_t buffersize = 4096;
- uint8_t *buffer = malloc(buffersize);
- if (buffer == NULL)
- return JIM_ERR;
-
- /* assume ok */
- e = JIM_OK;
- while (len) {
- /* Slurp... in buffer size chunks */
-
- count = len; /* in objects.. */
- if (count > (buffersize / width))
- count = (buffersize / width);
-
- if (is_phys)
- retval = target_read_phys_memory(target, addr, width, count, buffer);
- else
- retval = target_read_memory(target, addr, width, count, buffer);
- if (retval != ERROR_OK) {
- /* BOO !*/
- LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed",
- (unsigned int)addr,
- (int)width,
- (int)count);
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
- e = JIM_ERR;
- break;
- } else {
- v = 0; /* shut up gcc */
- for (i = 0; i < count ; i++, n++) {
- switch (width) {
- case 4:
- v = target_buffer_get_u32(target, &buffer[i*width]);
- break;
- case 2:
- v = target_buffer_get_u16(target, &buffer[i*width]);
- break;
- case 1:
- v = buffer[i] & 0x0ff;
- break;
- }
- new_int_array_element(interp, varname, n, v);
- }
- len -= count;
- addr += count * width;
- }
- }
-
- free(buffer);
-
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-
- return e;
-}
-
-static int get_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t *val)
-{
- char *namebuf;
- Jim_Obj *nameObjPtr, *valObjPtr;
- int result;
- long l;
-
- namebuf = alloc_printf("%s(%d)", varname, idx);
- if (!namebuf)
- return JIM_ERR;
-
- nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
- if (!nameObjPtr) {
- free(namebuf);
- return JIM_ERR;
- }
-
- Jim_IncrRefCount(nameObjPtr);
- valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
- Jim_DecrRefCount(interp, nameObjPtr);
- free(namebuf);
- if (valObjPtr == NULL)
- return JIM_ERR;
-
- result = Jim_GetLong(interp, valObjPtr, &l);
- /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
- *val = l;
- return result;
-}
-
-static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- struct command_context *context;
- struct target *target;
-
- context = current_command_context(interp);
- assert(context != NULL);
-
- target = get_current_target(context);
- if (target == NULL) {
- LOG_ERROR("array2mem: no current target");
- return JIM_ERR;
- }
-
- return target_array2mem(interp, target, argc-1, argv + 1);
-}
-
-static int target_array2mem(Jim_Interp *interp, struct target *target,
- int argc, Jim_Obj *const *argv)
-{
- long l;
- uint32_t width;
- int len;
- uint32_t addr;
- uint32_t count;
- uint32_t v;
- const char *varname;
- const char *phys;
- bool is_phys;
- int n, e, retval;
- uint32_t i;
-
- /* argv[1] = name of array to get the data
- * argv[2] = desired width
- * argv[3] = memory address
- * argv[4] = count to write
- */
- if (argc < 4 || argc > 5) {
- Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]");
- return JIM_ERR;
- }
- varname = Jim_GetString(argv[0], &len);
- /* given "foo" get space for worse case "foo(%d)" .. add 20 */
-
- e = Jim_GetLong(interp, argv[1], &l);
- width = l;
- if (e != JIM_OK)
- return e;
-
- e = Jim_GetLong(interp, argv[2], &l);
- addr = l;
- if (e != JIM_OK)
- return e;
- e = Jim_GetLong(interp, argv[3], &l);
- len = l;
- if (e != JIM_OK)
- return e;
- is_phys = false;
- if (argc > 4) {
- phys = Jim_GetString(argv[4], &n);
- if (!strncmp(phys, "phys", n))
- is_phys = true;
- else
- return JIM_ERR;
- }
- switch (width) {
- case 8:
- width = 1;
- break;
- case 16:
- width = 2;
- break;
- case 32:
- width = 4;
- break;
- default:
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp),
- "Invalid width param, must be 8/16/32", NULL);
- return JIM_ERR;
- }
- if (len == 0) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp),
- "array2mem: zero width read?", NULL);
- return JIM_ERR;
- }
- if ((addr + (len * width)) < addr) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp),
- "array2mem: addr + len - wraps to zero?", NULL);
- return JIM_ERR;
- }
- /* absurd transfer size? */
- if (len > 65536) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp),
- "array2mem: absurd > 64K item request", NULL);
- return JIM_ERR;
- }
-
- if ((width == 1) ||
- ((width == 2) && ((addr & 1) == 0)) ||
- ((width == 4) && ((addr & 3) == 0))) {
- /* all is well */
- } else {
- char buf[100];
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads",
- (unsigned int)addr,
- (int)width);
- Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
- return JIM_ERR;
- }
-
- /* Transfer loop */
-
- /* index counter */
- n = 0;
- /* assume ok */
- e = JIM_OK;
-
- size_t buffersize = 4096;
- uint8_t *buffer = malloc(buffersize);
- if (buffer == NULL)
- return JIM_ERR;
-
- while (len) {
- /* Slurp... in buffer size chunks */
-
- count = len; /* in objects.. */
- if (count > (buffersize / width))
- count = (buffersize / width);
-
- v = 0; /* shut up gcc */
- for (i = 0; i < count; i++, n++) {
- get_int_array_element(interp, varname, n, &v);
- switch (width) {
- case 4:
- target_buffer_set_u32(target, &buffer[i * width], v);
- break;
- case 2:
- target_buffer_set_u16(target, &buffer[i * width], v);
- break;
- case 1:
- buffer[i] = v & 0x0ff;
- break;
- }
- }
- len -= count;
-
- if (is_phys)
- retval = target_write_phys_memory(target, addr, width, count, buffer);
- else
- retval = target_write_memory(target, addr, width, count, buffer);
- if (retval != ERROR_OK) {
- /* BOO !*/
- LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed",
- (unsigned int)addr,
- (int)width,
- (int)count);
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL);
- e = JIM_ERR;
- break;
- }
- addr += count * width;
- }
-
- free(buffer);
-
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-
- return e;
-}
-
-/* FIX? should we propagate errors here rather than printing them
- * and continuing?
- */
-void target_handle_event(struct target *target, enum target_event e)
-{
- struct target_event_action *teap;
-
- for (teap = target->event_action; teap != NULL; teap = teap->next) {
- if (teap->event == e) {
- LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s",
- target->target_number,
- target_name(target),
- target_type_name(target),
- e,
- Jim_Nvp_value2name_simple(nvp_target_event, e)->name,
- Jim_GetString(teap->body, NULL));
- if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) {
- Jim_MakeErrorMessage(teap->interp);
- command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL));
- }
- }
- }
-}
-
-/**
- * Returns true only if the target has a handler for the specified event.
- */
-bool target_has_event_action(struct target *target, enum target_event event)
-{
- struct target_event_action *teap;
-
- for (teap = target->event_action; teap != NULL; teap = teap->next) {
- if (teap->event == event)
- return true;
- }
- return false;
-}
-
-enum target_cfg_param {
- TCFG_TYPE,
- TCFG_EVENT,
- TCFG_WORK_AREA_VIRT,
- TCFG_WORK_AREA_PHYS,
- TCFG_WORK_AREA_SIZE,
- TCFG_WORK_AREA_BACKUP,
- TCFG_ENDIAN,
- TCFG_COREID,
- TCFG_CHAIN_POSITION,
- TCFG_DBGBASE,
- TCFG_RTOS,
-};
-
-static Jim_Nvp nvp_config_opts[] = {
- { .name = "-type", .value = TCFG_TYPE },
- { .name = "-event", .value = TCFG_EVENT },
- { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT },
- { .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS },
- { .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE },
- { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP },
- { .name = "-endian" , .value = TCFG_ENDIAN },
- { .name = "-coreid", .value = TCFG_COREID },
- { .name = "-chain-position", .value = TCFG_CHAIN_POSITION },
- { .name = "-dbgbase", .value = TCFG_DBGBASE },
- { .name = "-rtos", .value = TCFG_RTOS },
- { .name = NULL, .value = -1 }
-};
-
-static int target_configure(Jim_GetOptInfo *goi, struct target *target)
-{
- Jim_Nvp *n;
- Jim_Obj *o;
- jim_wide w;
- int e;
-
- /* parse config or cget options ... */
- while (goi->argc > 0) {
- Jim_SetEmptyResult(goi->interp);
- /* Jim_GetOpt_Debug(goi); */
-
- if (target->type->target_jim_configure) {
- /* target defines a configure function */
- /* target gets first dibs on parameters */
- e = (*(target->type->target_jim_configure))(target, goi);
- if (e == JIM_OK) {
- /* more? */
- continue;
- }
- if (e == JIM_ERR) {
- /* An error */
- return e;
- }
- /* otherwise we 'continue' below */
- }
- e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
- return e;
- }
- switch (n->value) {
- case TCFG_TYPE:
- /* not setable */
- if (goi->isconfigure) {
- Jim_SetResultFormatted(goi->interp,
- "not settable: %s", n->name);
- return JIM_ERR;
- } else {
-no_params:
- if (goi->argc != 0) {
- Jim_WrongNumArgs(goi->interp,
- goi->argc, goi->argv,
- "NO PARAMS");
- return JIM_ERR;
- }
- }
- Jim_SetResultString(goi->interp,
- target_type_name(target), -1);
- /* loop for more */
- break;
- case TCFG_EVENT:
- if (goi->argc == 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
- return JIM_ERR;
- }
-
- e = Jim_GetOpt_Nvp(goi, nvp_target_event, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, nvp_target_event, 1);
- return e;
- }
-
- if (goi->isconfigure) {
- if (goi->argc != 1) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
- return JIM_ERR;
- }
- } else {
- if (goi->argc != 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
- return JIM_ERR;
- }
- }
-
- {
- struct target_event_action *teap;
-
- teap = target->event_action;
- /* replace existing? */
- while (teap) {
- if (teap->event == (enum target_event)n->value)
- break;
- teap = teap->next;
- }
-
- if (goi->isconfigure) {
- bool replace = true;
- if (teap == NULL) {
- /* create new */
- teap = calloc(1, sizeof(*teap));
- replace = false;
- }
- teap->event = n->value;
- teap->interp = goi->interp;
- Jim_GetOpt_Obj(goi, &o);
- if (teap->body)
- Jim_DecrRefCount(teap->interp, teap->body);
- teap->body = Jim_DuplicateObj(goi->interp, o);
- /*
- * FIXME:
- * Tcl/TK - "tk events" have a nice feature.
- * See the "BIND" command.
- * We should support that here.
- * You can specify %X and %Y in the event code.
- * The idea is: %T - target name.
- * The idea is: %N - target number
- * The idea is: %E - event name.
- */
- Jim_IncrRefCount(teap->body);
-
- if (!replace) {
- /* add to head of event list */
- teap->next = target->event_action;
- target->event_action = teap;
- }
- Jim_SetEmptyResult(goi->interp);
- } else {
- /* get */
- if (teap == NULL)
- Jim_SetEmptyResult(goi->interp);
- else
- Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body));
- }
- }
- /* loop for more */
- break;
-
- case TCFG_WORK_AREA_VIRT:
- if (goi->isconfigure) {
- target_free_all_working_areas(target);
- e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->working_area_virt = w;
- target->working_area_virt_spec = true;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt));
- /* loop for more */
- break;
-
- case TCFG_WORK_AREA_PHYS:
- if (goi->isconfigure) {
- target_free_all_working_areas(target);
- e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->working_area_phys = w;
- target->working_area_phys_spec = true;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys));
- /* loop for more */
- break;
-
- case TCFG_WORK_AREA_SIZE:
- if (goi->isconfigure) {
- target_free_all_working_areas(target);
- e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->working_area_size = w;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
- /* loop for more */
- break;
-
- case TCFG_WORK_AREA_BACKUP:
- if (goi->isconfigure) {
- target_free_all_working_areas(target);
- e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK)
- return e;
- /* make this exactly 1 or 0 */
- target->backup_working_area = (!!w);
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area));
- /* loop for more e*/
- break;
-
-
- case TCFG_ENDIAN:
- if (goi->isconfigure) {
- e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(goi, nvp_target_endian, 1);
- return e;
- }
- target->endianness = n->value;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness);
- if (n->name == NULL) {
- target->endianness = TARGET_LITTLE_ENDIAN;
- n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness);
- }
- Jim_SetResultString(goi->interp, n->name, -1);
- /* loop for more */
- break;
-
- case TCFG_COREID:
- if (goi->isconfigure) {
- e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->coreid = (int32_t)w;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
- /* loop for more */
- break;
-
- case TCFG_CHAIN_POSITION:
- if (goi->isconfigure) {
- Jim_Obj *o_t;
- struct jtag_tap *tap;
- target_free_all_working_areas(target);
- e = Jim_GetOpt_Obj(goi, &o_t);
- if (e != JIM_OK)
- return e;
- tap = jtag_tap_by_jim_obj(goi->interp, o_t);
- if (tap == NULL)
- return JIM_ERR;
- /* make this exactly 1 or 0 */
- target->tap = tap;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResultString(goi->interp, target->tap->dotted_name, -1);
- /* loop for more e*/
- break;
- case TCFG_DBGBASE:
- if (goi->isconfigure) {
- e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->dbgbase = (uint32_t)w;
- target->dbgbase_set = true;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
- /* loop for more */
- break;
-
- case TCFG_RTOS:
- /* RTOS */
- {
- int result = rtos_create(goi, target);
- if (result != JIM_OK)
- return result;
- }
- /* loop for more */
- break;
- }
- } /* while (goi->argc) */
-
-
- /* done - we return */
- return JIM_OK;
-}
-
-static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- Jim_GetOptInfo goi;
-
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
- goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure");
- int need_args = 1 + goi.isconfigure;
- if (goi.argc < need_args) {
- Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
- goi.isconfigure
- ? "missing: -option VALUE ..."
- : "missing: -option ...");
- return JIM_ERR;
- }
- struct target *target = Jim_CmdPrivData(goi.interp);
- return target_configure(&goi, target);
-}
-
-static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
-
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if (goi.argc < 2 || goi.argc > 4) {
- Jim_SetResultFormatted(goi.interp,
- "usage: %s [phys] <address> <data> [<count>]", cmd_name);
- return JIM_ERR;
- }
-
- target_write_fn fn;
- fn = target_write_memory;
-
- int e;
- if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) {
- /* consume it */
- struct Jim_Obj *obj;
- e = Jim_GetOpt_Obj(&goi, &obj);
- if (e != JIM_OK)
- return e;
-
- fn = target_write_phys_memory;
- }
-
- jim_wide a;
- e = Jim_GetOpt_Wide(&goi, &a);
- if (e != JIM_OK)
- return e;
-
- jim_wide b;
- e = Jim_GetOpt_Wide(&goi, &b);
- if (e != JIM_OK)
- return e;
-
- jim_wide c = 1;
- if (goi.argc == 1) {
- e = Jim_GetOpt_Wide(&goi, &c);
- if (e != JIM_OK)
- return e;
- }
-
- /* all args must be consumed */
- if (goi.argc != 0)
- return JIM_ERR;
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- unsigned data_size;
- if (strcasecmp(cmd_name, "mww") == 0)
- data_size = 4;
- else if (strcasecmp(cmd_name, "mwh") == 0)
- data_size = 2;
- else if (strcasecmp(cmd_name, "mwb") == 0)
- data_size = 1;
- else {
- LOG_ERROR("command '%s' unknown: ", cmd_name);
- return JIM_ERR;
- }
-
- return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR;
-}
-
-/**
-* @brief Reads an array of words/halfwords/bytes from target memory starting at specified address.
-*
-* Usage: mdw [phys] <address> [<count>] - for 32 bit reads
-* mdh [phys] <address> [<count>] - for 16 bit reads
-* mdb [phys] <address> [<count>] - for 8 bit reads
-*
-* Count defaults to 1.
-*
-* Calls target_read_memory or target_read_phys_memory depending on
-* the presence of the "phys" argument
-* Reads the target memory in blocks of max. 32 bytes, and returns an array of ints formatted
-* to int representation in base16.
-* Also outputs read data in a human readable form using command_print
-*
-* @param phys if present target_read_phys_memory will be used instead of target_read_memory
-* @param address address where to start the read. May be specified in decimal or hex using the standard "0x" prefix
-* @param count optional count parameter to read an array of values. If not specified, defaults to 1.
-* @returns: JIM_ERR on error or JIM_OK on success and sets the result string to an array of ascii formatted numbers
-* on success, with [<count>] number of elements.
-*
-* In case of little endian target:
-* Example1: "mdw 0x00000000" returns "10123456"
-* Exmaple2: "mdh 0x00000000 1" returns "3456"
-* Example3: "mdb 0x00000000" returns "56"
-* Example4: "mdh 0x00000000 2" returns "3456 1012"
-* Example5: "mdb 0x00000000 3" returns "56 34 12"
-**/
-static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- const char *cmd_name = Jim_GetString(argv[0], NULL);
-
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if ((goi.argc < 1) || (goi.argc > 3)) {
- Jim_SetResultFormatted(goi.interp,
- "usage: %s [phys] <address> [<count>]", cmd_name);
- return JIM_ERR;
- }
-
- int (*fn)(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
- fn = target_read_memory;
-
- int e;
- if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) {
- /* consume it */
- struct Jim_Obj *obj;
- e = Jim_GetOpt_Obj(&goi, &obj);
- if (e != JIM_OK)
- return e;
-
- fn = target_read_phys_memory;
- }
-
- /* Read address parameter */
- jim_wide addr;
- e = Jim_GetOpt_Wide(&goi, &addr);
- if (e != JIM_OK)
- return JIM_ERR;
-
- /* If next parameter exists, read it out as the count parameter, if not, set it to 1 (default) */
- jim_wide count;
- if (goi.argc == 1) {
- e = Jim_GetOpt_Wide(&goi, &count);
- if (e != JIM_OK)
- return JIM_ERR;
- } else
- count = 1;
-
- /* all args must be consumed */
- if (goi.argc != 0)
- return JIM_ERR;
-
- jim_wide dwidth = 1; /* shut up gcc */
- if (strcasecmp(cmd_name, "mdw") == 0)
- dwidth = 4;
- else if (strcasecmp(cmd_name, "mdh") == 0)
- dwidth = 2;
- else if (strcasecmp(cmd_name, "mdb") == 0)
- dwidth = 1;
- else {
- LOG_ERROR("command '%s' unknown: ", cmd_name);
- return JIM_ERR;
- }
-
- /* convert count to "bytes" */
- int bytes = count * dwidth;
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- uint8_t target_buf[32];
- jim_wide x, y, z;
- while (bytes > 0) {
- y = (bytes < 16) ? bytes : 16; /* y = min(bytes, 16); */
-
- /* Try to read out next block */
- e = fn(target, addr, dwidth, y / dwidth, target_buf);
-
- if (e != ERROR_OK) {
- Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr);
- return JIM_ERR;
- }
-
- command_print_sameline(NULL, "0x%08x ", (int)(addr));
- switch (dwidth) {
- case 4:
- for (x = 0; x < 16 && x < y; x += 4) {
- z = target_buffer_get_u32(target, &(target_buf[x]));
- command_print_sameline(NULL, "%08x ", (int)(z));
- }
- for (; (x < 16) ; x += 4)
- command_print_sameline(NULL, " ");
- break;
- case 2:
- for (x = 0; x < 16 && x < y; x += 2) {
- z = target_buffer_get_u16(target, &(target_buf[x]));
- command_print_sameline(NULL, "%04x ", (int)(z));
- }
- for (; (x < 16) ; x += 2)
- command_print_sameline(NULL, " ");
- break;
- case 1:
- default:
- for (x = 0 ; (x < 16) && (x < y) ; x += 1) {
- z = target_buffer_get_u8(target, &(target_buf[x]));
- command_print_sameline(NULL, "%02x ", (int)(z));
- }
- for (; (x < 16) ; x += 1)
- command_print_sameline(NULL, " ");
- break;
- }
- /* ascii-ify the bytes */
- for (x = 0 ; x < y ; x++) {
- if ((target_buf[x] >= 0x20) &&
- (target_buf[x] <= 0x7e)) {
- /* good */
- } else {
- /* smack it */
- target_buf[x] = '.';
- }
- }
- /* space pad */
- while (x < 16) {
- target_buf[x] = ' ';
- x++;
- }
- /* terminate */
- target_buf[16] = 0;
- /* print - with a newline */
- command_print_sameline(NULL, "%s\n", target_buf);
- /* NEXT... */
- bytes -= 16;
- addr += 16;
- }
- return JIM_OK;
-}
-
-static int jim_target_mem2array(Jim_Interp *interp,
- int argc, Jim_Obj *const *argv)
-{
- struct target *target = Jim_CmdPrivData(interp);
- return target_mem2array(interp, target, argc - 1, argv + 1);
-}
-
-static int jim_target_array2mem(Jim_Interp *interp,
- int argc, Jim_Obj *const *argv)
-{
- struct target *target = Jim_CmdPrivData(interp);
- return target_array2mem(interp, target, argc - 1, argv + 1);
-}
-
-static int jim_target_tap_disabled(Jim_Interp *interp)
-{
- Jim_SetResultFormatted(interp, "[TAP is disabled]");
- return JIM_ERR;
-}
-
-static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
- return JIM_ERR;
- }
- struct target *target = Jim_CmdPrivData(interp);
- if (!target->tap->enabled)
- return jim_target_tap_disabled(interp);
-
- int e = target->type->examine(target);
- if (e != ERROR_OK)
- return JIM_ERR;
- return JIM_OK;
-}
-
-static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
- return JIM_ERR;
- }
- struct target *target = Jim_CmdPrivData(interp);
-
- if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK)
- return JIM_ERR;
-
- return JIM_OK;
-}
-
-static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
- return JIM_ERR;
- }
- struct target *target = Jim_CmdPrivData(interp);
- if (!target->tap->enabled)
- return jim_target_tap_disabled(interp);
-
- int e;
- if (!(target_was_examined(target)))
- e = ERROR_TARGET_NOT_EXAMINED;
- else
- e = target->type->poll(target);
- if (e != ERROR_OK)
- return JIM_ERR;
- return JIM_OK;
-}
-
-static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- if (goi.argc != 2) {
- Jim_WrongNumArgs(interp, 0, argv,
- "([tT]|[fF]|assert|deassert) BOOL");
- return JIM_ERR;
- }
-
- Jim_Nvp *n;
- int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1);
- return e;
- }
- /* the halt or not param */
- jim_wide a;
- e = Jim_GetOpt_Wide(&goi, &a);
- if (e != JIM_OK)
- return e;
-
- struct target *target = Jim_CmdPrivData(goi.interp);
- if (!target->tap->enabled)
- return jim_target_tap_disabled(interp);
-
- if (!target->type->assert_reset || !target->type->deassert_reset) {
- Jim_SetResultFormatted(interp,
- "No target-specific reset for %s",
- target_name(target));
- return JIM_ERR;
- }
- /* determine if we should halt or not. */
- target->reset_halt = !!a;
- /* When this happens - all workareas are invalid. */
- target_free_all_working_areas_restore(target, 0);
-
- /* do the assert */
- if (n->value == NVP_ASSERT)
- e = target->type->assert_reset(target);
- else
- e = target->type->deassert_reset(target);
- return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
-}
-
-static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
- return JIM_ERR;
- }
- struct target *target = Jim_CmdPrivData(interp);
- if (!target->tap->enabled)
- return jim_target_tap_disabled(interp);
- int e = target->type->halt(target);
- return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
-}
-
-static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
- /* params: <name> statename timeoutmsecs */
- if (goi.argc != 2) {
- const char *cmd_name = Jim_GetString(argv[0], NULL);
- Jim_SetResultFormatted(goi.interp,
- "%s <state_name> <timeout_in_msec>", cmd_name);
- return JIM_ERR;
- }
-
- Jim_Nvp *n;
- int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(&goi, nvp_target_state, 1);
- return e;
- }
- jim_wide a;
- e = Jim_GetOpt_Wide(&goi, &a);
- if (e != JIM_OK)
- return e;
- struct target *target = Jim_CmdPrivData(interp);
- if (!target->tap->enabled)
- return jim_target_tap_disabled(interp);
-
- e = target_wait_state(target, n->value, a);
- if (e != ERROR_OK) {
- Jim_Obj *eObj = Jim_NewIntObj(interp, e);
- Jim_SetResultFormatted(goi.interp,
- "target: %s wait %s fails (%#s) %s",
- target_name(target), n->name,
- eObj, target_strerror_safe(e));
- Jim_FreeNewObj(interp, eObj);
- return JIM_ERR;
- }
- return JIM_OK;
-}
-/* List for human, Events defined for this target.
- * scripts/programs should use 'name cget -event NAME'
- */
-static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- struct command_context *cmd_ctx = current_command_context(interp);
- assert(cmd_ctx != NULL);
-
- struct target *target = Jim_CmdPrivData(interp);
- struct target_event_action *teap = target->event_action;
- command_print(cmd_ctx, "Event actions for target (%d) %s\n",
- target->target_number,
- target_name(target));
- command_print(cmd_ctx, "%-25s | Body", "Event");
- command_print(cmd_ctx, "------------------------- | "
- "----------------------------------------");
- while (teap) {
- Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event);
- command_print(cmd_ctx, "%-25s | %s",
- opt->name, Jim_GetString(teap->body, NULL));
- teap = teap->next;
- }
- command_print(cmd_ctx, "***END***");
- return JIM_OK;
-}
-static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
- return JIM_ERR;
- }
- struct target *target = Jim_CmdPrivData(interp);
- Jim_SetResultString(interp, target_state_name(target), -1);
- return JIM_OK;
-}
-static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
- if (goi.argc != 1) {
- const char *cmd_name = Jim_GetString(argv[0], NULL);
- Jim_SetResultFormatted(goi.interp, "%s <eventname>", cmd_name);
- return JIM_ERR;
- }
- Jim_Nvp *n;
- int e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n);
- if (e != JIM_OK) {
- Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1);
- return e;
- }
- struct target *target = Jim_CmdPrivData(interp);
- target_handle_event(target, n->value);
- return JIM_OK;
-}
-
-static const struct command_registration target_instance_command_handlers[] = {
- {
- .name = "configure",
- .mode = COMMAND_CONFIG,
- .jim_handler = jim_target_configure,
- .help = "configure a new target for use",
- .usage = "[target_attribute ...]",
- },
- {
- .name = "cget",
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_configure,
- .help = "returns the specified target attribute",
- .usage = "target_attribute",
- },
- {
- .name = "mww",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_mw,
- .help = "Write 32-bit word(s) to target memory",
- .usage = "address data [count]",
- },
- {
- .name = "mwh",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_mw,
- .help = "Write 16-bit half-word(s) to target memory",
- .usage = "address data [count]",
- },
- {
- .name = "mwb",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_mw,
- .help = "Write byte(s) to target memory",
- .usage = "address data [count]",
- },
- {
- .name = "mdw",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_md,
- .help = "Display target memory as 32-bit words",
- .usage = "address [count]",
- },
- {
- .name = "mdh",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_md,
- .help = "Display target memory as 16-bit half-words",
- .usage = "address [count]",
- },
- {
- .name = "mdb",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_md,
- .help = "Display target memory as 8-bit bytes",
- .usage = "address [count]",
- },
- {
- .name = "array2mem",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_array2mem,
- .help = "Writes Tcl array of 8/16/32 bit numbers "
- "to target memory",
- .usage = "arrayname bitwidth address count",
- },
- {
- .name = "mem2array",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_mem2array,
- .help = "Loads Tcl array of 8/16/32 bit numbers "
- "from target memory",
- .usage = "arrayname bitwidth address count",
- },
- {
- .name = "eventlist",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_event_list,
- .help = "displays a table of events defined for this target",
- },
- {
- .name = "curstate",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_current_state,
- .help = "displays the current state of this target",
- },
- {
- .name = "arp_examine",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_examine,
- .help = "used internally for reset processing",
- },
- {
- .name = "arp_halt_gdb",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_halt_gdb,
- .help = "used internally for reset processing to halt GDB",
- },
- {
- .name = "arp_poll",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_poll,
- .help = "used internally for reset processing",
- },
- {
- .name = "arp_reset",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_reset,
- .help = "used internally for reset processing",
- },
- {
- .name = "arp_halt",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_halt,
- .help = "used internally for reset processing",
- },
- {
- .name = "arp_waitstate",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_wait_state,
- .help = "used internally for reset processing",
- },
- {
- .name = "invoke-event",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_target_invoke_event,
- .help = "invoke handler for specified event",
- .usage = "event_name",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int target_create(Jim_GetOptInfo *goi)
-{
- Jim_Obj *new_cmd;
- Jim_Cmd *cmd;
- const char *cp;
- int e;
- int x;
- struct target *target;
- struct command_context *cmd_ctx;
-
- cmd_ctx = current_command_context(goi->interp);
- assert(cmd_ctx != NULL);
-
- if (goi->argc < 3) {
- Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
- return JIM_ERR;
- }
-
- /* COMMAND */
- Jim_GetOpt_Obj(goi, &new_cmd);
- /* does this command exist? */
- cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
- if (cmd) {
- cp = Jim_GetString(new_cmd, NULL);
- Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp);
- return JIM_ERR;
- }
-
- /* TYPE */
- e = Jim_GetOpt_String(goi, &cp, NULL);
- if (e != JIM_OK)
- return e;
- struct transport *tr = get_current_transport();
- if (tr->override_target) {
- e = tr->override_target(&cp);
- if (e != ERROR_OK) {
- LOG_ERROR("The selected transport doesn't support this target");
- return JIM_ERR;
- }
- LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD");
- }
- /* now does target type exist */
- for (x = 0 ; target_types[x] ; x++) {
- if (0 == strcmp(cp, target_types[x]->name)) {
- /* found */
- break;
- }
-
- /* check for deprecated name */
- if (target_types[x]->deprecated_name) {
- if (0 == strcmp(cp, target_types[x]->deprecated_name)) {
- /* found */
- LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name);
- break;
- }
- }
- }
- if (target_types[x] == NULL) {
- Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp);
- for (x = 0 ; target_types[x] ; x++) {
- if (target_types[x + 1]) {
- Jim_AppendStrings(goi->interp,
- Jim_GetResult(goi->interp),
- target_types[x]->name,
- ", ", NULL);
- } else {
- Jim_AppendStrings(goi->interp,
- Jim_GetResult(goi->interp),
- " or ",
- target_types[x]->name, NULL);
- }
- }
- return JIM_ERR;
- }
-
- /* Create it */
- target = calloc(1, sizeof(struct target));
- /* set target number */
- target->target_number = new_target_number();
- cmd_ctx->current_target = target->target_number;
-
- /* allocate memory for each unique target type */
- target->type = calloc(1, sizeof(struct target_type));
-
- memcpy(target->type, target_types[x], sizeof(struct target_type));
-
- /* will be set by "-endian" */
- target->endianness = TARGET_ENDIAN_UNKNOWN;
-
- /* default to first core, override with -coreid */
- target->coreid = 0;
-
- target->working_area = 0x0;
- target->working_area_size = 0x0;
- target->working_areas = NULL;
- target->backup_working_area = 0;
-
- target->state = TARGET_UNKNOWN;
- target->debug_reason = DBG_REASON_UNDEFINED;
- target->reg_cache = NULL;
- target->breakpoints = NULL;
- target->watchpoints = NULL;
- target->next = NULL;
- target->arch_info = NULL;
-
- target->display = 1;
-
- target->halt_issued = false;
-
- /* initialize trace information */
- target->trace_info = malloc(sizeof(struct trace));
- target->trace_info->num_trace_points = 0;
- target->trace_info->trace_points_size = 0;
- target->trace_info->trace_points = NULL;
- target->trace_info->trace_history_size = 0;
- target->trace_info->trace_history = NULL;
- target->trace_info->trace_history_pos = 0;
- target->trace_info->trace_history_overflowed = 0;
-
- target->dbgmsg = NULL;
- target->dbg_msg_enabled = 0;
-
- target->endianness = TARGET_ENDIAN_UNKNOWN;
-
- target->rtos = NULL;
- target->rtos_auto_detect = false;
-
- /* Do the rest as "configure" options */
- goi->isconfigure = 1;
- e = target_configure(goi, target);
-
- if (target->tap == NULL) {
- Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
- e = JIM_ERR;
- }
-
- if (e != JIM_OK) {
- free(target->type);
- free(target);
- return e;
- }
-
- if (target->endianness == TARGET_ENDIAN_UNKNOWN) {
- /* default endian to little if not specified */
- target->endianness = TARGET_LITTLE_ENDIAN;
- }
-
- cp = Jim_GetString(new_cmd, NULL);
- target->cmd_name = strdup(cp);
-
- /* create the target specific commands */
- if (target->type->commands) {
- e = register_commands(cmd_ctx, NULL, target->type->commands);
- if (ERROR_OK != e)
- LOG_ERROR("unable to register '%s' commands", cp);
- }
- if (target->type->target_create)
- (*(target->type->target_create))(target, goi->interp);
-
- /* append to end of list */
- {
- struct target **tpp;
- tpp = &(all_targets);
- while (*tpp)
- tpp = &((*tpp)->next);
- *tpp = target;
- }
-
- /* now - create the new target name command */
- const struct command_registration target_subcommands[] = {
- {
- .chain = target_instance_command_handlers,
- },
- {
- .chain = target->type->commands,
- },
- COMMAND_REGISTRATION_DONE
- };
- const struct command_registration target_commands[] = {
- {
- .name = cp,
- .mode = COMMAND_ANY,
- .help = "target command group",
- .usage = "",
- .chain = target_subcommands,
- },
- COMMAND_REGISTRATION_DONE
- };
- e = register_commands(cmd_ctx, NULL, target_commands);
- if (ERROR_OK != e)
- return JIM_ERR;
-
- struct command *c = command_find_in_context(cmd_ctx, cp);
- assert(c);
- command_set_handler_data(c, target);
-
- return (ERROR_OK == e) ? JIM_OK : JIM_ERR;
-}
-
-static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
- return JIM_ERR;
- }
- struct command_context *cmd_ctx = current_command_context(interp);
- assert(cmd_ctx != NULL);
-
- Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1);
- return JIM_OK;
-}
-
-static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
- return JIM_ERR;
- }
- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
- for (unsigned x = 0; NULL != target_types[x]; x++) {
- Jim_ListAppendElement(interp, Jim_GetResult(interp),
- Jim_NewStringObj(interp, target_types[x]->name, -1));
- }
- return JIM_OK;
-}
-
-static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
- return JIM_ERR;
- }
- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
- struct target *target = all_targets;
- while (target) {
- Jim_ListAppendElement(interp, Jim_GetResult(interp),
- Jim_NewStringObj(interp, target_name(target), -1));
- target = target->next;
- }
- return JIM_OK;
-}
-
-static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- int i;
- const char *targetname;
- int retval, len;
- struct target *target = (struct target *) NULL;
- struct target_list *head, *curr, *new;
- curr = (struct target_list *) NULL;
- head = (struct target_list *) NULL;
-
- retval = 0;
- LOG_DEBUG("%d", argc);
- /* argv[1] = target to associate in smp
- * argv[2] = target to assoicate in smp
- * argv[3] ...
- */
-
- for (i = 1; i < argc; i++) {
-
- targetname = Jim_GetString(argv[i], &len);
- target = get_target(targetname);
- LOG_DEBUG("%s ", targetname);
- if (target) {
- new = malloc(sizeof(struct target_list));
- new->target = target;
- new->next = (struct target_list *)NULL;
- if (head == (struct target_list *)NULL) {
- head = new;
- curr = head;
- } else {
- curr->next = new;
- curr = new;
- }
- }
- }
- /* now parse the list of cpu and put the target in smp mode*/
- curr = head;
-
- while (curr != (struct target_list *)NULL) {
- target = curr->target;
- target->smp = 1;
- target->head = head;
- curr = curr->next;
- }
-
- if (target && target->rtos)
- retval = rtos_smp_init(head->target);
-
- return retval;
-}
-
-
-static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- Jim_GetOptInfo goi;
- Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
- if (goi.argc < 3) {
- Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
- "<name> <target_type> [<target_options> ...]");
- return JIM_ERR;
- }
- return target_create(&goi);
-}
-
-static const struct command_registration target_subcommand_handlers[] = {
- {
- .name = "init",
- .mode = COMMAND_CONFIG,
- .handler = handle_target_init_command,
- .help = "initialize targets",
- },
- {
- .name = "create",
- /* REVISIT this should be COMMAND_CONFIG ... */
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_create,
- .usage = "name type '-chain-position' name [options ...]",
- .help = "Creates and selects a new target",
- },
- {
- .name = "current",
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_current,
- .help = "Returns the currently selected target",
- },
- {
- .name = "types",
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_types,
- .help = "Returns the available target types as "
- "a list of strings",
- },
- {
- .name = "names",
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_names,
- .help = "Returns the names of all targets as a list of strings",
- },
- {
- .name = "smp",
- .mode = COMMAND_ANY,
- .jim_handler = jim_target_smp,
- .usage = "targetname1 targetname2 ...",
- .help = "gather several target in a smp list"
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-struct FastLoad {
- uint32_t address;
- uint8_t *data;
- int length;
-
-};
-
-static int fastload_num;
-static struct FastLoad *fastload;
-
-static void free_fastload(void)
-{
- if (fastload != NULL) {
- int i;
- for (i = 0; i < fastload_num; i++) {
- if (fastload[i].data)
- free(fastload[i].data);
- }
- free(fastload);
- fastload = NULL;
- }
-}
-
-COMMAND_HANDLER(handle_fast_load_image_command)
-{
- uint8_t *buffer;
- size_t buf_cnt;
- uint32_t image_size;
- uint32_t min_address = 0;
- uint32_t max_address = 0xffffffff;
- int i;
-
- struct image image;
-
- int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV,
- &image, &min_address, &max_address);
- if (ERROR_OK != retval)
- return retval;
-
- struct duration bench;
- duration_start(&bench);
-
- retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL);
- if (retval != ERROR_OK)
- return retval;
-
- image_size = 0x0;
- retval = ERROR_OK;
- fastload_num = image.num_sections;
- fastload = malloc(sizeof(struct FastLoad)*image.num_sections);
- if (fastload == NULL) {
- command_print(CMD_CTX, "out of memory");
- image_close(&image);
- return ERROR_FAIL;
- }
- memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
- for (i = 0; i < image.num_sections; i++) {
- buffer = malloc(image.sections[i].size);
- if (buffer == NULL) {
- command_print(CMD_CTX, "error allocating buffer for section (%d bytes)",
- (int)(image.sections[i].size));
- retval = ERROR_FAIL;
- break;
- }
-
- retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
- if (retval != ERROR_OK) {
- free(buffer);
- break;
- }
-
- uint32_t offset = 0;
- uint32_t length = buf_cnt;
-
- /* DANGER!!! beware of unsigned comparision here!!! */
-
- if ((image.sections[i].base_address + buf_cnt >= min_address) &&
- (image.sections[i].base_address < max_address)) {
- if (image.sections[i].base_address < min_address) {
- /* clip addresses below */
- offset += min_address-image.sections[i].base_address;
- length -= offset;
- }
-
- if (image.sections[i].base_address + buf_cnt > max_address)
- length -= (image.sections[i].base_address + buf_cnt)-max_address;
-
- fastload[i].address = image.sections[i].base_address + offset;
- fastload[i].data = malloc(length);
- if (fastload[i].data == NULL) {
- free(buffer);
- command_print(CMD_CTX, "error allocating buffer for section (%" PRIu32 " bytes)",
- length);
- retval = ERROR_FAIL;
- break;
- }
- memcpy(fastload[i].data, buffer + offset, length);
- fastload[i].length = length;
-
- image_size += length;
- command_print(CMD_CTX, "%u bytes written at address 0x%8.8x",
- (unsigned int)length,
- ((unsigned int)(image.sections[i].base_address + offset)));
- }
-
- free(buffer);
- }
-
- if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
- command_print(CMD_CTX, "Loaded %" PRIu32 " bytes "
- "in %fs (%0.3f KiB/s)", image_size,
- duration_elapsed(&bench), duration_kbps(&bench, image_size));
-
- command_print(CMD_CTX,
- "WARNING: image has not been loaded to target!"
- "You can issue a 'fast_load' to finish loading.");
- }
-
- image_close(&image);
-
- if (retval != ERROR_OK)
- free_fastload();
-
- return retval;
-}
-
-COMMAND_HANDLER(handle_fast_load_command)
-{
- if (CMD_ARGC > 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (fastload == NULL) {
- LOG_ERROR("No image in memory");
- return ERROR_FAIL;
- }
- int i;
- int64_t ms = timeval_ms();
- int size = 0;
- int retval = ERROR_OK;
- for (i = 0; i < fastload_num; i++) {
- struct target *target = get_current_target(CMD_CTX);
- command_print(CMD_CTX, "Write to 0x%08x, length 0x%08x",
- (unsigned int)(fastload[i].address),
- (unsigned int)(fastload[i].length));
- retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
- if (retval != ERROR_OK)
- break;
- size += fastload[i].length;
- }
- if (retval == ERROR_OK) {
- int64_t after = timeval_ms();
- command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
- }
- return retval;
-}
-
-static const struct command_registration target_command_handlers[] = {
- {
- .name = "targets",
- .handler = handle_targets_command,
- .mode = COMMAND_ANY,
- .help = "change current default target (one parameter) "
- "or prints table of all targets (no parameters)",
- .usage = "[target]",
- },
- {
- .name = "target",
- .mode = COMMAND_CONFIG,
- .help = "configure target",
-
- .chain = target_subcommand_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int target_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, target_command_handlers);
-}
-
-static bool target_reset_nag = true;
-
-bool get_target_reset_nag(void)
-{
- return target_reset_nag;
-}
-
-COMMAND_HANDLER(handle_target_reset_nag)
-{
- return CALL_COMMAND_HANDLER(handle_command_parse_bool,
- &target_reset_nag, "Nag after each reset about options to improve "
- "performance");
-}
-
-COMMAND_HANDLER(handle_ps_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- char *display;
- if (target->state != TARGET_HALTED) {
- LOG_INFO("target not halted !!");
- return ERROR_OK;
- }
-
- if ((target->rtos) && (target->rtos->type)
- && (target->rtos->type->ps_command)) {
- display = target->rtos->type->ps_command(target);
- command_print(CMD_CTX, "%s", display);
- free(display);
- return ERROR_OK;
- } else {
- LOG_INFO("failed");
- return ERROR_TARGET_FAILURE;
- }
-}
-
-static void binprint(struct command_context *cmd_ctx, const char *text, const uint8_t *buf, int size)
-{
- if (text != NULL)
- command_print_sameline(cmd_ctx, "%s", text);
- for (int i = 0; i < size; i++)
- command_print_sameline(cmd_ctx, " %02x", buf[i]);
- command_print(cmd_ctx, " ");
-}
-
-COMMAND_HANDLER(handle_test_mem_access_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- uint32_t test_size;
- int retval = ERROR_OK;
-
- if (target->state != TARGET_HALTED) {
- LOG_INFO("target not halted !!");
- return ERROR_FAIL;
- }
-
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], test_size);
-
- /* Test reads */
- size_t num_bytes = test_size + 4;
-
- struct working_area *wa = NULL;
- retval = target_alloc_working_area(target, num_bytes, &wa);
- if (retval != ERROR_OK) {
- LOG_ERROR("Not enough working area");
- return ERROR_FAIL;
- }
-
- uint8_t *test_pattern = malloc(num_bytes);
-
- for (size_t i = 0; i < num_bytes; i++)
- test_pattern[i] = rand();
-
- retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern);
- if (retval != ERROR_OK) {
- LOG_ERROR("Test pattern write failed");
- goto out;
- }
-
- for (int host_offset = 0; host_offset <= 1; host_offset++) {
- for (int size = 1; size <= 4; size *= 2) {
- for (int offset = 0; offset < 4; offset++) {
- uint32_t count = test_size / size;
- size_t host_bufsiz = (count + 2) * size + host_offset;
- uint8_t *read_ref = malloc(host_bufsiz);
- uint8_t *read_buf = malloc(host_bufsiz);
-
- for (size_t i = 0; i < host_bufsiz; i++) {
- read_ref[i] = rand();
- read_buf[i] = read_ref[i];
- }
- command_print_sameline(CMD_CTX,
- "Test read %" PRIu32 " x %d @ %d to %saligned buffer: ", count,
- size, offset, host_offset ? "un" : "");
-
- struct duration bench;
- duration_start(&bench);
-
- retval = target_read_memory(target, wa->address + offset, size, count,
- read_buf + size + host_offset);
-
- duration_measure(&bench);
-
- if (retval == ERROR_TARGET_UNALIGNED_ACCESS) {
- command_print(CMD_CTX, "Unsupported alignment");
- goto next;
- } else if (retval != ERROR_OK) {
- command_print(CMD_CTX, "Memory read failed");
- goto next;
- }
-
- /* replay on host */
- memcpy(read_ref + size + host_offset, test_pattern + offset, count * size);
-
- /* check result */
- int result = memcmp(read_ref, read_buf, host_bufsiz);
- if (result == 0) {
- command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)",
- duration_elapsed(&bench),
- duration_kbps(&bench, count * size));
- } else {
- command_print(CMD_CTX, "Compare failed");
- binprint(CMD_CTX, "ref:", read_ref, host_bufsiz);
- binprint(CMD_CTX, "buf:", read_buf, host_bufsiz);
- }
-next:
- free(read_ref);
- free(read_buf);
- }
- }
- }
-
-out:
- free(test_pattern);
-
- if (wa != NULL)
- target_free_working_area(target, wa);
-
- /* Test writes */
- num_bytes = test_size + 4 + 4 + 4;
-
- retval = target_alloc_working_area(target, num_bytes, &wa);
- if (retval != ERROR_OK) {
- LOG_ERROR("Not enough working area");
- return ERROR_FAIL;
- }
-
- test_pattern = malloc(num_bytes);
-
- for (size_t i = 0; i < num_bytes; i++)
- test_pattern[i] = rand();
-
- for (int host_offset = 0; host_offset <= 1; host_offset++) {
- for (int size = 1; size <= 4; size *= 2) {
- for (int offset = 0; offset < 4; offset++) {
- uint32_t count = test_size / size;
- size_t host_bufsiz = count * size + host_offset;
- uint8_t *read_ref = malloc(num_bytes);
- uint8_t *read_buf = malloc(num_bytes);
- uint8_t *write_buf = malloc(host_bufsiz);
-
- for (size_t i = 0; i < host_bufsiz; i++)
- write_buf[i] = rand();
- command_print_sameline(CMD_CTX,
- "Test write %" PRIu32 " x %d @ %d from %saligned buffer: ", count,
- size, offset, host_offset ? "un" : "");
-
- retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX, "Test pattern write failed");
- goto nextw;
- }
-
- /* replay on host */
- memcpy(read_ref, test_pattern, num_bytes);
- memcpy(read_ref + size + offset, write_buf + host_offset, count * size);
-
- struct duration bench;
- duration_start(&bench);
-
- retval = target_write_memory(target, wa->address + size + offset, size, count,
- write_buf + host_offset);
-
- duration_measure(&bench);
-
- if (retval == ERROR_TARGET_UNALIGNED_ACCESS) {
- command_print(CMD_CTX, "Unsupported alignment");
- goto nextw;
- } else if (retval != ERROR_OK) {
- command_print(CMD_CTX, "Memory write failed");
- goto nextw;
- }
-
- /* read back */
- retval = target_read_memory(target, wa->address, 1, num_bytes, read_buf);
- if (retval != ERROR_OK) {
- command_print(CMD_CTX, "Test pattern write failed");
- goto nextw;
- }
-
- /* check result */
- int result = memcmp(read_ref, read_buf, num_bytes);
- if (result == 0) {
- command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)",
- duration_elapsed(&bench),
- duration_kbps(&bench, count * size));
- } else {
- command_print(CMD_CTX, "Compare failed");
- binprint(CMD_CTX, "ref:", read_ref, num_bytes);
- binprint(CMD_CTX, "buf:", read_buf, num_bytes);
- }
-nextw:
- free(read_ref);
- free(read_buf);
- }
- }
- }
-
- free(test_pattern);
-
- if (wa != NULL)
- target_free_working_area(target, wa);
- return retval;
-}
-
-static const struct command_registration target_exec_command_handlers[] = {
- {
- .name = "fast_load_image",
- .handler = handle_fast_load_image_command,
- .mode = COMMAND_ANY,
- .help = "Load image into server memory for later use by "
- "fast_load; primarily for profiling",
- .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] "
- "[min_address [max_length]]",
- },
- {
- .name = "fast_load",
- .handler = handle_fast_load_command,
- .mode = COMMAND_EXEC,
- .help = "loads active fast load image to current target "
- "- mainly for profiling purposes",
- .usage = "",
- },
- {
- .name = "profile",
- .handler = handle_profile_command,
- .mode = COMMAND_EXEC,
- .usage = "seconds filename [start end]",
- .help = "profiling samples the CPU PC",
- },
- /** @todo don't register virt2phys() unless target supports it */
- {
- .name = "virt2phys",
- .handler = handle_virt2phys_command,
- .mode = COMMAND_ANY,
- .help = "translate a virtual address into a physical address",
- .usage = "virtual_address",
- },
- {
- .name = "reg",
- .handler = handle_reg_command,
- .mode = COMMAND_EXEC,
- .help = "display (reread from target with \"force\") or set a register; "
- "with no arguments, displays all registers and their values",
- .usage = "[(register_number|register_name) [(value|'force')]]",
- },
- {
- .name = "poll",
- .handler = handle_poll_command,
- .mode = COMMAND_EXEC,
- .help = "poll target state; or reconfigure background polling",
- .usage = "['on'|'off']",
- },
- {
- .name = "wait_halt",
- .handler = handle_wait_halt_command,
- .mode = COMMAND_EXEC,
- .help = "wait up to the specified number of milliseconds "
- "(default 5000) for a previously requested halt",
- .usage = "[milliseconds]",
- },
- {
- .name = "halt",
- .handler = handle_halt_command,
- .mode = COMMAND_EXEC,
- .help = "request target to halt, then wait up to the specified"
- "number of milliseconds (default 5000) for it to complete",
- .usage = "[milliseconds]",
- },
- {
- .name = "resume",
- .handler = handle_resume_command,
- .mode = COMMAND_EXEC,
- .help = "resume target execution from current PC or address",
- .usage = "[address]",
- },
- {
- .name = "reset",
- .handler = handle_reset_command,
- .mode = COMMAND_EXEC,
- .usage = "[run|halt|init]",
- .help = "Reset all targets into the specified mode."
- "Default reset mode is run, if not given.",
- },
- {
- .name = "soft_reset_halt",
- .handler = handle_soft_reset_halt_command,
- .mode = COMMAND_EXEC,
- .usage = "",
- .help = "halt the target and do a soft reset",
- },
- {
- .name = "step",
- .handler = handle_step_command,
- .mode = COMMAND_EXEC,
- .help = "step one instruction from current PC or address",
- .usage = "[address]",
- },
- {
- .name = "mdw",
- .handler = handle_md_command,
- .mode = COMMAND_EXEC,
- .help = "display memory words",
- .usage = "['phys'] address [count]",
- },
- {
- .name = "mdh",
- .handler = handle_md_command,
- .mode = COMMAND_EXEC,
- .help = "display memory half-words",
- .usage = "['phys'] address [count]",
- },
- {
- .name = "mdb",
- .handler = handle_md_command,
- .mode = COMMAND_EXEC,
- .help = "display memory bytes",
- .usage = "['phys'] address [count]",
- },
- {
- .name = "mww",
- .handler = handle_mw_command,
- .mode = COMMAND_EXEC,
- .help = "write memory word",
- .usage = "['phys'] address value [count]",
- },
- {
- .name = "mwh",
- .handler = handle_mw_command,
- .mode = COMMAND_EXEC,
- .help = "write memory half-word",
- .usage = "['phys'] address value [count]",
- },
- {
- .name = "mwb",
- .handler = handle_mw_command,
- .mode = COMMAND_EXEC,
- .help = "write memory byte",
- .usage = "['phys'] address value [count]",
- },
- {
- .name = "bp",
- .handler = handle_bp_command,
- .mode = COMMAND_EXEC,
- .help = "list or set hardware or software breakpoint",
- .usage = "<address> [<asid>]<length> ['hw'|'hw_ctx']",
- },
- {
- .name = "rbp",
- .handler = handle_rbp_command,
- .mode = COMMAND_EXEC,
- .help = "remove breakpoint",
- .usage = "address",
- },
- {
- .name = "wp",
- .handler = handle_wp_command,
- .mode = COMMAND_EXEC,
- .help = "list (no params) or create watchpoints",
- .usage = "[address length [('r'|'w'|'a') value [mask]]]",
- },
- {
- .name = "rwp",
- .handler = handle_rwp_command,
- .mode = COMMAND_EXEC,
- .help = "remove watchpoint",
- .usage = "address",
- },
- {
- .name = "load_image",
- .handler = handle_load_image_command,
- .mode = COMMAND_EXEC,
- .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] "
- "[min_address] [max_length]",
- },
- {
- .name = "dump_image",
- .handler = handle_dump_image_command,
- .mode = COMMAND_EXEC,
- .usage = "filename address size",
- },
- {
- .name = "verify_image",
- .handler = handle_verify_image_command,
- .mode = COMMAND_EXEC,
- .usage = "filename [offset [type]]",
- },
- {
- .name = "test_image",
- .handler = handle_test_image_command,
- .mode = COMMAND_EXEC,
- .usage = "filename [offset [type]]",
- },
- {
- .name = "mem2array",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_mem2array,
- .help = "read 8/16/32 bit memory and return as a TCL array "
- "for script processing",
- .usage = "arrayname bitwidth address count",
- },
- {
- .name = "array2mem",
- .mode = COMMAND_EXEC,
- .jim_handler = jim_array2mem,
- .help = "convert a TCL array to memory locations "
- "and write the 8/16/32 bit values",
- .usage = "arrayname bitwidth address count",
- },
- {
- .name = "reset_nag",
- .handler = handle_target_reset_nag,
- .mode = COMMAND_ANY,
- .help = "Nag after each reset about options that could have been "
- "enabled to improve performance. ",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "ps",
- .handler = handle_ps_command,
- .mode = COMMAND_EXEC,
- .help = "list all tasks ",
- .usage = " ",
- },
- {
- .name = "test_mem_access",
- .handler = handle_test_mem_access_command,
- .mode = COMMAND_EXEC,
- .help = "Test the target's memory access functions",
- .usage = "size",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-static int target_register_user_commands(struct command_context *cmd_ctx)
-{
- int retval = ERROR_OK;
- retval = target_request_register_commands(cmd_ctx);
- if (retval != ERROR_OK)
- return retval;
-
- retval = trace_register_commands(cmd_ctx);
- if (retval != ERROR_OK)
- return retval;
-
-
- return register_commands(cmd_ctx, NULL, target_exec_command_handlers);
-}
diff --git a/src/target/target.h b/src/target/target.h
deleted file mode 100644
index 0cee117..0000000
--- a/src/target/target.h
+++ /dev/null
@@ -1,686 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * Copyright (C) 2011 by Broadcom Corporation *
- * Evan Hunter - ehunter@broadcom.com *
- * *
- * Copyright (C) ST-Ericsson SA 2011 *
- * michel.jaouen@stericsson.com : smp minimum support *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_TARGET_H
-#define OPENOCD_TARGET_TARGET_H
-
-#include <helper/list.h>
-
-struct reg;
-struct trace;
-struct command_context;
-struct breakpoint;
-struct watchpoint;
-struct mem_param;
-struct reg_param;
-struct target_list;
-struct gdb_fileio_info;
-
-/*
- * TARGET_UNKNOWN = 0: we don't know anything about the target yet
- * TARGET_RUNNING = 1: the target is executing user code
- * TARGET_HALTED = 2: the target is not executing code, and ready to talk to the
- * debugger. on an xscale it means that the debug handler is executing
- * TARGET_RESET = 3: the target is being held in reset (only a temporary state,
- * not sure how this is used with all the recent changes)
- * TARGET_DEBUG_RUNNING = 4: the target is running, but it is executing code on
- * behalf of the debugger (e.g. algorithm for flashing)
- *
- * also see: target_state_name();
- */
-
-enum target_state {
- TARGET_UNKNOWN = 0,
- TARGET_RUNNING = 1,
- TARGET_HALTED = 2,
- TARGET_RESET = 3,
- TARGET_DEBUG_RUNNING = 4,
-};
-
-enum nvp_assert {
- NVP_DEASSERT,
- NVP_ASSERT,
-};
-
-enum target_reset_mode {
- RESET_UNKNOWN = 0,
- RESET_RUN = 1, /* reset and let target run */
- RESET_HALT = 2, /* reset and halt target out of reset */
- RESET_INIT = 3, /* reset and halt target out of reset, then run init script */
-};
-
-enum target_debug_reason {
- DBG_REASON_DBGRQ = 0,
- DBG_REASON_BREAKPOINT = 1,
- DBG_REASON_WATCHPOINT = 2,
- DBG_REASON_WPTANDBKPT = 3,
- DBG_REASON_SINGLESTEP = 4,
- DBG_REASON_NOTHALTED = 5,
- DBG_REASON_EXIT = 6,
- DBG_REASON_UNDEFINED = 7,
-};
-
-enum target_endianness {
- TARGET_ENDIAN_UNKNOWN = 0,
- TARGET_BIG_ENDIAN = 1, TARGET_LITTLE_ENDIAN = 2
-};
-
-struct working_area {
- uint32_t address;
- uint32_t size;
- bool free;
- uint8_t *backup;
- struct working_area **user;
- struct working_area *next;
-};
-
-struct gdb_service {
- struct target *target;
- /* field for smp display */
- /* element 0 coreid currently displayed ( 1 till n) */
- /* element 1 coreid to be displayed at next resume 1 till n 0 means resume
- * all cores core displayed */
- int32_t core[2];
-};
-
-/* target back off timer */
-struct backoff_timer {
- int times;
- int count;
-};
-
-/* split target registers into multiple class */
-enum target_register_class {
- REG_CLASS_ALL,
- REG_CLASS_GENERAL,
-};
-
-/* target_type.h contains the full definition of struct target_type */
-struct target {
- struct target_type *type; /* target type definition (name, access functions) */
- const char *cmd_name; /* tcl Name of target */
- int target_number; /* DO NOT USE! field to be removed in 2010 */
- struct jtag_tap *tap; /* where on the jtag chain is this */
- int32_t coreid; /* which device on the TAP? */
-
- /**
- * Indicates whether this target has been examined.
- *
- * Do @b not access this field directly, use target_was_examined()
- * or target_set_examined().
- */
- bool examined;
-
- /**
- * true if the target is currently running a downloaded
- * "algorithm" instead of arbitrary user code. OpenOCD code
- * invoking algorithms is trusted to maintain correctness of
- * any cached state (e.g. for flash status), which arbitrary
- * code will have no reason to know about.
- */
- bool running_alg;
-
- struct target_event_action *event_action;
-
- int reset_halt; /* attempt resetting the CPU into the halted mode? */
- uint32_t working_area; /* working area (initialised RAM). Evaluated
- * upon first allocation from virtual/physical address. */
- bool working_area_virt_spec; /* virtual address specified? */
- uint32_t working_area_virt; /* virtual address */
- bool working_area_phys_spec; /* virtual address specified? */
- uint32_t working_area_phys; /* physical address */
- uint32_t working_area_size; /* size in bytes */
- uint32_t backup_working_area; /* whether the content of the working area has to be preserved */
- struct working_area *working_areas;/* list of allocated working areas */
- enum target_debug_reason debug_reason;/* reason why the target entered debug state */
- enum target_endianness endianness; /* target endianness */
- /* also see: target_state_name() */
- enum target_state state; /* the current backend-state (running, halted, ...) */
- struct reg_cache *reg_cache; /* the first register cache of the target (core regs) */
- struct breakpoint *breakpoints; /* list of breakpoints */
- struct watchpoint *watchpoints; /* list of watchpoints */
- struct trace *trace_info; /* generic trace information */
- struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */
- uint32_t dbg_msg_enabled; /* debug message status */
- void *arch_info; /* architecture specific information */
- struct target *next; /* next target in list */
-
- int display; /* display async info in telnet session. Do not display
- * lots of halted/resumed info when stepping in debugger. */
- bool halt_issued; /* did we transition to halted state? */
- int64_t halt_issued_time; /* Note time when halt was issued */
-
- bool dbgbase_set; /* By default the debug base is not set */
- uint32_t dbgbase; /* Really a Cortex-A specific option, but there is no
- * system in place to support target specific options
- * currently. */
- struct rtos *rtos; /* Instance of Real Time Operating System support */
- bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
- * and must be detected when symbols are offered */
- struct backoff_timer backoff;
- int smp; /* add some target attributes for smp support */
- struct target_list *head;
- /* the gdb service is there in case of smp, we have only one gdb server
- * for all smp target
- * the target attached to the gdb is changing dynamically by changing
- * gdb_service->target pointer */
- struct gdb_service *gdb_service;
-
- /* file-I/O information for host to do syscall */
- struct gdb_fileio_info *fileio_info;
-};
-
-struct target_list {
- struct target *target;
- struct target_list *next;
-};
-
-struct gdb_fileio_info {
- char *identifier;
- uint32_t param_1;
- uint32_t param_2;
- uint32_t param_3;
- uint32_t param_4;
-};
-
-/** Returns the instance-specific name of the specified target. */
-static inline const char *target_name(struct target *target)
-{
- return target->cmd_name;
-}
-
-const char *debug_reason_name(struct target *t);
-
-enum target_event {
-
- /* allow GDB to do stuff before others handle the halted event,
- * this is in lieu of defining ordering of invocation of events,
- * which would be more complicated
- *
- * Telling GDB to halt does not mean that the target stopped running,
- * simply that we're dropping out of GDB's waiting for step or continue.
- *
- * This can be useful when e.g. detecting power dropout.
- */
- TARGET_EVENT_GDB_HALT,
- TARGET_EVENT_HALTED, /* target entered debug state from normal execution or reset */
- TARGET_EVENT_RESUMED, /* target resumed to normal execution */
- TARGET_EVENT_RESUME_START,
- TARGET_EVENT_RESUME_END,
-
- TARGET_EVENT_GDB_START, /* debugger started execution (step/run) */
- TARGET_EVENT_GDB_END, /* debugger stopped execution (step/run) */
-
- TARGET_EVENT_RESET_START,
- TARGET_EVENT_RESET_ASSERT_PRE,
- TARGET_EVENT_RESET_ASSERT, /* C code uses this instead of SRST */
- TARGET_EVENT_RESET_ASSERT_POST,
- TARGET_EVENT_RESET_DEASSERT_PRE,
- TARGET_EVENT_RESET_DEASSERT_POST,
- TARGET_EVENT_RESET_HALT_PRE,
- TARGET_EVENT_RESET_HALT_POST,
- TARGET_EVENT_RESET_WAIT_PRE,
- TARGET_EVENT_RESET_WAIT_POST,
- TARGET_EVENT_RESET_INIT,
- TARGET_EVENT_RESET_END,
-
- TARGET_EVENT_DEBUG_HALTED, /* target entered debug state, but was executing on behalf of the debugger */
- TARGET_EVENT_DEBUG_RESUMED, /* target resumed to execute on behalf of the debugger */
-
- TARGET_EVENT_EXAMINE_START,
- TARGET_EVENT_EXAMINE_END,
-
- TARGET_EVENT_GDB_ATTACH,
- TARGET_EVENT_GDB_DETACH,
-
- TARGET_EVENT_GDB_FLASH_ERASE_START,
- TARGET_EVENT_GDB_FLASH_ERASE_END,
- TARGET_EVENT_GDB_FLASH_WRITE_START,
- TARGET_EVENT_GDB_FLASH_WRITE_END,
-
- TARGET_EVENT_TRACE_CONFIG,
-};
-
-struct target_event_action {
- enum target_event event;
- struct Jim_Interp *interp;
- struct Jim_Obj *body;
- int has_percent;
- struct target_event_action *next;
-};
-
-bool target_has_event_action(struct target *target, enum target_event event);
-
-struct target_event_callback {
- int (*callback)(struct target *target, enum target_event event, void *priv);
- void *priv;
- struct target_event_callback *next;
-};
-
-struct target_reset_callback {
- struct list_head list;
- void *priv;
- int (*callback)(struct target *target, enum target_reset_mode reset_mode, void *priv);
-};
-
-struct target_trace_callback {
- struct list_head list;
- void *priv;
- int (*callback)(struct target *target, size_t len, uint8_t *data, void *priv);
-};
-
-struct target_timer_callback {
- int (*callback)(void *priv);
- int time_ms;
- int periodic;
- bool removed;
- struct timeval when;
- void *priv;
- struct target_timer_callback *next;
-};
-
-int target_register_commands(struct command_context *cmd_ctx);
-int target_examine(void);
-
-int target_register_event_callback(
- int (*callback)(struct target *target,
- enum target_event event, void *priv),
- void *priv);
-int target_unregister_event_callback(
- int (*callback)(struct target *target,
- enum target_event event, void *priv),
- void *priv);
-
-int target_register_reset_callback(
- int (*callback)(struct target *target,
- enum target_reset_mode reset_mode, void *priv),
- void *priv);
-int target_unregister_reset_callback(
- int (*callback)(struct target *target,
- enum target_reset_mode reset_mode, void *priv),
- void *priv);
-
-int target_register_trace_callback(
- int (*callback)(struct target *target,
- size_t len, uint8_t *data, void *priv),
- void *priv);
-int target_unregister_trace_callback(
- int (*callback)(struct target *target,
- size_t len, uint8_t *data, void *priv),
- void *priv);
-
-/* Poll the status of the target, detect any error conditions and report them.
- *
- * Also note that this fn will clear such error conditions, so a subsequent
- * invocation will then succeed.
- *
- * These error conditions can be "sticky" error conditions. E.g. writing
- * to memory could be implemented as an open loop and if memory writes
- * fails, then a note is made of it, the error is sticky, but the memory
- * write loop still runs to completion. This improves performance in the
- * normal case as there is no need to verify that every single write succeed,
- * yet it is possible to detect error conditions.
- */
-int target_poll(struct target *target);
-int target_resume(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution);
-int target_halt(struct target *target);
-int target_call_event_callbacks(struct target *target, enum target_event event);
-int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode);
-int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data);
-
-/**
- * The period is very approximate, the callback can happen much more often
- * or much more rarely than specified
- */
-int target_register_timer_callback(int (*callback)(void *priv),
- int time_ms, int periodic, void *priv);
-int target_unregister_timer_callback(int (*callback)(void *priv), void *priv);
-int target_call_timer_callbacks(void);
-/**
- * Invoke this to ensure that e.g. polling timer callbacks happen before
- * a synchronous command completes.
- */
-int target_call_timer_callbacks_now(void);
-
-struct target *get_target_by_num(int num);
-struct target *get_current_target(struct command_context *cmd_ctx);
-struct target *get_target(const char *id);
-
-/**
- * Get the target type name.
- *
- * This routine is a wrapper for the target->type->name field.
- * Note that this is not an instance-specific name for his target.
- */
-const char *target_type_name(struct target *target);
-
-/**
- * Examine the specified @a target, letting it perform any
- * Initialisation that requires JTAG access.
- *
- * This routine is a wrapper for target->type->examine.
- */
-int target_examine_one(struct target *target);
-
-/** @returns @c true if target_set_examined() has been called. */
-static inline bool target_was_examined(struct target *target)
-{
- return target->examined;
-}
-
-/** Sets the @c examined flag for the given target. */
-/** Use in target->type->examine() after one-time setup is done. */
-static inline void target_set_examined(struct target *target)
-{
- target->examined = true;
-}
-
-/**
- * Add the @a breakpoint for @a target.
- *
- * This routine is a wrapper for target->type->add_breakpoint.
- */
-int target_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-/**
- * Add the @a ContextID breakpoint for @a target.
- *
- * This routine is a wrapper for target->type->add_context_breakpoint.
- */
-int target_add_context_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-/**
- * Add the @a ContextID & IVA breakpoint for @a target.
- *
- * This routine is a wrapper for target->type->add_hybrid_breakpoint.
- */
-int target_add_hybrid_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-/**
- * Remove the @a breakpoint for @a target.
- *
- * This routine is a wrapper for target->type->remove_breakpoint.
- */
-
-int target_remove_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-/**
- * Add the @a watchpoint for @a target.
- *
- * This routine is a wrapper for target->type->add_watchpoint.
- */
-int target_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint);
-/**
- * Remove the @a watchpoint for @a target.
- *
- * This routine is a wrapper for target->type->remove_watchpoint.
- */
-int target_remove_watchpoint(struct target *target,
- struct watchpoint *watchpoint);
-
-/**
- * Find out the just hit @a watchpoint for @a target.
- *
- * This routine is a wrapper for target->type->hit_watchpoint.
- */
-int target_hit_watchpoint(struct target *target,
- struct watchpoint **watchpoint);
-
-/**
- * Obtain the registers for GDB.
- *
- * This routine is a wrapper for target->type->get_gdb_reg_list.
- */
-int target_get_gdb_reg_list(struct target *target,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class);
-
-/**
- * Step the target.
- *
- * This routine is a wrapper for target->type->step.
- */
-int target_step(struct target *target,
- int current, uint32_t address, int handle_breakpoints);
-/**
- * Run an algorithm on the @a target given.
- *
- * This routine is a wrapper for target->type->run_algorithm.
- */
-int target_run_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_param,
- uint32_t entry_point, uint32_t exit_point,
- int timeout_ms, void *arch_info);
-
-/**
- * Starts an algorithm in the background on the @a target given.
- *
- * This routine is a wrapper for target->type->start_algorithm.
- */
-int target_start_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t entry_point, uint32_t exit_point,
- void *arch_info);
-
-/**
- * Wait for an algorithm on the @a target given.
- *
- * This routine is a wrapper for target->type->wait_algorithm.
- */
-int target_wait_algorithm(struct target *target,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t exit_point, int timeout_ms,
- void *arch_info);
-
-/**
- * This routine is a wrapper for asynchronous algorithms.
- *
- */
-int target_run_flash_async_algorithm(struct target *target,
- const uint8_t *buffer, uint32_t count, int block_size,
- int num_mem_params, struct mem_param *mem_params,
- int num_reg_params, struct reg_param *reg_params,
- uint32_t buffer_start, uint32_t buffer_size,
- uint32_t entry_point, uint32_t exit_point,
- void *arch_info);
-
-/**
- * Read @a count items of @a size bytes from the memory of @a target at
- * the @a address given.
- *
- * This routine is a wrapper for target->type->read_memory.
- */
-int target_read_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
-int target_read_phys_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
-/**
- * Write @a count items of @a size bytes to the memory of @a target at
- * the @a address given. @a address must be aligned to @a size
- * in target memory.
- *
- * The endianness is the same in the host and target memory for this
- * function.
- *
- * \todo TODO:
- * Really @a buffer should have been defined as "const void *" and
- * @a buffer should have been aligned to @a size in the host memory.
- *
- * This is not enforced via e.g. assert's today and e.g. the
- * target_write_buffer fn breaks this assumption.
- *
- * This routine is wrapper for target->type->write_memory.
- */
-int target_write_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-int target_write_phys_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
-
-/*
- * Write to target memory using the virtual address.
- *
- * Note that this fn is used to implement software breakpoints. Targets
- * can implement support for software breakpoints to memory marked as read
- * only by making this fn write to ram even if it is read only(MMU or
- * MPUs).
- *
- * It is sufficient to implement for writing a single word(16 or 32 in
- * ARM32/16 bit case) to write the breakpoint to ram.
- *
- * The target should also take care of "other things" to make sure that
- * software breakpoints can be written using this function. E.g.
- * when there is a separate instruction and data cache, this fn must
- * make sure that the instruction cache is synced up to the potential
- * code change that can happen as a result of the memory write(typically
- * by invalidating the cache).
- *
- * The high level wrapper fn in target.c will break down this memory write
- * request to multiple write requests to the target driver to e.g. guarantee
- * that writing 4 bytes to an aligned address happens with a single 32 bit
- * write operation, thus making this fn suitable to e.g. write to special
- * peripheral registers which do not support byte operations.
- */
-int target_write_buffer(struct target *target,
- uint32_t address, uint32_t size, const uint8_t *buffer);
-int target_read_buffer(struct target *target,
- uint32_t address, uint32_t size, uint8_t *buffer);
-int target_checksum_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t *crc);
-int target_blank_check_memory(struct target *target,
- uint32_t address, uint32_t size, uint32_t *blank);
-int target_wait_state(struct target *target, enum target_state state, int ms);
-
-/**
- * Obtain file-I/O information from target for GDB to do syscall.
- *
- * This routine is a wrapper for target->type->get_gdb_fileio_info.
- */
-int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info);
-
-/**
- * Pass GDB file-I/O response to target after finishing host syscall.
- *
- * This routine is a wrapper for target->type->gdb_fileio_end.
- */
-int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c);
-
-
-
-/** Return the *name* of this targets current state */
-const char *target_state_name(struct target *target);
-
-/** Return the *name* of a target event enumeration value */
-const char *target_event_name(enum target_event event);
-
-/** Return the *name* of a target reset reason enumeration value */
-const char *target_reset_mode_name(enum target_reset_mode reset_mode);
-
-/* DANGER!!!!!
- *
- * if "area" passed in to target_alloc_working_area() points to a memory
- * location that goes out of scope (e.g. a pointer on the stack), then
- * the caller of target_alloc_working_area() is responsible for invoking
- * target_free_working_area() before "area" goes out of scope.
- *
- * target_free_all_working_areas() will NULL out the "area" pointer
- * upon resuming or resetting the CPU.
- *
- */
-int target_alloc_working_area(struct target *target,
- uint32_t size, struct working_area **area);
-/* Same as target_alloc_working_area, except that no error is logged
- * when ERROR_TARGET_RESOURCE_NOT_AVAILABLE is returned.
- *
- * This allows the calling code to *try* to allocate target memory
- * and have a fallback to another behaviour(slower?).
- */
-int target_alloc_working_area_try(struct target *target,
- uint32_t size, struct working_area **area);
-int target_free_working_area(struct target *target, struct working_area *area);
-void target_free_all_working_areas(struct target *target);
-uint32_t target_get_working_area_avail(struct target *target);
-
-/**
- * Free all the resources allocated by targets and the target layer
- */
-void target_quit(void);
-
-extern struct target *all_targets;
-
-uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer);
-uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer);
-uint32_t target_buffer_get_u24(struct target *target, const uint8_t *buffer);
-uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer);
-void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value);
-void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value);
-void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value);
-void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value);
-
-void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, uint32_t count, uint64_t *dstbuf);
-void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf);
-void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf);
-void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_t count, const uint64_t *srcbuf);
-void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf);
-void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf);
-
-int target_read_u64(struct target *target, uint64_t address, uint64_t *value);
-int target_read_u32(struct target *target, uint32_t address, uint32_t *value);
-int target_read_u16(struct target *target, uint32_t address, uint16_t *value);
-int target_read_u8(struct target *target, uint32_t address, uint8_t *value);
-int target_write_u64(struct target *target, uint64_t address, uint64_t value);
-int target_write_u32(struct target *target, uint32_t address, uint32_t value);
-int target_write_u16(struct target *target, uint32_t address, uint16_t value);
-int target_write_u8(struct target *target, uint32_t address, uint8_t value);
-
-/* Issues USER() statements with target state information */
-int target_arch_state(struct target *target);
-
-void target_handle_event(struct target *t, enum target_event e);
-
-#define ERROR_TARGET_INVALID (-300)
-#define ERROR_TARGET_INIT_FAILED (-301)
-#define ERROR_TARGET_TIMEOUT (-302)
-#define ERROR_TARGET_NOT_HALTED (-304)
-#define ERROR_TARGET_FAILURE (-305)
-#define ERROR_TARGET_UNALIGNED_ACCESS (-306)
-#define ERROR_TARGET_DATA_ABORT (-307)
-#define ERROR_TARGET_RESOURCE_NOT_AVAILABLE (-308)
-#define ERROR_TARGET_TRANSLATION_FAULT (-309)
-#define ERROR_TARGET_NOT_RUNNING (-310)
-#define ERROR_TARGET_NOT_EXAMINED (-311)
-
-extern bool get_target_reset_nag(void);
-
-#endif /* OPENOCD_TARGET_TARGET_H */
diff --git a/src/target/target_request.c b/src/target/target_request.c
deleted file mode 100644
index 6ca204b..0000000
--- a/src/target/target_request.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include <helper/binarybuffer.h>
-
-#include "target.h"
-#include "target_request.h"
-#include "target_type.h"
-#include "trace.h"
-
-static bool got_message;
-
-bool target_got_message(void)
-{
- bool t = got_message;
- got_message = false;
- return t;
-}
-
-static int charmsg_mode;
-
-static int target_asciimsg(struct target *target, uint32_t length)
-{
- char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4);
- struct debug_msg_receiver *c = target->dbgmsg;
-
- target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t *)msg);
- msg[length] = 0;
-
- LOG_DEBUG("%s", msg);
-
- while (c) {
- command_print(c->cmd_ctx, "%s", msg);
- c = c->next;
- }
-
- return ERROR_OK;
-}
-
-static int target_charmsg(struct target *target, uint8_t msg)
-{
- LOG_USER_N("%c", msg);
-
- return ERROR_OK;
-}
-
-static int target_hexmsg(struct target *target, int size, uint32_t length)
-{
- uint8_t *data = malloc(DIV_ROUND_UP(length * size, 4) * 4);
- char line[128];
- int line_len;
- struct debug_msg_receiver *c = target->dbgmsg;
- uint32_t i;
-
- LOG_DEBUG("size: %i, length: %i", (int)size, (int)length);
-
- target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t *)data);
-
- line_len = 0;
- for (i = 0; i < length; i++) {
- switch (size) {
- case 4:
- line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i)));
- break;
- case 2:
- line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
- break;
- case 1:
- line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
- break;
- }
-
- if ((i%8 == 7) || (i == length - 1)) {
- LOG_DEBUG("%s", line);
-
- while (c) {
- command_print(c->cmd_ctx, "%s", line);
- c = c->next;
- }
- c = target->dbgmsg;
- line_len = 0;
- }
- }
-
- free(data);
-
- return ERROR_OK;
-}
-
-/* handle requests from the target received by a target specific
- * side-band channel (e.g. ARM7/9 DCC)
- */
-int target_request(struct target *target, uint32_t request)
-{
- target_req_cmd_t target_req_cmd = request & 0xff;
-
- assert(target->type->target_request_data);
-
- /* Record that we got a target message for back-off algorithm */
- got_message = true;
-
- if (charmsg_mode) {
- target_charmsg(target, target_req_cmd);
- return ERROR_OK;
- }
-
- switch (target_req_cmd) {
- case TARGET_REQ_TRACEMSG:
- trace_point(target, (request & 0xffffff00) >> 8);
- break;
- case TARGET_REQ_DEBUGMSG:
- if (((request & 0xff00) >> 8) == 0)
- target_asciimsg(target, (request & 0xffff0000) >> 16);
- else
- target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
- break;
- case TARGET_REQ_DEBUGCHAR:
- target_charmsg(target, (request & 0x00ff0000) >> 16);
- break;
-/* case TARGET_REQ_SEMIHOSTING:
- * break;
- */
- default:
- LOG_ERROR("unknown target request: %2.2x", target_req_cmd);
- break;
- }
-
- return ERROR_OK;
-}
-
-static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
-{
- struct debug_msg_receiver **p = &target->dbgmsg;
-
- if (target == NULL)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* see if there's already a list */
- if (*p) {
- /* find end of linked list */
- while ((*p)->next)
- p = &((*p)->next);
- p = &((*p)->next);
- }
-
- /* add new debug message receiver */
- (*p) = malloc(sizeof(struct debug_msg_receiver));
- (*p)->cmd_ctx = cmd_ctx;
- (*p)->next = NULL;
-
- /* enable callback */
- target->dbg_msg_enabled = 1;
-
- return ERROR_OK;
-}
-
-static struct debug_msg_receiver *find_debug_msg_receiver(struct command_context *cmd_ctx,
- struct target *target)
-{
- int do_all_targets = 0;
-
- /* if no target has been specified search all of them */
- if (target == NULL) {
- /* if no targets haven been specified */
- if (all_targets == NULL)
- return NULL;
-
- target = all_targets;
- do_all_targets = 1;
- }
-
- /* so we target != null */
- struct debug_msg_receiver **p = &target->dbgmsg;
- do {
- while (*p) {
- if ((*p)->cmd_ctx == cmd_ctx)
- return *p;
- p = &((*p)->next);
- }
-
- target = target->next;
- } while (target && do_all_targets);
-
- return NULL;
-}
-
-int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
-{
- struct debug_msg_receiver **p;
- struct debug_msg_receiver *c;
- int do_all_targets = 0;
-
- /* if no target has been specified search all of them */
- if (target == NULL) {
- /* if no targets haven been specified */
- if (all_targets == NULL)
- return ERROR_OK;
-
- target = all_targets;
- do_all_targets = 1;
- }
-
- do {
- p = &target->dbgmsg;
- c = *p;
- while (c) {
- struct debug_msg_receiver *next = c->next;
- if (c->cmd_ctx == cmd_ctx) {
- *p = next;
- free(c);
- if (*p == NULL) {
- /* disable callback */
- target->dbg_msg_enabled = 0;
- }
- return ERROR_OK;
- } else
- p = &(c->next);
- c = next;
- }
-
- target = target->next;
- } while (target && do_all_targets);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_target_request_debugmsgs_command)
-{
- struct target *target = get_current_target(CMD_CTX);
-
- int receiving = 0;
-
- if (target->type->target_request_data == NULL) {
- LOG_ERROR("Target %s does not support target requests", target_name(target));
- return ERROR_OK;
- }
-
- /* see if reciever is already registered */
- if (find_debug_msg_receiver(CMD_CTX, target) != NULL)
- receiving = 1;
-
- if (CMD_ARGC > 0) {
- if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg")) {
- /* don't register if this command context is already receiving */
- if (!receiving) {
- receiving = 1;
- add_debug_msg_receiver(CMD_CTX, target);
- }
- charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg");
- } else if (!strcmp(CMD_ARGV[0], "disable")) {
- /* no need to delete a receiver if none is registered */
- if (receiving) {
- receiving = 0;
- delete_debug_msg_receiver(CMD_CTX, target);
- }
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- command_print(CMD_CTX, "receiving debug messages from current target %s",
- (receiving) ? (charmsg_mode ? "charmsg" : "enabled") : "disabled");
- return ERROR_OK;
-}
-
-static const struct command_registration target_req_exec_command_handlers[] = {
- {
- .name = "debugmsgs",
- .handler = handle_target_request_debugmsgs_command,
- .mode = COMMAND_EXEC,
- .help = "display and/or modify reception of debug messages from target",
- .usage = "['enable'|'charmsg'|'disable']",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration target_req_command_handlers[] = {
- {
- .name = "target_request",
- .mode = COMMAND_ANY,
- .help = "target request command group",
- .usage = "",
- .chain = target_req_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int target_request_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, target_req_command_handlers);
-}
diff --git a/src/target/target_request.h b/src/target/target_request.h
deleted file mode 100644
index 1b13173..0000000
--- a/src/target/target_request.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_TARGET_REQUEST_H
-#define OPENOCD_TARGET_TARGET_REQUEST_H
-
-struct target;
-struct command_context;
-
-typedef enum target_req_cmd {
- TARGET_REQ_TRACEMSG,
- TARGET_REQ_DEBUGMSG,
- TARGET_REQ_DEBUGCHAR,
-/* TARGET_REQ_SEMIHOSTING, */
-} target_req_cmd_t;
-
-struct debug_msg_receiver {
- struct command_context *cmd_ctx;
- struct debug_msg_receiver *next;
-};
-
-int target_request(struct target *target, uint32_t request);
-int delete_debug_msg_receiver(struct command_context *cmd_ctx,
- struct target *target);
-int target_request_register_commands(struct command_context *cmd_ctx);
-/**
- * Read and clear the flag as to whether we got a message.
- *
- * This is used to implement the back-off algorithm on
- * sleeping in idle mode.
- */
-bool target_got_message(void);
-
-#endif /* OPENOCD_TARGET_TARGET_REQUEST_H */
diff --git a/src/target/target_type.h b/src/target/target_type.h
deleted file mode 100644
index 95c0fef..0000000
--- a/src/target/target_type.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007-2010 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 by Spencer Oliver *
- * spen@spen-soft.co.uk *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_TARGET_TYPE_H
-#define OPENOCD_TARGET_TARGET_TYPE_H
-
-#include <jim-nvp.h>
-
-struct target;
-
-/**
- * This holds methods shared between all instances of a given target
- * type. For example, all Cortex-M3 targets on a scan chain share
- * the same method table.
- */
-struct target_type {
- /**
- * Name of this type of target. Do @b not access this
- * field directly, use target_type_name() instead.
- */
- const char *name;
- const char *deprecated_name;
-
- /* poll current target status */
- int (*poll)(struct target *target);
- /* Invoked only from target_arch_state().
- * Issue USER() w/architecture specific status. */
- int (*arch_state)(struct target *target);
-
- /* target request support */
- int (*target_request_data)(struct target *target, uint32_t size, uint8_t *buffer);
-
- /* halt will log a warning, but return ERROR_OK if the target is already halted. */
- int (*halt)(struct target *target);
- /* See target.c target_resume() for documentation. */
- int (*resume)(struct target *target, int current, uint32_t address,
- int handle_breakpoints, int debug_execution);
- int (*step)(struct target *target, int current, uint32_t address,
- int handle_breakpoints);
-
- /* target reset control. assert reset can be invoked when OpenOCD and
- * the target is out of sync.
- *
- * A typical example is that the target was power cycled while OpenOCD
- * thought the target was halted or running.
- *
- * assert_reset() can therefore make no assumptions whatsoever about the
- * state of the target
- *
- * Before assert_reset() for the target is invoked, a TRST/tms and
- * chain validation is executed. TRST should not be asserted
- * during target assert unless there is no way around it due to
- * the way reset's are configured.
- *
- */
- int (*assert_reset)(struct target *target);
- /**
- * The implementation is responsible for polling the
- * target such that target->state reflects the
- * state correctly.
- *
- * Otherwise the following would fail, as there will not
- * be any "poll" invoked inbetween the "reset run" and
- * "halt".
- *
- * reset run; halt
- */
- int (*deassert_reset)(struct target *target);
- int (*soft_reset_halt)(struct target *target);
-
- /**
- * Target register access for GDB. Do @b not call this function
- * directly, use target_get_gdb_reg_list() instead.
- *
- * Danger! this function will succeed even if the target is running
- * and return a register list with dummy values.
- *
- * The reason is that GDB connection will fail without a valid register
- * list, however it is after GDB is connected that monitor commands can
- * be run to properly initialize the target
- */
- int (*get_gdb_reg_list)(struct target *target, struct reg **reg_list[],
- int *reg_list_size, enum target_register_class reg_class);
-
- /* target memory access
- * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
- * count: number of items of <size>
- */
-
- /**
- * Target memory read callback. Do @b not call this function
- * directly, use target_read_memory() instead.
- */
- int (*read_memory)(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer);
- /**
- * Target memory write callback. Do @b not call this function
- * directly, use target_write_memory() instead.
- */
- int (*write_memory)(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-
- /* Default implementation will do some fancy alignment to improve performance, target can override */
- int (*read_buffer)(struct target *target, uint32_t address,
- uint32_t size, uint8_t *buffer);
-
- /* Default implementation will do some fancy alignment to improve performance, target can override */
- int (*write_buffer)(struct target *target, uint32_t address,
- uint32_t size, const uint8_t *buffer);
-
- int (*checksum_memory)(struct target *target, uint32_t address,
- uint32_t count, uint32_t *checksum);
- int (*blank_check_memory)(struct target *target, uint32_t address,
- uint32_t count, uint32_t *blank);
-
- /*
- * target break-/watchpoint control
- * rw: 0 = write, 1 = read, 2 = access
- *
- * Target must be halted while this is invoked as this
- * will actually set up breakpoints on target.
- *
- * The breakpoint hardware will be set up upon adding the
- * first breakpoint.
- *
- * Upon GDB connection all breakpoints/watchpoints are cleared.
- */
- int (*add_breakpoint)(struct target *target, struct breakpoint *breakpoint);
- int (*add_context_breakpoint)(struct target *target, struct breakpoint *breakpoint);
- int (*add_hybrid_breakpoint)(struct target *target, struct breakpoint *breakpoint);
-
- /* remove breakpoint. hw will only be updated if the target
- * is currently halted.
- * However, this method can be invoked on unresponsive targets.
- */
- int (*remove_breakpoint)(struct target *target, struct breakpoint *breakpoint);
-
- /* add watchpoint ... see add_breakpoint() comment above. */
- int (*add_watchpoint)(struct target *target, struct watchpoint *watchpoint);
-
- /* remove watchpoint. hw will only be updated if the target
- * is currently halted.
- * However, this method can be invoked on unresponsive targets.
- */
- int (*remove_watchpoint)(struct target *target, struct watchpoint *watchpoint);
-
- /* Find out just hit watchpoint. After the target hits a watchpoint, the
- * information could assist gdb to locate where the modified/accessed memory is.
- */
- int (*hit_watchpoint)(struct target *target, struct watchpoint **hit_watchpoint);
-
- /**
- * Target algorithm support. Do @b not call this method directly,
- * use target_run_algorithm() instead.
- */
- int (*run_algorithm)(struct target *target, int num_mem_params,
- struct mem_param *mem_params, int num_reg_params,
- struct reg_param *reg_param, uint32_t entry_point,
- uint32_t exit_point, int timeout_ms, void *arch_info);
- int (*start_algorithm)(struct target *target, int num_mem_params,
- struct mem_param *mem_params, int num_reg_params,
- struct reg_param *reg_param, uint32_t entry_point,
- uint32_t exit_point, void *arch_info);
- int (*wait_algorithm)(struct target *target, int num_mem_params,
- struct mem_param *mem_params, int num_reg_params,
- struct reg_param *reg_param, uint32_t exit_point,
- int timeout_ms, void *arch_info);
-
- const struct command_registration *commands;
-
- /* called when target is created */
- int (*target_create)(struct target *target, Jim_Interp *interp);
-
- /* called for various config parameters */
- /* returns JIM_CONTINUE - if option not understood */
- /* otherwise: JIM_OK, or JIM_ERR, */
- int (*target_jim_configure)(struct target *target, Jim_GetOptInfo *goi);
-
- /* target commands specifically handled by the target */
- /* returns JIM_OK, or JIM_ERR, or JIM_CONTINUE - if option not understood */
- int (*target_jim_commands)(struct target *target, Jim_GetOptInfo *goi);
-
- /**
- * This method is used to perform target setup that requires
- * JTAG access.
- *
- * This may be called multiple times. It is called after the
- * scan chain is initially validated, or later after the target
- * is enabled by a JRC. It may also be called during some
- * parts of the reset sequence.
- *
- * For one-time initialization tasks, use target_was_examined()
- * and target_set_examined(). For example, probe the hardware
- * before setting up chip-specific state, and then set that
- * flag so you don't do that again.
- */
- int (*examine)(struct target *target);
-
- /* Set up structures for target.
- *
- * It is illegal to talk to the target at this stage as this fn is invoked
- * before the JTAG chain has been examined/verified
- * */
- int (*init_target)(struct command_context *cmd_ctx, struct target *target);
-
- /**
- * Free all the resources allocated by the target.
- *
- * @param target The target to deinit
- */
- void (*deinit_target)(struct target *target);
-
- /* translate from virtual to physical address. Default implementation is successful
- * no-op(i.e. virtual==physical).
- */
- int (*virt2phys)(struct target *target, uint32_t address, uint32_t *physical);
-
- /* read directly from physical memory. caches are bypassed and untouched.
- *
- * If the target does not support disabling caches, leaving them untouched,
- * then minimally the actual physical memory location will be read even
- * if cache states are unchanged, flushed, etc.
- *
- * Default implementation is to call read_memory.
- */
- int (*read_phys_memory)(struct target *target, uint32_t phys_address,
- uint32_t size, uint32_t count, uint8_t *buffer);
-
- /*
- * same as read_phys_memory, except that it writes...
- */
- int (*write_phys_memory)(struct target *target, uint32_t phys_address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-
- int (*mmu)(struct target *target, int *enabled);
-
- /* after reset is complete, the target can check if things are properly set up.
- *
- * This can be used to check if e.g. DCC memory writes have been enabled for
- * arm7/9 targets, which they really should except in the most contrived
- * circumstances.
- */
- int (*check_reset)(struct target *target);
-
- /* get GDB file-I/O parameters from target
- */
- int (*get_gdb_fileio_info)(struct target *target, struct gdb_fileio_info *fileio_info);
-
- /* pass GDB file-I/O response to target
- */
- int (*gdb_fileio_end)(struct target *target, int retcode, int fileio_errno, bool ctrl_c);
-
- /* do target profiling
- */
- int (*profiling)(struct target *target, uint32_t *samples,
- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
-};
-
-#endif /* OPENOCD_TARGET_TARGET_TYPE_H */
diff --git a/src/target/testee.c b/src/target/testee.c
deleted file mode 100644
index 5b6cced..0000000
--- a/src/target/testee.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-
-#include "target.h"
-#include "target_type.h"
-#include "hello.h"
-
-static const struct command_registration testee_command_handlers[] = {
- {
- .name = "testee",
- .mode = COMMAND_ANY,
- .help = "testee target commands",
-
- .chain = hello_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static int testee_init(struct command_context *cmd_ctx, struct target *target)
-{
- return ERROR_OK;
-}
-static int testee_poll(struct target *target)
-{
- if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))
- target->state = TARGET_HALTED;
- return ERROR_OK;
-}
-static int testee_halt(struct target *target)
-{
- target->state = TARGET_HALTED;
- return ERROR_OK;
-}
-static int testee_reset_assert(struct target *target)
-{
- target->state = TARGET_RESET;
- return ERROR_OK;
-}
-static int testee_reset_deassert(struct target *target)
-{
- target->state = TARGET_RUNNING;
- return ERROR_OK;
-}
-struct target_type testee_target = {
- .name = "testee",
- .commands = testee_command_handlers,
-
- .init_target = &testee_init,
- .poll = &testee_poll,
- .halt = &testee_halt,
- .assert_reset = &testee_reset_assert,
- .deassert_reset = &testee_reset_deassert,
-};
diff --git a/src/target/trace.c b/src/target/trace.c
deleted file mode 100644
index 63c477f..0000000
--- a/src/target/trace.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005, 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-#include "trace.h"
-#include "target.h"
-
-int trace_point(struct target *target, uint32_t number)
-{
- struct trace *trace = target->trace_info;
-
- LOG_DEBUG("tracepoint: %i", (int)number);
-
- if (number < trace->num_trace_points)
- trace->trace_points[number].hit_counter++;
-
- if (trace->trace_history_size) {
- trace->trace_history[trace->trace_history_pos++] = number;
- if (trace->trace_history_pos == trace->trace_history_size) {
- trace->trace_history_pos = 0;
- trace->trace_history_overflowed = 1;
- }
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_trace_point_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct trace *trace = target->trace_info;
-
- if (CMD_ARGC == 0) {
- uint32_t i;
-
- for (i = 0; i < trace->num_trace_points; i++) {
- command_print(CMD_CTX, "trace point 0x%8.8" PRIx32 " (%lld times hit)",
- trace->trace_points[i].address,
- (long long)trace->trace_points[i].hit_counter);
- }
-
- return ERROR_OK;
- }
-
- if (!strcmp(CMD_ARGV[0], "clear")) {
- if (trace->trace_points) {
- free(trace->trace_points);
- trace->trace_points = NULL;
- }
- trace->num_trace_points = 0;
- trace->trace_points_size = 0;
-
- return ERROR_OK;
- }
-
- /* resize array if necessary */
- if (!trace->trace_points || (trace->trace_points_size == trace->num_trace_points)) {
- trace->trace_points = realloc(trace->trace_points,
- sizeof(struct trace_point) * (trace->trace_points_size + 32));
- trace->trace_points_size += 32;
- }
-
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- trace->trace_points[trace->num_trace_points].address = address;
- trace->trace_points[trace->num_trace_points].hit_counter = 0;
- trace->num_trace_points++;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_trace_history_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct trace *trace = target->trace_info;
-
- if (CMD_ARGC > 0) {
- trace->trace_history_pos = 0;
- trace->trace_history_overflowed = 0;
-
- if (!strcmp(CMD_ARGV[0], "clear")) {
- /* clearing is implicit, we've just reset position anyway */
- return ERROR_OK;
- }
-
- if (trace->trace_history)
- free(trace->trace_history);
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], trace->trace_history_size);
- trace->trace_history = malloc(sizeof(uint32_t) * trace->trace_history_size);
-
- command_print(CMD_CTX, "new trace history size: %i", (int)(trace->trace_history_size));
- } else {
- uint32_t i;
- uint32_t first = 0;
- uint32_t last = trace->trace_history_pos;
-
- if (!trace->trace_history_size) {
- command_print(CMD_CTX, "trace history buffer is not allocated");
- return ERROR_OK;
- }
-
- if (trace->trace_history_overflowed) {
- first = trace->trace_history_pos;
- last = trace->trace_history_pos - 1;
- }
-
- for (i = first; (i % trace->trace_history_size) != last; i++) {
- if (trace->trace_history[i % trace->trace_history_size] < trace->num_trace_points) {
- uint32_t address;
- address = trace->trace_points[trace->trace_history[i % trace->trace_history_size]].address;
- command_print(CMD_CTX, "trace point %i: 0x%8.8" PRIx32 "",
- (int)(trace->trace_history[i % trace->trace_history_size]),
- address);
- } else
- command_print(CMD_CTX, "trace point %i: -not defined-",
- (int)(trace->trace_history[i % trace->trace_history_size]));
- }
- }
-
- return ERROR_OK;
-}
-
-static const struct command_registration trace_exec_command_handlers[] = {
- {
- .name = "history",
- .handler = handle_trace_history_command,
- .mode = COMMAND_EXEC,
- .help = "display trace history, clear history or set size",
- .usage = "['clear'|size]",
- },
- {
- .name = "point",
- .handler = handle_trace_point_command,
- .mode = COMMAND_EXEC,
- .help = "display trace points, clear list of trace points, "
- "or add new tracepoint at address",
- .usage = "['clear'|address]",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration trace_command_handlers[] = {
- {
- .name = "trace",
- .mode = COMMAND_EXEC,
- .help = "trace command group",
- .usage = "",
- .chain = trace_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int trace_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, trace_command_handlers);
-}
diff --git a/src/target/trace.h b/src/target/trace.h
deleted file mode 100644
index 2966bbd..0000000
--- a/src/target/trace.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_TRACE_H
-#define OPENOCD_TARGET_TRACE_H
-
-struct target;
-struct command_context;
-
-struct trace_point {
- uint32_t address;
- uint64_t hit_counter;
-};
-
-struct trace {
- uint32_t num_trace_points;
- uint32_t trace_points_size;
- struct trace_point *trace_points;
- uint32_t trace_history_size;
- uint32_t *trace_history;
- uint32_t trace_history_pos;
- int trace_history_overflowed;
-};
-
-/**
- * \todo This enum is one of the few things in this file related
- * to *hardware* tracing ... split such "real" tracing out from
- * the contrib/libdcc support.
- */
-typedef enum trace_status {
- TRACE_IDLE = 0x0,
- TRACE_RUNNING = 0x1,
- TRACE_TRIGGERED = 0x2,
- TRACE_COMPLETED = 0x4,
- TRACE_OVERFLOWED = 0x8,
-} trace_status_t;
-
-int trace_point(struct target *target, uint32_t number);
-int trace_register_commands(struct command_context *cmd_ctx);
-
-#define ERROR_TRACE_IMAGE_UNAVAILABLE (-1500)
-#define ERROR_TRACE_INSTRUCTION_UNAVAILABLE (-1501)
-
-#endif /* OPENOCD_TARGET_TRACE_H */
diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c
deleted file mode 100644
index 3f4c7aa..0000000
--- a/src/target/x86_32_common.c
+++ /dev/null
@@ -1,1497 +0,0 @@
-/*
- * Copyright(c) 2013 Intel Corporation.
- *
- * Adrian Burns (adrian.burns@intel.com)
- * Thomas Faust (thomas.faust@intel.com)
- * Ivan De Cesaris (ivan.de.cesaris@intel.com)
- * Julien Carreno (julien.carreno@intel.com)
- * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Contact Information:
- * Intel Corporation
- */
-
-/*
- * @file
- * This implements generic x86 32 bit memory and breakpoint operations.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <helper/log.h>
-
-#include "target.h"
-#include "target_type.h"
-#include "register.h"
-#include "breakpoints.h"
-#include "x86_32_common.h"
-
-static int set_debug_regs(struct target *t, uint32_t address,
- uint8_t bp_num, uint8_t bp_type, uint8_t bp_length);
-static int unset_debug_regs(struct target *t, uint8_t bp_num);
-static int read_mem(struct target *t, uint32_t size,
- uint32_t addr, uint8_t *buf);
-static int write_mem(struct target *t, uint32_t size,
- uint32_t addr, const uint8_t *buf);
-static int calcaddr_pyhsfromlin(struct target *t, uint32_t addr,
- uint32_t *physaddr);
-static int read_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, uint8_t *buffer);
-static int write_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-static int set_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-static int unset_breakpoint(struct target *target,
- struct breakpoint *breakpoint);
-static int set_watchpoint(struct target *target,
- struct watchpoint *watchpoint);
-static int unset_watchpoint(struct target *target,
- struct watchpoint *watchpoint);
-static int read_hw_reg_to_cache(struct target *t, int num);
-static int write_hw_reg_from_cache(struct target *t, int num);
-
-int x86_32_get_gdb_reg_list(struct target *t,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class)
-{
-
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- int i;
- *reg_list_size = x86_32->cache->num_regs;
- LOG_DEBUG("num_regs=%d, reg_class=%d", (*reg_list_size), reg_class);
- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
- if (*reg_list == NULL) {
- LOG_ERROR("%s out of memory", __func__);
- return ERROR_FAIL;
- }
- /* this will copy the values from our reg list to gdbs */
- for (i = 0; i < (*reg_list_size); i++) {
- (*reg_list)[i] = &x86_32->cache->reg_list[i];
- LOG_DEBUG("value %s = %08" PRIx32, x86_32->cache->reg_list[i].name,
- buf_get_u32(x86_32->cache->reg_list[i].value, 0, 32));
- }
- return ERROR_OK;
-}
-
-int x86_32_common_init_arch_info(struct target *t, struct x86_32_common *x86_32)
-{
- t->arch_info = x86_32;
- x86_32->common_magic = X86_32_COMMON_MAGIC;
- x86_32->num_hw_bpoints = MAX_DEBUG_REGS;
- x86_32->hw_break_list = calloc(x86_32->num_hw_bpoints,
- sizeof(struct x86_32_dbg_reg));
- if (x86_32->hw_break_list == NULL) {
- LOG_ERROR("%s out of memory", __func__);
- return ERROR_FAIL;
- }
- x86_32->curr_tap = t->tap;
- x86_32->fast_data_area = NULL;
- x86_32->flush = 1;
- x86_32->read_hw_reg_to_cache = read_hw_reg_to_cache;
- x86_32->write_hw_reg_from_cache = write_hw_reg_from_cache;
- return ERROR_OK;
-}
-
-int x86_32_common_mmu(struct target *t, int *enabled)
-{
- *enabled = true;
- return ERROR_OK;
-}
-
-int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- /*
- * We need to ignore 'segmentation' for now, as OpenOCD can't handle
- * segmented addresses.
- * In protected mode that is almost OK, as (almost) any known OS is using
- * flat segmentation. In real mode we use use the base of the DS segment,
- * as we don't know better ...
- */
-
- uint32_t cr0 = buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32);
- if (!(cr0 & CR0_PG)) {
- /* target halted in real mode */
- /* TODO: needs validation !!! */
- uint32_t dsb = buf_get_u32(x86_32->cache->reg_list[DSB].value, 0, 32);
- *physical = dsb + address;
-
- } else {
- /* target halted in protected mode */
- if (calcaddr_pyhsfromlin(t, address, physical) != ERROR_OK) {
- LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32,
- __func__, address);
- return ERROR_FAIL;
- }
- }
- return ERROR_OK;
-}
-
-int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- int error;
-
- error = read_phys_mem(t, phys_address, size, count, buffer);
- if (error != ERROR_OK)
- return error;
-
- /* After reading memory from target, we must replace software breakpoints
- * with the original instructions again.
- */
- struct swbp_mem_patch *iter = x86_32->swbbp_mem_patch_list;
- while (iter != NULL) {
- if (iter->physaddr >= phys_address && iter->physaddr < phys_address+(size*count)) {
- uint32_t offset = iter->physaddr - phys_address;
- buffer[offset] = iter->orig_byte;
- }
- iter = iter->next;
- }
- return ERROR_OK;
-}
-
-static int read_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- int retval = ERROR_OK;
- bool pg_disabled = false;
- LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p",
- phys_address, size, count, buffer);
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- if (!count || !buffer || !phys_address) {
- LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32,
- __func__, count, buffer, phys_address);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- /* to access physical memory, switch off the CR0.PG bit */
- if (x86_32->is_paging_enabled(t)) {
- retval = x86_32->disable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not disable paging", __func__);
- return retval;
- }
- pg_disabled = true;
- }
-
- for (uint32_t i = 0; i < count; i++) {
- switch (size) {
- case BYTE:
- retval = read_mem(t, size, phys_address + i, buffer + i);
- break;
- case WORD:
- retval = read_mem(t, size, phys_address + i * 2, buffer + i * 2);
- break;
- case DWORD:
- retval = read_mem(t, size, phys_address + i * 4, buffer + i * 4);
- break;
- default:
- LOG_ERROR("%s invalid read size", __func__);
- break;
- }
- }
- /* restore CR0.PG bit if needed (regardless of retval) */
- if (pg_disabled) {
- retval = x86_32->enable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not enable paging", __func__);
- return retval;
- }
- pg_disabled = true;
- }
- /* TODO: After reading memory from target, we must replace
- * software breakpoints with the original instructions again.
- * Solve this with the breakpoint fix
- */
- return retval;
-}
-
-int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- int error = ERROR_OK;
- uint8_t *newbuffer = NULL;
-
- check_not_halted(t);
- if (!count || !buffer || !phys_address) {
- LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32,
- __func__, count, buffer, phys_address);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- /* Before writing memory to target, we must update software breakpoints
- * with the new instructions and patch the memory buffer with the
- * breakpoint instruction.
- */
- newbuffer = malloc(size*count);
- if (newbuffer == NULL) {
- LOG_ERROR("%s out of memory", __func__);
- return ERROR_FAIL;
- }
- memcpy(newbuffer, buffer, size*count);
- struct swbp_mem_patch *iter = x86_32->swbbp_mem_patch_list;
- while (iter != NULL) {
- if (iter->physaddr >= phys_address && iter->physaddr < phys_address+(size*count)) {
- uint32_t offset = iter->physaddr - phys_address;
- newbuffer[offset] = SW_BP_OPCODE;
-
- /* update the breakpoint */
- struct breakpoint *pbiter = t->breakpoints;
- while (pbiter != NULL && pbiter->unique_id != iter->swbp_unique_id)
- pbiter = pbiter->next;
- if (pbiter)
- pbiter->orig_instr[0] = buffer[offset];
- }
- iter = iter->next;
- }
-
- error = write_phys_mem(t, phys_address, size, count, newbuffer);
- free(newbuffer);
- return error;
-}
-
-static int write_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- int retval = ERROR_OK;
- bool pg_disabled = false;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p",
- phys_address, size, count, buffer);
-
- check_not_halted(t);
- if (!count || !buffer || !phys_address) {
- LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32,
- __func__, count, buffer, phys_address);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- /* TODO: Before writing memory to target, we must update
- * software breakpoints with the new instructions and
- * patch the memory buffer with the breakpoint instruction.
- * Solve this with the breakpoint fix
- */
-
- /* to access physical memory, switch off the CR0.PG bit */
- if (x86_32->is_paging_enabled(t)) {
- retval = x86_32->disable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not disable paging", __func__);
- return retval;
- }
- pg_disabled = true;
- }
- for (uint32_t i = 0; i < count; i++) {
- switch (size) {
- case BYTE:
- retval = write_mem(t, size, phys_address + i, buffer + i);
- break;
- case WORD:
- retval = write_mem(t, size, phys_address + i * 2, buffer + i * 2);
- break;
- case DWORD:
- retval = write_mem(t, size, phys_address + i * 4, buffer + i * 4);
- break;
- default:
- LOG_DEBUG("invalid read size");
- break;
- }
- }
- /* restore CR0.PG bit if needed (regardless of retval) */
- if (pg_disabled) {
- retval = x86_32->enable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not enable paging", __func__);
- return retval;
- }
- }
- return retval;
-}
-
-static int read_mem(struct target *t, uint32_t size,
- uint32_t addr, uint8_t *buf)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
- bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D;
- int retval = x86_32->write_hw_reg(t, EAX, addr, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error write EAX", __func__);
- return retval;
- }
-
- switch (size) {
- case BYTE:
- if (use32)
- retval = x86_32->submit_instruction(t, MEMRDB32);
- else
- retval = x86_32->submit_instruction(t, MEMRDB16);
- break;
- case WORD:
- if (use32)
- retval = x86_32->submit_instruction(t, MEMRDH32);
- else
- retval = x86_32->submit_instruction(t, MEMRDH16);
- break;
- case DWORD:
- if (use32)
- retval = x86_32->submit_instruction(t, MEMRDW32);
- else
- retval = x86_32->submit_instruction(t, MEMRDW16);
- break;
- default:
- LOG_ERROR("%s invalid read mem size", __func__);
- break;
- }
-
- /* read_hw_reg() will write to 4 bytes (uint32_t)
- * Watch out, the buffer passed into read_mem() might be 1 or 2 bytes.
- */
- uint32_t regval;
- retval = x86_32->read_hw_reg(t, EDX, &regval, 0);
-
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error read EDX", __func__);
- return retval;
- }
- for (uint8_t i = 0; i < size; i++)
- buf[i] = (regval >> (i*8)) & 0x000000FF;
-
- retval = x86_32->transaction_status(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error on mem read", __func__);
- return retval;
- }
- return retval;
-}
-
-static int write_mem(struct target *t, uint32_t size,
- uint32_t addr, const uint8_t *buf)
-{
- uint32_t i = 0;
- uint32_t buf4bytes = 0;
- int retval = ERROR_OK;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- for (i = 0; i < size; ++i) {
- buf4bytes = buf4bytes << 8; /* first time we only shift 0s */
- buf4bytes += buf[(size-1)-i]; /* it was hard to write, should be hard to read! */
- }
- /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
- bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D;
- retval = x86_32->write_hw_reg(t, EAX, addr, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error write EAX", __func__);
- return retval;
- }
-
- /* write_hw_reg() will write to 4 bytes (uint32_t)
- * Watch out, the buffer passed into write_mem() might be 1 or 2 bytes.
- */
- retval = x86_32->write_hw_reg(t, EDX, buf4bytes, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error write EDX", __func__);
- return retval;
- }
- switch (size) {
- case BYTE:
- if (use32)
- retval = x86_32->submit_instruction(t, MEMWRB32);
- else
- retval = x86_32->submit_instruction(t, MEMWRB16);
- break;
- case WORD:
- if (use32)
- retval = x86_32->submit_instruction(t, MEMWRH32);
- else
- retval = x86_32->submit_instruction(t, MEMWRH16);
- break;
- case DWORD:
- if (use32)
- retval = x86_32->submit_instruction(t, MEMWRW32);
- else
- retval = x86_32->submit_instruction(t, MEMWRW16);
- break;
- default:
- LOG_ERROR("%s invalid write mem size", __func__);
- return ERROR_FAIL;
- }
- retval = x86_32->transaction_status(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error on mem write", __func__);
- return retval;
- }
- return retval;
-}
-
-int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, uint32_t *physaddr)
-{
- uint8_t entry_buffer[8];
-
- if (physaddr == NULL || t == NULL)
- return ERROR_FAIL;
-
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- /* The 'user-visible' CR0.PG should be set - otherwise the function shouldn't be called
- * (Don't check the CR0.PG on the target, this might be temporally disabled at this point)
- */
- uint32_t cr0 = buf_get_u32(x86_32->cache->reg_list[CR0].value, 0, 32);
- if (!(cr0 & CR0_PG)) {
- /* you are wrong in this function, never mind */
- *physaddr = addr;
- return ERROR_OK;
- }
-
- uint32_t cr4 = buf_get_u32(x86_32->cache->reg_list[CR4].value, 0, 32);
- bool isPAE = cr4 & 0x00000020; /* PAE - Physical Address Extension */
-
- uint32_t cr3 = buf_get_u32(x86_32->cache->reg_list[CR3].value, 0, 32);
- if (isPAE) {
- uint32_t pdpt_base = cr3 & 0xFFFFF000; /* lower 12 bits of CR3 must always be 0 */
- uint32_t pdpt_index = (addr & 0xC0000000) >> 30; /* A[31:30] index to PDPT */
- uint32_t pdpt_addr = pdpt_base + (8 * pdpt_index);
- if (x86_32_common_read_phys_mem(t, pdpt_addr, 4, 2, entry_buffer) != ERROR_OK) {
- LOG_ERROR("%s couldn't read page directory pointer table entry at 0x%08" PRIx32,
- __func__, pdpt_addr);
- return ERROR_FAIL;
- }
- uint64_t pdpt_entry = target_buffer_get_u64(t, entry_buffer);
- if (!(pdpt_entry & 0x0000000000000001)) {
- LOG_ERROR("%s page directory pointer table entry at 0x%08" PRIx32 " is not present",
- __func__, pdpt_addr);
- return ERROR_FAIL;
- }
-
- uint32_t pd_base = pdpt_entry & 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */
- uint32_t pd_index = (addr & 0x3FE00000) >> 21; /* A[29:21] index to PD entry with PAE */
- uint32_t pd_addr = pd_base + (8 * pd_index);
- if (x86_32_common_read_phys_mem(t, pd_addr, 4, 2, entry_buffer) != ERROR_OK) {
- LOG_ERROR("%s couldn't read page directory entry at 0x%08" PRIx32,
- __func__, pd_addr);
- return ERROR_FAIL;
- }
- uint64_t pd_entry = target_buffer_get_u64(t, entry_buffer);
- if (!(pd_entry & 0x0000000000000001)) {
- LOG_ERROR("%s page directory entry at 0x%08" PRIx32 " is not present",
- __func__, pd_addr);
- return ERROR_FAIL;
- }
-
- /* PS bit in PD entry is indicating 4KB or 2MB page size */
- if (pd_entry & 0x0000000000000080) {
-
- uint32_t page_base = (uint32_t)(pd_entry & 0x00000000FFE00000); /* [31:21] */
- uint32_t offset = addr & 0x001FFFFF; /* [20:0] */
- *physaddr = page_base + offset;
- return ERROR_OK;
-
- } else {
-
- uint32_t pt_base = (uint32_t)(pd_entry & 0x00000000FFFFF000); /*[31:12]*/
- uint32_t pt_index = (addr & 0x001FF000) >> 12; /*[20:12]*/
- uint32_t pt_addr = pt_base + (8 * pt_index);
- if (x86_32_common_read_phys_mem(t, pt_addr, 4, 2, entry_buffer) != ERROR_OK) {
- LOG_ERROR("%s couldn't read page table entry at 0x%08" PRIx32, __func__, pt_addr);
- return ERROR_FAIL;
- }
- uint64_t pt_entry = target_buffer_get_u64(t, entry_buffer);
- if (!(pt_entry & 0x0000000000000001)) {
- LOG_ERROR("%s page table entry at 0x%08" PRIx32 " is not present", __func__, pt_addr);
- return ERROR_FAIL;
- }
-
- uint32_t page_base = (uint32_t)(pt_entry & 0x00000000FFFFF000); /*[31:12]*/
- uint32_t offset = addr & 0x00000FFF; /*[11:0]*/
- *physaddr = page_base + offset;
- return ERROR_OK;
- }
- } else {
- uint32_t pd_base = cr3 & 0xFFFFF000; /* lower 12 bits of CR3 must always be 0 */
- uint32_t pd_index = (addr & 0xFFC00000) >> 22; /* A[31:22] index to PD entry */
- uint32_t pd_addr = pd_base + (4 * pd_index);
- if (x86_32_common_read_phys_mem(t, pd_addr, 4, 1, entry_buffer) != ERROR_OK) {
- LOG_ERROR("%s couldn't read page directory entry at 0x%08" PRIx32, __func__, pd_addr);
- return ERROR_FAIL;
- }
- uint32_t pd_entry = target_buffer_get_u32(t, entry_buffer);
- if (!(pd_entry & 0x00000001)) {
- LOG_ERROR("%s page directory entry at 0x%08" PRIx32 " is not present", __func__, pd_addr);
- return ERROR_FAIL;
- }
-
- /* Bit 7 in page directory entry is page size.
- */
- if (pd_entry & 0x00000080) {
- /* 4MB pages */
- uint32_t page_base = pd_entry & 0xFFC00000;
- *physaddr = page_base + (addr & 0x003FFFFF);
-
- } else {
- /* 4KB pages */
- uint32_t pt_base = pd_entry & 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */
- uint32_t pt_index = (addr & 0x003FF000) >> 12; /* A[21:12] index to page table entry */
- uint32_t pt_addr = pt_base + (4 * pt_index);
- if (x86_32_common_read_phys_mem(t, pt_addr, 4, 1, entry_buffer) != ERROR_OK) {
- LOG_ERROR("%s couldn't read page table entry at 0x%08" PRIx32, __func__, pt_addr);
- return ERROR_FAIL;
- }
- uint32_t pt_entry = target_buffer_get_u32(t, entry_buffer);
- if (!(pt_entry & 0x00000001)) {
- LOG_ERROR("%s page table entry at 0x%08" PRIx32 " is not present", __func__, pt_addr);
- return ERROR_FAIL;
- }
- uint32_t page_base = pt_entry & 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */
- *physaddr = page_base + (addr & 0x00000FFF); /* A[11:0] offset to 4KB page in linear address */
- }
- }
- return ERROR_OK;
-}
-
-int x86_32_common_read_memory(struct target *t, uint32_t addr,
- uint32_t size, uint32_t count, uint8_t *buf)
-{
- int retval = ERROR_OK;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p",
- addr, size, count, buf);
- check_not_halted(t);
- if (!count || !buf || !addr) {
- LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32,
- __func__, count, buf, addr);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- if (x86_32->is_paging_enabled(t)) {
- /* all memory accesses from debugger must be physical (CR0.PG == 0)
- * conversion to physical address space needed
- */
- retval = x86_32->disable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not disable paging", __func__);
- return retval;
- }
- uint32_t physaddr = 0;
- if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) {
- LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, addr);
- retval = ERROR_FAIL;
- }
- /* TODO: !!! Watch out for page boundaries
- * for every 4kB, the physical address has to be re-calculated
- * This should be fixed together with bulk memory reads
- */
-
- if (retval == ERROR_OK
- && x86_32_common_read_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) {
- LOG_ERROR("%s failed to read memory from physical address 0x%08" PRIx32, __func__, physaddr);
- retval = ERROR_FAIL;
- }
- /* restore PG bit if it was cleared prior (regardless of retval) */
- retval = x86_32->enable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not enable paging", __func__);
- return retval;
- }
- } else {
- /* paging is off - linear address is physical address */
- if (x86_32_common_read_phys_mem(t, addr, size, count, buf) != ERROR_OK) {
- LOG_ERROR("%s failed to read memory from address 0%08" PRIx32, __func__, addr);
- retval = ERROR_FAIL;
- }
- }
-
- return retval;
-}
-
-int x86_32_common_write_memory(struct target *t, uint32_t addr,
- uint32_t size, uint32_t count, const uint8_t *buf)
-{
- int retval = ERROR_OK;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p",
- addr, size, count, buf);
- check_not_halted(t);
- if (!count || !buf || !addr) {
- LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32,
- __func__, count, buf, addr);
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- if (x86_32->is_paging_enabled(t)) {
- /* all memory accesses from debugger must be physical (CR0.PG == 0)
- * conversion to physical address space needed
- */
- retval = x86_32->disable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not disable paging", __func__);
- return retval;
- }
- uint32_t physaddr = 0;
- if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) {
- LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32,
- __func__, addr);
- retval = ERROR_FAIL;
- }
- /* TODO: !!! Watch out for page boundaries
- * for every 4kB, the physical address has to be re-calculated
- * This should be fixed together with bulk memory reads
- */
- if (retval == ERROR_OK
- && x86_32_common_write_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) {
- LOG_ERROR("%s failed to write memory to physical address 0x%08" PRIx32,
- __func__, physaddr);
- retval = ERROR_FAIL;
- }
- /* restore PG bit if it was cleared prior (regardless of retval) */
- retval = x86_32->enable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not enable paging", __func__);
- return retval;
- }
- } else {
-
- /* paging is off - linear address is physical address */
- if (x86_32_common_write_phys_mem(t, addr, size, count, buf) != ERROR_OK) {
- LOG_ERROR("%s failed to write memory to address 0x%08" PRIx32,
- __func__, addr);
- retval = ERROR_FAIL;
- }
- }
- return retval;
-}
-
-int x86_32_common_read_io(struct target *t, uint32_t addr,
- uint32_t size, uint8_t *buf)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
- bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D;
- int retval = ERROR_FAIL;
- bool pg_disabled = false;
- LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", buf=%p", addr, size, buf);
- check_not_halted(t);
- if (!buf || !addr) {
- LOG_ERROR("%s invalid params buf=%p, addr=%08" PRIx32, __func__, buf, addr);
- return retval;
- }
- retval = x86_32->write_hw_reg(t, EDX, addr, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error EDX write", __func__);
- return retval;
- }
- /* to access physical memory, switch off the CR0.PG bit */
- if (x86_32->is_paging_enabled(t)) {
- retval = x86_32->disable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not disable paging", __func__);
- return retval;
- }
- pg_disabled = true;
- }
- switch (size) {
- case BYTE:
- if (use32)
- retval = x86_32->submit_instruction(t, IORDB32);
- else
- retval = x86_32->submit_instruction(t, IORDB16);
- break;
- case WORD:
- if (use32)
- retval = x86_32->submit_instruction(t, IORDH32);
- else
- retval = x86_32->submit_instruction(t, IORDH16);
- break;
- case DWORD:
- if (use32)
- retval = x86_32->submit_instruction(t, IORDW32);
- else
- retval = x86_32->submit_instruction(t, IORDW16);
- break;
- default:
- LOG_ERROR("%s invalid read io size", __func__);
- return ERROR_FAIL;
- }
- /* restore CR0.PG bit if needed */
- if (pg_disabled) {
- retval = x86_32->enable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not enable paging", __func__);
- return retval;
- }
- pg_disabled = false;
- }
- uint32_t regval = 0;
- retval = x86_32->read_hw_reg(t, EAX, &regval, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error on read EAX", __func__);
- return retval;
- }
- for (uint8_t i = 0; i < size; i++)
- buf[i] = (regval >> (i*8)) & 0x000000FF;
- retval = x86_32->transaction_status(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error on io read", __func__);
- return retval;
- }
- return retval;
-}
-
-int x86_32_common_write_io(struct target *t, uint32_t addr,
- uint32_t size, const uint8_t *buf)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
- bool use32 = (buf_get_u32(x86_32->cache->reg_list[CSAR].value, 0, 32)) & CSAR_D;
- LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", buf=%p", addr, size, buf);
- check_not_halted(t);
- int retval = ERROR_FAIL;
- bool pg_disabled = false;
- if (!buf || !addr) {
- LOG_ERROR("%s invalid params buf=%p, addr=0x%08" PRIx32, __func__, buf, addr);
- return retval;
- }
- /* no do the write */
- retval = x86_32->write_hw_reg(t, EDX, addr, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error on EDX write", __func__);
- return retval;
- }
- uint32_t regval = 0;
- for (uint8_t i = 0; i < size; i++)
- regval += (buf[i] << (i*8));
- retval = x86_32->write_hw_reg(t, EAX, regval, 0);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error on EAX write", __func__);
- return retval;
- }
- /* to access physical memory, switch off the CR0.PG bit */
- if (x86_32->is_paging_enabled(t)) {
- retval = x86_32->disable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not disable paging", __func__);
- return retval;
- }
- pg_disabled = true;
- }
- switch (size) {
- case BYTE:
- if (use32)
- retval = x86_32->submit_instruction(t, IOWRB32);
- else
- retval = x86_32->submit_instruction(t, IOWRB16);
- break;
- case WORD:
- if (use32)
- retval = x86_32->submit_instruction(t, IOWRH32);
- else
- retval = x86_32->submit_instruction(t, IOWRH16);
- break;
- case DWORD:
- if (use32)
- retval = x86_32->submit_instruction(t, IOWRW32);
- else
- retval = x86_32->submit_instruction(t, IOWRW16);
- break;
- default:
- LOG_ERROR("%s invalid write io size", __func__);
- return ERROR_FAIL;
- }
- /* restore CR0.PG bit if needed */
- if (pg_disabled) {
- retval = x86_32->enable_paging(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s could not enable paging", __func__);
- return retval;
- }
- pg_disabled = false;
- }
- retval = x86_32->transaction_status(t);
- if (retval != ERROR_OK) {
- LOG_ERROR("%s error on io write", __func__);
- return retval;
- }
- return retval;
-}
-
-int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp)
-{
- check_not_halted(t);
- /* set_watchpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all
- * hardware registers are gone
- */
- return set_watchpoint(t, wp);
-}
-
-int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp)
-{
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- if (wp->set)
- unset_watchpoint(t, wp);
- return ERROR_OK;
-}
-
-int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp)
-{
- LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address);
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- /* set_breakpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all
- * hardware registers are gone (for hardware breakpoints)
- */
- return set_breakpoint(t, bp);
-}
-
-int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp)
-{
- LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address);
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- if (bp->set)
- unset_breakpoint(t, bp);
-
- return ERROR_OK;
-}
-
-static int set_debug_regs(struct target *t, uint32_t address,
- uint8_t bp_num, uint8_t bp_type, uint8_t bp_length)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("addr=0x%08" PRIx32 ", bp_num=%" PRIu8 ", bp_type=%" PRIu8 ", pb_length=%" PRIu8,
- address, bp_num, bp_type, bp_length);
-
- /* DR7 - set global enable */
- uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32);
-
- if (bp_length != 1 && bp_length != 2 && bp_length != 4)
- return ERROR_FAIL;
-
- if (DR7_BP_FREE(dr7, bp_num))
- DR7_GLOBAL_ENABLE(dr7, bp_num);
- else {
- LOG_ERROR("%s dr7 error, already enabled, val=%08" PRIx32, __func__, dr7);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- switch (bp_type) {
- case 0:
- /* 00 - only on instruction execution */
- DR7_SET_EXE(dr7, bp_num);
- DR7_SET_LENGTH(dr7, bp_num, bp_length);
- break;
- case 1:
- /* 01 - only on data writes */
- DR7_SET_WRITE(dr7, bp_num);
- DR7_SET_LENGTH(dr7, bp_num, bp_length);
- break;
- case 2:
- /* 10 UNSUPPORTED - an I/O read and I/O write */
- LOG_ERROR("%s unsupported feature bp_type=%d", __func__, bp_type);
- return ERROR_FAIL;
- break;
- case 3:
- /* on data read or data write */
- DR7_SET_ACCESS(dr7, bp_num);
- DR7_SET_LENGTH(dr7, bp_num, bp_length);
- break;
- default:
- LOG_ERROR("%s invalid request [only 0-3] bp_type=%d", __func__, bp_type);
- return ERROR_FAIL;
- }
-
- /* update regs in the reg cache ready to be written to hardware
- * when we exit PM
- */
- buf_set_u32(x86_32->cache->reg_list[bp_num+DR0].value, 0, 32, address);
- x86_32->cache->reg_list[bp_num+DR0].dirty = 1;
- x86_32->cache->reg_list[bp_num+DR0].valid = 1;
- buf_set_u32(x86_32->cache->reg_list[DR6].value, 0, 32, PM_DR6);
- x86_32->cache->reg_list[DR6].dirty = 1;
- x86_32->cache->reg_list[DR6].valid = 1;
- buf_set_u32(x86_32->cache->reg_list[DR7].value, 0, 32, dr7);
- x86_32->cache->reg_list[DR7].dirty = 1;
- x86_32->cache->reg_list[DR7].valid = 1;
- return ERROR_OK;
-}
-
-static int unset_debug_regs(struct target *t, uint8_t bp_num)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("bp_num=%" PRIu8, bp_num);
-
- uint32_t dr7 = buf_get_u32(x86_32->cache->reg_list[DR7].value, 0, 32);
-
- if (!(DR7_BP_FREE(dr7, bp_num))) {
- DR7_GLOBAL_DISABLE(dr7, bp_num);
- } else {
- LOG_ERROR("%s dr7 error, not enabled, val=0x%08" PRIx32, __func__, dr7);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- /* this will clear rw and len bits */
- DR7_RESET_RWLEN_BITS(dr7, bp_num);
-
- /* update regs in the reg cache ready to be written to hardware
- * when we exit PM
- */
- buf_set_u32(x86_32->cache->reg_list[bp_num+DR0].value, 0, 32, 0);
- x86_32->cache->reg_list[bp_num+DR0].dirty = 1;
- x86_32->cache->reg_list[bp_num+DR0].valid = 1;
- buf_set_u32(x86_32->cache->reg_list[DR6].value, 0, 32, PM_DR6);
- x86_32->cache->reg_list[DR6].dirty = 1;
- x86_32->cache->reg_list[DR6].valid = 1;
- buf_set_u32(x86_32->cache->reg_list[DR7].value, 0, 32, dr7);
- x86_32->cache->reg_list[DR7].dirty = 1;
- x86_32->cache->reg_list[DR7].valid = 1;
- return ERROR_OK;
-}
-
-static int set_hwbp(struct target *t, struct breakpoint *bp)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list;
- uint8_t hwbp_num = 0;
-
- while (debug_reg_list[hwbp_num].used && (hwbp_num < x86_32->num_hw_bpoints))
- hwbp_num++;
- if (hwbp_num >= x86_32->num_hw_bpoints) {
- LOG_ERROR("%s no free hw breakpoint bpid=0x%" PRIx32, __func__, bp->unique_id);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- if (set_debug_regs(t, bp->address, hwbp_num, DR7_BP_EXECUTE, 1) != ERROR_OK)
- return ERROR_FAIL;
- bp->set = hwbp_num + 1;
- debug_reg_list[hwbp_num].used = 1;
- debug_reg_list[hwbp_num].bp_value = bp->address;
- LOG_USER("%s hardware breakpoint %" PRIu32 " set at 0x%08" PRIx32 " (hwreg=%" PRIu8 ")", __func__,
- bp->unique_id, debug_reg_list[hwbp_num].bp_value, hwbp_num);
- return ERROR_OK;
-}
-
-static int unset_hwbp(struct target *t, struct breakpoint *bp)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list;
- int hwbp_num = bp->set - 1;
-
- if ((hwbp_num < 0) || (hwbp_num >= x86_32->num_hw_bpoints)) {
- LOG_ERROR("%s invalid breakpoint number=%d, bpid=%" PRIu32,
- __func__, hwbp_num, bp->unique_id);
- return ERROR_OK;
- }
-
- if (unset_debug_regs(t, hwbp_num) != ERROR_OK)
- return ERROR_FAIL;
- debug_reg_list[hwbp_num].used = 0;
- debug_reg_list[hwbp_num].bp_value = 0;
-
- LOG_USER("%s hardware breakpoint %" PRIu32 " removed from 0x%08" PRIx32 " (hwreg=%d)",
- __func__, bp->unique_id, bp->address, hwbp_num);
- return ERROR_OK;
-}
-
-static int set_swbp(struct target *t, struct breakpoint *bp)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("id %" PRIx32, bp->unique_id);
- uint32_t physaddr;
- uint8_t opcode = SW_BP_OPCODE;
- uint8_t readback;
-
- if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK)
- return ERROR_FAIL;
- if (read_phys_mem(t, physaddr, 1, 1, bp->orig_instr))
- return ERROR_FAIL;
-
- LOG_DEBUG("set software breakpoint - orig byte=0x%02" PRIx8 "", *bp->orig_instr);
-
- /* just write the instruction trap byte */
- if (write_phys_mem(t, physaddr, 1, 1, &opcode))
- return ERROR_FAIL;
-
- /* verify that this is not invalid/read-only memory */
- if (read_phys_mem(t, physaddr, 1, 1, &readback))
- return ERROR_FAIL;
-
- if (readback != SW_BP_OPCODE) {
- LOG_ERROR("%s software breakpoint error at 0x%08" PRIx32 ", check memory",
- __func__, bp->address);
- LOG_ERROR("%s readback=0x%02" PRIx8 " orig=0x%02" PRIx8 "",
- __func__, readback, *bp->orig_instr);
- return ERROR_FAIL;
- }
- bp->set = SW_BP_OPCODE; /* just non 0 */
-
- /* add the memory patch */
- struct swbp_mem_patch *new_patch = malloc(sizeof(struct swbp_mem_patch));
- if (new_patch == NULL) {
- LOG_ERROR("%s out of memory", __func__);
- return ERROR_FAIL;
- }
- new_patch->next = NULL;
- new_patch->orig_byte = *bp->orig_instr;
- new_patch->physaddr = physaddr;
- new_patch->swbp_unique_id = bp->unique_id;
-
- struct swbp_mem_patch *addto = x86_32->swbbp_mem_patch_list;
- if (addto == NULL)
- x86_32->swbbp_mem_patch_list = new_patch;
- else {
- while (addto->next != NULL)
- addto = addto->next;
- addto->next = new_patch;
- }
- LOG_USER("%s software breakpoint %" PRIu32 " set at 0x%08" PRIx32,
- __func__, bp->unique_id, bp->address);
- return ERROR_OK;
-}
-
-static int unset_swbp(struct target *t, struct breakpoint *bp)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("id %" PRIx32, bp->unique_id);
- uint32_t physaddr;
- uint8_t current_instr;
-
- /* check that user program has not modified breakpoint instruction */
- if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK)
- return ERROR_FAIL;
- if (read_phys_mem(t, physaddr, 1, 1, &current_instr))
- return ERROR_FAIL;
-
- if (current_instr == SW_BP_OPCODE) {
- if (write_phys_mem(t, physaddr, 1, 1, bp->orig_instr))
- return ERROR_FAIL;
- } else {
- LOG_ERROR("%s software breakpoint remove error at 0x%08" PRIx32 ", check memory",
- __func__, bp->address);
- LOG_ERROR("%s current=0x%02" PRIx8 " orig=0x%02" PRIx8 "",
- __func__, current_instr, *bp->orig_instr);
- return ERROR_FAIL;
- }
-
- /* remove from patch */
- struct swbp_mem_patch *iter = x86_32->swbbp_mem_patch_list;
- if (iter != NULL) {
- if (iter->swbp_unique_id == bp->unique_id) {
- /* it's the first item */
- x86_32->swbbp_mem_patch_list = iter->next;
- free(iter);
- } else {
- while (iter->next != NULL && iter->next->swbp_unique_id != bp->unique_id)
- iter = iter->next;
- if (iter->next != NULL) {
- /* it's the next one */
- struct swbp_mem_patch *freeme = iter->next;
- iter->next = iter->next->next;
- free(freeme);
- }
- }
- }
-
- LOG_USER("%s software breakpoint %" PRIu32 " removed from 0x%08" PRIx32,
- __func__, bp->unique_id, bp->address);
- return ERROR_OK;
-}
-
-static int set_breakpoint(struct target *t, struct breakpoint *bp)
-{
- int error = ERROR_OK;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address);
- if (bp->set) {
- LOG_ERROR("breakpoint already set");
- return error;
- }
- if (bp->type == BKPT_HARD) {
- error = set_hwbp(t, bp);
- if (error != ERROR_OK) {
- LOG_ERROR("%s error setting hardware breakpoint at 0x%08" PRIx32,
- __func__, bp->address);
- return error;
- }
- } else {
- if (x86_32->sw_bpts_supported(t)) {
- error = set_swbp(t, bp);
- if (error != ERROR_OK) {
- LOG_ERROR("%s error setting software breakpoint at 0x%08" PRIx32,
- __func__, bp->address);
- return error;
- }
- } else {
- LOG_ERROR("%s core doesn't support SW breakpoints", __func__);
- error = ERROR_FAIL;
- return ERROR_FAIL;
- }
- }
- return error;
-}
-
-static int unset_breakpoint(struct target *t, struct breakpoint *bp)
-{
- LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address);
- if (!bp->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- if (bp->type == BKPT_HARD) {
- if (unset_hwbp(t, bp) != ERROR_OK) {
- LOG_ERROR("%s error removing hardware breakpoint at 0x%08" PRIx32,
- __func__, bp->address);
- return ERROR_FAIL;
- }
- } else {
- if (unset_swbp(t, bp) != ERROR_OK) {
- LOG_ERROR("%s error removing software breakpoint at 0x%08" PRIx32,
- __func__, bp->address);
- return ERROR_FAIL;
- }
- }
- bp->set = 0;
- return ERROR_OK;
-}
-
-static int set_watchpoint(struct target *t, struct watchpoint *wp)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list;
- int wp_num = 0;
- LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address);
-
- if (wp->set) {
- LOG_ERROR("%s watchpoint already set", __func__);
- return ERROR_OK;
- }
-
- if (wp->rw == WPT_READ) {
- LOG_ERROR("%s no support for 'read' watchpoints, use 'access' or 'write'"
- , __func__);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- while (debug_reg_list[wp_num].used && (wp_num < x86_32->num_hw_bpoints))
- wp_num++;
- if (wp_num >= x86_32->num_hw_bpoints) {
- LOG_ERROR("%s no debug registers left", __func__);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (wp->length != 4 && wp->length != 2 && wp->length != 1) {
- LOG_ERROR("%s only watchpoints of length 1, 2 or 4 are supported", __func__);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- switch (wp->rw) {
- case WPT_WRITE:
- if (set_debug_regs(t, wp->address, wp_num,
- DR7_BP_WRITE, wp->length) != ERROR_OK) {
- return ERROR_FAIL;
- }
- break;
- case WPT_ACCESS:
- if (set_debug_regs(t, wp->address, wp_num, DR7_BP_READWRITE,
- wp->length) != ERROR_OK) {
- return ERROR_FAIL;
- }
- break;
- default:
- LOG_ERROR("%s only 'access' or 'write' watchpoints are supported", __func__);
- break;
- }
- wp->set = wp_num + 1;
- debug_reg_list[wp_num].used = 1;
- debug_reg_list[wp_num].bp_value = wp->address;
- LOG_USER("'%s' watchpoint %d set at 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)",
- wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ?
- "write" : wp->rw == WPT_ACCESS ? "access" : "?",
- wp->unique_id, wp->address, wp->length, wp_num);
- return ERROR_OK;
-}
-
-static int unset_watchpoint(struct target *t, struct watchpoint *wp)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list;
- LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address);
- if (!wp->set) {
- LOG_WARNING("watchpoint not set");
- return ERROR_OK;
- }
-
- int wp_num = wp->set - 1;
- if ((wp_num < 0) || (wp_num >= x86_32->num_hw_bpoints)) {
- LOG_DEBUG("Invalid FP Comparator number in watchpoint");
- return ERROR_OK;
- }
- if (unset_debug_regs(t, wp_num) != ERROR_OK)
- return ERROR_FAIL;
-
- debug_reg_list[wp_num].used = 0;
- debug_reg_list[wp_num].bp_value = 0;
- wp->set = 0;
-
- LOG_USER("'%s' watchpoint %d removed from 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)",
- wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ?
- "write" : wp->rw == WPT_ACCESS ? "access" : "?",
- wp->unique_id, wp->address, wp->length, wp_num);
-
- return ERROR_OK;
-}
-
-static int read_hw_reg_to_cache(struct target *t, int num)
-{
- uint32_t reg_value;
- struct x86_32_common *x86_32 = target_to_x86_32(t);
-
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- if ((num < 0) || (num >= x86_32->get_num_user_regs(t)))
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (x86_32->read_hw_reg(t, num, &reg_value, 1) != ERROR_OK) {
- LOG_ERROR("%s fail for %s", x86_32->cache->reg_list[num].name, __func__);
- return ERROR_FAIL;
- }
- LOG_DEBUG("reg %s value 0x%08" PRIx32,
- x86_32->cache->reg_list[num].name, reg_value);
- return ERROR_OK;
-}
-
-static int write_hw_reg_from_cache(struct target *t, int num)
-{
- struct x86_32_common *x86_32 = target_to_x86_32(t);
- if (check_not_halted(t))
- return ERROR_TARGET_NOT_HALTED;
- if ((num < 0) || (num >= x86_32->get_num_user_regs(t)))
- return ERROR_COMMAND_SYNTAX_ERROR;
- if (x86_32->write_hw_reg(t, num, 0, 1) != ERROR_OK) {
- LOG_ERROR("%s fail for %s", x86_32->cache->reg_list[num].name, __func__);
- return ERROR_FAIL;
- }
- LOG_DEBUG("reg %s value 0x%08" PRIx32, x86_32->cache->reg_list[num].name,
- buf_get_u32(x86_32->cache->reg_list[num].value, 0, 32));
- return ERROR_OK;
-}
-
-/* x86 32 commands */
-static void handle_iod_output(struct command_context *cmd_ctx,
- struct target *target, uint32_t address, unsigned size,
- unsigned count, const uint8_t *buffer)
-{
- const unsigned line_bytecnt = 32;
- unsigned line_modulo = line_bytecnt / size;
-
- char output[line_bytecnt * 4 + 1];
- unsigned output_len = 0;
-
- const char *value_fmt;
- switch (size) {
- case 4:
- value_fmt = "%8.8x ";
- break;
- case 2:
- value_fmt = "%4.4x ";
- break;
- case 1:
- value_fmt = "%2.2x ";
- break;
- default:
- /* "can't happen", caller checked */
- LOG_ERROR("%s invalid memory read size: %u", __func__, size);
- return;
- }
-
- for (unsigned i = 0; i < count; i++) {
- if (i % line_modulo == 0) {
- output_len += snprintf(output + output_len,
- sizeof(output) - output_len,
- "0x%8.8x: ",
- (unsigned)(address + (i*size)));
- }
-
- uint32_t value = 0;
- const uint8_t *value_ptr = buffer + i * size;
- switch (size) {
- case 4:
- value = target_buffer_get_u32(target, value_ptr);
- break;
- case 2:
- value = target_buffer_get_u16(target, value_ptr);
- break;
- case 1:
- value = *value_ptr;
- }
- output_len += snprintf(output + output_len,
- sizeof(output) - output_len,
- value_fmt, value);
-
- if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) {
- command_print(cmd_ctx, "%s", output);
- output_len = 0;
- }
- }
-}
-
-COMMAND_HANDLER(handle_iod_command)
-{
- if (CMD_ARGC != 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- if (address > 0xffff) {
- LOG_ERROR("%s IA-32 I/O space is 2^16, 0x%08" PRIx32 " exceeds max", __func__, address);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- unsigned size = 0;
- switch (CMD_NAME[2]) {
- case 'w':
- size = 4;
- break;
- case 'h':
- size = 2;
- break;
- case 'b':
- size = 1;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- unsigned count = 1;
- uint8_t *buffer = calloc(count, size);
- struct target *target = get_current_target(CMD_CTX);
- int retval = x86_32_common_read_io(target, address, size, buffer);
- if (ERROR_OK == retval)
- handle_iod_output(CMD_CTX, target, address, size, count, buffer);
- free(buffer);
- return retval;
-}
-
-static int target_fill_io(struct target *target,
- uint32_t address,
- unsigned data_size,
- /* value */
- uint32_t b)
-{
- LOG_DEBUG("address=0x%08" PRIx32 ", data_size=%u, b=0x%08" PRIx32,
- address, data_size, b);
- uint8_t target_buf[data_size];
- switch (data_size) {
- case 4:
- target_buffer_set_u32(target, target_buf, b);
- break;
- case 2:
- target_buffer_set_u16(target, target_buf, b);
- break;
- case 1:
- target_buf[0] = (b & 0x0ff);
- break;
- default:
- exit(-1);
- }
- return x86_32_common_write_io(target, address, data_size, target_buf);
-}
-
-COMMAND_HANDLER(handle_iow_command)
-{
- if (CMD_ARGC != 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
- uint32_t address;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
- struct target *target = get_current_target(CMD_CTX);
-
- unsigned wordsize;
- switch (CMD_NAME[2]) {
- case 'w':
- wordsize = 4;
- break;
- case 'h':
- wordsize = 2;
- break;
- case 'b':
- wordsize = 1;
- break;
- default:
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- return target_fill_io(target, address, wordsize, value);
-}
-
-static const struct command_registration x86_32_exec_command_handlers[] = {
- {
- .name = "iww",
- .mode = COMMAND_EXEC,
- .handler = handle_iow_command,
- .help = "write I/O port word",
- .usage = "port data[word]",
- },
- {
- .name = "iwh",
- .mode = COMMAND_EXEC,
- .handler = handle_iow_command,
- .help = "write I/O port halfword",
- .usage = "port data[halfword]",
- },
- {
- .name = "iwb",
- .mode = COMMAND_EXEC,
- .handler = handle_iow_command,
- .help = "write I/O port byte",
- .usage = "port data[byte]",
- },
- {
- .name = "idw",
- .mode = COMMAND_EXEC,
- .handler = handle_iod_command,
- .help = "display I/O port word",
- .usage = "port",
- },
- {
- .name = "idh",
- .mode = COMMAND_EXEC,
- .handler = handle_iod_command,
- .help = "display I/O port halfword",
- .usage = "port",
- },
- {
- .name = "idb",
- .mode = COMMAND_EXEC,
- .handler = handle_iod_command,
- .help = "display I/O port byte",
- .usage = "port",
- },
-
- COMMAND_REGISTRATION_DONE
-};
-
-const struct command_registration x86_32_command_handlers[] = {
- {
- .name = "x86_32",
- .mode = COMMAND_ANY,
- .help = "x86_32 target commands",
- .usage = "",
- .chain = x86_32_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h
deleted file mode 100644
index b5877da..0000000
--- a/src/target/x86_32_common.h
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright(c) 2013-2016 Intel Corporation.
- *
- * Adrian Burns (adrian.burns@intel.com)
- * Thomas Faust (thomas.faust@intel.com)
- * Ivan De Cesaris (ivan.de.cesaris@intel.com)
- * Julien Carreno (julien.carreno@intel.com)
- * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Contact Information:
- * Intel Corporation
- */
-
-/*
- * @file
- * This is the interface to the x86 32 bit memory and breakpoint operations.
- */
-
-#ifndef OPENOCD_TARGET_X86_32_COMMON_H
-#define OPENOCD_TARGET_X86_32_COMMON_H
-
-#include <jtag/jtag.h>
-#include <helper/command.h>
-#include <helper/types.h>
-
-extern const struct command_registration x86_32_command_handlers[];
-
-/* for memory access */
-#define BYTE 1
-#define WORD 2
-#define DWORD 4
-
-#define EFLAGS_TF ((uint32_t)0x00000100) /* Trap Flag */
-#define EFLAGS_IF ((uint32_t)0x00000200) /* Interrupt Flag */
-#define EFLAGS_RF ((uint32_t)0x00010000) /* Resume Flag */
-#define EFLAGS_VM86 ((uint32_t)0x00020000) /* Virtual 8086 Mode */
-
-#define CSAR_DPL ((uint32_t)0x00006000)
-#define CSAR_D ((uint32_t)0x00400000)
-#define SSAR_DPL ((uint32_t)0x00006000)
-
-#define CR0_PE ((uint32_t)0x00000001) /* Protected Mode Enable */
-#define CR0_NW ((uint32_t)0x20000000) /* Non Write-Through */
-#define CR0_CD ((uint32_t)0x40000000) /* Cache Disable */
-#define CR0_PG ((uint32_t)0x80000000) /* Paging Enable */
-
-/* TODO - move back to PM specific file */
-#define PM_DR6 ((uint32_t)0xFFFF0FF0)
-
-#define DR6_BRKDETECT_0 ((uint32_t)0x00000001) /* B0 through B3 */
-#define DR6_BRKDETECT_1 ((uint32_t)0x00000002) /* breakpoint condition detected */
-#define DR6_BRKDETECT_2 ((uint32_t)0x00000004)
-#define DR6_BRKDETECT_3 ((uint32_t)0x00000008)
-
-enum {
- /* general purpose registers */
- EAX = 0,
- ECX,
- EDX,
- EBX,
- ESP,
- EBP,
- ESI,
- EDI,
- /* instruction pointer & flags */
- EIP,
- EFLAGS,
-
- /* segment registers */
- CS,
- SS,
- DS,
- ES,
- FS,
- GS,
-
- /* floating point unit registers */
- ST0,
- ST1,
- ST2,
- ST3,
- ST4,
- ST5,
- ST6,
- ST7,
- FCTRL,
- FSTAT,
- FTAG,
- FISEG,
- FIOFF,
- FOSEG,
- FOOFF,
- FOP,
-
- /* control registers */
- CR0,
- CR2,
- CR3,
- CR4,
-
- /* debug registers */
- DR0,
- DR1,
- DR2,
- DR3,
- DR6,
- DR7,
-
- /* descriptor tables */
- IDTB,
- IDTL,
- IDTAR,
- GDTB,
- GDTL,
- GDTAR,
- TR,
- LDTR,
- LDTB,
- LDTL,
- LDTAR,
-
- /* segment registers */
- CSB,
- CSL,
- CSAR,
- DSB,
- DSL,
- DSAR,
- ESB,
- ESL,
- ESAR,
- FSB,
- FSL,
- FSAR,
- GSB,
- GSL,
- GSAR,
- SSB,
- SSL,
- SSAR,
- TSSB,
- TSSL,
- TSSAR,
-
- /* PM control reg */
- PMCR,
-};
-
-#define X86_32_COMMON_MAGIC 0x86328632
-
-enum {
- /* memory read/write */
- MEMRDB32 = 0,
- MEMRDB16,
- MEMRDH32,
- MEMRDH16,
- MEMRDW32,
- MEMRDW16,
- MEMWRB32,
- MEMWRB16,
- MEMWRH32,
- MEMWRH16,
- MEMWRW32,
- MEMWRW16,
- /* IO read/write */
- IORDB32,
- IORDB16,
- IORDH32,
- IORDH16,
- IORDW32,
- IORDW16,
- IOWRB32,
- IOWRB16,
- IOWRH32,
- IOWRH16,
- IOWRW32,
- IOWRW16,
- /* lakemont1 core shadow ram access opcodes */
- SRAMACCESS,
- SRAM2PDR,
- PDR2SRAM,
- WBINVD,
-};
-
-enum x86_core_type {
- LMT1,
- LMT3_5
-};
-
-struct swbp_mem_patch {
- uint8_t orig_byte;
- uint32_t swbp_unique_id;
- uint32_t physaddr;
- struct swbp_mem_patch *next;
-};
-
-/* TODO - probemode specific - consider removing */
-#define NUM_PM_REGS 18 /* regs used in save/restore */
-
-struct x86_32_common {
- uint32_t common_magic;
- void *arch_info;
- enum x86_core_type core_type;
- struct reg_cache *cache;
- struct jtag_tap *curr_tap;
- uint32_t stored_pc;
- int flush;
-
- /* pm_regs are for probemode save/restore state */
- uint32_t pm_regs[NUM_PM_REGS];
-
- /* working area for fastdata access */
- struct working_area *fast_data_area;
-
- int num_hw_bpoints;
- struct x86_32_dbg_reg *hw_break_list;
- struct swbp_mem_patch *swbbp_mem_patch_list;
-
- /* core probemode implementation dependent functions */
- uint8_t (*get_num_user_regs)(struct target *t);
- bool (*is_paging_enabled)(struct target *t);
- int (*disable_paging)(struct target *t);
- int (*enable_paging)(struct target *t);
- bool (*sw_bpts_supported)(struct target *t);
- int (*transaction_status)(struct target *t);
- int (*submit_instruction)(struct target *t, int num);
- int (*read_hw_reg)(struct target *t, int reg, uint32_t *regval, uint8_t cache);
- int (*write_hw_reg)(struct target *t, int reg,
- uint32_t regval, uint8_t cache);
-
- /* register cache to processor synchronization */
- int (*read_hw_reg_to_cache)(struct target *target, int num);
- int (*write_hw_reg_from_cache)(struct target *target, int num);
-};
-
-static inline struct x86_32_common *
-target_to_x86_32(struct target *target)
-{
- return target->arch_info;
-}
-bool check_not_halted(const struct target *t);
-
-/* breakpoint defines */
-#define MAX_DEBUG_REGS 4
-#define SW_BP_OPCODE 0xf1
-#define MAX_SW_BPTS 20
-
-struct x86_32_dbg_reg {
- int used;
- uint32_t bp_value;
-};
-
-#define DR7_G_ENABLE_SHIFT 1
-#define DR7_ENABLE_SIZE 2 /* 2 bits per debug reg */
-#define DR7_RW_SHIFT 16
-#define DR7_LENGTH_SHIFT 18
-#define DR7_RW_LEN_SIZE 4
-#define DR7_BP_EXECUTE 0 /* 00 - only on instruction execution*/
-#define DR7_BP_WRITE 1 /* 01 - only on data writes */
-/*#define DR7_RW_IORW 2 UNSUPPORTED 10 - an I/O read and I/O write */
-#define DR7_BP_READWRITE 3 /* on data read or data write */
-#define DR7_BP_LENGTH_1 0 /* 00 - 1 byte length */
-#define DR7_BP_LENGTH_2 1 /* 01 - 2 byte length */
-#define DR7_BP_LENGTH_4 3 /* 11 - 4 byte length */
-
-#define DR7_GLOBAL_ENABLE(val, regnum) \
- (val |= (1 << (DR7_G_ENABLE_SHIFT + (DR7_ENABLE_SIZE * (regnum)))))
-
-#define DR7_GLOBAL_DISABLE(val, regnum) \
- (val &= ~(3 << (DR7_ENABLE_SIZE * (regnum))))
-
-#define DR7_BP_FREE(val, regnum) \
- ((val & (3 << (DR7_ENABLE_SIZE * (regnum)))) == 0)
-
-#define DR7_RESET_RWLEN_BITS(val, regnum) \
- (val &= ~(0x0f << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum))))
-
-#define DR7_SET_EXE(val, regnum) \
- (val &= ~(0x0f << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum))))
-
-#define DR7_SET_WRITE(val, regnum) \
- (val |= (DR7_BP_WRITE << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum))))
-
-#define DR7_SET_ACCESS(val, regnum) \
- (val |= (DR7_BP_READWRITE << (DR7_RW_SHIFT + DR7_RW_LEN_SIZE * (regnum))))
-
-#define DR7_SET_LENGTH(val, regnum, len) \
- (val |= (len == 1) ? (DR7_BP_LENGTH_1 << (DR7_LENGTH_SHIFT + DR7_RW_LEN_SIZE * (regnum))) : \
- (len == 2) ? (DR7_BP_LENGTH_2 << (DR7_LENGTH_SHIFT + DR7_RW_LEN_SIZE * (regnum))) : \
- (DR7_BP_LENGTH_4 << (DR7_LENGTH_SHIFT + DR7_RW_LEN_SIZE * (regnum))))
-
-/* public interface */
-int x86_32_get_gdb_reg_list(struct target *t,
- struct reg **reg_list[], int *reg_list_size,
- enum target_register_class reg_class);
-int x86_32_common_init_arch_info(struct target *target,
- struct x86_32_common *x86_32);
-int x86_32_common_mmu(struct target *t, int *enabled);
-int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical);
-int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, uint8_t *buffer);
-int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address,
- uint32_t size, uint32_t count, const uint8_t *buffer);
-int x86_32_common_read_memory(struct target *t, uint32_t addr,
- uint32_t size, uint32_t count, uint8_t *buf);
-int x86_32_common_write_memory(struct target *t, uint32_t addr,
- uint32_t size, uint32_t count, const uint8_t *buf);
-int x86_32_common_read_io(struct target *t, uint32_t addr,
- uint32_t size, uint8_t *buf);
-int x86_32_common_write_io(struct target *t, uint32_t addr,
- uint32_t size, const uint8_t *buf);
-int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp);
-int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp);
-int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp);
-int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp);
-
-#endif /* OPENOCD_TARGET_X86_32_COMMON_H */
diff --git a/src/target/xscale.c b/src/target/xscale.c
deleted file mode 100644
index 140ea58..0000000
--- a/src/target/xscale.c
+++ /dev/null
@@ -1,3728 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006, 2007 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2009 Michael Schwingen *
- * michael@schwingen.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "breakpoints.h"
-#include "xscale.h"
-#include "target_type.h"
-#include "arm_jtag.h"
-#include "arm_simulator.h"
-#include "arm_disassembler.h"
-#include <helper/time_support.h>
-#include "register.h"
-#include "image.h"
-#include "arm_opcodes.h"
-#include "armv4_5.h"
-
-/*
- * Important XScale documents available as of October 2009 include:
- *
- * Intel XScale® Core Developer’s Manual, January 2004
- * Order Number: 273473-002
- * This has a chapter detailing debug facilities, and punts some
- * details to chip-specific microarchitecture documents.
- *
- * Hot-Debug for Intel XScale® Core Debug White Paper, May 2005
- * Document Number: 273539-005
- * Less detailed than the developer's manual, but summarizes those
- * missing details (for most XScales) and gives LOTS of notes about
- * debugger/handler interaction issues. Presents a simpler reset
- * and load-handler sequence than the arch doc. (Note, OpenOCD
- * doesn't currently support "Hot-Debug" as defined there.)
- *
- * Chip-specific microarchitecture documents may also be useful.
- */
-
-/* forward declarations */
-static int xscale_resume(struct target *, int current,
- uint32_t address, int handle_breakpoints, int debug_execution);
-static int xscale_debug_entry(struct target *);
-static int xscale_restore_banked(struct target *);
-static int xscale_get_reg(struct reg *reg);
-static int xscale_set_reg(struct reg *reg, uint8_t *buf);
-static int xscale_set_breakpoint(struct target *, struct breakpoint *);
-static int xscale_set_watchpoint(struct target *, struct watchpoint *);
-static int xscale_unset_breakpoint(struct target *, struct breakpoint *);
-static int xscale_read_trace(struct target *);
-
-/* This XScale "debug handler" is loaded into the processor's
- * mini-ICache, which is 2K of code writable only via JTAG.
- */
-static const uint8_t xscale_debug_handler[] = {
-#include "xscale_debug.inc"
-};
-
-static const char *const xscale_reg_list[] = {
- "XSCALE_MAINID", /* 0 */
- "XSCALE_CACHETYPE",
- "XSCALE_CTRL",
- "XSCALE_AUXCTRL",
- "XSCALE_TTB",
- "XSCALE_DAC",
- "XSCALE_FSR",
- "XSCALE_FAR",
- "XSCALE_PID",
- "XSCALE_CPACCESS",
- "XSCALE_IBCR0", /* 10 */
- "XSCALE_IBCR1",
- "XSCALE_DBR0",
- "XSCALE_DBR1",
- "XSCALE_DBCON",
- "XSCALE_TBREG",
- "XSCALE_CHKPT0",
- "XSCALE_CHKPT1",
- "XSCALE_DCSR",
- "XSCALE_TX",
- "XSCALE_RX", /* 20 */
- "XSCALE_TXRXCTRL",
-};
-
-static const struct xscale_reg xscale_reg_arch_info[] = {
- {XSCALE_MAINID, NULL},
- {XSCALE_CACHETYPE, NULL},
- {XSCALE_CTRL, NULL},
- {XSCALE_AUXCTRL, NULL},
- {XSCALE_TTB, NULL},
- {XSCALE_DAC, NULL},
- {XSCALE_FSR, NULL},
- {XSCALE_FAR, NULL},
- {XSCALE_PID, NULL},
- {XSCALE_CPACCESS, NULL},
- {XSCALE_IBCR0, NULL},
- {XSCALE_IBCR1, NULL},
- {XSCALE_DBR0, NULL},
- {XSCALE_DBR1, NULL},
- {XSCALE_DBCON, NULL},
- {XSCALE_TBREG, NULL},
- {XSCALE_CHKPT0, NULL},
- {XSCALE_CHKPT1, NULL},
- {XSCALE_DCSR, NULL}, /* DCSR accessed via JTAG or SW */
- {-1, NULL}, /* TX accessed via JTAG */
- {-1, NULL}, /* RX accessed via JTAG */
- {-1, NULL}, /* TXRXCTRL implicit access via JTAG */
-};
-
-/* convenience wrapper to access XScale specific registers */
-static int xscale_set_reg_u32(struct reg *reg, uint32_t value)
-{
- uint8_t buf[4];
-
- buf_set_u32(buf, 0, 32, value);
-
- return xscale_set_reg(reg, buf);
-}
-
-static const char xscale_not[] = "target is not an XScale";
-
-static int xscale_verify_pointer(struct command_context *cmd_ctx,
- struct xscale_common *xscale)
-{
- if (xscale->common_magic != XSCALE_COMMON_MAGIC) {
- command_print(cmd_ctx, xscale_not);
- return ERROR_TARGET_INVALID;
- }
- return ERROR_OK;
-}
-
-static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state)
-{
- assert(tap != NULL);
-
- if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) {
- struct scan_field field;
- uint8_t scratch[4];
-
- memset(&field, 0, sizeof field);
- field.num_bits = tap->ir_length;
- field.out_value = scratch;
- buf_set_u32(scratch, 0, field.num_bits, new_instr);
-
- jtag_add_ir_scan(tap, &field, end_state);
- }
-
- return ERROR_OK;
-}
-
-static int xscale_read_dcsr(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
- struct scan_field fields[3];
- uint8_t field0 = 0x0;
- uint8_t field0_check_value = 0x2;
- uint8_t field0_check_mask = 0x7;
- uint8_t field2 = 0x0;
- uint8_t field2_check_value = 0x0;
- uint8_t field2_check_mask = 0x1;
-
- xscale_jtag_set_instr(target->tap,
- XSCALE_SELDCSR << xscale->xscale_variant,
- TAP_DRPAUSE);
-
- buf_set_u32(&field0, 1, 1, xscale->hold_rst);
- buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
-
- memset(&fields, 0, sizeof fields);
-
- fields[0].num_bits = 3;
- fields[0].out_value = &field0;
- uint8_t tmp;
- fields[0].in_value = &tmp;
-
- fields[1].num_bits = 32;
- fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
-
- fields[2].num_bits = 1;
- fields[2].out_value = &field2;
- uint8_t tmp2;
- fields[2].in_value = &tmp2;
-
- jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE);
-
- jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
- jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while reading DCSR");
- return retval;
- }
-
- xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
- xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
-
- /* write the register with the value we just read
- * on this second pass, only the first bit of field0 is guaranteed to be 0)
- */
- field0_check_mask = 0x1;
- fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
- fields[1].in_value = NULL;
-
- jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE);
-
- /* DANGER!!! this must be here. It will make sure that the arguments
- * to jtag_set_check_value() does not go out of scope! */
- return jtag_execute_queue();
-}
-
-
-static void xscale_getbuf(jtag_callback_data_t arg)
-{
- uint8_t *in = (uint8_t *)arg;
- *((uint32_t *)arg) = buf_get_u32(in, 0, 32);
-}
-
-static int xscale_receive(struct target *target, uint32_t *buffer, int num_words)
-{
- if (num_words == 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- struct xscale_common *xscale = target_to_xscale(target);
- int retval = ERROR_OK;
- tap_state_t path[3];
- struct scan_field fields[3];
- uint8_t *field0 = malloc(num_words * 1);
- uint8_t field0_check_value = 0x2;
- uint8_t field0_check_mask = 0x6;
- uint32_t *field1 = malloc(num_words * 4);
- uint8_t field2_check_value = 0x0;
- uint8_t field2_check_mask = 0x1;
- int words_done = 0;
- int words_scheduled = 0;
- int i;
-
- path[0] = TAP_DRSELECT;
- path[1] = TAP_DRCAPTURE;
- path[2] = TAP_DRSHIFT;
-
- memset(&fields, 0, sizeof fields);
-
- fields[0].num_bits = 3;
- uint8_t tmp;
- fields[0].in_value = &tmp;
- fields[0].check_value = &field0_check_value;
- fields[0].check_mask = &field0_check_mask;
-
- fields[1].num_bits = 32;
-
- fields[2].num_bits = 1;
- uint8_t tmp2;
- fields[2].in_value = &tmp2;
- fields[2].check_value = &field2_check_value;
- fields[2].check_mask = &field2_check_mask;
-
- xscale_jtag_set_instr(target->tap,
- XSCALE_DBGTX << xscale->xscale_variant,
- TAP_IDLE);
- jtag_add_runtest(1, TAP_IDLE); /* ensures that we're in the TAP_IDLE state as the above
- *could be a no-op */
-
- /* repeat until all words have been collected */
- int attempts = 0;
- while (words_done < num_words) {
- /* schedule reads */
- words_scheduled = 0;
- for (i = words_done; i < num_words; i++) {
- fields[0].in_value = &field0[i];
-
- jtag_add_pathmove(3, path);
-
- fields[1].in_value = (uint8_t *)(field1 + i);
-
- jtag_add_dr_scan_check(target->tap, 3, fields, TAP_IDLE);
-
- jtag_add_callback(xscale_getbuf, (jtag_callback_data_t)(field1 + i));
-
- words_scheduled++;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while receiving data from debug handler");
- break;
- }
-
- /* examine results */
- for (i = words_done; i < num_words; i++) {
- if (!(field0[i] & 1)) {
- /* move backwards if necessary */
- int j;
- for (j = i; j < num_words - 1; j++) {
- field0[j] = field0[j + 1];
- field1[j] = field1[j + 1];
- }
- words_scheduled--;
- }
- }
- if (words_scheduled == 0) {
- if (attempts++ == 1000) {
- LOG_ERROR(
- "Failed to receiving data from debug handler after 1000 attempts");
- retval = ERROR_TARGET_TIMEOUT;
- break;
- }
- }
-
- words_done += words_scheduled;
- }
-
- for (i = 0; i < num_words; i++)
- *(buffer++) = buf_get_u32((uint8_t *)&field1[i], 0, 32);
-
- free(field1);
-
- return retval;
-}
-
-static int xscale_read_tx(struct target *target, int consume)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- tap_state_t path[3];
- tap_state_t noconsume_path[6];
- int retval;
- struct timeval timeout, now;
- struct scan_field fields[3];
- uint8_t field0_in = 0x0;
- uint8_t field0_check_value = 0x2;
- uint8_t field0_check_mask = 0x6;
- uint8_t field2_check_value = 0x0;
- uint8_t field2_check_mask = 0x1;
-
- xscale_jtag_set_instr(target->tap,
- XSCALE_DBGTX << xscale->xscale_variant,
- TAP_IDLE);
-
- path[0] = TAP_DRSELECT;
- path[1] = TAP_DRCAPTURE;
- path[2] = TAP_DRSHIFT;
-
- noconsume_path[0] = TAP_DRSELECT;
- noconsume_path[1] = TAP_DRCAPTURE;
- noconsume_path[2] = TAP_DREXIT1;
- noconsume_path[3] = TAP_DRPAUSE;
- noconsume_path[4] = TAP_DREXIT2;
- noconsume_path[5] = TAP_DRSHIFT;
-
- memset(&fields, 0, sizeof fields);
-
- fields[0].num_bits = 3;
- fields[0].in_value = &field0_in;
-
- fields[1].num_bits = 32;
- fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_TX].value;
-
- fields[2].num_bits = 1;
- uint8_t tmp;
- fields[2].in_value = &tmp;
-
- gettimeofday(&timeout, NULL);
- timeval_add_time(&timeout, 1, 0);
-
- for (;; ) {
- /* if we want to consume the register content (i.e. clear TX_READY),
- * we have to go straight from Capture-DR to Shift-DR
- * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR
- */
- if (consume)
- jtag_add_pathmove(3, path);
- else
- jtag_add_pathmove(ARRAY_SIZE(noconsume_path), noconsume_path);
-
- jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
-
- jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
- jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while reading TX");
- return ERROR_TARGET_TIMEOUT;
- }
-
- gettimeofday(&now, NULL);
- if ((now.tv_sec > timeout.tv_sec) ||
- ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) {
- LOG_ERROR("time out reading TX register");
- return ERROR_TARGET_TIMEOUT;
- }
- if (!((!(field0_in & 1)) && consume))
- goto done;
- if (debug_level >= 3) {
- LOG_DEBUG("waiting 100ms");
- alive_sleep(100); /* avoid flooding the logs */
- } else
- keep_alive();
- }
-done:
-
- if (!(field0_in & 1))
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- return ERROR_OK;
-}
-
-static int xscale_write_rx(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
- struct timeval timeout, now;
- struct scan_field fields[3];
- uint8_t field0_out = 0x0;
- uint8_t field0_in = 0x0;
- uint8_t field0_check_value = 0x2;
- uint8_t field0_check_mask = 0x6;
- uint8_t field2 = 0x0;
- uint8_t field2_check_value = 0x0;
- uint8_t field2_check_mask = 0x1;
-
- xscale_jtag_set_instr(target->tap,
- XSCALE_DBGRX << xscale->xscale_variant,
- TAP_IDLE);
-
- memset(&fields, 0, sizeof fields);
-
- fields[0].num_bits = 3;
- fields[0].out_value = &field0_out;
- fields[0].in_value = &field0_in;
-
- fields[1].num_bits = 32;
- fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_RX].value;
-
- fields[2].num_bits = 1;
- fields[2].out_value = &field2;
- uint8_t tmp;
- fields[2].in_value = &tmp;
-
- gettimeofday(&timeout, NULL);
- timeval_add_time(&timeout, 1, 0);
-
- /* poll until rx_read is low */
- LOG_DEBUG("polling RX");
- for (;;) {
- jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
-
- jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
- jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while writing RX");
- return retval;
- }
-
- gettimeofday(&now, NULL);
- if ((now.tv_sec > timeout.tv_sec) ||
- ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) {
- LOG_ERROR("time out writing RX register");
- return ERROR_TARGET_TIMEOUT;
- }
- if (!(field0_in & 1))
- goto done;
- if (debug_level >= 3) {
- LOG_DEBUG("waiting 100ms");
- alive_sleep(100); /* avoid flooding the logs */
- } else
- keep_alive();
- }
-done:
-
- /* set rx_valid */
- field2 = 0x1;
- jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while writing RX");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-/* send count elements of size byte to the debug handler */
-static int xscale_send(struct target *target, const uint8_t *buffer, int count, int size)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
- int done_count = 0;
-
- xscale_jtag_set_instr(target->tap,
- XSCALE_DBGRX << xscale->xscale_variant,
- TAP_IDLE);
-
- static const uint8_t t0;
- uint8_t t1[4];
- static const uint8_t t2 = 1;
- struct scan_field fields[3] = {
- { .num_bits = 3, .out_value = &t0 },
- { .num_bits = 32, .out_value = t1 },
- { .num_bits = 1, .out_value = &t2 },
- };
-
- int endianness = target->endianness;
- while (done_count++ < count) {
- uint32_t t;
-
- switch (size) {
- case 4:
- if (endianness == TARGET_LITTLE_ENDIAN)
- t = le_to_h_u32(buffer);
- else
- t = be_to_h_u32(buffer);
- break;
- case 2:
- if (endianness == TARGET_LITTLE_ENDIAN)
- t = le_to_h_u16(buffer);
- else
- t = be_to_h_u16(buffer);
- break;
- case 1:
- t = buffer[0];
- break;
- default:
- LOG_ERROR("BUG: size neither 4, 2 nor 1");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- buf_set_u32(t1, 0, 32, t);
-
- jtag_add_dr_scan(target->tap,
- 3,
- fields,
- TAP_IDLE);
- buffer += size;
- }
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while sending data to debug handler");
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_send_u32(struct target *target, uint32_t value)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);
- return xscale_write_rx(target);
-}
-
-static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_brk)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
- struct scan_field fields[3];
- uint8_t field0 = 0x0;
- uint8_t field0_check_value = 0x2;
- uint8_t field0_check_mask = 0x7;
- uint8_t field2 = 0x0;
- uint8_t field2_check_value = 0x0;
- uint8_t field2_check_mask = 0x1;
-
- if (hold_rst != -1)
- xscale->hold_rst = hold_rst;
-
- if (ext_dbg_brk != -1)
- xscale->external_debug_break = ext_dbg_brk;
-
- xscale_jtag_set_instr(target->tap,
- XSCALE_SELDCSR << xscale->xscale_variant,
- TAP_IDLE);
-
- buf_set_u32(&field0, 1, 1, xscale->hold_rst);
- buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
-
- memset(&fields, 0, sizeof fields);
-
- fields[0].num_bits = 3;
- fields[0].out_value = &field0;
- uint8_t tmp;
- fields[0].in_value = &tmp;
-
- fields[1].num_bits = 32;
- fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
-
- fields[2].num_bits = 1;
- fields[2].out_value = &field2;
- uint8_t tmp2;
- fields[2].in_value = &tmp2;
-
- jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
-
- jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
- jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
-
- retval = jtag_execute_queue();
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG error while writing DCSR");
- return retval;
- }
-
- xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
- xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
-
- return ERROR_OK;
-}
-
-/* parity of the number of bits 0 if even; 1 if odd. for 32 bit words */
-static unsigned int parity(unsigned int v)
-{
- /* unsigned int ov = v; */
- v ^= v >> 16;
- v ^= v >> 8;
- v ^= v >> 4;
- v &= 0xf;
- /* LOG_DEBUG("parity of 0x%x is %i", ov, (0x6996 >> v) & 1); */
- return (0x6996 >> v) & 1;
-}
-
-static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8])
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint8_t packet[4];
- uint8_t cmd;
- int word;
- struct scan_field fields[2];
-
- LOG_DEBUG("loading miniIC at 0x%8.8" PRIx32 "", va);
-
- /* LDIC into IR */
- xscale_jtag_set_instr(target->tap,
- XSCALE_LDIC << xscale->xscale_variant,
- TAP_IDLE);
-
- /* CMD is b011 to load a cacheline into the Mini ICache.
- * Loading into the main ICache is deprecated, and unused.
- * It's followed by three zero bits, and 27 address bits.
- */
- buf_set_u32(&cmd, 0, 6, 0x3);
-
- /* virtual address of desired cache line */
- buf_set_u32(packet, 0, 27, va >> 5);
-
- memset(&fields, 0, sizeof fields);
-
- fields[0].num_bits = 6;
- fields[0].out_value = &cmd;
-
- fields[1].num_bits = 27;
- fields[1].out_value = packet;
-
- jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
-
- /* rest of packet is a cacheline: 8 instructions, with parity */
- fields[0].num_bits = 32;
- fields[0].out_value = packet;
-
- fields[1].num_bits = 1;
- fields[1].out_value = &cmd;
-
- for (word = 0; word < 8; word++) {
- buf_set_u32(packet, 0, 32, buffer[word]);
-
- uint32_t value;
- memcpy(&value, packet, sizeof(uint32_t));
- cmd = parity(value);
-
- jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
- }
-
- return jtag_execute_queue();
-}
-
-static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint8_t packet[4];
- uint8_t cmd;
- struct scan_field fields[2];
-
- xscale_jtag_set_instr(target->tap,
- XSCALE_LDIC << xscale->xscale_variant,
- TAP_IDLE);
-
- /* CMD for invalidate IC line b000, bits [6:4] b000 */
- buf_set_u32(&cmd, 0, 6, 0x0);
-
- /* virtual address of desired cache line */
- buf_set_u32(packet, 0, 27, va >> 5);
-
- memset(&fields, 0, sizeof fields);
-
- fields[0].num_bits = 6;
- fields[0].out_value = &cmd;
-
- fields[1].num_bits = 27;
- fields[1].out_value = packet;
-
- jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
-
- return ERROR_OK;
-}
-
-static int xscale_update_vectors(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- int i;
- int retval;
-
- uint32_t low_reset_branch, high_reset_branch;
-
- for (i = 1; i < 8; i++) {
- /* if there's a static vector specified for this exception, override */
- if (xscale->static_high_vectors_set & (1 << i))
- xscale->high_vectors[i] = xscale->static_high_vectors[i];
- else {
- retval = target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]);
- if (retval == ERROR_TARGET_TIMEOUT)
- return retval;
- if (retval != ERROR_OK) {
- /* Some of these reads will fail as part of normal execution */
- xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
- }
- }
- }
-
- for (i = 1; i < 8; i++) {
- if (xscale->static_low_vectors_set & (1 << i))
- xscale->low_vectors[i] = xscale->static_low_vectors[i];
- else {
- retval = target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]);
- if (retval == ERROR_TARGET_TIMEOUT)
- return retval;
- if (retval != ERROR_OK) {
- /* Some of these reads will fail as part of normal execution */
- xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
- }
- }
- }
-
- /* calculate branches to debug handler */
- low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;
- high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;
-
- xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);
- xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);
-
- /* invalidate and load exception vectors in mini i-cache */
- xscale_invalidate_ic_line(target, 0x0);
- xscale_invalidate_ic_line(target, 0xffff0000);
-
- xscale_load_ic(target, 0x0, xscale->low_vectors);
- xscale_load_ic(target, 0xffff0000, xscale->high_vectors);
-
- return ERROR_OK;
-}
-
-static int xscale_arch_state(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct arm *arm = &xscale->arm;
-
- static const char *state[] = {
- "disabled", "enabled"
- };
-
- static const char *arch_dbg_reason[] = {
- "", "\n(processor reset)", "\n(trace buffer full)"
- };
-
- if (arm->common_magic != ARM_COMMON_MAGIC) {
- LOG_ERROR("BUG: called for a non-ARMv4/5 target");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- arm_arch_state(target);
- LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s%s",
- state[xscale->armv4_5_mmu.mmu_enabled],
- state[xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
- state[xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled],
- arch_dbg_reason[xscale->arch_debug_reason]);
-
- return ERROR_OK;
-}
-
-static int xscale_poll(struct target *target)
-{
- int retval = ERROR_OK;
-
- if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING)) {
- enum target_state previous_state = target->state;
- retval = xscale_read_tx(target, 0);
- if (retval == ERROR_OK) {
-
- /* there's data to read from the tx register, we entered debug state */
- target->state = TARGET_HALTED;
-
- /* process debug entry, fetching current mode regs */
- retval = xscale_debug_entry(target);
- } else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
- LOG_USER("error while polling TX register, reset CPU");
- /* here we "lie" so GDB won't get stuck and a reset can be perfomed */
- target->state = TARGET_HALTED;
- }
-
- /* debug_entry could have overwritten target state (i.e. immediate resume)
- * don't signal event handlers in that case
- */
- if (target->state != TARGET_HALTED)
- return ERROR_OK;
-
- /* if target was running, signal that we halted
- * otherwise we reentered from debug execution */
- if (previous_state == TARGET_RUNNING)
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
- else
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
- }
-
- return retval;
-}
-
-static int xscale_debug_entry(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct arm *arm = &xscale->arm;
- uint32_t pc;
- uint32_t buffer[10];
- unsigned i;
- int retval;
- uint32_t moe;
-
- /* clear external dbg break (will be written on next DCSR read) */
- xscale->external_debug_break = 0;
- retval = xscale_read_dcsr(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* get r0, pc, r1 to r7 and cpsr */
- retval = xscale_receive(target, buffer, 10);
- if (retval != ERROR_OK)
- return retval;
-
- /* move r0 from buffer to register cache */
- buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, buffer[0]);
- arm->core_cache->reg_list[0].dirty = 1;
- arm->core_cache->reg_list[0].valid = 1;
- LOG_DEBUG("r0: 0x%8.8" PRIx32 "", buffer[0]);
-
- /* move pc from buffer to register cache */
- buf_set_u32(arm->pc->value, 0, 32, buffer[1]);
- arm->pc->dirty = 1;
- arm->pc->valid = 1;
- LOG_DEBUG("pc: 0x%8.8" PRIx32 "", buffer[1]);
-
- /* move data from buffer to register cache */
- for (i = 1; i <= 7; i++) {
- buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, buffer[1 + i]);
- arm->core_cache->reg_list[i].dirty = 1;
- arm->core_cache->reg_list[i].valid = 1;
- LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, buffer[i + 1]);
- }
-
- arm_set_cpsr(arm, buffer[9]);
- LOG_DEBUG("cpsr: 0x%8.8" PRIx32 "", buffer[9]);
-
- if (!is_arm_mode(arm->core_mode)) {
- target->state = TARGET_UNKNOWN;
- LOG_ERROR("cpsr contains invalid mode value - communication failure");
- return ERROR_TARGET_FAILURE;
- }
- LOG_DEBUG("target entered debug state in %s mode",
- arm_mode_name(arm->core_mode));
-
- /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */
- if (arm->spsr) {
- xscale_receive(target, buffer, 8);
- buf_set_u32(arm->spsr->value, 0, 32, buffer[7]);
- arm->spsr->dirty = false;
- arm->spsr->valid = true;
- } else {
- /* r8 to r14, but no spsr */
- xscale_receive(target, buffer, 7);
- }
-
- /* move data from buffer to right banked register in cache */
- for (i = 8; i <= 14; i++) {
- struct reg *r = arm_reg_current(arm, i);
-
- buf_set_u32(r->value, 0, 32, buffer[i - 8]);
- r->dirty = false;
- r->valid = true;
- }
-
- /* mark xscale regs invalid to ensure they are retrieved from the
- * debug handler if requested */
- for (i = 0; i < xscale->reg_cache->num_regs; i++)
- xscale->reg_cache->reg_list[i].valid = 0;
-
- /* examine debug reason */
- xscale_read_dcsr(target);
- moe = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 2, 3);
-
- /* stored PC (for calculating fixup) */
- pc = buf_get_u32(arm->pc->value, 0, 32);
-
- switch (moe) {
- case 0x0: /* Processor reset */
- target->debug_reason = DBG_REASON_DBGRQ;
- xscale->arch_debug_reason = XSCALE_DBG_REASON_RESET;
- pc -= 4;
- break;
- case 0x1: /* Instruction breakpoint hit */
- target->debug_reason = DBG_REASON_BREAKPOINT;
- xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
- pc -= 4;
- break;
- case 0x2: /* Data breakpoint hit */
- target->debug_reason = DBG_REASON_WATCHPOINT;
- xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
- pc -= 4;
- break;
- case 0x3: /* BKPT instruction executed */
- target->debug_reason = DBG_REASON_BREAKPOINT;
- xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
- pc -= 4;
- break;
- case 0x4: /* Ext. debug event */
- target->debug_reason = DBG_REASON_DBGRQ;
- xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
- pc -= 4;
- break;
- case 0x5: /* Vector trap occured */
- target->debug_reason = DBG_REASON_BREAKPOINT;
- xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
- pc -= 4;
- break;
- case 0x6: /* Trace buffer full break */
- target->debug_reason = DBG_REASON_DBGRQ;
- xscale->arch_debug_reason = XSCALE_DBG_REASON_TB_FULL;
- pc -= 4;
- break;
- case 0x7: /* Reserved (may flag Hot-Debug support) */
- default:
- LOG_ERROR("Method of Entry is 'Reserved'");
- exit(-1);
- break;
- }
-
- /* apply PC fixup */
- buf_set_u32(arm->pc->value, 0, 32, pc);
-
- /* on the first debug entry, identify cache type */
- if (xscale->armv4_5_mmu.armv4_5_cache.ctype == -1) {
- uint32_t cache_type_reg;
-
- /* read cp15 cache type register */
- xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CACHETYPE]);
- cache_type_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CACHETYPE].value,
- 0,
- 32);
-
- armv4_5_identify_cache(cache_type_reg, &xscale->armv4_5_mmu.armv4_5_cache);
- }
-
- /* examine MMU and Cache settings
- * read cp15 control register */
- xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
- xscale->cp15_control_reg =
- buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
- xscale->armv4_5_mmu.mmu_enabled = (xscale->cp15_control_reg & 0x1U) ? 1 : 0;
- xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
- (xscale->cp15_control_reg & 0x4U) ? 1 : 0;
- xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
- (xscale->cp15_control_reg & 0x1000U) ? 1 : 0;
-
- /* tracing enabled, read collected trace data */
- if (xscale->trace.mode != XSCALE_TRACE_DISABLED) {
- xscale_read_trace(target);
-
- /* Resume if entered debug due to buffer fill and we're still collecting
- * trace data. Note that a debug exception due to trace buffer full
- * can only happen in fill mode. */
- if (xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL) {
- if (--xscale->trace.fill_counter > 0)
- xscale_resume(target, 1, 0x0, 1, 0);
- } else /* entered debug for other reason; reset counter */
- xscale->trace.fill_counter = 0;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_halt(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- if (target->state == TARGET_HALTED) {
- LOG_DEBUG("target was already halted");
- return ERROR_OK;
- } else if (target->state == TARGET_UNKNOWN) {
- /* this must not happen for a xscale target */
- LOG_ERROR("target was in unknown state when halt was requested");
- return ERROR_TARGET_INVALID;
- } else if (target->state == TARGET_RESET)
- LOG_DEBUG("target->state == TARGET_RESET");
- else {
- /* assert external dbg break */
- xscale->external_debug_break = 1;
- xscale_read_dcsr(target);
-
- target->debug_reason = DBG_REASON_DBGRQ;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_enable_single_step(struct target *target, uint32_t next_pc)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct reg *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
- int retval;
-
- if (xscale->ibcr0_used) {
- struct breakpoint *ibcr0_bp =
- breakpoint_find(target, buf_get_u32(ibcr0->value, 0, 32) & 0xfffffffe);
-
- if (ibcr0_bp)
- xscale_unset_breakpoint(target, ibcr0_bp);
- else {
- LOG_ERROR(
- "BUG: xscale->ibcr0_used is set, but no breakpoint with that address found");
- exit(-1);
- }
- }
-
- retval = xscale_set_reg_u32(ibcr0, next_pc | 0x1);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static int xscale_disable_single_step(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct reg *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
- int retval;
-
- retval = xscale_set_reg_u32(ibcr0, 0x0);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_OK;
-}
-
-static void xscale_enable_watchpoints(struct target *target)
-{
- struct watchpoint *watchpoint = target->watchpoints;
-
- while (watchpoint) {
- if (watchpoint->set == 0)
- xscale_set_watchpoint(target, watchpoint);
- watchpoint = watchpoint->next;
- }
-}
-
-static void xscale_enable_breakpoints(struct target *target)
-{
- struct breakpoint *breakpoint = target->breakpoints;
-
- /* set any pending breakpoints */
- while (breakpoint) {
- if (breakpoint->set == 0)
- xscale_set_breakpoint(target, breakpoint);
- breakpoint = breakpoint->next;
- }
-}
-
-static void xscale_free_trace_data(struct xscale_common *xscale)
-{
- struct xscale_trace_data *td = xscale->trace.data;
- while (td) {
- struct xscale_trace_data *next_td = td->next;
- if (td->entries)
- free(td->entries);
- free(td);
- td = next_td;
- }
- xscale->trace.data = NULL;
-}
-
-static int xscale_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct arm *arm = &xscale->arm;
- uint32_t current_pc;
- int retval;
- int i;
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!debug_execution)
- target_free_all_working_areas(target);
-
- /* update vector tables */
- retval = xscale_update_vectors(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current)
- buf_set_u32(arm->pc->value, 0, 32, address);
-
- current_pc = buf_get_u32(arm->pc->value, 0, 32);
-
- /* if we're at the reset vector, we have to simulate the branch */
- if (current_pc == 0x0) {
- arm_simulate_step(target, NULL);
- current_pc = buf_get_u32(arm->pc->value, 0, 32);
- }
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints) {
- struct breakpoint *breakpoint;
- breakpoint = breakpoint_find(target,
- buf_get_u32(arm->pc->value, 0, 32));
- if (breakpoint != NULL) {
- uint32_t next_pc;
- enum trace_mode saved_trace_mode;
-
- /* there's a breakpoint at the current PC, we have to step over it */
- LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
- xscale_unset_breakpoint(target, breakpoint);
-
- /* calculate PC of next instruction */
- retval = arm_simulate_step(target, &next_pc);
- if (retval != ERROR_OK) {
- uint32_t current_opcode;
- target_read_u32(target, current_pc, &current_opcode);
- LOG_ERROR(
- "BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "",
- current_opcode);
- }
-
- LOG_DEBUG("enable single-step");
- xscale_enable_single_step(target, next_pc);
-
- /* restore banked registers */
- retval = xscale_restore_banked(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* send resume request */
- xscale_send_u32(target, 0x30);
-
- /* send CPSR */
- xscale_send_u32(target,
- buf_get_u32(arm->cpsr->value, 0, 32));
- LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32,
- buf_get_u32(arm->cpsr->value, 0, 32));
-
- for (i = 7; i >= 0; i--) {
- /* send register */
- xscale_send_u32(target,
- buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32));
- LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "",
- i, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32));
- }
-
- /* send PC */
- xscale_send_u32(target,
- buf_get_u32(arm->pc->value, 0, 32));
- LOG_DEBUG("writing PC with value 0x%8.8" PRIx32,
- buf_get_u32(arm->pc->value, 0, 32));
-
- /* disable trace data collection in xscale_debug_entry() */
- saved_trace_mode = xscale->trace.mode;
- xscale->trace.mode = XSCALE_TRACE_DISABLED;
-
- /* wait for and process debug entry */
- xscale_debug_entry(target);
-
- /* re-enable trace buffer, if enabled previously */
- xscale->trace.mode = saved_trace_mode;
-
- LOG_DEBUG("disable single-step");
- xscale_disable_single_step(target);
-
- LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
- xscale_set_breakpoint(target, breakpoint);
- }
- }
-
- /* enable any pending breakpoints and watchpoints */
- xscale_enable_breakpoints(target);
- xscale_enable_watchpoints(target);
-
- /* restore banked registers */
- retval = xscale_restore_banked(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* send resume request (command 0x30 or 0x31)
- * clean the trace buffer if it is to be enabled (0x62) */
- if (xscale->trace.mode != XSCALE_TRACE_DISABLED) {
- if (xscale->trace.mode == XSCALE_TRACE_FILL) {
- /* If trace enabled in fill mode and starting collection of new set
- * of buffers, initialize buffer counter and free previous buffers */
- if (xscale->trace.fill_counter == 0) {
- xscale->trace.fill_counter = xscale->trace.buffer_fill;
- xscale_free_trace_data(xscale);
- }
- } else /* wrap mode; free previous buffer */
- xscale_free_trace_data(xscale);
-
- xscale_send_u32(target, 0x62);
- xscale_send_u32(target, 0x31);
- } else
- xscale_send_u32(target, 0x30);
-
- /* send CPSR */
- xscale_send_u32(target, buf_get_u32(arm->cpsr->value, 0, 32));
- LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32,
- buf_get_u32(arm->cpsr->value, 0, 32));
-
- for (i = 7; i >= 0; i--) {
- /* send register */
- xscale_send_u32(target, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32));
- LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "",
- i, buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32));
- }
-
- /* send PC */
- xscale_send_u32(target, buf_get_u32(arm->pc->value, 0, 32));
- LOG_DEBUG("wrote PC with value 0x%8.8" PRIx32,
- buf_get_u32(arm->pc->value, 0, 32));
-
- target->debug_reason = DBG_REASON_NOTHALTED;
-
- if (!debug_execution) {
- /* registers are now invalid */
- register_cache_invalidate(arm->core_cache);
- target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
- } else {
- target->state = TARGET_DEBUG_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
- }
-
- LOG_DEBUG("target resumed");
-
- return ERROR_OK;
-}
-
-static int xscale_step_inner(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct arm *arm = &xscale->arm;
- uint32_t next_pc;
- int retval;
- int i;
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
-
- /* calculate PC of next instruction */
- retval = arm_simulate_step(target, &next_pc);
- if (retval != ERROR_OK) {
- uint32_t current_opcode, current_pc;
- current_pc = buf_get_u32(arm->pc->value, 0, 32);
-
- target_read_u32(target, current_pc, &current_opcode);
- LOG_ERROR(
- "BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "",
- current_opcode);
- return retval;
- }
-
- LOG_DEBUG("enable single-step");
- retval = xscale_enable_single_step(target, next_pc);
- if (retval != ERROR_OK)
- return retval;
-
- /* restore banked registers */
- retval = xscale_restore_banked(target);
- if (retval != ERROR_OK)
- return retval;
-
- /* send resume request (command 0x30 or 0x31)
- * clean the trace buffer if it is to be enabled (0x62) */
- if (xscale->trace.mode != XSCALE_TRACE_DISABLED) {
- retval = xscale_send_u32(target, 0x62);
- if (retval != ERROR_OK)
- return retval;
- retval = xscale_send_u32(target, 0x31);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = xscale_send_u32(target, 0x30);
- if (retval != ERROR_OK)
- return retval;
- }
-
- /* send CPSR */
- retval = xscale_send_u32(target,
- buf_get_u32(arm->cpsr->value, 0, 32));
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32,
- buf_get_u32(arm->cpsr->value, 0, 32));
-
- for (i = 7; i >= 0; i--) {
- /* send register */
- retval = xscale_send_u32(target,
- buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32));
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "", i,
- buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32));
- }
-
- /* send PC */
- retval = xscale_send_u32(target,
- buf_get_u32(arm->pc->value, 0, 32));
- if (retval != ERROR_OK)
- return retval;
- LOG_DEBUG("wrote PC with value 0x%8.8" PRIx32,
- buf_get_u32(arm->pc->value, 0, 32));
-
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-
- /* registers are now invalid */
- register_cache_invalidate(arm->core_cache);
-
- /* wait for and process debug entry */
- retval = xscale_debug_entry(target);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_DEBUG("disable single-step");
- retval = xscale_disable_single_step(target);
- if (retval != ERROR_OK)
- return retval;
-
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- return ERROR_OK;
-}
-
-static int xscale_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
-{
- struct arm *arm = target_to_arm(target);
- struct breakpoint *breakpoint = NULL;
-
- uint32_t current_pc;
- int retval;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* current = 1: continue on current pc, otherwise continue at <address> */
- if (!current)
- buf_set_u32(arm->pc->value, 0, 32, address);
-
- current_pc = buf_get_u32(arm->pc->value, 0, 32);
-
- /* if we're at the reset vector, we have to simulate the step */
- if (current_pc == 0x0) {
- retval = arm_simulate_step(target, NULL);
- if (retval != ERROR_OK)
- return retval;
- current_pc = buf_get_u32(arm->pc->value, 0, 32);
- LOG_DEBUG("current pc %" PRIx32, current_pc);
-
- target->debug_reason = DBG_REASON_SINGLESTEP;
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-
- return ERROR_OK;
- }
-
- /* the front-end may request us not to handle breakpoints */
- if (handle_breakpoints)
- breakpoint = breakpoint_find(target,
- buf_get_u32(arm->pc->value, 0, 32));
- if (breakpoint != NULL) {
- retval = xscale_unset_breakpoint(target, breakpoint);
- if (retval != ERROR_OK)
- return retval;
- }
-
- retval = xscale_step_inner(target, current, address, handle_breakpoints);
- if (retval != ERROR_OK)
- return retval;
-
- if (breakpoint)
- xscale_set_breakpoint(target, breakpoint);
-
- LOG_DEBUG("target stepped");
-
- return ERROR_OK;
-
-}
-
-static int xscale_assert_reset(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- /* TODO: apply hw reset signal in not examined state */
- if (!(target_was_examined(target))) {
- LOG_WARNING("Reset is not asserted because the target is not examined.");
- LOG_WARNING("Use a reset button or power cycle the target.");
- return ERROR_TARGET_NOT_EXAMINED;
- }
-
- LOG_DEBUG("target->state: %s",
- target_state_name(target));
-
- /* assert reset */
- jtag_add_reset(0, 1);
-
- /* sleep 1ms, to be sure we fulfill any requirements */
- jtag_add_sleep(1000);
- jtag_execute_queue();
-
- /* select DCSR instruction (set endstate to R-T-I to ensure we don't
- * end up in T-L-R, which would reset JTAG
- */
- xscale_jtag_set_instr(target->tap,
- XSCALE_SELDCSR << xscale->xscale_variant,
- TAP_IDLE);
-
- /* set Hold reset, Halt mode and Trap Reset */
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
- xscale_write_dcsr(target, 1, 0);
-
- /* select BYPASS, because having DCSR selected caused problems on the PXA27x */
- xscale_jtag_set_instr(target->tap, ~0, TAP_IDLE);
- jtag_execute_queue();
-
- target->state = TARGET_RESET;
-
- if (target->reset_halt) {
- int retval = target_halt(target);
- if (retval != ERROR_OK)
- return retval;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_deassert_reset(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct breakpoint *breakpoint = target->breakpoints;
-
- LOG_DEBUG("-");
-
- xscale->ibcr_available = 2;
- xscale->ibcr0_used = 0;
- xscale->ibcr1_used = 0;
-
- xscale->dbr_available = 2;
- xscale->dbr0_used = 0;
- xscale->dbr1_used = 0;
-
- /* mark all hardware breakpoints as unset */
- while (breakpoint) {
- if (breakpoint->type == BKPT_HARD)
- breakpoint->set = 0;
- breakpoint = breakpoint->next;
- }
-
- xscale->trace.mode = XSCALE_TRACE_DISABLED;
- xscale_free_trace_data(xscale);
-
- register_cache_invalidate(xscale->arm.core_cache);
-
- /* FIXME mark hardware watchpoints got unset too. Also,
- * at least some of the XScale registers are invalid...
- */
-
- /*
- * REVISIT: *assumes* we had a SRST+TRST reset so the mini-icache
- * contents got invalidated. Safer to force that, so writing new
- * contents can't ever fail..
- */
- {
- uint32_t address;
- unsigned buf_cnt;
- const uint8_t *buffer = xscale_debug_handler;
- int retval;
-
- /* release SRST */
- jtag_add_reset(0, 0);
-
- /* wait 300ms; 150 and 100ms were not enough */
- jtag_add_sleep(300*1000);
-
- jtag_add_runtest(2030, TAP_IDLE);
- jtag_execute_queue();
-
- /* set Hold reset, Halt mode and Trap Reset */
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
- xscale_write_dcsr(target, 1, 0);
-
- /* Load the debug handler into the mini-icache. Since
- * it's using halt mode (not monitor mode), it runs in
- * "Special Debug State" for access to registers, memory,
- * coprocessors, trace data, etc.
- */
- address = xscale->handler_address;
- for (unsigned binary_size = sizeof xscale_debug_handler;
- binary_size > 0;
- binary_size -= buf_cnt, buffer += buf_cnt) {
- uint32_t cache_line[8];
- unsigned i;
-
- buf_cnt = binary_size;
- if (buf_cnt > 32)
- buf_cnt = 32;
-
- for (i = 0; i < buf_cnt; i += 4) {
- /* convert LE buffer to host-endian uint32_t */
- cache_line[i / 4] = le_to_h_u32(&buffer[i]);
- }
-
- for (; i < 32; i += 4)
- cache_line[i / 4] = 0xe1a08008;
-
- /* only load addresses other than the reset vectors */
- if ((address % 0x400) != 0x0) {
- retval = xscale_load_ic(target, address,
- cache_line);
- if (retval != ERROR_OK)
- return retval;
- }
-
- address += buf_cnt;
- }
-
- retval = xscale_load_ic(target, 0x0,
- xscale->low_vectors);
- if (retval != ERROR_OK)
- return retval;
- retval = xscale_load_ic(target, 0xffff0000,
- xscale->high_vectors);
- if (retval != ERROR_OK)
- return retval;
-
- jtag_add_runtest(30, TAP_IDLE);
-
- jtag_add_sleep(100000);
-
- /* set Hold reset, Halt mode and Trap Reset */
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
- xscale_write_dcsr(target, 1, 0);
-
- /* clear Hold reset to let the target run (should enter debug handler) */
- xscale_write_dcsr(target, 0, 1);
- target->state = TARGET_RUNNING;
-
- if (!target->reset_halt) {
- jtag_add_sleep(10000);
-
- /* we should have entered debug now */
- xscale_debug_entry(target);
- target->state = TARGET_HALTED;
-
- /* resume the target */
- xscale_resume(target, 1, 0x0, 1, 0);
- }
- }
-
- return ERROR_OK;
-}
-
-static int xscale_read_core_reg(struct target *target, struct reg *r,
- int num, enum arm_mode mode)
-{
- /** \todo add debug handler support for core register reads */
- LOG_ERROR("not implemented");
- return ERROR_OK;
-}
-
-static int xscale_write_core_reg(struct target *target, struct reg *r,
- int num, enum arm_mode mode, uint8_t *value)
-{
- /** \todo add debug handler support for core register writes */
- LOG_ERROR("not implemented");
- return ERROR_OK;
-}
-
-static int xscale_full_context(struct target *target)
-{
- struct arm *arm = target_to_arm(target);
-
- uint32_t *buffer;
-
- int i, j;
-
- LOG_DEBUG("-");
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- buffer = malloc(4 * 8);
-
- /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)
- * we can't enter User mode on an XScale (unpredictable),
- * but User shares registers with SYS
- */
- for (i = 1; i < 7; i++) {
- enum arm_mode mode = armv4_5_number_to_mode(i);
- bool valid = true;
- struct reg *r;
-
- if (mode == ARM_MODE_USR)
- continue;
-
- /* check if there are invalid registers in the current mode
- */
- for (j = 0; valid && j <= 16; j++) {
- if (!ARMV4_5_CORE_REG_MODE(arm->core_cache,
- mode, j).valid)
- valid = false;
- }
- if (valid)
- continue;
-
- /* request banked registers */
- xscale_send_u32(target, 0x0);
-
- /* send CPSR for desired bank mode */
- xscale_send_u32(target, mode | 0xc0 /* I/F bits */);
-
- /* get banked registers: r8 to r14; and SPSR
- * except in USR/SYS mode
- */
- if (mode != ARM_MODE_SYS) {
- /* SPSR */
- r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
- mode, 16);
-
- xscale_receive(target, buffer, 8);
-
- buf_set_u32(r->value, 0, 32, buffer[7]);
- r->dirty = false;
- r->valid = true;
- } else
- xscale_receive(target, buffer, 7);
-
- /* move data from buffer to register cache */
- for (j = 8; j <= 14; j++) {
- r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
- mode, j);
-
- buf_set_u32(r->value, 0, 32, buffer[j - 8]);
- r->dirty = false;
- r->valid = true;
- }
- }
-
- free(buffer);
-
- return ERROR_OK;
-}
-
-static int xscale_restore_banked(struct target *target)
-{
- struct arm *arm = target_to_arm(target);
-
- int i, j;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)
- * and check if any banked registers need to be written. Ignore
- * USR mode (number 0) in favor of SYS; we can't enter User mode on
- * an XScale (unpredictable), but they share all registers.
- */
- for (i = 1; i < 7; i++) {
- enum arm_mode mode = armv4_5_number_to_mode(i);
- struct reg *r;
-
- if (mode == ARM_MODE_USR)
- continue;
-
- /* check if there are dirty registers in this mode */
- for (j = 8; j <= 14; j++) {
- if (ARMV4_5_CORE_REG_MODE(arm->core_cache,
- mode, j).dirty)
- goto dirty;
- }
-
- /* if not USR/SYS, check if the SPSR needs to be written */
- if (mode != ARM_MODE_SYS) {
- if (ARMV4_5_CORE_REG_MODE(arm->core_cache,
- mode, 16).dirty)
- goto dirty;
- }
-
- /* there's nothing to flush for this mode */
- continue;
-
-dirty:
- /* command 0x1: "send banked registers" */
- xscale_send_u32(target, 0x1);
-
- /* send CPSR for desired mode */
- xscale_send_u32(target, mode | 0xc0 /* I/F bits */);
-
- /* send r8 to r14/lr ... only FIQ needs more than r13..r14,
- * but this protocol doesn't understand that nuance.
- */
- for (j = 8; j <= 14; j++) {
- r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
- mode, j);
- xscale_send_u32(target, buf_get_u32(r->value, 0, 32));
- r->dirty = false;
- }
-
- /* send spsr if not in USR/SYS mode */
- if (mode != ARM_MODE_SYS) {
- r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
- mode, 16);
- xscale_send_u32(target, buf_get_u32(r->value, 0, 32));
- r->dirty = false;
- }
- }
-
- return ERROR_OK;
-}
-
-static int xscale_read_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t *buf32;
- uint32_t i;
- int retval;
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32,
- address,
- size,
- count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- /* send memory read request (command 0x1n, n: access size) */
- retval = xscale_send_u32(target, 0x10 | size);
- if (retval != ERROR_OK)
- return retval;
-
- /* send base address for read request */
- retval = xscale_send_u32(target, address);
- if (retval != ERROR_OK)
- return retval;
-
- /* send number of requested data words */
- retval = xscale_send_u32(target, count);
- if (retval != ERROR_OK)
- return retval;
-
- /* receive data from target (count times 32-bit words in host endianness) */
- buf32 = malloc(4 * count);
- retval = xscale_receive(target, buf32, count);
- if (retval != ERROR_OK) {
- free(buf32);
- return retval;
- }
-
- /* extract data from host-endian buffer into byte stream */
- for (i = 0; i < count; i++) {
- switch (size) {
- case 4:
- target_buffer_set_u32(target, buffer, buf32[i]);
- buffer += 4;
- break;
- case 2:
- target_buffer_set_u16(target, buffer, buf32[i] & 0xffff);
- buffer += 2;
- break;
- case 1:
- *buffer++ = buf32[i] & 0xff;
- break;
- default:
- LOG_ERROR("invalid read size");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- free(buf32);
-
- /* examine DCSR, to see if Sticky Abort (SA) got set */
- retval = xscale_read_dcsr(target);
- if (retval != ERROR_OK)
- return retval;
- if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1) {
- /* clear SA bit */
- retval = xscale_send_u32(target, 0x60);
- if (retval != ERROR_OK)
- return retval;
-
- return ERROR_TARGET_DATA_ABORT;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_read_phys_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, uint8_t *buffer)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- /* with MMU inactive, there are only physical addresses */
- if (!xscale->armv4_5_mmu.mmu_enabled)
- return xscale_read_memory(target, address, size, count, buffer);
-
- /** \todo: provide a non-stub implementation of this routine. */
- LOG_ERROR("%s: %s is not implemented. Disable MMU?",
- target_name(target), __func__);
- return ERROR_FAIL;
-}
-
-static int xscale_write_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
-
- LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32,
- address,
- size,
- count);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* sanitize arguments */
- if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
- return ERROR_TARGET_UNALIGNED_ACCESS;
-
- /* send memory write request (command 0x2n, n: access size) */
- retval = xscale_send_u32(target, 0x20 | size);
- if (retval != ERROR_OK)
- return retval;
-
- /* send base address for read request */
- retval = xscale_send_u32(target, address);
- if (retval != ERROR_OK)
- return retval;
-
- /* send number of requested data words to be written*/
- retval = xscale_send_u32(target, count);
- if (retval != ERROR_OK)
- return retval;
-
- /* extract data from host-endian buffer into byte stream */
-#if 0
- for (i = 0; i < count; i++) {
- switch (size) {
- case 4:
- value = target_buffer_get_u32(target, buffer);
- xscale_send_u32(target, value);
- buffer += 4;
- break;
- case 2:
- value = target_buffer_get_u16(target, buffer);
- xscale_send_u32(target, value);
- buffer += 2;
- break;
- case 1:
- value = *buffer;
- xscale_send_u32(target, value);
- buffer += 1;
- break;
- default:
- LOG_ERROR("should never get here");
- exit(-1);
- }
- }
-#endif
- retval = xscale_send(target, buffer, count, size);
- if (retval != ERROR_OK)
- return retval;
-
- /* examine DCSR, to see if Sticky Abort (SA) got set */
- retval = xscale_read_dcsr(target);
- if (retval != ERROR_OK)
- return retval;
- if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1) {
- /* clear SA bit */
- retval = xscale_send_u32(target, 0x60);
- if (retval != ERROR_OK)
- return retval;
-
- LOG_ERROR("data abort writing memory");
- return ERROR_TARGET_DATA_ABORT;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_write_phys_memory(struct target *target, uint32_t address,
- uint32_t size, uint32_t count, const uint8_t *buffer)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- /* with MMU inactive, there are only physical addresses */
- if (!xscale->armv4_5_mmu.mmu_enabled)
- return xscale_write_memory(target, address, size, count, buffer);
-
- /** \todo: provide a non-stub implementation of this routine. */
- LOG_ERROR("%s: %s is not implemented. Disable MMU?",
- target_name(target), __func__);
- return ERROR_FAIL;
-}
-
-static int xscale_get_ttb(struct target *target, uint32_t *result)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t ttb;
- int retval;
-
- retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_TTB]);
- if (retval != ERROR_OK)
- return retval;
- ttb = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_TTB].value, 0, 32);
-
- *result = ttb;
-
- return ERROR_OK;
-}
-
-static int xscale_disable_mmu_caches(struct target *target, int mmu,
- int d_u_cache, int i_cache)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
- if (retval != ERROR_OK)
- return retval;
- cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
-
- if (mmu)
- cp15_control &= ~0x1U;
-
- if (d_u_cache) {
- /* clean DCache */
- retval = xscale_send_u32(target, 0x50);
- if (retval != ERROR_OK)
- return retval;
- retval = xscale_send_u32(target, xscale->cache_clean_address);
- if (retval != ERROR_OK)
- return retval;
-
- /* invalidate DCache */
- retval = xscale_send_u32(target, 0x51);
- if (retval != ERROR_OK)
- return retval;
-
- cp15_control &= ~0x4U;
- }
-
- if (i_cache) {
- /* invalidate ICache */
- retval = xscale_send_u32(target, 0x52);
- if (retval != ERROR_OK)
- return retval;
- cp15_control &= ~0x1000U;
- }
-
- /* write new cp15 control register */
- retval = xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
- if (retval != ERROR_OK)
- return retval;
-
- /* execute cpwait to ensure outstanding operations complete */
- retval = xscale_send_u32(target, 0x53);
- return retval;
-}
-
-static int xscale_enable_mmu_caches(struct target *target, int mmu,
- int d_u_cache, int i_cache)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t cp15_control;
- int retval;
-
- /* read cp15 control register */
- retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
- if (retval != ERROR_OK)
- return retval;
- cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
-
- if (mmu)
- cp15_control |= 0x1U;
-
- if (d_u_cache)
- cp15_control |= 0x4U;
-
- if (i_cache)
- cp15_control |= 0x1000U;
-
- /* write new cp15 control register */
- retval = xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
- if (retval != ERROR_OK)
- return retval;
-
- /* execute cpwait to ensure outstanding operations complete */
- retval = xscale_send_u32(target, 0x53);
- return retval;
-}
-
-static int xscale_set_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- int retval;
- struct xscale_common *xscale = target_to_xscale(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (breakpoint->set) {
- LOG_WARNING("breakpoint already set");
- return ERROR_OK;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- uint32_t value = breakpoint->address | 1;
- if (!xscale->ibcr0_used) {
- xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value);
- xscale->ibcr0_used = 1;
- breakpoint->set = 1; /* breakpoint set on first breakpoint register */
- } else if (!xscale->ibcr1_used) {
- xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value);
- xscale->ibcr1_used = 1;
- breakpoint->set = 2; /* breakpoint set on second breakpoint register */
- } else {/* bug: availability previously verified in xscale_add_breakpoint() */
- LOG_ERROR("BUG: no hardware comparator available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
- } else if (breakpoint->type == BKPT_SOFT) {
- if (breakpoint->length == 4) {
- /* keep the original instruction in target endianness */
- retval = target_read_memory(target, breakpoint->address, 4, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- /* write the bkpt instruction in target endianness
- *(arm7_9->arm_bkpt is host endian) */
- retval = target_write_u32(target, breakpoint->address,
- xscale->arm_bkpt);
- if (retval != ERROR_OK)
- return retval;
- } else {
- /* keep the original instruction in target endianness */
- retval = target_read_memory(target, breakpoint->address, 2, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- /* write the bkpt instruction in target endianness
- *(arm7_9->arm_bkpt is host endian) */
- retval = target_write_u16(target, breakpoint->address,
- xscale->thumb_bkpt);
- if (retval != ERROR_OK)
- return retval;
- }
- breakpoint->set = 1;
-
- xscale_send_u32(target, 0x50); /* clean dcache */
- xscale_send_u32(target, xscale->cache_clean_address);
- xscale_send_u32(target, 0x51); /* invalidate dcache */
- xscale_send_u32(target, 0x52); /* invalidate icache and flush fetch buffers */
- }
-
- return ERROR_OK;
-}
-
-static int xscale_add_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1)) {
- LOG_ERROR("no breakpoint unit available for hardware breakpoint");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if ((breakpoint->length != 2) && (breakpoint->length != 4)) {
- LOG_ERROR("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (breakpoint->type == BKPT_HARD)
- xscale->ibcr_available--;
-
- return xscale_set_breakpoint(target, breakpoint);
-}
-
-static int xscale_unset_breakpoint(struct target *target,
- struct breakpoint *breakpoint)
-{
- int retval;
- struct xscale_common *xscale = target_to_xscale(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!breakpoint->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- if (breakpoint->type == BKPT_HARD) {
- if (breakpoint->set == 1) {
- xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], 0x0);
- xscale->ibcr0_used = 0;
- } else if (breakpoint->set == 2) {
- xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], 0x0);
- xscale->ibcr1_used = 0;
- }
- breakpoint->set = 0;
- } else {
- /* restore original instruction (kept in target endianness) */
- if (breakpoint->length == 4) {
- retval = target_write_memory(target, breakpoint->address, 4, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- } else {
- retval = target_write_memory(target, breakpoint->address, 2, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- }
- breakpoint->set = 0;
-
- xscale_send_u32(target, 0x50); /* clean dcache */
- xscale_send_u32(target, xscale->cache_clean_address);
- xscale_send_u32(target, 0x51); /* invalidate dcache */
- xscale_send_u32(target, 0x52); /* invalidate icache and flush fetch buffers */
- }
-
- return ERROR_OK;
-}
-
-static int xscale_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (breakpoint->set)
- xscale_unset_breakpoint(target, breakpoint);
-
- if (breakpoint->type == BKPT_HARD)
- xscale->ibcr_available++;
-
- return ERROR_OK;
-}
-
-static int xscale_set_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t enable = 0;
- struct reg *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
- uint32_t dbcon_value = buf_get_u32(dbcon->value, 0, 32);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- switch (watchpoint->rw) {
- case WPT_READ:
- enable = 0x3;
- break;
- case WPT_ACCESS:
- enable = 0x2;
- break;
- case WPT_WRITE:
- enable = 0x1;
- break;
- default:
- LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
- }
-
- /* For watchpoint across more than one word, both DBR registers must
- be enlisted, with the second used as a mask. */
- if (watchpoint->length > 4) {
- if (xscale->dbr0_used || xscale->dbr1_used) {
- LOG_ERROR("BUG: sufficient hardware comparators unavailable");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- /* Write mask value to DBR1, based on the length argument.
- * Address bits ignored by the comparator are those set in mask. */
- xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1],
- watchpoint->length - 1);
- xscale->dbr1_used = 1;
- enable |= 0x100; /* DBCON[M] */
- }
-
- if (!xscale->dbr0_used) {
- xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address);
- dbcon_value |= enable;
- xscale_set_reg_u32(dbcon, dbcon_value);
- watchpoint->set = 1;
- xscale->dbr0_used = 1;
- } else if (!xscale->dbr1_used) {
- xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address);
- dbcon_value |= enable << 2;
- xscale_set_reg_u32(dbcon, dbcon_value);
- watchpoint->set = 2;
- xscale->dbr1_used = 1;
- } else {
- LOG_ERROR("BUG: no hardware comparator available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_add_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- if (xscale->dbr_available < 1) {
- LOG_ERROR("no more watchpoint registers available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (watchpoint->value)
- LOG_WARNING("xscale does not support value, mask arguments; ignoring");
-
- /* check that length is a power of two */
- for (uint32_t len = watchpoint->length; len != 1; len /= 2) {
- if (len % 2) {
- LOG_ERROR("xscale requires that watchpoint length is a power of two");
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
- }
-
- if (watchpoint->length == 4) { /* single word watchpoint */
- xscale->dbr_available--;/* one DBR reg used */
- return ERROR_OK;
- }
-
- /* watchpoints across multiple words require both DBR registers */
- if (xscale->dbr_available < 2) {
- LOG_ERROR("insufficient watchpoint registers available");
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
-
- if (watchpoint->length > watchpoint->address) {
- LOG_ERROR("xscale does not support watchpoints with length "
- "greater than address");
- return ERROR_COMMAND_ARGUMENT_INVALID;
- }
-
- xscale->dbr_available = 0;
- return ERROR_OK;
-}
-
-static int xscale_unset_watchpoint(struct target *target,
- struct watchpoint *watchpoint)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct reg *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
- uint32_t dbcon_value = buf_get_u32(dbcon->value, 0, 32);
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (!watchpoint->set) {
- LOG_WARNING("breakpoint not set");
- return ERROR_OK;
- }
-
- if (watchpoint->set == 1) {
- if (watchpoint->length > 4) {
- dbcon_value &= ~0x103; /* clear DBCON[M] as well */
- xscale->dbr1_used = 0; /* DBR1 was used for mask */
- } else
- dbcon_value &= ~0x3;
-
- xscale_set_reg_u32(dbcon, dbcon_value);
- xscale->dbr0_used = 0;
- } else if (watchpoint->set == 2) {
- dbcon_value &= ~0xc;
- xscale_set_reg_u32(dbcon, dbcon_value);
- xscale->dbr1_used = 0;
- }
- watchpoint->set = 0;
-
- return ERROR_OK;
-}
-
-static int xscale_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- if (watchpoint->set)
- xscale_unset_watchpoint(target, watchpoint);
-
- if (watchpoint->length > 4)
- xscale->dbr_available++;/* both DBR regs now available */
-
- xscale->dbr_available++;
-
- return ERROR_OK;
-}
-
-static int xscale_get_reg(struct reg *reg)
-{
- struct xscale_reg *arch_info = reg->arch_info;
- struct target *target = arch_info->target;
- struct xscale_common *xscale = target_to_xscale(target);
-
- /* DCSR, TX and RX are accessible via JTAG */
- if (strcmp(reg->name, "XSCALE_DCSR") == 0)
- return xscale_read_dcsr(arch_info->target);
- else if (strcmp(reg->name, "XSCALE_TX") == 0) {
- /* 1 = consume register content */
- return xscale_read_tx(arch_info->target, 1);
- } else if (strcmp(reg->name, "XSCALE_RX") == 0) {
- /* can't read from RX register (host -> debug handler) */
- return ERROR_OK;
- } else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0) {
- /* can't (explicitly) read from TXRXCTRL register */
- return ERROR_OK;
- } else {/* Other DBG registers have to be transfered by the debug handler
- * send CP read request (command 0x40) */
- xscale_send_u32(target, 0x40);
-
- /* send CP register number */
- xscale_send_u32(target, arch_info->dbg_handler_number);
-
- /* read register value */
- xscale_read_tx(target, 1);
- buf_cpy(xscale->reg_cache->reg_list[XSCALE_TX].value, reg->value, 32);
-
- reg->dirty = 0;
- reg->valid = 1;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_set_reg(struct reg *reg, uint8_t *buf)
-{
- struct xscale_reg *arch_info = reg->arch_info;
- struct target *target = arch_info->target;
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t value = buf_get_u32(buf, 0, 32);
-
- /* DCSR, TX and RX are accessible via JTAG */
- if (strcmp(reg->name, "XSCALE_DCSR") == 0) {
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32, value);
- return xscale_write_dcsr(arch_info->target, -1, -1);
- } else if (strcmp(reg->name, "XSCALE_RX") == 0) {
- buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);
- return xscale_write_rx(arch_info->target);
- } else if (strcmp(reg->name, "XSCALE_TX") == 0) {
- /* can't write to TX register (debug-handler -> host) */
- return ERROR_OK;
- } else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0) {
- /* can't (explicitly) write to TXRXCTRL register */
- return ERROR_OK;
- } else {/* Other DBG registers have to be transfered by the debug handler
- * send CP write request (command 0x41) */
- xscale_send_u32(target, 0x41);
-
- /* send CP register number */
- xscale_send_u32(target, arch_info->dbg_handler_number);
-
- /* send CP register value */
- xscale_send_u32(target, value);
- buf_set_u32(reg->value, 0, 32, value);
- }
-
- return ERROR_OK;
-}
-
-static int xscale_write_dcsr_sw(struct target *target, uint32_t value)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct reg *dcsr = &xscale->reg_cache->reg_list[XSCALE_DCSR];
- struct xscale_reg *dcsr_arch_info = dcsr->arch_info;
-
- /* send CP write request (command 0x41) */
- xscale_send_u32(target, 0x41);
-
- /* send CP register number */
- xscale_send_u32(target, dcsr_arch_info->dbg_handler_number);
-
- /* send CP register value */
- xscale_send_u32(target, value);
- buf_set_u32(dcsr->value, 0, 32, value);
-
- return ERROR_OK;
-}
-
-static int xscale_read_trace(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct arm *arm = &xscale->arm;
- struct xscale_trace_data **trace_data_p;
-
- /* 258 words from debug handler
- * 256 trace buffer entries
- * 2 checkpoint addresses
- */
- uint32_t trace_buffer[258];
- int is_address[256];
- int i, j;
- unsigned int num_checkpoints = 0;
-
- if (target->state != TARGET_HALTED) {
- LOG_WARNING("target must be stopped to read trace data");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- /* send read trace buffer command (command 0x61) */
- xscale_send_u32(target, 0x61);
-
- /* receive trace buffer content */
- xscale_receive(target, trace_buffer, 258);
-
- /* parse buffer backwards to identify address entries */
- for (i = 255; i >= 0; i--) {
- /* also count number of checkpointed entries */
- if ((trace_buffer[i] & 0xe0) == 0xc0)
- num_checkpoints++;
-
- is_address[i] = 0;
- if (((trace_buffer[i] & 0xf0) == 0x90) ||
- ((trace_buffer[i] & 0xf0) == 0xd0)) {
- if (i > 0)
- is_address[--i] = 1;
- if (i > 0)
- is_address[--i] = 1;
- if (i > 0)
- is_address[--i] = 1;
- if (i > 0)
- is_address[--i] = 1;
- }
- }
-
-
- /* search first non-zero entry that is not part of an address */
- for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++)
- ;
-
- if (j == 256) {
- LOG_DEBUG("no trace data collected");
- return ERROR_XSCALE_NO_TRACE_DATA;
- }
-
- /* account for possible partial address at buffer start (wrap mode only) */
- if (is_address[0]) { /* first entry is address; complete set of 4? */
- i = 1;
- while (i < 4)
- if (!is_address[i++])
- break;
- if (i < 4)
- j += i; /* partial address; can't use it */
- }
-
- /* if first valid entry is indirect branch, can't use that either (no address) */
- if (((trace_buffer[j] & 0xf0) == 0x90) || ((trace_buffer[j] & 0xf0) == 0xd0))
- j++;
-
- /* walk linked list to terminating entry */
- for (trace_data_p = &xscale->trace.data; *trace_data_p;
- trace_data_p = &(*trace_data_p)->next)
- ;
-
- *trace_data_p = malloc(sizeof(struct xscale_trace_data));
- (*trace_data_p)->next = NULL;
- (*trace_data_p)->chkpt0 = trace_buffer[256];
- (*trace_data_p)->chkpt1 = trace_buffer[257];
- (*trace_data_p)->last_instruction = buf_get_u32(arm->pc->value, 0, 32);
- (*trace_data_p)->entries = malloc(sizeof(struct xscale_trace_entry) * (256 - j));
- (*trace_data_p)->depth = 256 - j;
- (*trace_data_p)->num_checkpoints = num_checkpoints;
-
- for (i = j; i < 256; i++) {
- (*trace_data_p)->entries[i - j].data = trace_buffer[i];
- if (is_address[i])
- (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_ADDRESS;
- else
- (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_MESSAGE;
- }
-
- return ERROR_OK;
-}
-
-static int xscale_read_instruction(struct target *target, uint32_t pc,
- struct arm_instruction *instruction)
-{
- struct xscale_common *const xscale = target_to_xscale(target);
- int i;
- int section = -1;
- size_t size_read;
- uint32_t opcode;
- int retval;
-
- if (!xscale->trace.image)
- return ERROR_TRACE_IMAGE_UNAVAILABLE;
-
- /* search for the section the current instruction belongs to */
- for (i = 0; i < xscale->trace.image->num_sections; i++) {
- if ((xscale->trace.image->sections[i].base_address <= pc) &&
- (xscale->trace.image->sections[i].base_address +
- xscale->trace.image->sections[i].size > pc)) {
- section = i;
- break;
- }
- }
-
- if (section == -1) {
- /* current instruction couldn't be found in the image */
- return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
- }
-
- if (xscale->trace.core_state == ARM_STATE_ARM) {
- uint8_t buf[4];
- retval = image_read_section(xscale->trace.image, section,
- pc - xscale->trace.image->sections[section].base_address,
- 4, buf, &size_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("error while reading instruction");
- return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
- }
- opcode = target_buffer_get_u32(target, buf);
- arm_evaluate_opcode(opcode, pc, instruction);
- } else if (xscale->trace.core_state == ARM_STATE_THUMB) {
- uint8_t buf[2];
- retval = image_read_section(xscale->trace.image, section,
- pc - xscale->trace.image->sections[section].base_address,
- 2, buf, &size_read);
- if (retval != ERROR_OK) {
- LOG_ERROR("error while reading instruction");
- return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
- }
- opcode = target_buffer_get_u16(target, buf);
- thumb_evaluate_opcode(opcode, pc, instruction);
- } else {
- LOG_ERROR("BUG: unknown core state encountered");
- exit(-1);
- }
-
- return ERROR_OK;
-}
-
-/* Extract address encoded into trace data.
- * Write result to address referenced by argument 'target', or 0 if incomplete. */
-static inline void xscale_branch_address(struct xscale_trace_data *trace_data,
- int i, uint32_t *target)
-{
- /* if there are less than four entries prior to the indirect branch message
- * we can't extract the address */
- if (i < 4)
- *target = 0;
- else {
- *target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |
- (trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);
- }
-}
-
-static inline void xscale_display_instruction(struct target *target, uint32_t pc,
- struct arm_instruction *instruction,
- struct command_context *cmd_ctx)
-{
- int retval = xscale_read_instruction(target, pc, instruction);
- if (retval == ERROR_OK)
- command_print(cmd_ctx, "%s", instruction->text);
- else
- command_print(cmd_ctx, "0x%8.8" PRIx32 "\t<not found in image>", pc);
-}
-
-static int xscale_analyze_trace(struct target *target, struct command_context *cmd_ctx)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct xscale_trace_data *trace_data = xscale->trace.data;
- int i, retval;
- uint32_t breakpoint_pc = 0;
- struct arm_instruction instruction;
- uint32_t current_pc = 0;/* initialized when address determined */
-
- if (!xscale->trace.image)
- LOG_WARNING("No trace image loaded; use 'xscale trace_image'");
-
- /* loop for each trace buffer that was loaded from target */
- while (trace_data) {
- int chkpt = 0; /* incremented as checkpointed entries found */
- int j;
-
- /* FIXME: set this to correct mode when trace buffer is first enabled */
- xscale->trace.core_state = ARM_STATE_ARM;
-
- /* loop for each entry in this trace buffer */
- for (i = 0; i < trace_data->depth; i++) {
- int exception = 0;
- uint32_t chkpt_reg = 0x0;
- uint32_t branch_target = 0;
- int count;
-
- /* trace entry type is upper nybble of 'message byte' */
- int trace_msg_type = (trace_data->entries[i].data & 0xf0) >> 4;
-
- /* Target addresses of indirect branches are written into buffer
- * before the message byte representing the branch. Skip past it */
- if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
- continue;
-
- switch (trace_msg_type) {
- case 0: /* Exceptions */
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- exception = (trace_data->entries[i].data & 0x70) >> 4;
-
- /* FIXME: vector table may be at ffff0000 */
- branch_target = (trace_data->entries[i].data & 0xf0) >> 2;
- break;
-
- case 8: /* Direct Branch */
- break;
-
- case 9: /* Indirect Branch */
- xscale_branch_address(trace_data, i, &branch_target);
- break;
-
- case 13: /* Checkpointed Indirect Branch */
- xscale_branch_address(trace_data, i, &branch_target);
- if ((trace_data->num_checkpoints == 2) && (chkpt == 0))
- chkpt_reg = trace_data->chkpt1; /* 2 chkpts, this is
- *oldest */
- else
- chkpt_reg = trace_data->chkpt0; /* 1 chkpt, or 2 and
- *newest */
-
- chkpt++;
- break;
-
- case 12: /* Checkpointed Direct Branch */
- if ((trace_data->num_checkpoints == 2) && (chkpt == 0))
- chkpt_reg = trace_data->chkpt1; /* 2 chkpts, this is
- *oldest */
- else
- chkpt_reg = trace_data->chkpt0; /* 1 chkpt, or 2 and
- *newest */
-
- /* if no current_pc, checkpoint will be starting point */
- if (current_pc == 0)
- branch_target = chkpt_reg;
-
- chkpt++;
- break;
-
- case 15:/* Roll-over */
- break;
-
- default:/* Reserved */
- LOG_WARNING("trace is suspect: invalid trace message byte");
- continue;
-
- }
-
- /* If we don't have the current_pc yet, but we did get the branch target
- * (either from the trace buffer on indirect branch, or from a checkpoint reg),
- * then we can start displaying instructions at the next iteration, with
- * branch_target as the starting point.
- */
- if (current_pc == 0) {
- current_pc = branch_target; /* remains 0 unless branch_target *obtained */
- continue;
- }
-
- /* We have current_pc. Read and display the instructions from the image.
- * First, display count instructions (lower nybble of message byte). */
- count = trace_data->entries[i].data & 0x0f;
- for (j = 0; j < count; j++) {
- xscale_display_instruction(target, current_pc, &instruction,
- cmd_ctx);
- current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2;
- }
-
- /* An additional instruction is implicitly added to count for
- * rollover and some exceptions: undef, swi, prefetch abort. */
- if ((trace_msg_type == 15) || (exception > 0 && exception < 4)) {
- xscale_display_instruction(target, current_pc, &instruction,
- cmd_ctx);
- current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2;
- }
-
- if (trace_msg_type == 15) /* rollover */
- continue;
-
- if (exception) {
- command_print(cmd_ctx, "--- exception %i ---", exception);
- continue;
- }
-
- /* not exception or rollover; next instruction is a branch and is
- * not included in the count */
- xscale_display_instruction(target, current_pc, &instruction, cmd_ctx);
-
- /* for direct branches, extract branch destination from instruction */
- if ((trace_msg_type == 8) || (trace_msg_type == 12)) {
- retval = xscale_read_instruction(target, current_pc, &instruction);
- if (retval == ERROR_OK)
- current_pc = instruction.info.b_bl_bx_blx.target_address;
- else
- current_pc = 0; /* branch destination unknown */
-
- /* direct branch w/ checkpoint; can also get from checkpoint reg */
- if (trace_msg_type == 12) {
- if (current_pc == 0)
- current_pc = chkpt_reg;
- else if (current_pc != chkpt_reg) /* sanity check */
- LOG_WARNING("trace is suspect: checkpoint register "
- "inconsistent with adddress from image");
- }
-
- if (current_pc == 0)
- command_print(cmd_ctx, "address unknown");
-
- continue;
- }
-
- /* indirect branch; the branch destination was read from trace buffer */
- if ((trace_msg_type == 9) || (trace_msg_type == 13)) {
- current_pc = branch_target;
-
- /* sanity check (checkpoint reg is redundant) */
- if ((trace_msg_type == 13) && (chkpt_reg != branch_target))
- LOG_WARNING("trace is suspect: checkpoint register "
- "inconsistent with address from trace buffer");
- }
-
- } /* END: for (i = 0; i < trace_data->depth; i++) */
-
- breakpoint_pc = trace_data->last_instruction; /* used below */
- trace_data = trace_data->next;
-
- } /* END: while (trace_data) */
-
- /* Finally... display all instructions up to the value of the pc when the
- * debug break occurred (saved when trace data was collected from target).
- * This is necessary because the trace only records execution branches and 16
- * consecutive instructions (rollovers), so last few typically missed.
- */
- if (current_pc == 0)
- return ERROR_OK;/* current_pc was never found */
-
- /* how many instructions remaining? */
- int gap_count = (breakpoint_pc - current_pc) /
- (xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2);
-
- /* should never be negative or over 16, but verify */
- if (gap_count < 0 || gap_count > 16) {
- LOG_WARNING("trace is suspect: excessive gap at end of trace");
- return ERROR_OK;/* bail; large number or negative value no good */
- }
-
- /* display remaining instructions */
- for (i = 0; i < gap_count; i++) {
- xscale_display_instruction(target, current_pc, &instruction, cmd_ctx);
- current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2;
- }
-
- return ERROR_OK;
-}
-
-static const struct reg_arch_type xscale_reg_type = {
- .get = xscale_get_reg,
- .set = xscale_set_reg,
-};
-
-static void xscale_build_reg_cache(struct target *target)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- struct arm *arm = &xscale->arm;
- struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct xscale_reg *arch_info = malloc(sizeof(xscale_reg_arch_info));
- int i;
- int num_regs = ARRAY_SIZE(xscale_reg_arch_info);
-
- (*cache_p) = arm_build_reg_cache(target, arm);
-
- (*cache_p)->next = malloc(sizeof(struct reg_cache));
- cache_p = &(*cache_p)->next;
-
- /* fill in values for the xscale reg cache */
- (*cache_p)->name = "XScale registers";
- (*cache_p)->next = NULL;
- (*cache_p)->reg_list = malloc(num_regs * sizeof(struct reg));
- (*cache_p)->num_regs = num_regs;
-
- for (i = 0; i < num_regs; i++) {
- (*cache_p)->reg_list[i].name = xscale_reg_list[i];
- (*cache_p)->reg_list[i].value = calloc(4, 1);
- (*cache_p)->reg_list[i].dirty = 0;
- (*cache_p)->reg_list[i].valid = 0;
- (*cache_p)->reg_list[i].size = 32;
- (*cache_p)->reg_list[i].arch_info = &arch_info[i];
- (*cache_p)->reg_list[i].type = &xscale_reg_type;
- arch_info[i] = xscale_reg_arch_info[i];
- arch_info[i].target = target;
- }
-
- xscale->reg_cache = (*cache_p);
-}
-
-static int xscale_init_target(struct command_context *cmd_ctx,
- struct target *target)
-{
- xscale_build_reg_cache(target);
- return ERROR_OK;
-}
-
-static int xscale_init_arch_info(struct target *target,
- struct xscale_common *xscale, struct jtag_tap *tap)
-{
- struct arm *arm;
- uint32_t high_reset_branch, low_reset_branch;
- int i;
-
- arm = &xscale->arm;
-
- /* store architecture specfic data */
- xscale->common_magic = XSCALE_COMMON_MAGIC;
-
- /* PXA3xx with 11 bit IR shifts the JTAG instructions */
- if (tap->ir_length == 11)
- xscale->xscale_variant = XSCALE_PXA3XX;
- else
- xscale->xscale_variant = XSCALE_IXP4XX_PXA2XX;
-
- /* the debug handler isn't installed (and thus not running) at this time */
- xscale->handler_address = 0xfe000800;
-
- /* clear the vectors we keep locally for reference */
- memset(xscale->low_vectors, 0, sizeof(xscale->low_vectors));
- memset(xscale->high_vectors, 0, sizeof(xscale->high_vectors));
-
- /* no user-specified vectors have been configured yet */
- xscale->static_low_vectors_set = 0x0;
- xscale->static_high_vectors_set = 0x0;
-
- /* calculate branches to debug handler */
- low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;
- high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;
-
- xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);
- xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);
-
- for (i = 1; i <= 7; i++) {
- xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
- xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
- }
-
- /* 64kB aligned region used for DCache cleaning */
- xscale->cache_clean_address = 0xfffe0000;
-
- xscale->hold_rst = 0;
- xscale->external_debug_break = 0;
-
- xscale->ibcr_available = 2;
- xscale->ibcr0_used = 0;
- xscale->ibcr1_used = 0;
-
- xscale->dbr_available = 2;
- xscale->dbr0_used = 0;
- xscale->dbr1_used = 0;
-
- LOG_INFO("%s: hardware has 2 breakpoints and 2 watchpoints",
- target_name(target));
-
- xscale->arm_bkpt = ARMV5_BKPT(0x0);
- xscale->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
-
- xscale->vector_catch = 0x1;
-
- xscale->trace.data = NULL;
- xscale->trace.image = NULL;
- xscale->trace.mode = XSCALE_TRACE_DISABLED;
- xscale->trace.buffer_fill = 0;
- xscale->trace.fill_counter = 0;
-
- /* prepare ARMv4/5 specific information */
- arm->arch_info = xscale;
- arm->core_type = ARM_MODE_ANY;
- arm->read_core_reg = xscale_read_core_reg;
- arm->write_core_reg = xscale_write_core_reg;
- arm->full_context = xscale_full_context;
-
- arm_init_arch_info(target, arm);
-
- xscale->armv4_5_mmu.armv4_5_cache.ctype = -1;
- xscale->armv4_5_mmu.get_ttb = xscale_get_ttb;
- xscale->armv4_5_mmu.read_memory = xscale_read_memory;
- xscale->armv4_5_mmu.write_memory = xscale_write_memory;
- xscale->armv4_5_mmu.disable_mmu_caches = xscale_disable_mmu_caches;
- xscale->armv4_5_mmu.enable_mmu_caches = xscale_enable_mmu_caches;
- xscale->armv4_5_mmu.has_tiny_pages = 1;
- xscale->armv4_5_mmu.mmu_enabled = 0;
-
- return ERROR_OK;
-}
-
-static int xscale_target_create(struct target *target, Jim_Interp *interp)
-{
- struct xscale_common *xscale;
-
- if (sizeof xscale_debug_handler > 0x800) {
- LOG_ERROR("debug_handler.bin: larger than 2kb");
- return ERROR_FAIL;
- }
-
- xscale = calloc(1, sizeof(*xscale));
- if (!xscale)
- return ERROR_FAIL;
-
- return xscale_init_arch_info(target, xscale, target->tap);
-}
-
-COMMAND_HANDLER(xscale_handle_debug_handler_command)
-{
- struct target *target = NULL;
- struct xscale_common *xscale;
- int retval;
- uint32_t handler_address;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_target(CMD_ARGV[0]);
- if (target == NULL) {
- LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
-
- xscale = target_to_xscale(target);
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], handler_address);
-
- if (((handler_address >= 0x800) && (handler_address <= 0x1fef800)) ||
- ((handler_address >= 0xfe000800) && (handler_address <= 0xfffff800)))
- xscale->handler_address = handler_address;
- else {
- LOG_ERROR(
- "xscale debug_handler <address> must be between 0x800 and 0x1fef800 or between 0xfe000800 and 0xfffff800");
- return ERROR_FAIL;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_cache_clean_address_command)
-{
- struct target *target = NULL;
- struct xscale_common *xscale;
- int retval;
- uint32_t cache_clean_address;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- target = get_target(CMD_ARGV[0]);
- if (target == NULL) {
- LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
- xscale = target_to_xscale(target);
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cache_clean_address);
-
- if (cache_clean_address & 0xffff)
- LOG_ERROR("xscale cache_clean_address <address> must be 64kb aligned");
- else
- xscale->cache_clean_address = cache_clean_address;
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_cache_info_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- return armv4_5_handle_cache_info_command(CMD_CTX, &xscale->armv4_5_mmu.armv4_5_cache);
-}
-
-static int xscale_virt2phys(struct target *target,
- uint32_t virtual, uint32_t *physical)
-{
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t cb;
-
- if (xscale->common_magic != XSCALE_COMMON_MAGIC) {
- LOG_ERROR(xscale_not);
- return ERROR_TARGET_INVALID;
- }
-
- uint32_t ret;
- int retval = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu,
- virtual, &cb, &ret);
- if (retval != ERROR_OK)
- return retval;
- *physical = ret;
- return ERROR_OK;
-}
-
-static int xscale_mmu(struct target *target, int *enabled)
-{
- struct xscale_common *xscale = target_to_xscale(target);
-
- if (target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_INVALID;
- }
- *enabled = xscale->armv4_5_mmu.mmu_enabled;
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_mmu_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- if (CMD_ARGC >= 1) {
- bool enable;
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
- if (enable)
- xscale_enable_mmu_caches(target, 1, 0, 0);
- else
- xscale_disable_mmu_caches(target, 1, 0, 0);
- xscale->armv4_5_mmu.mmu_enabled = enable;
- }
-
- command_print(CMD_CTX, "mmu %s",
- (xscale->armv4_5_mmu.mmu_enabled) ? "enabled" : "disabled");
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_idcache_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
-
- int retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- bool icache = false;
- if (strcmp(CMD_NAME, "icache") == 0)
- icache = true;
- if (CMD_ARGC >= 1) {
- bool enable;
- COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
- if (icache) {
- xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = enable;
- if (enable)
- xscale_enable_mmu_caches(target, 0, 0, 1);
- else
- xscale_disable_mmu_caches(target, 0, 0, 1);
- } else {
- xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = enable;
- if (enable)
- xscale_enable_mmu_caches(target, 0, 1, 0);
- else
- xscale_disable_mmu_caches(target, 0, 1, 0);
- }
- }
-
- bool enabled = icache ?
- xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled :
- xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled;
- const char *msg = enabled ? "enabled" : "disabled";
- command_print(CMD_CTX, "%s %s", CMD_NAME, msg);
-
- return ERROR_OK;
-}
-
-static const struct {
- char name[15];
- unsigned mask;
-} vec_ids[] = {
- { "fiq", DCSR_TF, },
- { "irq", DCSR_TI, },
- { "dabt", DCSR_TD, },
- { "pabt", DCSR_TA, },
- { "swi", DCSR_TS, },
- { "undef", DCSR_TU, },
- { "reset", DCSR_TR, },
-};
-
-COMMAND_HANDLER(xscale_handle_vector_catch_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
- uint32_t dcsr_value;
- uint32_t catch = 0;
- struct reg *dcsr_reg = &xscale->reg_cache->reg_list[XSCALE_DCSR];
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- dcsr_value = buf_get_u32(dcsr_reg->value, 0, 32);
- if (CMD_ARGC > 0) {
- if (CMD_ARGC == 1) {
- if (strcmp(CMD_ARGV[0], "all") == 0) {
- catch = DCSR_TRAP_MASK;
- CMD_ARGC--;
- } else if (strcmp(CMD_ARGV[0], "none") == 0) {
- catch = 0;
- CMD_ARGC--;
- }
- }
- while (CMD_ARGC-- > 0) {
- unsigned i;
- for (i = 0; i < ARRAY_SIZE(vec_ids); i++) {
- if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name))
- continue;
- catch |= vec_ids[i].mask;
- break;
- }
- if (i == ARRAY_SIZE(vec_ids)) {
- LOG_ERROR("No vector '%s'", CMD_ARGV[CMD_ARGC]);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
- buf_set_u32(dcsr_reg->value, 0, 32,
- (buf_get_u32(dcsr_reg->value, 0, 32) & ~DCSR_TRAP_MASK) | catch);
- xscale_write_dcsr(target, -1, -1);
- }
-
- dcsr_value = buf_get_u32(dcsr_reg->value, 0, 32);
- for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) {
- command_print(CMD_CTX, "%15s: %s", vec_ids[i].name,
- (dcsr_value & vec_ids[i].mask) ? "catch" : "ignore");
- }
-
- return ERROR_OK;
-}
-
-
-COMMAND_HANDLER(xscale_handle_vector_table_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- int err = 0;
- int retval;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- if (CMD_ARGC == 0) { /* print current settings */
- int idx;
-
- command_print(CMD_CTX, "active user-set static vectors:");
- for (idx = 1; idx < 8; idx++)
- if (xscale->static_low_vectors_set & (1 << idx))
- command_print(CMD_CTX,
- "low %d: 0x%" PRIx32,
- idx,
- xscale->static_low_vectors[idx]);
- for (idx = 1; idx < 8; idx++)
- if (xscale->static_high_vectors_set & (1 << idx))
- command_print(CMD_CTX,
- "high %d: 0x%" PRIx32,
- idx,
- xscale->static_high_vectors[idx]);
- return ERROR_OK;
- }
-
- if (CMD_ARGC != 3)
- err = 1;
- else {
- int idx;
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], idx);
- uint32_t vec;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], vec);
-
- if (idx < 1 || idx >= 8)
- err = 1;
-
- if (!err && strcmp(CMD_ARGV[0], "low") == 0) {
- xscale->static_low_vectors_set |= (1<<idx);
- xscale->static_low_vectors[idx] = vec;
- } else if (!err && (strcmp(CMD_ARGV[0], "high") == 0)) {
- xscale->static_high_vectors_set |= (1<<idx);
- xscale->static_high_vectors[idx] = vec;
- } else
- err = 1;
- }
-
- if (err)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-
-COMMAND_HANDLER(xscale_handle_trace_buffer_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- uint32_t dcsr_value;
- int retval;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- if (CMD_ARGC >= 1) {
- if (strcmp("enable", CMD_ARGV[0]) == 0)
- xscale->trace.mode = XSCALE_TRACE_WRAP; /* default */
- else if (strcmp("disable", CMD_ARGV[0]) == 0)
- xscale->trace.mode = XSCALE_TRACE_DISABLED;
- else
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
-
- if (CMD_ARGC >= 2 && xscale->trace.mode != XSCALE_TRACE_DISABLED) {
- if (strcmp("fill", CMD_ARGV[1]) == 0) {
- int buffcount = 1; /* default */
- if (CMD_ARGC >= 3)
- COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], buffcount);
- if (buffcount < 1) { /* invalid */
- command_print(CMD_CTX, "fill buffer count must be > 0");
- xscale->trace.mode = XSCALE_TRACE_DISABLED;
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- xscale->trace.buffer_fill = buffcount;
- xscale->trace.mode = XSCALE_TRACE_FILL;
- } else if (strcmp("wrap", CMD_ARGV[1]) == 0)
- xscale->trace.mode = XSCALE_TRACE_WRAP;
- else {
- xscale->trace.mode = XSCALE_TRACE_DISABLED;
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- }
-
- if (xscale->trace.mode != XSCALE_TRACE_DISABLED) {
- char fill_string[12];
- sprintf(fill_string, "fill %d", xscale->trace.buffer_fill);
- command_print(CMD_CTX, "trace buffer enabled (%s)",
- (xscale->trace.mode == XSCALE_TRACE_FILL)
- ? fill_string : "wrap");
- } else
- command_print(CMD_CTX, "trace buffer disabled");
-
- dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);
- if (xscale->trace.mode == XSCALE_TRACE_FILL)
- xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);
- else
- xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_trace_image_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- if (xscale->trace.image) {
- image_close(xscale->trace.image);
- free(xscale->trace.image);
- command_print(CMD_CTX, "previously loaded image found and closed");
- }
-
- xscale->trace.image = malloc(sizeof(struct image));
- xscale->trace.image->base_address_set = 0;
- xscale->trace.image->start_address_set = 0;
-
- /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
- if (CMD_ARGC >= 2) {
- xscale->trace.image->base_address_set = 1;
- COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], xscale->trace.image->base_address);
- } else
- xscale->trace.image->base_address_set = 0;
-
- if (image_open(xscale->trace.image, CMD_ARGV[0],
- (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) {
- free(xscale->trace.image);
- xscale->trace.image = NULL;
- return ERROR_OK;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_dump_trace_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- struct xscale_trace_data *trace_data;
- struct fileio *file;
- int retval;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
-
- if (CMD_ARGC < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- trace_data = xscale->trace.data;
-
- if (!trace_data) {
- command_print(CMD_CTX, "no trace data collected");
- return ERROR_OK;
- }
-
- if (fileio_open(&file, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
- return ERROR_OK;
-
- while (trace_data) {
- int i;
-
- fileio_write_u32(file, trace_data->chkpt0);
- fileio_write_u32(file, trace_data->chkpt1);
- fileio_write_u32(file, trace_data->last_instruction);
- fileio_write_u32(file, trace_data->depth);
-
- for (i = 0; i < trace_data->depth; i++)
- fileio_write_u32(file, trace_data->entries[i].data |
- ((trace_data->entries[i].type & 0xffff) << 16));
-
- trace_data = trace_data->next;
- }
-
- fileio_close(file);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_analyze_trace_buffer_command)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- xscale_analyze_trace(target, CMD_CTX);
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(xscale_handle_cp15)
-{
- struct target *target = get_current_target(CMD_CTX);
- struct xscale_common *xscale = target_to_xscale(target);
- int retval;
-
- retval = xscale_verify_pointer(CMD_CTX, xscale);
- if (retval != ERROR_OK)
- return retval;
-
- if (target->state != TARGET_HALTED) {
- command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
- return ERROR_OK;
- }
- uint32_t reg_no = 0;
- struct reg *reg = NULL;
- if (CMD_ARGC > 0) {
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], reg_no);
- /*translate from xscale cp15 register no to openocd register*/
- switch (reg_no) {
- case 0:
- reg_no = XSCALE_MAINID;
- break;
- case 1:
- reg_no = XSCALE_CTRL;
- break;
- case 2:
- reg_no = XSCALE_TTB;
- break;
- case 3:
- reg_no = XSCALE_DAC;
- break;
- case 5:
- reg_no = XSCALE_FSR;
- break;
- case 6:
- reg_no = XSCALE_FAR;
- break;
- case 13:
- reg_no = XSCALE_PID;
- break;
- case 15:
- reg_no = XSCALE_CPACCESS;
- break;
- default:
- command_print(CMD_CTX, "invalid register number");
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
- reg = &xscale->reg_cache->reg_list[reg_no];
-
- }
- if (CMD_ARGC == 1) {
- uint32_t value;
-
- /* read cp15 control register */
- xscale_get_reg(reg);
- value = buf_get_u32(reg->value, 0, 32);
- command_print(CMD_CTX, "%s (/%i): 0x%" PRIx32 "", reg->name, (int)(reg->size),
- value);
- } else if (CMD_ARGC == 2) {
- uint32_t value;
- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
-
- /* send CP write request (command 0x41) */
- xscale_send_u32(target, 0x41);
-
- /* send CP register number */
- xscale_send_u32(target, reg_no);
-
- /* send CP register value */
- xscale_send_u32(target, value);
-
- /* execute cpwait to ensure outstanding operations complete */
- xscale_send_u32(target, 0x53);
- } else
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- return ERROR_OK;
-}
-
-static const struct command_registration xscale_exec_command_handlers[] = {
- {
- .name = "cache_info",
- .handler = xscale_handle_cache_info_command,
- .mode = COMMAND_EXEC,
- .help = "display information about CPU caches",
- },
- {
- .name = "mmu",
- .handler = xscale_handle_mmu_command,
- .mode = COMMAND_EXEC,
- .help = "enable or disable the MMU",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "icache",
- .handler = xscale_handle_idcache_command,
- .mode = COMMAND_EXEC,
- .help = "display ICache state, optionally enabling or "
- "disabling it",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "dcache",
- .handler = xscale_handle_idcache_command,
- .mode = COMMAND_EXEC,
- .help = "display DCache state, optionally enabling or "
- "disabling it",
- .usage = "['enable'|'disable']",
- },
- {
- .name = "vector_catch",
- .handler = xscale_handle_vector_catch_command,
- .mode = COMMAND_EXEC,
- .help = "set or display mask of vectors "
- "that should trigger debug entry",
- .usage = "['all'|'none'|'fiq'|'irq'|'dabt'|'pabt'|'swi'|'undef'|'reset']",
- },
- {
- .name = "vector_table",
- .handler = xscale_handle_vector_table_command,
- .mode = COMMAND_EXEC,
- .help = "set vector table entry in mini-ICache, "
- "or display current tables",
- .usage = "[('high'|'low') index code]",
- },
- {
- .name = "trace_buffer",
- .handler = xscale_handle_trace_buffer_command,
- .mode = COMMAND_EXEC,
- .help = "display trace buffer status, enable or disable "
- "tracing, and optionally reconfigure trace mode",
- .usage = "['enable'|'disable' ['fill' [number]|'wrap']]",
- },
- {
- .name = "dump_trace",
- .handler = xscale_handle_dump_trace_command,
- .mode = COMMAND_EXEC,
- .help = "dump content of trace buffer to file",
- .usage = "filename",
- },
- {
- .name = "analyze_trace",
- .handler = xscale_handle_analyze_trace_buffer_command,
- .mode = COMMAND_EXEC,
- .help = "analyze content of trace buffer",
- .usage = "",
- },
- {
- .name = "trace_image",
- .handler = xscale_handle_trace_image_command,
- .mode = COMMAND_EXEC,
- .help = "load image from file to address (default 0)",
- .usage = "filename [offset [filetype]]",
- },
- {
- .name = "cp15",
- .handler = xscale_handle_cp15,
- .mode = COMMAND_EXEC,
- .help = "Read or write coprocessor 15 register.",
- .usage = "register [value]",
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration xscale_any_command_handlers[] = {
- {
- .name = "debug_handler",
- .handler = xscale_handle_debug_handler_command,
- .mode = COMMAND_ANY,
- .help = "Change address used for debug handler.",
- .usage = "<target> <address>",
- },
- {
- .name = "cache_clean_address",
- .handler = xscale_handle_cache_clean_address_command,
- .mode = COMMAND_ANY,
- .help = "Change address used for cleaning data cache.",
- .usage = "address",
- },
- {
- .chain = xscale_exec_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-static const struct command_registration xscale_command_handlers[] = {
- {
- .chain = arm_command_handlers,
- },
- {
- .name = "xscale",
- .mode = COMMAND_ANY,
- .help = "xscale command group",
- .usage = "",
- .chain = xscale_any_command_handlers,
- },
- COMMAND_REGISTRATION_DONE
-};
-
-struct target_type xscale_target = {
- .name = "xscale",
-
- .poll = xscale_poll,
- .arch_state = xscale_arch_state,
-
- .halt = xscale_halt,
- .resume = xscale_resume,
- .step = xscale_step,
-
- .assert_reset = xscale_assert_reset,
- .deassert_reset = xscale_deassert_reset,
-
- /* REVISIT on some cores, allow exporting iwmmxt registers ... */
- .get_gdb_reg_list = arm_get_gdb_reg_list,
-
- .read_memory = xscale_read_memory,
- .read_phys_memory = xscale_read_phys_memory,
- .write_memory = xscale_write_memory,
- .write_phys_memory = xscale_write_phys_memory,
-
- .checksum_memory = arm_checksum_memory,
- .blank_check_memory = arm_blank_check_memory,
-
- .run_algorithm = armv4_5_run_algorithm,
-
- .add_breakpoint = xscale_add_breakpoint,
- .remove_breakpoint = xscale_remove_breakpoint,
- .add_watchpoint = xscale_add_watchpoint,
- .remove_watchpoint = xscale_remove_watchpoint,
-
- .commands = xscale_command_handlers,
- .target_create = xscale_target_create,
- .init_target = xscale_init_target,
-
- .virt2phys = xscale_virt2phys,
- .mmu = xscale_mmu
-};
diff --git a/src/target/xscale.h b/src/target/xscale.h
deleted file mode 100644
index a86edb2..0000000
--- a/src/target/xscale.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_TARGET_XSCALE_H
-#define OPENOCD_TARGET_XSCALE_H
-
-#include "arm.h"
-#include "armv4_5_mmu.h"
-#include "trace.h"
-
-#define XSCALE_COMMON_MAGIC 0x58534341
-
-/* These four JTAG instructions are architecturally defined.
- * Lengths are core-specific; originally 5 bits, later 7.
- */
-#define XSCALE_DBGRX 0x02
-#define XSCALE_DBGTX 0x10
-#define XSCALE_LDIC 0x07
-#define XSCALE_SELDCSR 0x09
-
-/* Possible CPU types */
-#define XSCALE_IXP4XX_PXA2XX 0x0
-#define XSCALE_PXA3XX 0x4
-
-enum xscale_debug_reason {
- XSCALE_DBG_REASON_GENERIC,
- XSCALE_DBG_REASON_RESET,
- XSCALE_DBG_REASON_TB_FULL,
-};
-
-enum xscale_trace_entry_type {
- XSCALE_TRACE_MESSAGE = 0x0,
- XSCALE_TRACE_ADDRESS = 0x1,
-};
-
-struct xscale_trace_entry {
- uint8_t data;
- enum xscale_trace_entry_type type;
-};
-
-struct xscale_trace_data {
- struct xscale_trace_entry *entries;
- int depth;
- uint32_t chkpt0;
- uint32_t chkpt1;
- uint32_t last_instruction;
- unsigned int num_checkpoints;
- struct xscale_trace_data *next;
-};
-
-enum trace_mode {
- XSCALE_TRACE_DISABLED,
- XSCALE_TRACE_FILL,
- XSCALE_TRACE_WRAP
-};
-
-struct xscale_trace {
- struct image *image; /* source for target opcodes */
- struct xscale_trace_data *data; /* linked list of collected trace data */
- int buffer_fill; /* maximum number of trace runs to read */
- int fill_counter; /* running count during trace collection */
- enum trace_mode mode;
- enum arm_state core_state; /* current core state (ARM, Thumb) */
-};
-
-struct xscale_common {
- /* armv4/5 common stuff */
- struct arm arm;
-
- int common_magic;
-
- /* XScale registers (CP15, DBG) */
- struct reg_cache *reg_cache;
-
- /* current state of the debug handler */
- uint32_t handler_address;
-
- /* target-endian buffers with exception vectors */
- uint32_t low_vectors[8];
- uint32_t high_vectors[8];
-
- /* static low vectors */
- uint8_t static_low_vectors_set; /* bit field with static vectors set by the user */
- uint8_t static_high_vectors_set; /* bit field with static vectors set by the user */
- uint32_t static_low_vectors[8];
- uint32_t static_high_vectors[8];
-
- /* DCache cleaning */
- uint32_t cache_clean_address;
-
- /* whether hold_rst and ext_dbg_break should be set */
- int hold_rst;
- int external_debug_break;
-
- /* breakpoint / watchpoint handling */
- int dbr_available;
- int dbr0_used;
- int dbr1_used;
- int ibcr_available;
- int ibcr0_used;
- int ibcr1_used;
- uint32_t arm_bkpt;
- uint16_t thumb_bkpt;
-
- uint8_t vector_catch;
-
- struct xscale_trace trace;
-
- int arch_debug_reason;
-
- /* MMU/Caches */
- struct armv4_5_mmu_common armv4_5_mmu;
- uint32_t cp15_control_reg;
-
- int fast_memory_access;
-
- /* CPU variant */
- int xscale_variant;
-};
-
-static inline struct xscale_common *
-target_to_xscale(struct target *target)
-{
- return container_of(target->arch_info, struct xscale_common, arm);
-}
-
-struct xscale_reg {
- int dbg_handler_number;
- struct target *target;
-};
-
-enum {
- XSCALE_MAINID, /* 0 */
- XSCALE_CACHETYPE,
- XSCALE_CTRL,
- XSCALE_AUXCTRL,
- XSCALE_TTB,
- XSCALE_DAC,
- XSCALE_FSR,
- XSCALE_FAR,
- XSCALE_PID,
- XSCALE_CPACCESS,
- XSCALE_IBCR0, /* 10 */
- XSCALE_IBCR1,
- XSCALE_DBR0,
- XSCALE_DBR1,
- XSCALE_DBCON,
- XSCALE_TBREG,
- XSCALE_CHKPT0,
- XSCALE_CHKPT1,
- XSCALE_DCSR,
- XSCALE_TX,
- XSCALE_RX, /* 20 */
- XSCALE_TXRXCTRL,
-};
-
-#define ERROR_XSCALE_NO_TRACE_DATA (-700)
-
-/* DCSR bit and field definitions */
-#define DCSR_TR (1 << 16)
-#define DCSR_TU (1 << 17)
-#define DCSR_TS (1 << 18)
-#define DCSR_TA (1 << 19)
-#define DCSR_TD (1 << 20)
-#define DCSR_TI (1 << 22)
-#define DCSR_TF (1 << 23)
-#define DCSR_TRAP_MASK \
- (DCSR_TF | DCSR_TI | DCSR_TD | DCSR_TA | DCSR_TS | DCSR_TU | DCSR_TR)
-
-#endif /* OPENOCD_TARGET_XSCALE_H */
diff --git a/src/target/xscale/build.sh b/src/target/xscale/build.sh
deleted file mode 100755
index fc828b2..0000000
--- a/src/target/xscale/build.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-arm-none-eabi-gcc -c debug_handler.S -o debug_handler.o
-arm-none-eabi-ld -EL -n -Tdebug_handler.cmd debug_handler.o -o debug_handler.out
-arm-none-eabi-objcopy -O binary debug_handler.out debug_handler.bin
-
-#arm-none-eabi-gcc -mbig-endian -c debug_handler.S -o debug_handler_be.o
-#arm-none-eabi-ld -EB -n -Tdebug_handler.cmd debug_handler_be.o -o debug_handler_be.out
-#arm-none-eabi-objcopy -O binary debug_handler_be.out debug_handler_be.bin
diff --git a/src/target/xscale/debug_handler.S b/src/target/xscale/debug_handler.S
deleted file mode 100644
index 66dfa88..0000000
--- a/src/target/xscale/debug_handler.S
+++ /dev/null
@@ -1,716 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-#include "protocol.h"
-
- .text
- .align 4
-
-@ Disable thumb mode
- .code 32
-
-@ send word to debugger
-.macro m_send_to_debugger reg
-1:
- mrc p14, 0, r15, c14, c0, 0
- bvs 1b
- mcr p14, 0, \reg, c8, c0, 0
-.endm
-
-@ receive word from debugger
-.macro m_receive_from_debugger reg
-1:
- mrc p14, 0, r15, c14, c0, 0
- bpl 1b
- mrc p14, 0, \reg, c9, c0, 0
-.endm
-
-@ save register on debugger, small
-.macro m_small_save_reg reg
- mov r0, \reg
- bl send_to_debugger
-.endm
-
-@ save status register on debugger, small
-.macro m_small_save_psr
- mrs r0, spsr
- bl send_to_debugger
-.endm
-
-@ wait for all outstanding coprocessor accesses to complete
-.macro m_cpwait
- mrc p15, 0, r0, c2, c0, 0
- mov r0, r0
- sub pc, pc, #4
-.endm
-
-.global reset_handler
-.global undef_handler
-.global swi_handler
-.global prefetch_abort_handler
-.global data_abort_handler
-.global irq_handler
-.global fiq_handler
-
-.section .part1 , "ax"
-
-reset_handler:
- @ read DCSR
- mrc p14, 0, r13, c10, c0
- @ check if global enable bit (GE) is set
- ands r13, r13, #0x80000000
-
- bne debug_handler
-
- @ set global enable bit (GE)
- mov r13, #0xc0000000
- mcr p14, 0, r13, c10, c0
-
-debug_handler:
-
- @ save r0 without modifying other registers
- m_send_to_debugger r0
-
- @ save lr (program PC) without branching (use macro)
- m_send_to_debugger r14
-
- @ save non-banked registers and spsr (program CPSR)
- m_small_save_reg r1
- m_small_save_reg r2
- m_small_save_reg r3
- m_small_save_reg r4
- m_small_save_reg r5
- m_small_save_reg r6
- m_small_save_reg r7
- m_small_save_psr
-
- mrs r0, spsr
-
- @ prepare program PSR for debug use (clear Thumb, set I/F to disable interrupts)
- bic r0, r0, #PSR_T
- orr r0, r0, #(PSR_I | PSR_F)
-
- @ examine mode bits
- and r1, r0, #MODE_MASK
- cmp r1, #MODE_USR
-
- bne not_user_mode
-
- @ replace USR mode with SYS
- bic r0, r0, #MODE_MASK
- orr r0, r0, #MODE_SYS
-
-not_user_mode:
-
- b save_banked_registers
-
-@ command loop
-@ wait for command from debugger, than execute desired function
-get_command:
- bl receive_from_debugger
-
- @ 0x0n - register access
- cmp r0, #0x0
- beq get_banked_registers
-
- cmp r0, #0x1
- beq set_banked_registers
-
- @ 0x1n - read memory
- cmp r0, #0x11
- beq read_byte
-
- cmp r0, #0x12
- beq read_half_word
-
- cmp r0, #0x14
- beq read_word
-
- @ 0x2n - write memory
- cmp r0, #0x21
- beq write_byte
-
- cmp r0, #0x22
- beq write_half_word
-
- cmp r0, #0x24
- beq write_word
-
- @ 0x3n - program execution
- cmp r0, #0x30
- beq resume
-
- cmp r0, #0x31
- beq resume_w_trace
-
- @ 0x4n - coprocessor access
- cmp r0, #0x40
- beq read_cp_reg
-
- cmp r0, #0x41
- beq write_cp_reg
-
- @ 0x5n - cache and mmu functions
- cmp r0, #0x50
- beq clean_d_cache
-
- cmp r0, #0x51
- beq invalidate_d_cache
-
- cmp r0, #0x52
- beq invalidate_i_cache
-
- cmp r0, #0x53
- beq cpwait
-
- @ 0x6n - misc functions
- cmp r0, #0x60
- beq clear_sa
-
- cmp r0, #0x61
- beq read_trace_buffer
-
- cmp r0, #0x62
- beq clean_trace_buffer
-
- @ return (back to get_command)
- b get_command
-
-@ ----
-
-@ resume program execution
-resume:
- @ restore CPSR (SPSR_dbg)
- bl receive_from_debugger
- msr spsr, r0
-
- @ restore registers (r7 - r0)
- bl receive_from_debugger @ r7
- mov r7, r0
- bl receive_from_debugger @ r6
- mov r6, r0
- bl receive_from_debugger @ r5
- mov r5, r0
- bl receive_from_debugger @ r4
- mov r4, r0
- bl receive_from_debugger @ r3
- mov r3, r0
- bl receive_from_debugger @ r2
- mov r2, r0
- bl receive_from_debugger @ r1
- mov r1, r0
- bl receive_from_debugger @ r0
-
- @ resume addresss
- m_receive_from_debugger lr
-
- @ branch back to application code, restoring CPSR
- subs pc, lr, #0
-
-@ get banked registers
-@ receive mode bits from host, then run into save_banked_registers to
-
-get_banked_registers:
- bl receive_from_debugger
-
-@ save banked registers
-@ r0[4:0]: desired mode bits
-save_banked_registers:
- @ backup CPSR
- mrs r7, cpsr
- msr cpsr_c, r0
- nop
-
- @ keep current mode bits in r1 for later use
- and r1, r0, #MODE_MASK
-
- @ backup banked registers
- m_send_to_debugger r8
- m_send_to_debugger r9
- m_send_to_debugger r10
- m_send_to_debugger r11
- m_send_to_debugger r12
- m_send_to_debugger r13
- m_send_to_debugger r14
-
- @ if not in SYS mode (or USR, which we replaced with SYS before)
- cmp r1, #MODE_SYS
-
- beq no_spsr_to_save
-
- @ backup SPSR
- mrs r0, spsr
- m_send_to_debugger r0
-
-no_spsr_to_save:
-
- @ restore CPSR for SDS
- msr cpsr_c, r7
- nop
-
- @ return
- b get_command
-
-@ ----
-
-
-@ set banked registers
-@ receive mode bits from host, then run into save_banked_registers to
-
-set_banked_registers:
- bl receive_from_debugger
-
-@ restore banked registers
-@ r0[4:0]: desired mode bits
-restore_banked_registers:
- @ backup CPSR
- mrs r7, cpsr
- msr cpsr_c, r0
- nop
-
- @ keep current mode bits in r1 for later use
- and r1, r0, #MODE_MASK
-
- @ set banked registers
- m_receive_from_debugger r8
- m_receive_from_debugger r9
- m_receive_from_debugger r10
- m_receive_from_debugger r11
- m_receive_from_debugger r12
- m_receive_from_debugger r13
- m_receive_from_debugger r14
-
- @ if not in SYS mode (or USR, which we replaced with SYS before)
- cmp r1, #MODE_SYS
-
- beq no_spsr_to_restore
-
- @ set SPSR
- m_receive_from_debugger r0
- msr spsr, r0
-
-no_spsr_to_restore:
-
- @ restore CPSR for SDS
- msr cpsr_c, r7
- nop
-
- @ return
- b get_command
-
-@ ----
-
-read_byte:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
-
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
-
-rb_loop:
- ldrb r0, [r2], #1
-
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
-
- bl send_to_debugger
-
- subs r1, r1, #1
- bne rb_loop
-
- @ return
- b get_command
-
-@ ----
-
-read_half_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
-
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
-
-rh_loop:
- ldrh r0, [r2], #2
-
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
-
- bl send_to_debugger
-
- subs r1, r1, #1
- bne rh_loop
-
- @ return
- b get_command
-
-@ ----
-
-read_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
-
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
-
-rw_loop:
- ldr r0, [r2], #4
-
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
-
- bl send_to_debugger
-
- subs r1, r1, #1
- bne rw_loop
-
- @ return
- b get_command
-
-@ ----
-
-write_byte:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
-
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
-
-wb_loop:
- bl receive_from_debugger
- strb r0, [r2], #1
-
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
-
- subs r1, r1, #1
- bne wb_loop
-
- @ return
- b get_command
-
-@ ----
-
-write_half_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
-
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
-
-wh_loop:
- bl receive_from_debugger
- strh r0, [r2], #2
-
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
-
- subs r1, r1, #1
- bne wh_loop
-
- @ return
- b get_command
-
-@ ----
-
-write_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
-
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
-
-ww_loop:
- bl receive_from_debugger
- str r0, [r2], #4
-
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
-
- subs r1, r1, #1
- bne ww_loop
-
- @ return
- b get_command
-
-@ ----
-
-clear_sa:
- @ read DCSR
- mrc p14, 0, r0, c10, c0
-
- @ clear SA bit
- bic r0, r0, #0x20
-
- @ write DCSR
- mcr p14, 0, r0, c10, c0
-
- @ return
- b get_command
-
-@ ----
-
-clean_d_cache:
- @ r0: cache clean area
- bl receive_from_debugger
-
- mov r1, #1024
-clean_loop:
- mcr p15, 0, r0, c7, c2, 5
- add r0, r0, #32
- subs r1, r1, #1
- bne clean_loop
-
- @ return
- b get_command
-
-@ ----
-
-invalidate_d_cache:
- mcr p15, 0, r0, c7, c6, 0
-
- @ return
- b get_command
-
-@ ----
-
-invalidate_i_cache:
- mcr p15, 0, r0, c7, c5, 0
-
- @ return
- b get_command
-
-@ ----
-
-cpwait:
- m_cpwait
-
- @return
- b get_command
-
-@ ----
-
-.section .part2 , "ax"
-
-read_cp_reg:
- @ requested cp register
- bl receive_from_debugger
-
- adr r1, read_cp_table
- add pc, r1, r0, lsl #3
-
-read_cp_table:
- mrc p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID
- b read_cp_reg_reply
- mrc p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE
- b read_cp_reg_reply
- mrc p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL
- b read_cp_reg_reply
- mrc p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL
- b read_cp_reg_reply
- mrc p15, 0, r0, c2, c0, 0 @ XSCALE_TTB
- b read_cp_reg_reply
- mrc p15, 0, r0, c3, c0, 0 @ XSCALE_DAC
- b read_cp_reg_reply
- mrc p15, 0, r0, c5, c0, 0 @ XSCALE_FSR
- b read_cp_reg_reply
- mrc p15, 0, r0, c6, c0, 0 @ XSCALE_FAR
- b read_cp_reg_reply
- mrc p15, 0, r0, c13, c0, 0 @ XSCALE_PID
- b read_cp_reg_reply
- mrc p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON
- b read_cp_reg_reply
- mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
- b read_cp_reg_reply
- mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0
- b read_cp_reg_reply
- mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1
- b read_cp_reg_reply
- mrc p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR
- b read_cp_reg_reply
-
-read_cp_reg_reply:
- bl send_to_debugger
-
- @ return
- b get_command
-
-@ ----
-
-write_cp_reg:
- @ requested cp register
- bl receive_from_debugger
- mov r1, r0
-
- @ value to be written
- bl receive_from_debugger
-
- adr r2, write_cp_table
- add pc, r2, r1, lsl #3
-
-write_cp_table:
- mcr p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID (0x0)
- b get_command
- mcr p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE (0x1)
- b get_command
- mcr p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL (0x2)
- b get_command
- mcr p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL (0x3)
- b get_command
- mcr p15, 0, r0, c2, c0, 0 @ XSCALE_TTB (0x4)
- b get_command
- mcr p15, 0, r0, c3, c0, 0 @ XSCALE_DAC (0x5)
- b get_command
- mcr p15, 0, r0, c5, c0, 0 @ XSCALE_FSR (0x6)
- b get_command
- mcr p15, 0, r0, c6, c0, 0 @ XSCALE_FAR (0x7)
- b get_command
- mcr p15, 0, r0, c13, c0, 0 @ XSCALE_PID (0x8)
- b get_command
- mcr p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS (0x9)
- b get_command
- mcr p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 (0xa)
- b get_command
- mcr p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 (0xb)
- b get_command
- mcr p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 (0xc)
- b get_command
- mcr p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 (0xd)
- b get_command
- mcr p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON (0xe)
- b get_command
- mcr p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG (0xf)
- b get_command
- mcr p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10)
- b get_command
- mcr p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11)
- b get_command
- mcr p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR (0x12)
- b get_command
-
-@ ----
-
-read_trace_buffer:
-
- @ dump 256 entries from trace buffer
- mov r1, #256
-read_tb_loop:
- mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
- bl send_to_debugger
- subs r1, r1, #1
- bne read_tb_loop
-
- @ dump checkpoint register 0
- mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10)
- bl send_to_debugger
-
- @ dump checkpoint register 1
- mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11)
- bl send_to_debugger
-
- @ return
- b get_command
-
-@ ----
-
-clean_trace_buffer:
-
- @ clean 256 entries from trace buffer
- mov r1, #256
-clean_tb_loop:
- mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
- subs r1, r1, #1
- bne clean_tb_loop
-
- @ return
- b get_command
-
-@ ----
-
-
-@ resume program execution with trace buffer enabled
-resume_w_trace:
- @ restore CPSR (SPSR_dbg)
- bl receive_from_debugger
- msr spsr, r0
-
- @ restore registers (r7 - r0)
- bl receive_from_debugger @ r7
- mov r7, r0
- bl receive_from_debugger @ r6
- mov r6, r0
- bl receive_from_debugger @ r5
- mov r5, r0
- bl receive_from_debugger @ r4
- mov r4, r0
- bl receive_from_debugger @ r3
- mov r3, r0
- bl receive_from_debugger @ r2
- mov r2, r0
- bl receive_from_debugger @ r1
- mov r1, r0
- bl receive_from_debugger @ r0
-
- @ resume addresss
- m_receive_from_debugger lr
-
- mrc p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR
- orr r13, r13, #1
- mcr p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR
-
- @ branch back to application code, restoring CPSR
- subs pc, lr, #0
-
-undef_handler:
-swi_handler:
-prefetch_abort_handler:
-data_abort_handler:
-irq_handler:
-fiq_handler:
-1:
- b 1b
-
-send_to_debugger:
- m_send_to_debugger r0
- mov pc, lr
-
-receive_from_debugger:
- m_receive_from_debugger r0
- mov pc, lr
-
diff --git a/src/target/xscale/debug_handler.bin b/src/target/xscale/debug_handler.bin
deleted file mode 100755
index 2dde185..0000000
--- a/src/target/xscale/debug_handler.bin
+++ /dev/null
Binary files differ
diff --git a/src/target/xscale/debug_handler.cmd b/src/target/xscale/debug_handler.cmd
deleted file mode 100644
index d943b13..0000000
--- a/src/target/xscale/debug_handler.cmd
+++ /dev/null
@@ -1,49 +0,0 @@
-/* identify the Entry Point */
-ENTRY(reset_handler)
-
-/* specify the mini-ICache memory areas */
-MEMORY
-{
- mini_icache_0 (x) : ORIGIN = 0x0, LENGTH = 1024 /* first part of mini icache (sets 0-31) */
- mini_icache_1 (x) : ORIGIN = 0x400, LENGTH = 1024 /* second part of mini icache (sets 0-31) */
-}
-
-/* now define the output sections */
-SECTIONS
-{
- .part1 :
- {
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- *(.part1)
- } >mini_icache_0
-
- .part2 :
- {
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- *(.part2)
- FILL(0x0)
- } >mini_icache_1
-
- /DISCARD/ :
- {
- *(.text)
- *(.glue_7)
- *(.glue_7t)
- *(.data)
- *(.bss)
- }
-}
diff --git a/src/target/xscale/protocol.h b/src/target/xscale/protocol.h
deleted file mode 100644
index cb01655..0000000
--- a/src/target/xscale/protocol.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#define REG_R0 0
-#define REG_R1 1
-#define REG_R2 2
-#define REG_R3 3
-#define REG_R4 4
-#define REG_R5 5
-#define REG_R6 6
-#define REG_R7 7
-#define REG_R8 8
-#define REG_R9 9
-#define REG_R10 10
-#define REG_R11 11
-#define REG_R12 12
-#define REG_R13 13
-#define REG_R14 14
-#define REG_R15 15
-#define REG_CPSR 16
-#define REG_SPSR 17
-
-#define MODE_USR 0x10
-#define MODE_FIQ 0x11
-#define MODE_IRQ 0x12
-#define MODE_SVC 0x13
-#define MODE_ABT 0x17
-#define MODE_UND 0x1b
-#define MODE_SYS 0x1f
-
-#define MODE_ANY 0x40
-#define MODE_CURRENT 0x80
-
-#define MODE_MASK 0x1f
-#define PSR_I 0x80
-#define PSR_F 0x40
-#define PSR_T 0x20
-
-#define XSCALE_DBG_MAINID 0x0
-#define XSCALE_DBG_CACHETYPE 0x1
-#define XSCALE_DBG_CTRL 0x2
-#define XSCALE_DBG_AUXCTRL 0x3
-#define XSCALE_DBG_TTB 0x4
-#define XSCALE_DBG_DAC 0x5
-#define XSCALE_DBG_FSR 0x6
-#define XSCALE_DBG_FAR 0x7
-#define XSCALE_DBG_PID 0x8
-#define XSCALE_DBG_CPACCESS 0x9
-#define XSCALE_DBG_IBCR0 0xa
-#define XSCALE_DBG_IBCR1 0xb
-#define XSCALE_DBG_DBR0 0xc
-#define XSCALE_DBG_DBR1 0xd
-#define XSCALE_DBG_DBCON 0xe
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
deleted file mode 100644
index 7c6224a..0000000
--- a/src/transport/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-include $(top_srcdir)/common.mk
-
-#METASOURCES = AUTO
-noinst_LTLIBRARIES = libtransport.la
-libtransport_la_SOURCES = \
- transport.c
-
-noinst_HEADERS = \
- transport.h
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/transport/transport.c b/src/transport/transport.c
deleted file mode 100644
index 7085947..0000000
--- a/src/transport/transport.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (c) 2010 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/** @file
- * Infrastructure for specifying and managing the transport protocol
- * used in a given debug or programming session.
- *
- * Examples of "debug-capable" transports are JTAG or SWD.
- * Additionally, JTAG supports boundary scan testing.
- *
- * Examples of "programming-capable" transports include SPI or UART;
- * those are used (often mediated by a ROM bootloader) for ISP style
- * programming, to perform an initial load of code into flash, or
- * sometimes into SRAM. Target code could use "variant" options to
- * decide how to use such protocols. For example, Cortex-M3 cores
- * from TI/Luminary and from NXP use different protocols for for
- * UART or SPI based firmware loading.
- *
- * As a rule, there are protocols layered on top of the transport.
- * For example, different chip families use JTAG in different ways
- * for debugging. Also, each family that supports programming over
- * a UART link for initial firmware loading tends to define its own
- * messaging and error handling.
- */
-
-#include <helper/log.h>
-#include <transport/transport.h>
-
-extern struct command_context *global_cmd_ctx;
-
-/*-----------------------------------------------------------------------*/
-
-/*
- * Infrastructure internals
- */
-
-/** List of transports known to OpenOCD. */
-static struct transport *transport_list;
-
-/**
- * NULL-terminated Vector of names of transports which the
- * currently selected debug adapter supports. This is declared
- * by the time that adapter is fully set up.
- */
-static const char * const *allowed_transports;
-
-/** * The transport being used for the current OpenOCD session. */
-static struct transport *session;
-
-static int transport_select(struct command_context *ctx, const char *name)
-{
- /* name may only identify a known transport;
- * caller guarantees session's transport isn't yet set.*/
- for (struct transport *t = transport_list; t; t = t->next) {
- if (strcmp(t->name, name) == 0) {
- int retval = t->select(ctx);
- /* select() registers commands specific to this
- * transport, and may also reset the link, e.g.
- * forcing it to JTAG or SWD mode.
- */
- if (retval == ERROR_OK)
- session = t;
- else
- LOG_ERROR("Error selecting '%s' as transport", t->name);
- return retval;
- }
- }
-
- LOG_ERROR("No transport named '%s' is available.", name);
- return ERROR_FAIL;
-}
-
-/**
- * Called by debug adapter drivers, or affiliated Tcl config scripts,
- * to declare the set of transports supported by an adapter. When
- * there is only one member of that set, it is automatically selected.
- */
-int allow_transports(struct command_context *ctx, const char * const *vector)
-{
- /* NOTE: caller is required to provide only a list
- * of *valid* transport names
- *
- * REVISIT should we validate that? and insist there's
- * at least one non-NULL element in that list?
- *
- * ... allow removals, e.g. external strapping prevents use
- * of one transport; C code should be definitive about what
- * can be used when all goes well.
- */
- if (allowed_transports != NULL || session) {
- LOG_ERROR("Can't modify the set of allowed transports.");
- return ERROR_FAIL;
- }
-
- allowed_transports = vector;
-
- /* autoselect if there's no choice ... */
- if (!vector[1]) {
- LOG_INFO("only one transport option; autoselect '%s'", vector[0]);
- return transport_select(ctx, vector[0]);
- }
-
- return ERROR_OK;
-}
-
-/**
- * Used to verify corrrect adapter driver initialization.
- *
- * @returns true iff the adapter declared one or more transports.
- */
-bool transports_are_declared(void)
-{
- return allowed_transports != NULL;
-}
-
-/**
- * Registers a transport. There are general purpose transports
- * (such as JTAG), as well as relatively proprietary ones which are
- * specific to a given chip (or chip family).
- *
- * Code implementing a transport needs to register it before it can
- * be selected and then activated. This is a dynamic process, so
- * that chips (and families) can define transports as needed (without
- * nneeding error-prone static tables).
- *
- * @param new_transport the transport being registered. On a
- * successful return, this memory is owned by the transport framework.
- *
- * @returns ERROR_OK on success, else a fault code.
- */
-int transport_register(struct transport *new_transport)
-{
- struct transport *t;
-
- for (t = transport_list; t; t = t->next) {
- if (strcmp(t->name, new_transport->name) == 0) {
- LOG_ERROR("transport name already used");
- return ERROR_FAIL;
- }
- }
-
- if (!new_transport->select || !new_transport->init)
- LOG_ERROR("invalid transport %s", new_transport->name);
-
- /* splice this into the list */
- new_transport->next = transport_list;
- transport_list = new_transport;
- LOG_DEBUG("register '%s'", new_transport->name);
-
- return ERROR_OK;
-}
-
-/**
- * Returns the transport currently being used by this debug or
- * programming session.
- *
- * @returns handle to the read-only transport entity.
- */
-struct transport *get_current_transport(void)
-{
- /* REVISIT -- constify */
- return session;
-}
-
-/*-----------------------------------------------------------------------*/
-
-/*
- * Infrastructure for Tcl interface to transports.
- */
-
-/**
- * Makes and stores a copy of a set of transports passed as
- * parameters to a command.
- *
- * @param vector where the resulting copy is stored, as an argv-style
- * NULL-terminated vector.
- */
-COMMAND_HELPER(transport_list_parse, char ***vector)
-{
- char **argv;
- unsigned n = CMD_ARGC;
- unsigned j = 0;
-
- *vector = NULL;
-
- if (n < 1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* our return vector must be NULL terminated */
- argv = calloc(n + 1, sizeof(char *));
- if (argv == NULL)
- return ERROR_FAIL;
-
- for (unsigned i = 0; i < n; i++) {
- struct transport *t;
-
- for (t = transport_list; t; t = t->next) {
- if (strcmp(t->name, CMD_ARGV[i]) != 0)
- continue;
- argv[j++] = strdup(CMD_ARGV[i]);
- break;
- }
- if (!t) {
- LOG_ERROR("no such transport '%s'", CMD_ARGV[i]);
- goto fail;
- }
- }
-
- *vector = argv;
- return ERROR_OK;
-
-fail:
- for (unsigned i = 0; i < n; i++)
- free(argv[i]);
- free(argv);
- return ERROR_FAIL;
-}
-
-COMMAND_HANDLER(handle_transport_init)
-{
- LOG_DEBUG("%s", __func__);
- if (!session) {
- LOG_ERROR("session transport was not selected. Use 'transport select <transport>'");
-
- /* no session transport configured, print transports then fail */
- LOG_ERROR("Transports available:");
- const char * const *vector = allowed_transports;
- while (*vector) {
- LOG_ERROR("%s", *vector);
- vector++;
- }
- return ERROR_FAIL;
- }
-
- return session->init(CMD_CTX);
-}
-
-COMMAND_HANDLER(handle_transport_list)
-{
- if (CMD_ARGC != 0)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- command_print(CMD_CTX, "The following transports are available:");
-
- for (struct transport *t = transport_list; t; t = t->next)
- command_print(CMD_CTX, "\t%s", t->name);
-
- return ERROR_OK;
-}
-
-/**
- * Implements the Tcl "transport select" command, choosing the
- * transport to be used in this debug session from among the
- * set supported by the debug adapter being used. Return value
- * is scriptable (allowing "if swd then..." etc).
- */
-static int jim_transport_select(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
-{
- int res;
- switch (argc) {
- case 1: /* autoselect if necessary, then return/display current config */
- if (!session) {
- if (!allowed_transports) {
- LOG_ERROR("Debug adapter does not support any transports? Check config file order.");
- return JIM_ERR;
- }
- LOG_INFO("auto-selecting first available session transport \"%s\". "
- "To override use 'transport select <transport>'.", allowed_transports[0]);
- res = transport_select(global_cmd_ctx, allowed_transports[0]);
- if (res != JIM_OK)
- return res;
- }
- Jim_SetResultString(interp, session->name, -1);
- return JIM_OK;
- break;
- case 2: /* assign */
- if (session) {
- if (!strcmp(session->name, argv[1]->bytes)) {
- LOG_WARNING("Transport \"%s\" was already selected", session->name);
- Jim_SetResultString(interp, session->name, -1);
- return JIM_OK;
- } else {
- LOG_ERROR("Can't change session's transport after the initial selection was made");
- return JIM_ERR;
- }
- }
-
- /* Is this transport supported by our debug adapter?
- * Example, "JTAG-only" means SWD is not supported.
- *
- * NOTE: requires adapter to have been set up, with
- * transports declared via C.
- */
- if (!allowed_transports) {
- LOG_ERROR("Debug adapter doesn't support any transports?");
- return JIM_ERR;
- }
-
- for (unsigned i = 0; allowed_transports[i]; i++) {
-
- if (strcmp(allowed_transports[i], argv[1]->bytes) == 0) {
- if (transport_select(global_cmd_ctx, argv[1]->bytes) == ERROR_OK) {
- Jim_SetResultString(interp, session->name, -1);
- return JIM_OK;
- }
- return JIM_ERR;
- }
- }
-
- LOG_ERROR("Debug adapter doesn't support '%s' transport", argv[1]->bytes);
- return JIM_ERR;
- break;
- default:
- Jim_WrongNumArgs(interp, 1, argv, "[too many parameters]");
- return JIM_ERR;
- }
-}
-
-static const struct command_registration transport_commands[] = {
- {
- .name = "init",
- .handler = handle_transport_init,
- /* this would be COMMAND_CONFIG ... except that
- * it needs to trigger event handlers that may
- * require COMMAND_EXEC ...
- */
- .mode = COMMAND_ANY,
- .help = "Initialize this session's transport",
- .usage = ""
- },
- {
- .name = "list",
- .handler = handle_transport_list,
- .mode = COMMAND_ANY,
- .help = "list all built-in transports",
- .usage = ""
- },
- {
- .name = "select",
- .jim_handler = jim_transport_select,
- .mode = COMMAND_ANY,
- .help = "Select this session's transport",
- .usage = "[transport_name]",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration transport_group[] = {
- {
- .name = "transport",
- .mode = COMMAND_ANY,
- .help = "Transport command group",
- .chain = transport_commands,
- .usage = ""
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int transport_register_commands(struct command_context *ctx)
-{
- return register_commands(ctx, NULL, transport_group);
-}
diff --git a/src/transport/transport.h b/src/transport/transport.h
deleted file mode 100644
index 6c57067..0000000
--- a/src/transport/transport.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2010 by David Brownell
- * Copyright (C) 2011 Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef OPENOCD_TRANSPORT_TRANSPORT_H
-#define OPENOCD_TRANSPORT_TRANSPORT_H
-
-#include "helper/command.h"
-
-/**
- * Wrapper for transport lifecycle operations.
- *
- * OpenOCD talks to targets through some kind of debugging
- * or programming adapter, using some protocol that probably
- * has target-specific aspects.
- *
- * A "transport" reflects electrical protocol to the target,
- * e..g jtag, swd, spi, uart, ... NOT the messaging protocols
- * layered over it (e.g. JTAG has eICE, CoreSight, Nexus, OnCE,
- * and more).
- *
- * In addition to the lifecycle operations packaged by this
- * structure, a transport also involves an interface supported
- * by debug adapters and used by components such as debug targets.
- * For non-debug transports, there may be interfaces used to
- * write to flash chips.
- */
-struct transport {
- /**
- * Each transport has a unique name, used to select it
- * from among the alternatives. Examples might include
- * "jtag", * "swd", "AVR_ISP" and more.
- */
- const char *name;
-
- /**
- * When a transport is selected, this method registers
- * its commands and activates the transport (e.g. resets
- * the link).
- *
- * After those commands are registered, they will often
- * be used for further configuration of the debug link.
- */
- int (*select)(struct command_context *ctx);
-
- /**
- * server startup uses this method to validate transport
- * configuration. (For example, with JTAG this interrogates
- * the scan chain against the list of expected TAPs.)
- */
- int (*init)(struct command_context *ctx);
-
- /**
- * Optional. If defined, allows transport to override target
- * name prior to initialisation.
- *
- * @returns ERROR_OK on success, or an error code on failure.
- */
- int (*override_target)(const char **targetname);
-
- /**
- * Transports are stored in a singly linked list.
- */
- struct transport *next;
-};
-
-int transport_register(struct transport *new_transport);
-
-struct transport *get_current_transport(void);
-
-int transport_register_commands(struct command_context *ctx);
-
-COMMAND_HELPER(transport_list_parse, char ***vector);
-
-int allow_transports(struct command_context *ctx, const char * const *vector);
-
-bool transports_are_declared(void);
-
-#endif /* OPENOCD_TRANSPORT_TRANSPORT_H */
diff --git a/src/xsvf/Makefile.am b/src/xsvf/Makefile.am
deleted file mode 100644
index 1b9cfab..0000000
--- a/src/xsvf/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
-include $(top_srcdir)/common.mk
-
-METASOURCES = AUTO
-noinst_LTLIBRARIES = libxsvf.la
-noinst_HEADERS = xsvf.h
-libxsvf_la_SOURCES = xsvf.c
-
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c
deleted file mode 100644
index 63c8915..0000000
--- a/src/xsvf/xsvf.c
+++ /dev/null
@@ -1,1113 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * Copyright (C) 2007,2008 Øyvind Harboe *
- * oyvind.harboe@zylin.com *
- * *
- * Copyright (C) 2008 Peter Hettkamp *
- * peter.hettkamp@htp-tel.de *
- * *
- * Copyright (C) 2009 SoftPLC Corporation. http://softplc.com *
- * Dick Hollenbeck <dick@softplc.com> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-/* The specification for SVF is available here:
- * http://www.asset-intertech.com/support/svf.pdf
- * Below, this document is refered to as the "SVF spec".
- *
- * The specification for XSVF is available here:
- * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf
- * Below, this document is refered to as the "XSVF spec".
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xsvf.h"
-#include <jtag/jtag.h>
-#include <svf/svf.h>
-
-/* XSVF commands, from appendix B of xapp503.pdf */
-#define XCOMPLETE 0x00
-#define XTDOMASK 0x01
-#define XSIR 0x02
-#define XSDR 0x03
-#define XRUNTEST 0x04
-#define XREPEAT 0x07
-#define XSDRSIZE 0x08
-#define XSDRTDO 0x09
-#define XSETSDRMASKS 0x0A
-#define XSDRINC 0x0B
-#define XSDRB 0x0C
-#define XSDRC 0x0D
-#define XSDRE 0x0E
-#define XSDRTDOB 0x0F
-#define XSDRTDOC 0x10
-#define XSDRTDOE 0x11
-#define XSTATE 0x12
-#define XENDIR 0x13
-#define XENDDR 0x14
-#define XSIR2 0x15
-#define XCOMMENT 0x16
-#define XWAIT 0x17
-
-/* XWAITSTATE is not in the xilinx XSVF spec, but the svf2xsvf.py translator
- * generates this. Arguably it is needed because the XSVF XRUNTEST command
- * was ill conceived and does not directly flow out of the SVF RUNTEST command.
- * This XWAITSTATE does map directly from the SVF RUNTEST command.
- */
-#define XWAITSTATE 0x18
-
-/* Lattice has extended the SVF file format, and Dick Hollenbeck's python based
- * SVF2XSVF converter supports these 3 additional XSVF opcodes, LCOUNT, LDELAY, LSDR.
- * Here is an example of usage of the 3 lattice opcode extensions:
-
-! Set the maximum loop count to 25.
-LCOUNT 25;
-! Step to DRPAUSE give 5 clocks and wait for 1.00e + 000 SEC.
-LDELAY DRPAUSE 5 TCK 1.00E-003 SEC;
-! Test for the completed status. Match means pass.
-! Loop back to LDELAY line if not match and loop count less than 25.
-
-LSDR 1 TDI (0)
-TDO (1);
-*/
-
-#define LCOUNT 0x19
-#define LDELAY 0x1A
-#define LSDR 0x1B
-#define XTRST 0x1C
-
-/* XSVF valid state values for the XSTATE command, from appendix B of xapp503.pdf */
-#define XSV_RESET 0x00
-#define XSV_IDLE 0x01
-#define XSV_DRSELECT 0x02
-#define XSV_DRCAPTURE 0x03
-#define XSV_DRSHIFT 0x04
-#define XSV_DREXIT1 0x05
-#define XSV_DRPAUSE 0x06
-#define XSV_DREXIT2 0x07
-#define XSV_DRUPDATE 0x08
-#define XSV_IRSELECT 0x09
-#define XSV_IRCAPTURE 0x0A
-#define XSV_IRSHIFT 0x0B
-#define XSV_IREXIT1 0x0C
-#define XSV_IRPAUSE 0x0D
-#define XSV_IREXIT2 0x0E
-#define XSV_IRUPDATE 0x0F
-
-/* arguments to XTRST */
-#define XTRST_ON 0
-#define XTRST_OFF 1
-#define XTRST_Z 2
-#define XTRST_ABSENT 3
-
-#define XSTATE_MAX_PATH 12
-
-static int xsvf_fd;
-
-/* map xsvf tap state to an openocd "tap_state_t" */
-static tap_state_t xsvf_to_tap(int xsvf_state)
-{
- tap_state_t ret;
-
- switch (xsvf_state) {
- case XSV_RESET:
- ret = TAP_RESET;
- break;
- case XSV_IDLE:
- ret = TAP_IDLE;
- break;
- case XSV_DRSELECT:
- ret = TAP_DRSELECT;
- break;
- case XSV_DRCAPTURE:
- ret = TAP_DRCAPTURE;
- break;
- case XSV_DRSHIFT:
- ret = TAP_DRSHIFT;
- break;
- case XSV_DREXIT1:
- ret = TAP_DREXIT1;
- break;
- case XSV_DRPAUSE:
- ret = TAP_DRPAUSE;
- break;
- case XSV_DREXIT2:
- ret = TAP_DREXIT2;
- break;
- case XSV_DRUPDATE:
- ret = TAP_DRUPDATE;
- break;
- case XSV_IRSELECT:
- ret = TAP_IRSELECT;
- break;
- case XSV_IRCAPTURE:
- ret = TAP_IRCAPTURE;
- break;
- case XSV_IRSHIFT:
- ret = TAP_IRSHIFT;
- break;
- case XSV_IREXIT1:
- ret = TAP_IREXIT1;
- break;
- case XSV_IRPAUSE:
- ret = TAP_IRPAUSE;
- break;
- case XSV_IREXIT2:
- ret = TAP_IREXIT2;
- break;
- case XSV_IRUPDATE:
- ret = TAP_IRUPDATE;
- break;
- default:
- LOG_ERROR("UNKNOWN XSVF STATE 0x%02X", xsvf_state);
- exit(1);
- }
-
- return ret;
-}
-
-static int xsvf_read_buffer(int num_bits, int fd, uint8_t *buf)
-{
- int num_bytes;
-
- for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--) {
- /* reverse the order of bytes as they are read sequentially from file */
- if (read(fd, buf + num_bytes - 1, 1) < 0)
- return ERROR_XSVF_EOF;
- }
-
- return ERROR_OK;
-}
-
-COMMAND_HANDLER(handle_xsvf_command)
-{
- uint8_t *dr_out_buf = NULL; /* from host to device (TDI) */
- uint8_t *dr_in_buf = NULL; /* from device to host (TDO) */
- uint8_t *dr_in_mask = NULL;
-
- int xsdrsize = 0;
- int xruntest = 0; /* number of TCK cycles OR *microseconds */
- int xrepeat = 0; /* number of retries */
-
- tap_state_t xendir = TAP_IDLE; /* see page 8 of the SVF spec, initial
- *xendir to be TAP_IDLE */
- tap_state_t xenddr = TAP_IDLE;
-
- uint8_t opcode;
- uint8_t uc = 0;
- long file_offset = 0;
-
- int loop_count = 0;
- tap_state_t loop_state = TAP_IDLE;
- int loop_clocks = 0;
- int loop_usecs = 0;
-
- int do_abort = 0;
- int unsupported = 0;
- int tdo_mismatch = 0;
- int result;
- int verbose = 1;
-
- bool collecting_path = false;
- tap_state_t path[XSTATE_MAX_PATH];
- unsigned pathlen = 0;
-
- /* a flag telling whether to clock TCK during waits,
- * or simply sleep, controled by virt2
- */
- int runtest_requires_tck = 0;
-
- /* use NULL to indicate a "plain" xsvf file which accounts for
- * additional devices in the scan chain, otherwise the device
- * that should be affected
- */
- struct jtag_tap *tap = NULL;
-
- if (CMD_ARGC < 2)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- /* we mess with CMD_ARGV starting point below, snapshot filename here */
- const char *filename = CMD_ARGV[1];
-
- if (strcmp(CMD_ARGV[0], "plain") != 0) {
- tap = jtag_tap_by_string(CMD_ARGV[0]);
- if (!tap) {
- command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[0]);
- return ERROR_FAIL;
- }
- }
-
- xsvf_fd = open(filename, O_RDONLY);
- if (xsvf_fd < 0) {
- command_print(CMD_CTX, "file \"%s\" not found", filename);
- return ERROR_FAIL;
- }
-
- /* if this argument is present, then interpret xruntest counts as TCK cycles rather than as
- *usecs */
- if ((CMD_ARGC > 2) && (strcmp(CMD_ARGV[2], "virt2") == 0)) {
- runtest_requires_tck = 1;
- --CMD_ARGC;
- ++CMD_ARGV;
- }
-
- if ((CMD_ARGC > 2) && (strcmp(CMD_ARGV[2], "quiet") == 0))
- verbose = 0;
-
- LOG_WARNING("XSVF support in OpenOCD is limited. Consider using SVF instead");
- LOG_USER("xsvf processing file: \"%s\"", filename);
-
- while (read(xsvf_fd, &opcode, 1) > 0) {
- /* record the position of this opcode within the file */
- file_offset = lseek(xsvf_fd, 0, SEEK_CUR) - 1;
-
- /* maybe collect another state for a pathmove();
- * or terminate a path.
- */
- if (collecting_path) {
- tap_state_t mystate;
-
- switch (opcode) {
- case XCOMMENT:
- /* ignore/show comments between XSTATE ops */
- break;
- case XSTATE:
- /* try to collect another transition */
- if (pathlen == XSTATE_MAX_PATH) {
- LOG_ERROR("XSVF: path too long");
- do_abort = 1;
- break;
- }
-
- if (read(xsvf_fd, &uc, 1) < 0) {
- do_abort = 1;
- break;
- }
-
- mystate = xsvf_to_tap(uc);
- path[pathlen++] = mystate;
-
- LOG_DEBUG("XSTATE 0x%02X %s", uc,
- tap_state_name(mystate));
-
- /* If path is incomplete, collect more */
- if (!svf_tap_state_is_stable(mystate))
- continue;
-
- /* Else execute the path transitions we've
- * collected so far.
- *
- * NOTE: Punting on the saved path is not
- * strictly correct, but we must to do this
- * unless jtag_add_pathmove() stops rejecting
- * paths containing RESET. This is probably
- * harmless, since there aren't many options
- * for going from a stable state to reset;
- * at the worst, we may issue extra clocks
- * once we get to RESET.
- */
- if (mystate == TAP_RESET) {
- LOG_WARNING("XSVF: dodgey RESET");
- path[0] = mystate;
- }
-
- /* FALL THROUGH */
- default:
- /* Execute the path we collected
- *
- * NOTE: OpenOCD requires something that XSVF
- * doesn't: the last TAP state in the path
- * must be stable. In practice, tools that
- * create XSVF seem to follow that rule too.
- */
- collecting_path = false;
-
- if (path[0] == TAP_RESET)
- jtag_add_tlr();
- else
- jtag_add_pathmove(pathlen, path);
-
- result = jtag_execute_queue();
- if (result != ERROR_OK) {
- LOG_ERROR("XSVF: pathmove error %d", result);
- do_abort = 1;
- break;
- }
- continue;
- }
- }
-
- switch (opcode) {
- case XCOMPLETE:
- LOG_DEBUG("XCOMPLETE");
-
- result = jtag_execute_queue();
- if (result != ERROR_OK) {
- tdo_mismatch = 1;
- break;
- }
- break;
-
- case XTDOMASK:
- LOG_DEBUG("XTDOMASK");
- if (dr_in_mask &&
- (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))
- do_abort = 1;
- break;
-
- case XRUNTEST:
- {
- uint8_t xruntest_buf[4];
-
- if (read(xsvf_fd, xruntest_buf, 4) < 0) {
- do_abort = 1;
- break;
- }
-
- xruntest = be_to_h_u32(xruntest_buf);
- LOG_DEBUG("XRUNTEST %d 0x%08X", xruntest, xruntest);
- }
- break;
-
- case XREPEAT:
- {
- uint8_t myrepeat;
-
- if (read(xsvf_fd, &myrepeat, 1) < 0)
- do_abort = 1;
- else {
- xrepeat = myrepeat;
- LOG_DEBUG("XREPEAT %d", xrepeat);
- }
- }
- break;
-
- case XSDRSIZE:
- {
- uint8_t xsdrsize_buf[4];
-
- if (read(xsvf_fd, xsdrsize_buf, 4) < 0) {
- do_abort = 1;
- break;
- }
-
- xsdrsize = be_to_h_u32(xsdrsize_buf);
- LOG_DEBUG("XSDRSIZE %d", xsdrsize);
-
- if (dr_out_buf)
- free(dr_out_buf);
- if (dr_in_buf)
- free(dr_in_buf);
- if (dr_in_mask)
- free(dr_in_mask);
-
- dr_out_buf = malloc((xsdrsize + 7) / 8);
- dr_in_buf = malloc((xsdrsize + 7) / 8);
- dr_in_mask = malloc((xsdrsize + 7) / 8);
- }
- break;
-
- case XSDR: /* these two are identical except for the dr_in_buf */
- case XSDRTDO:
- {
- int limit = xrepeat;
- int matched = 0;
- int attempt;
-
- const char *op_name = (opcode == XSDR ? "XSDR" : "XSDRTDO");
-
- if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK) {
- do_abort = 1;
- break;
- }
-
- if (opcode == XSDRTDO) {
- if (xsvf_read_buffer(xsdrsize, xsvf_fd,
- dr_in_buf) != ERROR_OK) {
- do_abort = 1;
- break;
- }
- }
-
- if (limit < 1)
- limit = 1;
-
- LOG_DEBUG("%s %d", op_name, xsdrsize);
-
- for (attempt = 0; attempt < limit; ++attempt) {
- struct scan_field field;
-
- if (attempt > 0) {
- /* perform the XC9500 exception handling sequence shown in xapp067.pdf and
- * illustrated in psuedo code at end of this file. We start from state
- * DRPAUSE:
- * go to Exit2-DR
- * go to Shift-DR
- * go to Exit1-DR
- * go to Update-DR
- * go to Run-Test/Idle
- *
- * This sequence should be harmless for other devices, and it
- * will be skipped entirely if xrepeat is set to zero.
- */
-
- static tap_state_t exception_path[] = {
- TAP_DREXIT2,
- TAP_DRSHIFT,
- TAP_DREXIT1,
- TAP_DRUPDATE,
- TAP_IDLE,
- };
-
- jtag_add_pathmove(ARRAY_SIZE(exception_path), exception_path);
-
- if (verbose)
- LOG_USER("%s mismatch, xsdrsize=%d retry=%d",
- op_name,
- xsdrsize,
- attempt);
- }
-
- field.num_bits = xsdrsize;
- field.out_value = dr_out_buf;
- field.in_value = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
-
- if (tap == NULL)
- jtag_add_plain_dr_scan(field.num_bits,
- field.out_value,
- field.in_value,
- TAP_DRPAUSE);
- else
- jtag_add_dr_scan(tap, 1, &field, TAP_DRPAUSE);
-
- jtag_check_value_mask(&field, dr_in_buf, dr_in_mask);
-
- free(field.in_value);
-
- /* LOG_DEBUG("FLUSHING QUEUE"); */
- result = jtag_execute_queue();
- if (result == ERROR_OK) {
- matched = 1;
- break;
- }
- }
-
- if (!matched) {
- LOG_USER("%s mismatch", op_name);
- tdo_mismatch = 1;
- break;
- }
-
- /* See page 19 of XSVF spec regarding opcode "XSDR" */
- if (xruntest) {
- result = svf_add_statemove(TAP_IDLE);
- if (result != ERROR_OK)
- return result;
-
- if (runtest_requires_tck)
- jtag_add_clocks(xruntest);
- else
- jtag_add_sleep(xruntest);
- } else if (xendir != TAP_DRPAUSE) {
- /* we are already in TAP_DRPAUSE */
- result = svf_add_statemove(xenddr);
- if (result != ERROR_OK)
- return result;
- }
- }
- break;
-
- case XSETSDRMASKS:
- LOG_ERROR("unsupported XSETSDRMASKS");
- unsupported = 1;
- break;
-
- case XSDRINC:
- LOG_ERROR("unsupported XSDRINC");
- unsupported = 1;
- break;
-
- case XSDRB:
- LOG_ERROR("unsupported XSDRB");
- unsupported = 1;
- break;
-
- case XSDRC:
- LOG_ERROR("unsupported XSDRC");
- unsupported = 1;
- break;
-
- case XSDRE:
- LOG_ERROR("unsupported XSDRE");
- unsupported = 1;
- break;
-
- case XSDRTDOB:
- LOG_ERROR("unsupported XSDRTDOB");
- unsupported = 1;
- break;
-
- case XSDRTDOC:
- LOG_ERROR("unsupported XSDRTDOC");
- unsupported = 1;
- break;
-
- case XSDRTDOE:
- LOG_ERROR("unsupported XSDRTDOE");
- unsupported = 1;
- break;
-
- case XSTATE:
- {
- tap_state_t mystate;
-
- if (read(xsvf_fd, &uc, 1) < 0) {
- do_abort = 1;
- break;
- }
-
- mystate = xsvf_to_tap(uc);
-
- LOG_DEBUG("XSTATE 0x%02X %s", uc, tap_state_name(mystate));
-
- if (mystate == TAP_INVALID) {
- LOG_ERROR("XSVF: bad XSTATE %02x", uc);
- do_abort = 1;
- break;
- }
-
- /* NOTE: the current state is SVF-stable! */
-
- /* no change == NOP */
- if (mystate == cmd_queue_cur_state
- && mystate != TAP_RESET)
- break;
-
- /* Hand off to SVF? */
- if (svf_tap_state_is_stable(mystate)) {
- result = svf_add_statemove(mystate);
- if (result != ERROR_OK)
- unsupported = 1;
- break;
- }
-
- /*
- * A sequence of XSTATE transitions, each TAP
- * state adjacent to the previous one. Start
- * collecting them.
- */
- collecting_path = true;
- pathlen = 1;
- path[0] = mystate;
- }
- break;
-
- case XENDIR:
-
- if (read(xsvf_fd, &uc, 1) < 0) {
- do_abort = 1;
- break;
- }
-
- /* see page 22 of XSVF spec */
- if (uc == 0)
- xendir = TAP_IDLE;
- else if (uc == 1)
- xendir = TAP_IRPAUSE;
- else {
- LOG_ERROR("illegial XENDIR argument: 0x%02X", uc);
- unsupported = 1;
- break;
- }
-
- LOG_DEBUG("XENDIR 0x%02X %s", uc, tap_state_name(xendir));
- break;
-
- case XENDDR:
-
- if (read(xsvf_fd, &uc, 1) < 0) {
- do_abort = 1;
- break;
- }
-
- /* see page 22 of XSVF spec */
- if (uc == 0)
- xenddr = TAP_IDLE;
- else if (uc == 1)
- xenddr = TAP_DRPAUSE;
- else {
- LOG_ERROR("illegial XENDDR argument: 0x%02X", uc);
- unsupported = 1;
- break;
- }
-
- LOG_DEBUG("XENDDR %02X %s", uc, tap_state_name(xenddr));
- break;
-
- case XSIR:
- case XSIR2:
- {
- uint8_t short_buf[2];
- uint8_t *ir_buf;
- int bitcount;
- tap_state_t my_end_state = xruntest ? TAP_IDLE : xendir;
-
- if (opcode == XSIR) {
- /* one byte bitcount */
- if (read(xsvf_fd, short_buf, 1) < 0) {
- do_abort = 1;
- break;
- }
- bitcount = short_buf[0];
- LOG_DEBUG("XSIR %d", bitcount);
- } else {
- if (read(xsvf_fd, short_buf, 2) < 0) {
- do_abort = 1;
- break;
- }
- bitcount = be_to_h_u16(short_buf);
- LOG_DEBUG("XSIR2 %d", bitcount);
- }
-
- ir_buf = malloc((bitcount + 7) / 8);
-
- if (xsvf_read_buffer(bitcount, xsvf_fd, ir_buf) != ERROR_OK)
- do_abort = 1;
- else {
- struct scan_field field;
-
- field.num_bits = bitcount;
- field.out_value = ir_buf;
-
- field.in_value = NULL;
-
- if (tap == NULL)
- jtag_add_plain_ir_scan(field.num_bits,
- field.out_value, field.in_value, my_end_state);
- else
- jtag_add_ir_scan(tap, &field, my_end_state);
-
- if (xruntest) {
- if (runtest_requires_tck)
- jtag_add_clocks(xruntest);
- else
- jtag_add_sleep(xruntest);
- }
-
- /* Note that an -irmask of non-zero in your config file
- * can cause this to fail. Setting -irmask to zero cand work
- * around the problem.
- */
-
- /* LOG_DEBUG("FLUSHING QUEUE"); */
- result = jtag_execute_queue();
- if (result != ERROR_OK)
- tdo_mismatch = 1;
- }
- free(ir_buf);
- }
- break;
-
- case XCOMMENT:
- {
- unsigned int ndx = 0;
- char comment[128];
-
- do {
- if (read(xsvf_fd, &uc, 1) < 0) {
- do_abort = 1;
- break;
- }
-
- if (ndx < sizeof(comment)-1)
- comment[ndx++] = uc;
-
- } while (uc != 0);
-
- comment[sizeof(comment)-1] = 0; /* regardless, terminate */
- if (verbose)
- LOG_USER("# %s", comment);
- }
- break;
-
- case XWAIT:
- {
- /* expected in stream:
- XWAIT <uint8_t wait_state> <uint8_t end_state> <uint32_t usecs>
- */
-
- uint8_t wait_local;
- uint8_t end;
- uint8_t delay_buf[4];
-
- tap_state_t wait_state;
- tap_state_t end_state;
- int delay;
-
- if (read(xsvf_fd, &wait_local, 1) < 0
- || read(xsvf_fd, &end, 1) < 0
- || read(xsvf_fd, delay_buf, 4) < 0) {
- do_abort = 1;
- break;
- }
-
- wait_state = xsvf_to_tap(wait_local);
- end_state = xsvf_to_tap(end);
- delay = be_to_h_u32(delay_buf);
-
- LOG_DEBUG("XWAIT %s %s usecs:%d", tap_state_name(
- wait_state), tap_state_name(end_state), delay);
-
- if (runtest_requires_tck && wait_state == TAP_IDLE)
- jtag_add_runtest(delay, end_state);
- else {
- /* FIXME handle statemove errors ... */
- result = svf_add_statemove(wait_state);
- if (result != ERROR_OK)
- return result;
- jtag_add_sleep(delay);
- result = svf_add_statemove(end_state);
- if (result != ERROR_OK)
- return result;
- }
- }
- break;
-
- case XWAITSTATE:
- {
- /* expected in stream:
- * XWAITSTATE <uint8_t wait_state> <uint8_t end_state> <uint32_t clock_count>
- * <uint32_t usecs>
- */
-
- uint8_t clock_buf[4];
- uint8_t usecs_buf[4];
- uint8_t wait_local;
- uint8_t end;
- tap_state_t wait_state;
- tap_state_t end_state;
- int clock_count;
- int usecs;
-
- if (read(xsvf_fd, &wait_local, 1) < 0
- || read(xsvf_fd, &end, 1) < 0
- || read(xsvf_fd, clock_buf, 4) < 0
- || read(xsvf_fd, usecs_buf, 4) < 0) {
- do_abort = 1;
- break;
- }
-
- wait_state = xsvf_to_tap(wait_local);
- end_state = xsvf_to_tap(end);
-
- clock_count = be_to_h_u32(clock_buf);
- usecs = be_to_h_u32(usecs_buf);
-
- LOG_DEBUG("XWAITSTATE %s %s clocks:%i usecs:%i",
- tap_state_name(wait_state),
- tap_state_name(end_state),
- clock_count, usecs);
-
- /* the following states are 'stable', meaning that they have a transition
- * in the state diagram back to themselves. This is necessary because we will
- * be issuing a number of clocks in this state. This set of allowed states is also
- * determined by the SVF RUNTEST command's allowed states.
- */
- if (!svf_tap_state_is_stable(wait_state)) {
- LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"",
- tap_state_name(wait_state));
- unsupported = 1;
- /* REVISIT "break" so we won't run? */
- }
-
- /* FIXME handle statemove errors ... */
- result = svf_add_statemove(wait_state);
- if (result != ERROR_OK)
- return result;
-
- jtag_add_clocks(clock_count);
- jtag_add_sleep(usecs);
-
- result = svf_add_statemove(end_state);
- if (result != ERROR_OK)
- return result;
- }
- break;
-
- case LCOUNT:
- {
- /* expected in stream:
- * LCOUNT <uint32_t loop_count>
- */
- uint8_t count_buf[4];
-
- if (read(xsvf_fd, count_buf, 4) < 0) {
- do_abort = 1;
- break;
- }
-
- loop_count = be_to_h_u32(count_buf);
- LOG_DEBUG("LCOUNT %d", loop_count);
- }
- break;
-
- case LDELAY:
- {
- /* expected in stream:
- * LDELAY <uint8_t wait_state> <uint32_t clock_count> <uint32_t usecs_to_sleep>
- */
- uint8_t state;
- uint8_t clock_buf[4];
- uint8_t usecs_buf[4];
-
- if (read(xsvf_fd, &state, 1) < 0
- || read(xsvf_fd, clock_buf, 4) < 0
- || read(xsvf_fd, usecs_buf, 4) < 0) {
- do_abort = 1;
- break;
- }
-
- /* NOTE: loop_state must be stable! */
- loop_state = xsvf_to_tap(state);
- loop_clocks = be_to_h_u32(clock_buf);
- loop_usecs = be_to_h_u32(usecs_buf);
-
- LOG_DEBUG("LDELAY %s clocks:%d usecs:%d", tap_state_name(
- loop_state), loop_clocks, loop_usecs);
- }
- break;
-
- /* LSDR is more like XSDRTDO than it is like XSDR. It uses LDELAY which
- * comes with clocks !AND! sleep requirements.
- */
- case LSDR:
- {
- int limit = loop_count;
- int matched = 0;
- int attempt;
-
- LOG_DEBUG("LSDR");
-
- if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK
- || xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK) {
- do_abort = 1;
- break;
- }
-
- if (limit < 1)
- limit = 1;
-
- for (attempt = 0; attempt < limit; ++attempt) {
- struct scan_field field;
-
- result = svf_add_statemove(loop_state);
- if (result != ERROR_OK)
- return result;
- jtag_add_clocks(loop_clocks);
- jtag_add_sleep(loop_usecs);
-
- field.num_bits = xsdrsize;
- field.out_value = dr_out_buf;
- field.in_value = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
-
- if (attempt > 0 && verbose)
- LOG_USER("LSDR retry %d", attempt);
-
- if (tap == NULL)
- jtag_add_plain_dr_scan(field.num_bits,
- field.out_value,
- field.in_value,
- TAP_DRPAUSE);
- else
- jtag_add_dr_scan(tap, 1, &field, TAP_DRPAUSE);
-
- jtag_check_value_mask(&field, dr_in_buf, dr_in_mask);
-
- free(field.in_value);
-
-
- /* LOG_DEBUG("FLUSHING QUEUE"); */
- result = jtag_execute_queue();
- if (result == ERROR_OK) {
- matched = 1;
- break;
- }
- }
-
- if (!matched) {
- LOG_USER("LSDR mismatch");
- tdo_mismatch = 1;
- break;
- }
- }
- break;
-
- case XTRST:
- {
- uint8_t trst_mode;
-
- if (read(xsvf_fd, &trst_mode, 1) < 0) {
- do_abort = 1;
- break;
- }
-
- switch (trst_mode) {
- case XTRST_ON:
- jtag_add_reset(1, 0);
- break;
- case XTRST_OFF:
- case XTRST_Z:
- jtag_add_reset(0, 0);
- break;
- case XTRST_ABSENT:
- break;
- default:
- LOG_ERROR("XTRST mode argument (0x%02X) out of range", trst_mode);
- do_abort = 1;
- }
- }
- break;
-
- default:
- LOG_ERROR("unknown xsvf command (0x%02X)", uc);
- unsupported = 1;
- }
-
- if (do_abort || unsupported || tdo_mismatch) {
- LOG_DEBUG("xsvf failed, setting taps to reasonable state");
-
- /* upon error, return the TAPs to a reasonable state */
- result = svf_add_statemove(TAP_IDLE);
- if (result != ERROR_OK)
- return result;
- result = jtag_execute_queue();
- if (result != ERROR_OK)
- return result;
- break;
- }
- }
-
- if (tdo_mismatch) {
- command_print(CMD_CTX,
- "TDO mismatch, somewhere near offset %lu in xsvf file, aborting",
- file_offset);
-
- return ERROR_FAIL;
- }
-
- if (unsupported) {
- off_t offset = lseek(xsvf_fd, 0, SEEK_CUR) - 1;
- command_print(CMD_CTX,
- "unsupported xsvf command (0x%02X) at offset %jd, aborting",
- uc, (intmax_t)offset);
- return ERROR_FAIL;
- }
-
- if (do_abort) {
- command_print(CMD_CTX, "premature end of xsvf file detected, aborting");
- return ERROR_FAIL;
- }
-
- if (dr_out_buf)
- free(dr_out_buf);
-
- if (dr_in_buf)
- free(dr_in_buf);
-
- if (dr_in_mask)
- free(dr_in_mask);
-
- close(xsvf_fd);
-
- command_print(CMD_CTX, "XSVF file programmed successfully");
-
- return ERROR_OK;
-}
-
-static const struct command_registration xsvf_command_handlers[] = {
- {
- .name = "xsvf",
- .handler = handle_xsvf_command,
- .mode = COMMAND_EXEC,
- .help = "Runs a XSVF file. If 'virt2' is given, xruntest "
- "counts are interpreted as TCK cycles rather than "
- "as microseconds. Without the 'quiet' option, all "
- "comments, retries, and mismatches will be reported.",
- .usage = "(tapname|'plain') filename ['virt2'] ['quiet']",
- },
- COMMAND_REGISTRATION_DONE
-};
-
-int xsvf_register_commands(struct command_context *cmd_ctx)
-{
- return register_commands(cmd_ctx, NULL, xsvf_command_handlers);
-}
-
-/*
-
-PSUEDO-Code from Xilinx Appnote XAPP067.pdf :
-
-the following pseudo code clarifies the intent of the xrepeat support.The
-flow given is for the entire processing of an SVF file, not an XSVF file.
-No idea if this is just for the XC9500/XL/XV devices or all Xilinx parts.
-
-"Pseudo-Code Algorithm for SVF-Based ISP"
-
-1. Go to Test-Logic-Reset state
-2. Go to Run-Test Idle state
-3. Read SVF record
-
-4. if SIR record then
-go to Shift-IR state
-Scan in <TDI value>
-
-5. else if SDR record then
-set <repeat count> to 0
-store <TDI value> as <current TDI value>
-store <TDO value> as <current TDO value>
-6. go to Shift-DR state
-scan in <current TDI value>
-if < current TDO value > is specified then
-if < current TDO value > does not equal <actual TDO value> then
-if < repeat count > > 32 then
-LOG ERROR
-go to Run-Test Idle state
-go to Step 3
-end if
-go to Pause-DR
-go to Exit2-DR
-go to Shift-DR
-go to Exit1-DR
-go to Update-DR
-go to Run-Test/Idle
-increment <repeat count> by 1
-pause <current pause time> microseconds
-go to Step 6)
-end if
-else
- go to Run-Test Idle state
- go to Step 3
- endif
- else if RUNTEST record then
- pause tester for < TCK value > microseconds
- store <TCK value> as <current pause time>
- end if
-
-*/
diff --git a/src/xsvf/xsvf.h b/src/xsvf/xsvf.h
deleted file mode 100644
index aa0f4f0..0000000
--- a/src/xsvf/xsvf.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
-
-#ifndef OPENOCD_XSVF_XSVF_H
-#define OPENOCD_XSVF_XSVF_H
-
-#include <helper/command.h>
-
-int xsvf_register_commands(struct command_context *cmd_ctx);
-
-#define ERROR_XSVF_EOF (-200)
-#define ERROR_XSVF_FAILED (-201)
-
-#endif /* OPENOCD_XSVF_XSVF_H */