tcl/fpga/xilinx-xadc.cfg: add support for XADC
[openocd.git] / tcl / fpga / xilinx-xadc.cfg
1 # Xilinx XADC support for 7 Series FPGAs
2 #
3 # The 7 Series FPGAs contain an on-chip 12 bit ADC that can probe die
4 # temperature, internal power supply rail voltages as well as external
5 # voltages. The XADC is available both from fabric as well as through the
6 # JTAG TAP.
7 #
8 # This code implements access throught the JTAG TAP.
9 #
10 # https://www.xilinx.com/support/documentation/user_guides/ug480_7Series_XADC.pdf
11
12 # build a 32 bit DRP command for the XADC DR
13 proc xadc_cmd {cmd addr data} {
14         array set cmds {
15                 NOP 0x00
16                 READ 0x01
17                 WRITE 0x02
18         }
19         return [expr ($cmds($cmd) << 26) | ($addr << 16) | ($data << 0)]
20 }
21
22 # XADC register addresses
23 # Some addresses (status registers 0-3) have special function when written to.
24 proc XADC {key} {
25         array set addrs {
26                 TEMP 0x00
27                 LOCK 0x00
28                 VCCINT 0x01
29                 VCCAUX 0x02
30                 VAUXEN 0x02
31                 VPVN 0x03
32                 RESET 0x03
33                 VREFP 0x04
34                 VREFN 0x05
35                 VCCBRAM 0x06
36                 SUPAOFFS 0x08
37                 ADCAOFFS 0x09
38                 ADCAGAIN 0x0a
39                 VCCPINT 0x0d
40                 VCCPAUX 0x0e
41                 VCCODDR 0x0f
42                 VAUX0 0x10
43                 VAUX1 0x11
44                 VAUX2 0x12
45                 VAUX3 0x13
46                 VAUX4 0x14
47                 VAUX5 0x15
48                 VAUX6 0x16
49                 VAUX7 0x17
50                 VAUX8 0x18
51                 VAUX9 0x19
52                 VAUX10 0x1a
53                 VAUX11 0x1b
54                 VAUX12 0x1c
55                 VAUX13 0x1d
56                 VAUX14 0x1e
57                 VAUX15 0x1f
58                 SUPBOFFS 0x30
59                 ADCBOFFS 0x31
60                 ADCBGAIN 0x32
61                 FLAG 0x3f
62                 CFG0 0x40
63                 CFG1 0x41
64                 CFG2 0x42
65                 SEQ0 0x48
66                 SEQ1 0x49
67                 SEQ2 0x4a
68                 SEQ3 0x4b
69                 SEQ4 0x4c
70                 SEQ5 0x4d
71                 SEQ6 0x4e
72                 SEQ7 0x4f
73                 ALARM0 0x50
74                 ALARM1 0x51
75                 ALARM2 0x52
76                 ALARM3 0x53
77                 ALARM4 0x54
78                 ALARM5 0x55
79                 ALARM6 0x56
80                 ALARM7 0x57
81                 ALARM8 0x58
82                 ALARM9 0x59
83                 ALARM10 0x5a
84                 ALARM11 0x5b
85                 ALARM12 0x5c
86                 ALARM13 0x5d
87                 ALARM14 0x5e
88                 ALARM15 0x5f
89         }
90         return $addrs($key)
91 }
92
93 # Select the XADC DR
94 proc xadc_select {tap} {
95         set XADC_IR 0x37
96         irscan $tap $XADC_IR
97         runtest 10
98 }
99
100 # XADC transfer
101 proc xadc_xfer {tap cmd addr data} {
102         set ret [drscan $tap 32 [xadc_cmd $cmd $addr $data]]
103         runtest 10
104         return [expr 0x$ret]
105 }
106
107 # XADC register write
108 proc xadc_write {tap addr data} {
109         xadc_xfer $tap WRITE $addr $data
110 }
111
112 # XADC register read, non-pipelined
113 proc xadc_read {tap addr} {
114         xadc_xfer $tap READ $addr 0
115         return [xadc_xfer $tap NOP 0 0]
116 }
117
118 # convert 16 bit register code from ADC measurement on
119 # external voltages (VAUX) to Volt
120 proc xadc_volt {code} {
121         return [expr $code * 1./(1 << 16)]
122 }
123
124 # convert 16 bit temperature measurement to Celsius
125 proc xadc_temp {code} {
126         return [expr $code * 503.975/(1 << 16) - 273.15]
127 }
128
129 # convert 16 bit suppply voltage measurement to Volt
130 proc xadc_sup {code} {
131         return [expr $code * 3./(1 << 16)]
132 }
133
134 # perform a single channel measurement using default settings
135 proc xadc_single {tap ch} {
136         set cfg0 [xadc_read $tap [XADC CFG0]]
137         set cfg1 [xadc_read $tap [XADC CFG1]]
138         # set channel
139         xadc_write $tap [XADC CFG0] $cfg0
140         # single channel, disable the sequencer
141         xadc_write $tap [XADC CFG1] 0x3000
142         # leave some time for the conversion
143         runtest 100
144         set ret [xadc_read $tap [XADC $ch]]
145         # restore CFG0/1
146         xadc_write $tap [XADC CFG0] $cfg0
147         xadc_write $tap [XADC CFG1] $cfg1
148         return $ret
149 }
150
151 # measure all internal voltages
152 proc xadc_report {tap} {
153         xadc_select $tap
154         echo "TEMP [format %.2f [xadc_temp [xadc_single $tap TEMP]]] C"
155         foreach ch [list VCCINT VCCAUX VCCBRAM VPVN VREFP VREFN \
156                 VCCPINT VCCPAUX VCCODDR] {
157                 echo "$ch [format %.3f [xadc_sup [xadc_single $tap $ch]]] V"
158         }
159 }