You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

378 lines
11 KiB

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