On the S905Y2 SoC, JTAG is accessible through two separate ports:
- JTAG_A, accessible on GPIOAO_6 through GPIOAO_9
- JTAG_B, accessible on GPIOC_0, GPIOC_1, GPIOC_4 and GPIOC_5
JTAG_B is designed to be accessible on the SD card port. GPIOAO_6 and GPIOAO_7 are not accessible in the Radxa Zero, at least not without HW modifications, making it necessary to use JTAG_B.
There is an SMC (Secure Monitor Call) numbered 0x82000040 which can be used to enable JTAG. Calling it with the argument 0x2 in x1 enables JTAG for the A53 CPU. However, this enables JTAG_A and there is no support for enabling JTAG_B.
The implementation for the SMC is in bl31.img, but this just uses a mailbox to communicate with bl30.bin which is code running on the Cortex-M3.
To enable JTAG for A53 in bl30.bin, the following is done:
- Pin mux registers are set up to enable the appropriate functions on GPIO pins in question
- Two undocumentted registers are written: the bits 0xffff are set in 0xFF634648, and 0x400 is set in 0xFF634668
- The bits 0x5300 are set in AO_SEC_JTAG_SCP_CNTL to disable JTAG for PWD_SCP and M_3 (0x3 in bits 8:10) and select A53 for JTAG_A TDO (0x5 in bits 14:12).
The last register does not seem to be accessible from the Cortex-A53 and seems to need to be written from the Cortex-M3, necessitating a patch for bl30.bin.
Unfortunately, there is no full datasheet for S905Y2 available, however Hardkernel provides one for S905X3. It's close enough in most regards, the main difference in the JTAG section is that the S905X3 has an A55 CPU where the S905Y2 has an A53. This has made it possible to figure out what registers to set to enable JTAG_B.
To select A53 for JTAG_B TDO in AO_SEC_JTAG_SCP_CNTL, 0x5 has to be written in bits 18:16 instead of 14:12. jtag_sel_a53_in also has to be set to 1 to enable JTAG_B TDI. This patch also sets jtag_sel_pwd_scp_in and jtag_sel_m3_in to JTAG_B, but it does not attempt to enable M4 or M3 TDO for JTAG_B. It also doesn't set up the pin muxes for JTAG_B. bl30.bin sets the pin mux functions for JTAG_A in AO_RTI_PINMUX_REG0 and AO_RTI_PINMUX_REG1, but for JTAG_B the pin mux functions in PERIPHS_PIN_MUX_9 need to be set up.
First, make sure that you have bare-metal crosscompilation tools for ARM 32-bit, arm-none-eabi-as etc. On Debian, this can be installed by installing the binutils-arm-none-eabi package.
- Clone https://github.com/radxa/fip.git
- Make sure the md5sum of radxa-zero/bl30.bin is 7d5693a25a56613ee29b579a7ff1b03d, otherwise check out commit 5b8beba2f50ce06219c4e4844101226a81aef854.
- Copy radxa-zero/bl30.bin from it to the directory where you cloned this git
- run
make
in this git - Replace radxa-zero/bl30.bin in the radxa/fip git with bl30.bin.patched that was generated
- run
make
in the radxa/fip git - See https://wiki.radxa.com/Zero/dev/u-boot for how to boot with a custom u-boot. I personally use
boot-g21.py
.
- Support JTAG M3/M4
- Set up pin mux registers for JTAG_B
- I don't know if EL1 is enough for writing the pin mux registers, my own bare metal code is doing this from EL2.
- The easiest way to write to PERIPHS_PIN_MUX_9 without writing any code may be to use the
nm
command in u-boot.
- Look into convenient ways of calling the SMC
- It can only be called in EL1 (kernel space) or higher
- There seems to exist a way to call a SMC in u-boot. Might be the easiest way without writing any code. See CMD_SMC in https://github.com/u-boot/u-boot/blob/master/cmd/Kconfig
- Invaluable help provided by @mambrus