tcl/target: add SPDX tag
[fw/openocd] / tcl / target / davinci.cfg
1 # SPDX-License-Identifier: GPL-2.0-or-later
2
3 #
4 # Utility code for DaVinci-family chips
5 #
6
7 # davinci_pinmux: assigns PINMUX$reg <== $value
8 proc davinci_pinmux {soc reg value} {
9         mww [expr {[dict get $soc sysbase] + 4 * $reg}] $value
10 }
11
12 source [find mem_helper.tcl]
13
14 #
15 # pll_setup: initialize PLL
16 #  - pll_addr ... physical addr of controller
17 #  - mult ... pll multiplier
18 #  - config ... dict mapping { prediv, postdiv, div[1-9] } to dividers
19 #
20 # For PLLs that don't have a given register (e.g. plldiv8), or where a
21 # given divider is non-programmable, caller provides *NO* config mapping.
22 #
23
24 # PLL version 0x02: tested on dm355
25 # REVISIT: On dm6446/dm357 the PLLRST polarity is different.
26 proc pll_v02_setup {pll_addr mult config} {
27         set pll_ctrl_addr [expr {$pll_addr + 0x100}]
28         set pll_ctrl [mrw $pll_ctrl_addr]
29
30         # 1 - clear CLKMODE (bit 8) iff using on-chip oscillator
31         # NOTE: this assumes we should clear that bit
32         set pll_ctrl [expr {$pll_ctrl & ~0x0100}]
33         mww $pll_ctrl_addr $pll_ctrl
34
35         # 2 - clear PLLENSRC (bit 5)
36         set pll_ctrl [expr {$pll_ctrl & ~0x0020}]
37         mww $pll_ctrl_addr $pll_ctrl
38
39         # 3 - clear PLLEN (bit 0) ... enter bypass mode
40         set pll_ctrl [expr {$pll_ctrl & ~0x0001}]
41         mww $pll_ctrl_addr $pll_ctrl
42
43         # 4 - wait at least 4 refclk cycles
44         sleep 1
45
46         # 5 - set PLLRST (bit 3)
47         set pll_ctrl [expr {$pll_ctrl | 0x0008}]
48         mww $pll_ctrl_addr $pll_ctrl
49
50         # 6 - set PLLDIS (bit 4)
51         set pll_ctrl [expr {$pll_ctrl | 0x0010}]
52         mww $pll_ctrl_addr $pll_ctrl
53
54         # 7 - clear PLLPWRDN (bit 1)
55         set pll_ctrl [expr {$pll_ctrl & ~0x0002}]
56         mww $pll_ctrl_addr $pll_ctrl
57
58         # 8 - clear PLLDIS (bit 4)
59         set pll_ctrl [expr {$pll_ctrl & ~0x0010}]
60         mww $pll_ctrl_addr $pll_ctrl
61
62         # 9 - optional: write prediv, postdiv, and pllm
63         # NOTE: for dm355 PLL1, postdiv is controlled via MISC register
64         mww [expr {$pll_addr + 0x0110}] [expr {($mult - 1) & 0xff}]
65         if { [dict exists $config prediv] } {
66                 set div [dict get $config prediv]
67                 set div [expr {0x8000 | ($div - 1)}]
68                 mww [expr {$pll_addr + 0x0114}] $div
69         }
70         if { [dict exists $config postdiv] } {
71                 set div [dict get $config postdiv]
72                 set div [expr {0x8000 | ($div - 1)}]
73                 mww [expr {$pll_addr + 0x0128}] $div
74         }
75
76         # 10 - optional: set plldiv1, plldiv2, ...
77         # NOTE:  this assumes some registers have their just-reset values:
78         #       - PLLSTAT.GOSTAT is clear when we enter
79         #       - ALNCTL has everything set
80         set go 0
81         if { [dict exists $config div1] } {
82                 set div [dict get $config div1]
83                 set div [expr {0x8000 | ($div - 1)}]
84                 mww [expr {$pll_addr + 0x0118}] $div
85                 set go 1
86         }
87         if { [dict exists $config div2] } {
88                 set div [dict get $config div2]
89                 set div [expr {0x8000 | ($div - 1)}]
90                 mww [expr {$pll_addr + 0x011c}] $div
91                 set go 1
92         }
93         if { [dict exists $config div3] } {
94                 set div [dict get $config div3]
95                 set div [expr {0x8000 | ($div - 1)}]
96                 mww [expr {$pll_addr + 0x0120}] $div
97                 set go 1
98         }
99         if { [dict exists $config div4] } {
100                 set div [dict get $config div4]
101                 set div [expr {0x8000 | ($div - 1)}]
102                 mww [expr {$pll_addr + 0x0160}] $div
103                 set go 1
104         }
105         if { [dict exists $config div5] } {
106                 set div [dict get $config div5]
107                 set div [expr {0x8000 | ($div - 1)}]
108                 mww [expr {$pll_addr + 0x0164}] $div
109                 set go 1
110         }
111         if {$go != 0} {
112                 # write pllcmd.GO; poll pllstat.GO
113                 mww [expr {$pll_addr + 0x0138}] 0x01
114                 set pllstat [expr {$pll_addr + 0x013c}]
115                 while {[expr {[mrw $pllstat] & 0x01}] != 0} { sleep 1 }
116         }
117         mww [expr {$pll_addr + 0x0138}] 0x00
118
119         # 11 - wait at least 5 usec for reset to finish
120         # (assume covered by overheads including JTAG messaging)
121
122         # 12 - clear PLLRST (bit 3)
123         set pll_ctrl [expr {$pll_ctrl & ~0x0008}]
124         mww $pll_ctrl_addr $pll_ctrl
125
126         # 13 - wait at least 8000 refclk cycles for PLL to lock
127         # if we assume 24 MHz (slowest osc), that's 1/3 msec
128         sleep 3
129
130         # 14 - set PLLEN (bit 0) ... leave bypass mode
131         set pll_ctrl [expr {$pll_ctrl | 0x0001}]
132         mww $pll_ctrl_addr $pll_ctrl
133 }
134
135 # PLL version 0x03: tested on dm365
136 proc pll_v03_setup {pll_addr mult config} {
137         set pll_ctrl_addr [expr {$pll_addr + 0x100}]
138         set pll_secctrl_addr [expr {$pll_addr + 0x108}]
139         set pll_ctrl [mrw $pll_ctrl_addr]
140
141         # 1 - power up the PLL
142         set pll_ctrl [expr {$pll_ctrl & ~0x0002}]
143         mww $pll_ctrl_addr $pll_ctrl
144
145         # 2 - clear PLLENSRC (bit 5)
146         set pll_ctrl [expr {$pll_ctrl & ~0x0020}]
147         mww $pll_ctrl_addr $pll_ctrl
148
149         # 2 - clear PLLEN (bit 0) ... enter bypass mode
150         set pll_ctrl [expr {$pll_ctrl & ~0x0001}]
151         mww $pll_ctrl_addr $pll_ctrl
152
153         # 3 - wait at least 4 refclk cycles
154         sleep 1
155
156         # 4 - set PLLRST (bit 3)
157         set pll_ctrl [expr {$pll_ctrl | 0x0008}]
158         mww $pll_ctrl_addr $pll_ctrl
159
160         # 5 - wait at least 5 usec
161         sleep 1
162
163         # 6 - clear PLLRST (bit 3)
164         set pll_ctrl [expr {$pll_ctrl & ~0x0008}]
165         mww $pll_ctrl_addr $pll_ctrl
166
167         # 9 - optional: write prediv, postdiv, and pllm
168         mww [expr {$pll_addr + 0x0110}] [expr {($mult / 2) & 0x1ff}]
169         if { [dict exists $config prediv] } {
170                 set div [dict get $config prediv]
171                 set div [expr {0x8000 | ($div - 1)}]
172                 mww [expr {$pll_addr + 0x0114}] $div
173         }
174         if { [dict exists $config postdiv] } {
175                 set div [dict get $config postdiv]
176                 set div [expr {0x8000 | ($div - 1)}]
177                 mww [expr {$pll_addr + 0x0128}] $div
178         }
179
180         # 10 - write start sequence to PLLSECCTL
181         mww $pll_secctrl_addr 0x00470000
182         mww $pll_secctrl_addr 0x00460000
183         mww $pll_secctrl_addr 0x00400000
184         mww $pll_secctrl_addr 0x00410000
185
186         # 11 - optional: set plldiv1, plldiv2, ...
187         # NOTE: this assumes some registers have their just-reset values:
188         #       - PLLSTAT.GOSTAT is clear when we enter
189         set aln 0
190         if { [dict exists $config div1] } {
191                 set div [dict get $config div1]
192                 set div [expr {0x8000 | ($div - 1)}]
193                 mww [expr {$pll_addr + 0x0118}] $div
194                 set aln [expr {$aln | 0x1}]
195         } else {
196                 mww [expr {$pll_addr + 0x0118}] 0
197         }
198         if { [dict exists $config div2] } {
199                 set div [dict get $config div2]
200                 set div [expr {0x8000 | ($div - 1)}]
201                 mww [expr {$pll_addr + 0x011c}] $div
202                 set aln [expr {$aln | 0x2}]
203         } else {
204                 mww [expr {$pll_addr + 0x011c}] 0
205         }
206         if { [dict exists $config div3] } {
207                 set div [dict get $config div3]
208                 set div [expr {0x8000 | ($div - 1)}]
209                 mww [expr {$pll_addr + 0x0120}] $div
210                 set aln [expr {$aln | 0x4}]
211         } else {
212                 mww [expr {$pll_addr + 0x0120}] 0
213         }
214         if { [dict exists $config oscdiv] } {
215                 set div [dict get $config oscdiv]
216                 set div [expr {0x8000 | ($div - 1)}]
217                 mww [expr {$pll_addr + 0x0124}] $div
218         } else {
219                 mww [expr {$pll_addr + 0x0124}] 0
220         }
221         if { [dict exists $config div4] } {
222                 set div [dict get $config div4]
223                 set div [expr {0x8000 | ($div - 1)}]
224                 mww [expr {$pll_addr + 0x0160}] $div
225                 set aln [expr {$aln | 0x8}]
226         } else {
227                 mww [expr {$pll_addr + 0x0160}] 0
228         }
229         if { [dict exists $config div5] } {
230                 set div [dict get $config div5]
231                 set div [expr {0x8000 | ($div - 1)}]
232                 mww [expr {$pll_addr + 0x0164}] $div
233                 set aln [expr {$aln | 0x10}]
234         } else {
235                 mww [expr {$pll_addr + 0x0164}] 0
236         }
237         if { [dict exists $config div6] } {
238                 set div [dict get $config div6]
239                 set div [expr {0x8000 | ($div - 1)}]
240                 mww [expr {$pll_addr + 0x0168}] $div
241                 set aln [expr {$aln | 0x20}]
242         } else {
243                 mww [expr {$pll_addr + 0x0168}] 0
244         }
245         if { [dict exists $config div7] } {
246                 set div [dict get $config div7]
247                 set div [expr {0x8000 | ($div - 1)}]
248                 mww [expr {$pll_addr + 0x016c}] $div
249                 set aln [expr {$aln | 0x40}]
250         } else {
251                 mww [expr {$pll_addr + 0x016c}] 0
252         }
253         if { [dict exists $config div8] } {
254                 set div [dict get $config div8]
255                 set div [expr {0x8000 | ($div - 1)}]
256                 mww [expr {$pll_addr + 0x0170}] $div
257                 set aln [expr {$aln | 0x80}]
258         } else {
259                 mww [expr {$pll_addr + 0x0170}] 0
260         }
261         if { [dict exists $config div9] } {
262                 set div [dict get $config div9]
263                 set div [expr {0x8000 | ($div - 1)}]
264                 mww [expr {$pll_addr + 0x0174}] $div
265                 set aln [expr {$aln | 0x100}]
266         } else {
267                 mww [expr {$pll_addr + 0x0174}] 0
268         }
269         if {$aln != 0} {
270                 # clear pllcmd.GO
271                 mww [expr {$pll_addr + 0x0138}] 0x00
272                 # write alignment flags
273                 mww [expr {$pll_addr + 0x0140}] $aln
274                 # write pllcmd.GO; poll pllstat.GO
275                 mww [expr {$pll_addr + 0x0138}] 0x01
276                 set pllstat [expr {$pll_addr + 0x013c}]
277                 while {[expr {[mrw $pllstat] & 0x01}] != 0} { sleep 1 }
278         }
279         mww [expr {$pll_addr + 0x0138}] 0x00
280         set addr [dict get $config ctladdr]
281         while {[expr {[mrw $addr] & 0x0e000000}] != 0x0e000000} { sleep 1 }
282
283         # 12 - set PLLEN (bit 0) ... leave bypass mode
284         set pll_ctrl [expr {$pll_ctrl | 0x0001}]
285         mww $pll_ctrl_addr $pll_ctrl
286 }
287
288 # NOTE: dm6446 requires EMURSTIE set in MDCTL before certain
289 # modules can be enabled.
290
291 # prepare a non-DSP module to be enabled; finish with psc_go
292 proc psc_enable {module} {
293         set psc_addr 0x01c41000
294         # write MDCTL
295         mmw [expr {$psc_addr + 0x0a00 + (4 * $module)}] 0x03 0x1f
296 }
297
298 # prepare a non-DSP module to be reset; finish with psc_go
299 proc psc_reset {module} {
300         set psc_addr 0x01c41000
301         # write MDCTL
302         mmw [expr {$psc_addr + 0x0a00 + (4 * $module)}] 0x01 0x1f
303 }
304
305 # execute non-DSP PSC transition(s) set up by psc_enable, psc_reset, etc
306 proc psc_go {} {
307         set psc_addr 0x01c41000
308         set ptstat_addr [expr {$psc_addr + 0x0128}]
309
310         # just in case PTSTAT.go isn't clear
311         while { [expr {[mrw $ptstat_addr] & 0x01}] != 0 } { sleep 1 }
312
313         # write PTCMD.go ... ignoring any DSP power domain
314         mww [expr {$psc_addr + 0x0120}] 1
315
316         # wait for PTSTAT.go to clear (again ignoring DSP power domain)
317         while { [expr {[mrw $ptstat_addr] & 0x01}] != 0 } { sleep 1 }
318 }
319
320 #
321 # A reset using only SRST is a "Warm Reset", resetting everything in the
322 # chip except ARM emulation (and everything _outside_ the chip that hooks
323 # up to SRST).  But many boards don't expose SRST via their JTAG connectors
324 # (it's not present on TI-14 headers).
325 #
326 # From the chip-only perspective, a "Max Reset" is a "Warm" reset ... except
327 # without any board-wide side effects, since it's triggered using JTAG using
328 # either (a) ARM watchdog timer, or (b) ICEpick.
329 #
330 proc davinci_wdog_reset {} {
331         set timer2_phys 0x01c21c00
332
333         # NOTE -- on entry
334         #   - JTAG communication with the ARM *must* be working OK; this
335         #     may imply using adaptive clocking or disabling WFI-in-idle
336         #   - current target must be the DaVinci ARM
337         #   - that ARM core must be halted
338         #   - timer2 clock is still enabled (PSC 29 on most chips)
339
340         #
341         # Part I -- run regardless of being halted via JTAG
342         #
343         # NOTE:  for now, we assume there's no DSP that could control the
344         # watchdog; or, equivalently, SUSPSRC.TMR2SRC says the watchdog
345         # suspend signal is controlled via ARM emulation suspend.
346         #
347
348         # EMUMGT_CLKSPEED: write FREE bit to run despite emulation halt
349         mww phys [expr {$timer2_phys + 0x28}] 0x00004000
350
351         #
352         # Part II -- in case watchdog hasn't been set up
353         #
354
355         # TCR: disable, force internal clock source
356         mww phys [expr {$timer2_phys + 0x20}] 0
357
358         # TGCR: reset, force to 64-bit wdog mode, un-reset ("initial" state)
359         mww phys [expr {$timer2_phys + 0x24}] 0
360         mww phys [expr {$timer2_phys + 0x24}] 0x110b
361
362         # clear counter (TIM12, TIM34) and period (PRD12, PRD34) registers
363         # so watchdog triggers ASAP
364         mww phys [expr {$timer2_phys + 0x10}] 0
365         mww phys [expr {$timer2_phys + 0x14}] 0
366         mww phys [expr {$timer2_phys + 0x18}] 0
367         mww phys [expr {$timer2_phys + 0x1c}] 0
368
369         # WDTCR: put into pre-active state, then active
370         mww phys [expr {$timer2_phys + 0x28}] 0xa5c64000
371         mww phys [expr {$timer2_phys + 0x28}] 0xda7e4000
372
373         #
374         # Part III -- it's ready to rumble
375         #
376
377         # WDTCR: write invalid WDKEY to trigger reset
378         mww phys [expr {$timer2_phys + 0x28}] 0x00004000
379 }