cps-vec.S 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /*
  2. * Copyright (C) 2013 Imagination Technologies
  3. * Author: Paul Burton <paul.burton@imgtec.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. */
  10. #include <asm/addrspace.h>
  11. #include <asm/asm.h>
  12. #include <asm/asm-offsets.h>
  13. #include <asm/asmmacro.h>
  14. #include <asm/cacheops.h>
  15. #include <asm/eva.h>
  16. #include <asm/mipsregs.h>
  17. #include <asm/mipsmtregs.h>
  18. #include <asm/pm.h>
  19. #define GCR_CL_COHERENCE_OFS 0x2008
  20. #define GCR_CL_ID_OFS 0x2028
  21. .extern mips_cm_base
  22. .set noreorder
  23. #ifdef CONFIG_64BIT
  24. # define STATUS_BITDEPS ST0_KX
  25. #else
  26. # define STATUS_BITDEPS 0
  27. #endif
  28. #ifdef CONFIG_MIPS_CPS_NS16550
  29. #define DUMP_EXCEP(name) \
  30. PTR_LA a0, 8f; \
  31. jal mips_cps_bev_dump; \
  32. nop; \
  33. TEXT(name)
  34. #else /* !CONFIG_MIPS_CPS_NS16550 */
  35. #define DUMP_EXCEP(name)
  36. #endif /* !CONFIG_MIPS_CPS_NS16550 */
  37. /*
  38. * Set dest to non-zero if the core supports the MT ASE, else zero. If
  39. * MT is not supported then branch to nomt.
  40. */
  41. .macro has_mt dest, nomt
  42. mfc0 \dest, CP0_CONFIG, 1
  43. bgez \dest, \nomt
  44. mfc0 \dest, CP0_CONFIG, 2
  45. bgez \dest, \nomt
  46. mfc0 \dest, CP0_CONFIG, 3
  47. andi \dest, \dest, MIPS_CONF3_MT
  48. beqz \dest, \nomt
  49. nop
  50. .endm
  51. .section .text.cps-vec
  52. .balign 0x1000
  53. LEAF(mips_cps_core_entry)
  54. /*
  55. * These first 4 bytes will be patched by cps_smp_setup to load the
  56. * CCA to use into register s0.
  57. */
  58. .word 0
  59. /* Check whether we're here due to an NMI */
  60. mfc0 k0, CP0_STATUS
  61. and k0, k0, ST0_NMI
  62. beqz k0, not_nmi
  63. nop
  64. /* This is an NMI */
  65. PTR_LA k0, nmi_handler
  66. jr k0
  67. nop
  68. not_nmi:
  69. /* Setup Cause */
  70. li t0, CAUSEF_IV
  71. mtc0 t0, CP0_CAUSE
  72. /* Setup Status */
  73. li t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
  74. mtc0 t0, CP0_STATUS
  75. /*
  76. * Clear the bits used to index the caches. Note that the architecture
  77. * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
  78. * be valid for all MIPS32 CPUs, even those for which said writes are
  79. * unnecessary.
  80. */
  81. mtc0 zero, CP0_TAGLO, 0
  82. mtc0 zero, CP0_TAGHI, 0
  83. mtc0 zero, CP0_TAGLO, 2
  84. mtc0 zero, CP0_TAGHI, 2
  85. ehb
  86. /* Primary cache configuration is indicated by Config1 */
  87. mfc0 v0, CP0_CONFIG, 1
  88. /* Detect I-cache line size */
  89. _EXT t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
  90. beqz t0, icache_done
  91. li t1, 2
  92. sllv t0, t1, t0
  93. /* Detect I-cache size */
  94. _EXT t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
  95. xori t2, t1, 0x7
  96. beqz t2, 1f
  97. li t3, 32
  98. addiu t1, t1, 1
  99. sllv t1, t3, t1
  100. 1: /* At this point t1 == I-cache sets per way */
  101. _EXT t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
  102. addiu t2, t2, 1
  103. mul t1, t1, t0
  104. mul t1, t1, t2
  105. li a0, CKSEG0
  106. PTR_ADD a1, a0, t1
  107. 1: cache Index_Store_Tag_I, 0(a0)
  108. PTR_ADD a0, a0, t0
  109. bne a0, a1, 1b
  110. nop
  111. icache_done:
  112. /* Detect D-cache line size */
  113. _EXT t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
  114. beqz t0, dcache_done
  115. li t1, 2
  116. sllv t0, t1, t0
  117. /* Detect D-cache size */
  118. _EXT t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
  119. xori t2, t1, 0x7
  120. beqz t2, 1f
  121. li t3, 32
  122. addiu t1, t1, 1
  123. sllv t1, t3, t1
  124. 1: /* At this point t1 == D-cache sets per way */
  125. _EXT t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
  126. addiu t2, t2, 1
  127. mul t1, t1, t0
  128. mul t1, t1, t2
  129. li a0, CKSEG0
  130. PTR_ADDU a1, a0, t1
  131. PTR_SUBU a1, a1, t0
  132. 1: cache Index_Store_Tag_D, 0(a0)
  133. bne a0, a1, 1b
  134. PTR_ADD a0, a0, t0
  135. dcache_done:
  136. /* Set Kseg0 CCA to that in s0 */
  137. mfc0 t0, CP0_CONFIG
  138. ori t0, 0x7
  139. xori t0, 0x7
  140. or t0, t0, s0
  141. mtc0 t0, CP0_CONFIG
  142. ehb
  143. /* Calculate an uncached address for the CM GCRs */
  144. MFC0 v1, CP0_CMGCRBASE
  145. PTR_SLL v1, v1, 4
  146. PTR_LI t0, UNCAC_BASE
  147. PTR_ADDU v1, v1, t0
  148. /* Enter the coherent domain */
  149. li t0, 0xff
  150. sw t0, GCR_CL_COHERENCE_OFS(v1)
  151. ehb
  152. /* Jump to kseg0 */
  153. PTR_LA t0, 1f
  154. jr t0
  155. nop
  156. /*
  157. * We're up, cached & coherent. Perform any further required core-level
  158. * initialisation.
  159. */
  160. 1: jal mips_cps_core_init
  161. nop
  162. /* Do any EVA initialization if necessary */
  163. eva_init
  164. /*
  165. * Boot any other VPEs within this core that should be online, and
  166. * deactivate this VPE if it should be offline.
  167. */
  168. jal mips_cps_boot_vpes
  169. nop
  170. /* Off we go! */
  171. PTR_L t1, VPEBOOTCFG_PC(v0)
  172. PTR_L gp, VPEBOOTCFG_GP(v0)
  173. PTR_L sp, VPEBOOTCFG_SP(v0)
  174. jr t1
  175. nop
  176. END(mips_cps_core_entry)
  177. .org 0x200
  178. LEAF(excep_tlbfill)
  179. DUMP_EXCEP("TLB Fill")
  180. b .
  181. nop
  182. END(excep_tlbfill)
  183. .org 0x280
  184. LEAF(excep_xtlbfill)
  185. DUMP_EXCEP("XTLB Fill")
  186. b .
  187. nop
  188. END(excep_xtlbfill)
  189. .org 0x300
  190. LEAF(excep_cache)
  191. DUMP_EXCEP("Cache")
  192. b .
  193. nop
  194. END(excep_cache)
  195. .org 0x380
  196. LEAF(excep_genex)
  197. DUMP_EXCEP("General")
  198. b .
  199. nop
  200. END(excep_genex)
  201. .org 0x400
  202. LEAF(excep_intex)
  203. DUMP_EXCEP("Interrupt")
  204. b .
  205. nop
  206. END(excep_intex)
  207. .org 0x480
  208. LEAF(excep_ejtag)
  209. DUMP_EXCEP("EJTAG")
  210. PTR_LA k0, ejtag_debug_handler
  211. jr k0
  212. nop
  213. END(excep_ejtag)
  214. LEAF(mips_cps_core_init)
  215. #ifdef CONFIG_MIPS_MT_SMP
  216. /* Check that the core implements the MT ASE */
  217. has_mt t0, 3f
  218. .set push
  219. .set mips64r2
  220. .set mt
  221. /* Only allow 1 TC per VPE to execute... */
  222. dmt
  223. /* ...and for the moment only 1 VPE */
  224. dvpe
  225. PTR_LA t1, 1f
  226. jr.hb t1
  227. nop
  228. /* Enter VPE configuration state */
  229. 1: mfc0 t0, CP0_MVPCONTROL
  230. ori t0, t0, MVPCONTROL_VPC
  231. mtc0 t0, CP0_MVPCONTROL
  232. /* Retrieve the number of VPEs within the core */
  233. mfc0 t0, CP0_MVPCONF0
  234. srl t0, t0, MVPCONF0_PVPE_SHIFT
  235. andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
  236. addiu ta3, t0, 1
  237. /* If there's only 1, we're done */
  238. beqz t0, 2f
  239. nop
  240. /* Loop through each VPE within this core */
  241. li ta1, 1
  242. 1: /* Operate on the appropriate TC */
  243. mtc0 ta1, CP0_VPECONTROL
  244. ehb
  245. /* Bind TC to VPE (1:1 TC:VPE mapping) */
  246. mttc0 ta1, CP0_TCBIND
  247. /* Set exclusive TC, non-active, master */
  248. li t0, VPECONF0_MVP
  249. sll t1, ta1, VPECONF0_XTC_SHIFT
  250. or t0, t0, t1
  251. mttc0 t0, CP0_VPECONF0
  252. /* Set TC non-active, non-allocatable */
  253. mttc0 zero, CP0_TCSTATUS
  254. /* Set TC halted */
  255. li t0, TCHALT_H
  256. mttc0 t0, CP0_TCHALT
  257. /* Next VPE */
  258. addiu ta1, ta1, 1
  259. slt t0, ta1, ta3
  260. bnez t0, 1b
  261. nop
  262. /* Leave VPE configuration state */
  263. 2: mfc0 t0, CP0_MVPCONTROL
  264. xori t0, t0, MVPCONTROL_VPC
  265. mtc0 t0, CP0_MVPCONTROL
  266. 3: .set pop
  267. #endif
  268. jr ra
  269. nop
  270. END(mips_cps_core_init)
  271. LEAF(mips_cps_boot_vpes)
  272. /* Retrieve CM base address */
  273. PTR_LA t0, mips_cm_base
  274. PTR_L t0, 0(t0)
  275. /* Calculate a pointer to this cores struct core_boot_config */
  276. lw t0, GCR_CL_ID_OFS(t0)
  277. li t1, COREBOOTCFG_SIZE
  278. mul t0, t0, t1
  279. PTR_LA t1, mips_cps_core_bootcfg
  280. PTR_L t1, 0(t1)
  281. PTR_ADDU t0, t0, t1
  282. /* Calculate this VPEs ID. If the core doesn't support MT use 0 */
  283. li t9, 0
  284. #ifdef CONFIG_MIPS_MT_SMP
  285. has_mt ta2, 1f
  286. /* Find the number of VPEs present in the core */
  287. mfc0 t1, CP0_MVPCONF0
  288. srl t1, t1, MVPCONF0_PVPE_SHIFT
  289. andi t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
  290. addiu t1, t1, 1
  291. /* Calculate a mask for the VPE ID from EBase.CPUNum */
  292. clz t1, t1
  293. li t2, 31
  294. subu t1, t2, t1
  295. li t2, 1
  296. sll t1, t2, t1
  297. addiu t1, t1, -1
  298. /* Retrieve the VPE ID from EBase.CPUNum */
  299. mfc0 t9, $15, 1
  300. and t9, t9, t1
  301. #endif
  302. 1: /* Calculate a pointer to this VPEs struct vpe_boot_config */
  303. li t1, VPEBOOTCFG_SIZE
  304. mul v0, t9, t1
  305. PTR_L ta3, COREBOOTCFG_VPECONFIG(t0)
  306. PTR_ADDU v0, v0, ta3
  307. #ifdef CONFIG_MIPS_MT_SMP
  308. /* If the core doesn't support MT then return */
  309. bnez ta2, 1f
  310. nop
  311. jr ra
  312. nop
  313. .set push
  314. .set mips64r2
  315. .set mt
  316. 1: /* Enter VPE configuration state */
  317. dvpe
  318. PTR_LA t1, 1f
  319. jr.hb t1
  320. nop
  321. 1: mfc0 t1, CP0_MVPCONTROL
  322. ori t1, t1, MVPCONTROL_VPC
  323. mtc0 t1, CP0_MVPCONTROL
  324. ehb
  325. /* Loop through each VPE */
  326. PTR_L ta2, COREBOOTCFG_VPEMASK(t0)
  327. move t8, ta2
  328. li ta1, 0
  329. /* Check whether the VPE should be running. If not, skip it */
  330. 1: andi t0, ta2, 1
  331. beqz t0, 2f
  332. nop
  333. /* Operate on the appropriate TC */
  334. mfc0 t0, CP0_VPECONTROL
  335. ori t0, t0, VPECONTROL_TARGTC
  336. xori t0, t0, VPECONTROL_TARGTC
  337. or t0, t0, ta1
  338. mtc0 t0, CP0_VPECONTROL
  339. ehb
  340. /* Skip the VPE if its TC is not halted */
  341. mftc0 t0, CP0_TCHALT
  342. beqz t0, 2f
  343. nop
  344. /* Calculate a pointer to the VPEs struct vpe_boot_config */
  345. li t0, VPEBOOTCFG_SIZE
  346. mul t0, t0, ta1
  347. addu t0, t0, ta3
  348. /* Set the TC restart PC */
  349. lw t1, VPEBOOTCFG_PC(t0)
  350. mttc0 t1, CP0_TCRESTART
  351. /* Set the TC stack pointer */
  352. lw t1, VPEBOOTCFG_SP(t0)
  353. mttgpr t1, sp
  354. /* Set the TC global pointer */
  355. lw t1, VPEBOOTCFG_GP(t0)
  356. mttgpr t1, gp
  357. /* Copy config from this VPE */
  358. mfc0 t0, CP0_CONFIG
  359. mttc0 t0, CP0_CONFIG
  360. /* Ensure no software interrupts are pending */
  361. mttc0 zero, CP0_CAUSE
  362. mttc0 zero, CP0_STATUS
  363. /* Set TC active, not interrupt exempt */
  364. mftc0 t0, CP0_TCSTATUS
  365. li t1, ~TCSTATUS_IXMT
  366. and t0, t0, t1
  367. ori t0, t0, TCSTATUS_A
  368. mttc0 t0, CP0_TCSTATUS
  369. /* Clear the TC halt bit */
  370. mttc0 zero, CP0_TCHALT
  371. /* Set VPE active */
  372. mftc0 t0, CP0_VPECONF0
  373. ori t0, t0, VPECONF0_VPA
  374. mttc0 t0, CP0_VPECONF0
  375. /* Next VPE */
  376. 2: srl ta2, ta2, 1
  377. addiu ta1, ta1, 1
  378. bnez ta2, 1b
  379. nop
  380. /* Leave VPE configuration state */
  381. mfc0 t1, CP0_MVPCONTROL
  382. xori t1, t1, MVPCONTROL_VPC
  383. mtc0 t1, CP0_MVPCONTROL
  384. ehb
  385. evpe
  386. /* Check whether this VPE is meant to be running */
  387. li t0, 1
  388. sll t0, t0, t9
  389. and t0, t0, t8
  390. bnez t0, 2f
  391. nop
  392. /* This VPE should be offline, halt the TC */
  393. li t0, TCHALT_H
  394. mtc0 t0, CP0_TCHALT
  395. PTR_LA t0, 1f
  396. 1: jr.hb t0
  397. nop
  398. 2: .set pop
  399. #endif /* CONFIG_MIPS_MT_SMP */
  400. /* Return */
  401. jr ra
  402. nop
  403. END(mips_cps_boot_vpes)
  404. #if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM)
  405. /* Calculate a pointer to this CPUs struct mips_static_suspend_state */
  406. .macro psstate dest
  407. .set push
  408. .set noat
  409. lw $1, TI_CPU(gp)
  410. sll $1, $1, LONGLOG
  411. PTR_LA \dest, __per_cpu_offset
  412. addu $1, $1, \dest
  413. lw $1, 0($1)
  414. PTR_LA \dest, cps_cpu_state
  415. addu \dest, \dest, $1
  416. .set pop
  417. .endm
  418. LEAF(mips_cps_pm_save)
  419. /* Save CPU state */
  420. SUSPEND_SAVE_REGS
  421. psstate t1
  422. SUSPEND_SAVE_STATIC
  423. jr v0
  424. nop
  425. END(mips_cps_pm_save)
  426. LEAF(mips_cps_pm_restore)
  427. /* Restore CPU state */
  428. psstate t1
  429. RESUME_RESTORE_STATIC
  430. RESUME_RESTORE_REGS_RETURN
  431. END(mips_cps_pm_restore)
  432. #endif /* CONFIG_MIPS_CPS_PM && CONFIG_CPU_PM */