arm_dcc.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Copyright (C) 2004-2007 ARM Limited.
  3. * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License version 2
  7. * as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. * As a special exception, if other files instantiate templates or use macros
  19. * or inline functions from this file, or you compile this file and link it
  20. * with other works to produce a work based on this file, this file does not
  21. * by itself cause the resulting work to be covered by the GNU General Public
  22. * License. However the source code for this file must still be made available
  23. * in accordance with section (3) of the GNU General Public License.
  24. * This exception does not invalidate any other reasons why a work based on
  25. * this file might be covered by the GNU General Public License.
  26. */
  27. #include <common.h>
  28. #include <devices.h>
  29. #define DCC_ARM9_RBIT (1 << 0)
  30. #define DCC_ARM9_WBIT (1 << 1)
  31. #define DCC_ARM11_RBIT (1 << 30)
  32. #define DCC_ARM11_WBIT (1 << 29)
  33. #define read_core_id(x) do { \
  34. __asm__ ("mrc p15, 0, %0, c0, c0, 0\n" : "=r" (x)); \
  35. x = (x >> 4) & 0xFFF; \
  36. } while (0);
  37. /*
  38. * ARM9
  39. */
  40. #define write_arm9_dcc(x) \
  41. __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x))
  42. #define read_arm9_dcc(x) \
  43. __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x))
  44. #define status_arm9_dcc(x) \
  45. __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x))
  46. #define can_read_arm9_dcc(x) do { \
  47. status_arm9_dcc(x); \
  48. x &= DCC_ARM9_RBIT; \
  49. } while (0);
  50. #define can_write_arm9_dcc(x) do { \
  51. status_arm9_dcc(x); \
  52. x &= DCC_ARM9_WBIT; \
  53. x = (x == 0); \
  54. } while (0);
  55. /*
  56. * ARM11
  57. */
  58. #define write_arm11_dcc(x) \
  59. __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x))
  60. #define read_arm11_dcc(x) \
  61. __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x))
  62. #define status_arm11_dcc(x) \
  63. __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x))
  64. #define can_read_arm11_dcc(x) do { \
  65. status_arm11_dcc(x); \
  66. x &= DCC_ARM11_RBIT; \
  67. } while (0);
  68. #define can_write_arm11_dcc(x) do { \
  69. status_arm11_dcc(x); \
  70. x &= DCC_ARM11_WBIT; \
  71. x = (x == 0); \
  72. } while (0);
  73. #define TIMEOUT_COUNT 0x4000000
  74. static enum {
  75. arm9_and_earlier,
  76. arm11_and_later
  77. } arm_type = arm9_and_earlier;
  78. #ifndef CONFIG_ARM_DCC_MULTI
  79. #define arm_dcc_init serial_init
  80. void serial_setbrg(void) {}
  81. #define arm_dcc_getc serial_getc
  82. #define arm_dcc_putc serial_putc
  83. #define arm_dcc_puts serial_puts
  84. #define arm_dcc_tstc serial_tstc
  85. #endif
  86. int arm_dcc_init(void)
  87. {
  88. register unsigned int id;
  89. read_core_id(id);
  90. if (id >= 0xb00)
  91. arm_type = arm11_and_later;
  92. else
  93. arm_type = arm9_and_earlier;
  94. return 0;
  95. }
  96. int arm_dcc_getc(void)
  97. {
  98. int ch;
  99. register unsigned int reg;
  100. switch (arm_type) {
  101. case arm11_and_later:
  102. do {
  103. can_read_arm11_dcc(reg);
  104. } while (!reg);
  105. read_arm11_dcc(ch);
  106. break;
  107. case arm9_and_earlier:
  108. default:
  109. do {
  110. can_read_arm9_dcc(reg);
  111. } while (!reg);
  112. read_arm9_dcc(ch);
  113. break;
  114. }
  115. return ch;
  116. }
  117. void arm_dcc_putc(char ch)
  118. {
  119. register unsigned int reg;
  120. unsigned int timeout_count = TIMEOUT_COUNT;
  121. switch (arm_type) {
  122. case arm11_and_later:
  123. while (--timeout_count) {
  124. can_write_arm11_dcc(reg);
  125. if (reg)
  126. break;
  127. }
  128. if (timeout_count == 0)
  129. return;
  130. else
  131. write_arm11_dcc(ch);
  132. break;
  133. case arm9_and_earlier:
  134. default:
  135. while (--timeout_count) {
  136. can_write_arm9_dcc(reg);
  137. if (reg)
  138. break;
  139. }
  140. if (timeout_count == 0)
  141. return;
  142. else
  143. write_arm9_dcc(ch);
  144. break;
  145. }
  146. }
  147. void arm_dcc_puts(const char *s)
  148. {
  149. while (*s)
  150. arm_dcc_putc(*s++);
  151. }
  152. int arm_dcc_tstc(void)
  153. {
  154. register unsigned int reg;
  155. switch (arm_type) {
  156. case arm11_and_later:
  157. can_read_arm11_dcc(reg);
  158. break;
  159. case arm9_and_earlier:
  160. default:
  161. can_read_arm9_dcc(reg);
  162. break;
  163. }
  164. return reg;
  165. }
  166. #ifdef CONFIG_ARM_DCC_MULTI
  167. static device_t arm_dcc_dev;
  168. int drv_arm_dcc_init(void)
  169. {
  170. int rc;
  171. /* Device initialization */
  172. memset(&arm_dcc_dev, 0, sizeof(arm_dcc_dev));
  173. strcpy(arm_dcc_dev.name, "dcc");
  174. arm_dcc_dev.ext = 0; /* No extensions */
  175. arm_dcc_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT;
  176. arm_dcc_dev.tstc = arm_dcc_tstc; /* 'tstc' function */
  177. arm_dcc_dev.getc = arm_dcc_getc; /* 'getc' function */
  178. arm_dcc_dev.putc = arm_dcc_putc; /* 'putc' function */
  179. arm_dcc_dev.puts = arm_dcc_puts; /* 'puts' function */
  180. rc = device_register(&arm_dcc_dev);
  181. if (rc == 0) {
  182. arm_dcc_init();
  183. return 1;
  184. }
  185. return 0;
  186. }
  187. #endif