mips-extns.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
  3. * reserved.
  4. *
  5. * This software is available to you under a choice of one of two
  6. * licenses. You may choose to be licensed under the terms of the GNU
  7. * General Public License (GPL) Version 2, available from the file
  8. * COPYING in the main directory of this source tree, or the NetLogic
  9. * license below:
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
  23. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  29. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  30. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  31. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  32. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #ifndef _ASM_NLM_MIPS_EXTS_H
  35. #define _ASM_NLM_MIPS_EXTS_H
  36. /*
  37. * XLR and XLP interrupt request and interrupt mask registers
  38. */
  39. /*
  40. * NOTE: Do not save/restore flags around write_c0_eimr().
  41. * On non-R2 platforms the flags has part of EIMR that is shadowed in STATUS
  42. * register. Restoring flags will overwrite the lower 8 bits of EIMR.
  43. *
  44. * Call with interrupts disabled.
  45. */
  46. #define write_c0_eimr(val) \
  47. do { \
  48. if (sizeof(unsigned long) == 4) { \
  49. __asm__ __volatile__( \
  50. ".set\tmips64\n\t" \
  51. "dsll\t%L0, %L0, 32\n\t" \
  52. "dsrl\t%L0, %L0, 32\n\t" \
  53. "dsll\t%M0, %M0, 32\n\t" \
  54. "or\t%L0, %L0, %M0\n\t" \
  55. "dmtc0\t%L0, $9, 7\n\t" \
  56. ".set\tmips0" \
  57. : : "r" (val)); \
  58. } else \
  59. __write_64bit_c0_register($9, 7, (val)); \
  60. } while (0)
  61. /*
  62. * Handling the 64 bit EIMR and EIRR registers in 32-bit mode with
  63. * standard functions will be very inefficient. This provides
  64. * optimized functions for the normal operations on the registers.
  65. *
  66. * Call with interrupts disabled.
  67. */
  68. static inline void ack_c0_eirr(int irq)
  69. {
  70. __asm__ __volatile__(
  71. ".set push\n\t"
  72. ".set mips64\n\t"
  73. ".set noat\n\t"
  74. "li $1, 1\n\t"
  75. "dsllv $1, $1, %0\n\t"
  76. "dmtc0 $1, $9, 6\n\t"
  77. ".set pop"
  78. : : "r" (irq));
  79. }
  80. static inline void set_c0_eimr(int irq)
  81. {
  82. __asm__ __volatile__(
  83. ".set push\n\t"
  84. ".set mips64\n\t"
  85. ".set noat\n\t"
  86. "li $1, 1\n\t"
  87. "dsllv %0, $1, %0\n\t"
  88. "dmfc0 $1, $9, 7\n\t"
  89. "or $1, %0\n\t"
  90. "dmtc0 $1, $9, 7\n\t"
  91. ".set pop"
  92. : "+r" (irq));
  93. }
  94. static inline void clear_c0_eimr(int irq)
  95. {
  96. __asm__ __volatile__(
  97. ".set push\n\t"
  98. ".set mips64\n\t"
  99. ".set noat\n\t"
  100. "li $1, 1\n\t"
  101. "dsllv %0, $1, %0\n\t"
  102. "dmfc0 $1, $9, 7\n\t"
  103. "or $1, %0\n\t"
  104. "xor $1, %0\n\t"
  105. "dmtc0 $1, $9, 7\n\t"
  106. ".set pop"
  107. : "+r" (irq));
  108. }
  109. /*
  110. * Read c0 eimr and c0 eirr, do AND of the two values, the result is
  111. * the interrupts which are raised and are not masked.
  112. */
  113. static inline uint64_t read_c0_eirr_and_eimr(void)
  114. {
  115. uint64_t val;
  116. #ifdef CONFIG_64BIT
  117. val = __read_64bit_c0_register($9, 6) & __read_64bit_c0_register($9, 7);
  118. #else
  119. __asm__ __volatile__(
  120. ".set push\n\t"
  121. ".set mips64\n\t"
  122. ".set noat\n\t"
  123. "dmfc0 %M0, $9, 6\n\t"
  124. "dmfc0 %L0, $9, 7\n\t"
  125. "and %M0, %L0\n\t"
  126. "dsll %L0, %M0, 32\n\t"
  127. "dsra %M0, %M0, 32\n\t"
  128. "dsra %L0, %L0, 32\n\t"
  129. ".set pop"
  130. : "=r" (val));
  131. #endif
  132. return val;
  133. }
  134. static inline int hard_smp_processor_id(void)
  135. {
  136. return __read_32bit_c0_register($15, 1) & 0x3ff;
  137. }
  138. static inline int nlm_nodeid(void)
  139. {
  140. uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
  141. if ((prid == PRID_IMP_NETLOGIC_XLP9XX) ||
  142. (prid == PRID_IMP_NETLOGIC_XLP5XX))
  143. return (__read_32bit_c0_register($15, 1) >> 7) & 0x7;
  144. else
  145. return (__read_32bit_c0_register($15, 1) >> 5) & 0x3;
  146. }
  147. static inline unsigned int nlm_core_id(void)
  148. {
  149. uint32_t prid = read_c0_prid() & PRID_IMP_MASK;
  150. if ((prid == PRID_IMP_NETLOGIC_XLP9XX) ||
  151. (prid == PRID_IMP_NETLOGIC_XLP5XX))
  152. return (read_c0_ebase() & 0x7c) >> 2;
  153. else
  154. return (read_c0_ebase() & 0x1c) >> 2;
  155. }
  156. static inline unsigned int nlm_thread_id(void)
  157. {
  158. return read_c0_ebase() & 0x3;
  159. }
  160. #define __read_64bit_c2_split(source, sel) \
  161. ({ \
  162. unsigned long long __val; \
  163. unsigned long __flags; \
  164. \
  165. local_irq_save(__flags); \
  166. if (sel == 0) \
  167. __asm__ __volatile__( \
  168. ".set\tmips64\n\t" \
  169. "dmfc2\t%M0, " #source "\n\t" \
  170. "dsll\t%L0, %M0, 32\n\t" \
  171. "dsra\t%M0, %M0, 32\n\t" \
  172. "dsra\t%L0, %L0, 32\n\t" \
  173. ".set\tmips0\n\t" \
  174. : "=r" (__val)); \
  175. else \
  176. __asm__ __volatile__( \
  177. ".set\tmips64\n\t" \
  178. "dmfc2\t%M0, " #source ", " #sel "\n\t" \
  179. "dsll\t%L0, %M0, 32\n\t" \
  180. "dsra\t%M0, %M0, 32\n\t" \
  181. "dsra\t%L0, %L0, 32\n\t" \
  182. ".set\tmips0\n\t" \
  183. : "=r" (__val)); \
  184. local_irq_restore(__flags); \
  185. \
  186. __val; \
  187. })
  188. #define __write_64bit_c2_split(source, sel, val) \
  189. do { \
  190. unsigned long __flags; \
  191. \
  192. local_irq_save(__flags); \
  193. if (sel == 0) \
  194. __asm__ __volatile__( \
  195. ".set\tmips64\n\t" \
  196. "dsll\t%L0, %L0, 32\n\t" \
  197. "dsrl\t%L0, %L0, 32\n\t" \
  198. "dsll\t%M0, %M0, 32\n\t" \
  199. "or\t%L0, %L0, %M0\n\t" \
  200. "dmtc2\t%L0, " #source "\n\t" \
  201. ".set\tmips0\n\t" \
  202. : : "r" (val)); \
  203. else \
  204. __asm__ __volatile__( \
  205. ".set\tmips64\n\t" \
  206. "dsll\t%L0, %L0, 32\n\t" \
  207. "dsrl\t%L0, %L0, 32\n\t" \
  208. "dsll\t%M0, %M0, 32\n\t" \
  209. "or\t%L0, %L0, %M0\n\t" \
  210. "dmtc2\t%L0, " #source ", " #sel "\n\t" \
  211. ".set\tmips0\n\t" \
  212. : : "r" (val)); \
  213. local_irq_restore(__flags); \
  214. } while (0)
  215. #define __read_32bit_c2_register(source, sel) \
  216. ({ uint32_t __res; \
  217. if (sel == 0) \
  218. __asm__ __volatile__( \
  219. ".set\tmips32\n\t" \
  220. "mfc2\t%0, " #source "\n\t" \
  221. ".set\tmips0\n\t" \
  222. : "=r" (__res)); \
  223. else \
  224. __asm__ __volatile__( \
  225. ".set\tmips32\n\t" \
  226. "mfc2\t%0, " #source ", " #sel "\n\t" \
  227. ".set\tmips0\n\t" \
  228. : "=r" (__res)); \
  229. __res; \
  230. })
  231. #define __read_64bit_c2_register(source, sel) \
  232. ({ unsigned long long __res; \
  233. if (sizeof(unsigned long) == 4) \
  234. __res = __read_64bit_c2_split(source, sel); \
  235. else if (sel == 0) \
  236. __asm__ __volatile__( \
  237. ".set\tmips64\n\t" \
  238. "dmfc2\t%0, " #source "\n\t" \
  239. ".set\tmips0\n\t" \
  240. : "=r" (__res)); \
  241. else \
  242. __asm__ __volatile__( \
  243. ".set\tmips64\n\t" \
  244. "dmfc2\t%0, " #source ", " #sel "\n\t" \
  245. ".set\tmips0\n\t" \
  246. : "=r" (__res)); \
  247. __res; \
  248. })
  249. #define __write_64bit_c2_register(register, sel, value) \
  250. do { \
  251. if (sizeof(unsigned long) == 4) \
  252. __write_64bit_c2_split(register, sel, value); \
  253. else if (sel == 0) \
  254. __asm__ __volatile__( \
  255. ".set\tmips64\n\t" \
  256. "dmtc2\t%z0, " #register "\n\t" \
  257. ".set\tmips0\n\t" \
  258. : : "Jr" (value)); \
  259. else \
  260. __asm__ __volatile__( \
  261. ".set\tmips64\n\t" \
  262. "dmtc2\t%z0, " #register ", " #sel "\n\t" \
  263. ".set\tmips0\n\t" \
  264. : : "Jr" (value)); \
  265. } while (0)
  266. #define __write_32bit_c2_register(reg, sel, value) \
  267. ({ \
  268. if (sel == 0) \
  269. __asm__ __volatile__( \
  270. ".set\tmips32\n\t" \
  271. "mtc2\t%z0, " #reg "\n\t" \
  272. ".set\tmips0\n\t" \
  273. : : "Jr" (value)); \
  274. else \
  275. __asm__ __volatile__( \
  276. ".set\tmips32\n\t" \
  277. "mtc2\t%z0, " #reg ", " #sel "\n\t" \
  278. ".set\tmips0\n\t" \
  279. : : "Jr" (value)); \
  280. })
  281. #endif /*_ASM_NLM_MIPS_EXTS_H */