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