From 7f13abce6ed801c14c069a6d5338c7cce0a133b8 Mon Sep 17 00:00:00 2001
From: Keith Rothman <537074+litghost@users.noreply.github.com>
Date: Fri, 3 Apr 2020 13:42:15 -0700
Subject: [PATCH] Initial Zynq US+ JTAG documentation.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
---
docs/zynq_jtag.md | 110 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 110 insertions(+)
create mode 100644 docs/zynq_jtag.md
diff --git a/docs/zynq_jtag.md b/docs/zynq_jtag.md
new file mode 100644
index 0000000..a35cbba
--- /dev/null
+++ b/docs/zynq_jtag.md
@@ -0,0 +1,110 @@
+Zynq UltraScale+ JTAG Notes
+===========================
+
+The Zynq UltraScale+ JTAG chain can be a little confusing, and xsdb interacts
+with the JTAG a little different than might be expected.
+
+There are 3 primary JTAG controllers addressed by xsdb:
+ - PS TAP
+ - PL TAP
+ - ARM DAP TAP
+
+See the following figures from UG1085:
+ - Figure 93-1 JTAG Chain Block Diagram
+ - Figure 39-3 CoreSight Debug Block Diagram
+
+In both of these diagrams, the PS and PL TAP's are shown as different blocks.
+However, both xsdb and the openocd configuration
+(tcl/target/xilinx\_zynqmp.cfg @83c5aa5c) treat the PS and PL TAP as 1 TAP.
+This confusion means some of the documentation of the 3 controllers does not
+match expection.
+
+This document explains the apparent behavior of the PS and PL TAP, and how to
+match it with existing documentation.
+
+Document References
+-------------------
+
+The 3 JTAG TAPs are documented in the following locations:
+
+| TAP | Documents |
+|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| PS TAP | Table 39-4: PS TAP Controller Instructions from Xilinx UG1085 |
+| PL TAP | Table 6-2: JTAG Registers and Table 6-3: UltraScale FPGA Boundary-Scan Instructions from Xilinx UG570 |
+| ARM DAP TAP | Table 3-209: JTAG-DP register summary from ARM DDI0480F
Table 2-6: DPv2 address map from ARM IHI0031C
Section 6.2: Selecting and accessing an AP from ARM IHI0031C |
+
+Security gates
+--------------
+
+When the Zynq UltraScale+ initially powers on in JTAG mode, only the PS TAP
+is actually enabled. The ARM DAP is permanently in BYPASS mode when disabled.
+The PL TAP IR is part of the JTAG chian, however the PL TAP DR is by default
+**not** in BYPASS mode. The PL TAP DR register appears to be completely
+removed from the JTAG chain.
+
+Enabling PL and ARM TAPs
+------------------------
+
+The PS TAP register 0x20 has two control bits (Table 39-5: PS TAP Controller
+JTAG Control Register from Xilinx UG1085) that enable the PL and ARM
+controllers. Writing a 32-bit `0x3` to PL TAP IR `0x20` enables both the PL
+and ARM controllers (if the security bits allow it).
+
+Once that is written, the ARM DAP controller can be accessed as expected via
+OpenOCD. However, when you look at xilinx\_zynqmp.cfg the following commands
+are issued:
+
+```
+irscan $_CHIPNAME.ps 0x824
+drscan $_CHIPNAME.ps 32 0x00000003
+```
+
+The DR scan matches the documentation, but the IR scan does not. This will be
+explained in the next section.
+
+PS / PL DR chain
+----------------
+
+The question from the previous section is why does OpenOCD use the following
+commands:
+
+```
+irscan $_CHIPNAME.ps 0x824
+drscan $_CHIPNAME.ps 32 0x00000003
+```
+
+to enable the ARM DAP controller? For additional context here is the TAP
+definition lines from higher in the file:
+
+```
+jtag newtap $_CHIPNAME tap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID
+jtag newtap $_CHIPNAME ps -irlen 12 -ircapture 0x1 -irmask 0x03 -expected-id $_PS_TAPID
+```
+
+The `-irlen` argument for the ARM DAP matches the documentation indicatinng an
+IR register length of 4. However the PS TAP `-irlen` register length is
+reported as 12. xsdb also appears to treat the PS TAP IR register length as
+12 bits.
+
+The PS and PL TAP IR length are both 6-bits. The following table
+lists the IR register ordering in the Zynq US+ JTAG chain:
+
+| Shift position | IR chain position | TAP | Width (bits) |
+|----------------|-------------------|---------|--------------|
+| 0 | 2 | ARM TAP | 4 |
+| 1 | 1 | PL TAP | 6 |
+| 2 | 0 | PS TAP | 6 |
+
+The ARM TAP should be shifted out first, because it is the last TAP in the
+chain, followed by the PL TAP IR, followed last by the PS TAP.
+
+So the question is, why does both xsdb and OpenOCD treat the PL TAP as part of
+the PS TAP? There appears to be an undocumented IR instruction 0x24 in both
+the PS and PL TAPs that removes the TAP from the DR shift chain, making the
+controller disappear from the DR scan. In the OpenOCD command, the IR scan'd
+was "0x824" which is `(0x20 << 6) | 0x24`, e.g. DR shift into the PS TAP
+JTAG\_CTRL register and remove the PL TAP DR register from the DR shift
+completely.
+
+In all other respects, the PL TAP and PS TAP behave as documented in their
+respective documents list in "Document References" section.