tc.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * tc-init: We assume the TURBOchannel to be up and running so
  3. * just probe for Modules and fill in the global data structure
  4. * tc_bus.
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file "COPYING" in the main directory of this archive
  8. * for more details.
  9. *
  10. * Copyright (c) Harald Koerfgen, 1998
  11. * Copyright (c) 2001, 2003, 2005 Maciej W. Rozycki
  12. */
  13. #include <linux/init.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/string.h>
  17. #include <linux/types.h>
  18. #include <asm/addrspace.h>
  19. #include <asm/bug.h>
  20. #include <asm/errno.h>
  21. #include <asm/io.h>
  22. #include <asm/paccess.h>
  23. #include <asm/dec/machtype.h>
  24. #include <asm/dec/prom.h>
  25. #include <asm/dec/tcinfo.h>
  26. #include <asm/dec/tcmodule.h>
  27. #include <asm/dec/interrupts.h>
  28. MODULE_LICENSE("GPL");
  29. slot_info tc_bus[MAX_SLOT];
  30. static int num_tcslots;
  31. static tcinfo *info;
  32. /*
  33. * Interface to the world. Read comment in include/asm-mips/tc.h.
  34. */
  35. int search_tc_card(const char *name)
  36. {
  37. int slot;
  38. slot_info *sip;
  39. for (slot = 0; slot < num_tcslots; slot++) {
  40. sip = &tc_bus[slot];
  41. if ((sip->flags & FREE) &&
  42. (strncmp(sip->name, name, strlen(name)) == 0)) {
  43. return slot;
  44. }
  45. }
  46. return -ENODEV;
  47. }
  48. void claim_tc_card(int slot)
  49. {
  50. if (tc_bus[slot].flags & IN_USE) {
  51. printk("claim_tc_card: attempting to claim a card already in use\n");
  52. return;
  53. }
  54. tc_bus[slot].flags &= ~FREE;
  55. tc_bus[slot].flags |= IN_USE;
  56. }
  57. void release_tc_card(int slot)
  58. {
  59. if (tc_bus[slot].flags & FREE) {
  60. printk("release_tc_card: "
  61. "attempting to release a card already free\n");
  62. return;
  63. }
  64. tc_bus[slot].flags &= ~IN_USE;
  65. tc_bus[slot].flags |= FREE;
  66. }
  67. unsigned long get_tc_base_addr(int slot)
  68. {
  69. return tc_bus[slot].base_addr;
  70. }
  71. unsigned long get_tc_irq_nr(int slot)
  72. {
  73. return tc_bus[slot].interrupt;
  74. }
  75. unsigned long get_tc_speed(void)
  76. {
  77. return 100000 * (10000 / (unsigned long)info->clk_period);
  78. }
  79. /*
  80. * Probing for TURBOchannel modules
  81. */
  82. static void __init tc_probe(unsigned long startaddr, unsigned long size,
  83. int slots)
  84. {
  85. unsigned long slotaddr;
  86. int i, slot, err;
  87. long offset;
  88. u8 pattern[4];
  89. volatile u8 *module;
  90. for (slot = 0; slot < slots; slot++) {
  91. slotaddr = startaddr + slot * size;
  92. module = ioremap_nocache(slotaddr, size);
  93. BUG_ON(!module);
  94. offset = OLDCARD;
  95. err = 0;
  96. err |= get_dbe(pattern[0], module + OLDCARD + TC_PATTERN0);
  97. err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1);
  98. err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2);
  99. err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3);
  100. if (err) {
  101. iounmap(module);
  102. continue;
  103. }
  104. if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
  105. pattern[2] != 0xaa || pattern[3] != 0xff) {
  106. offset = NEWCARD;
  107. err = 0;
  108. err |= get_dbe(pattern[0], module + TC_PATTERN0);
  109. err |= get_dbe(pattern[1], module + TC_PATTERN1);
  110. err |= get_dbe(pattern[2], module + TC_PATTERN2);
  111. err |= get_dbe(pattern[3], module + TC_PATTERN3);
  112. if (err) {
  113. iounmap(module);
  114. continue;
  115. }
  116. }
  117. if (pattern[0] != 0x55 || pattern[1] != 0x00 ||
  118. pattern[2] != 0xaa || pattern[3] != 0xff) {
  119. iounmap(module);
  120. continue;
  121. }
  122. tc_bus[slot].base_addr = slotaddr;
  123. for (i = 0; i < 8; i++) {
  124. tc_bus[slot].firmware[i] =
  125. module[TC_FIRM_VER + offset + 4 * i];
  126. tc_bus[slot].vendor[i] =
  127. module[TC_VENDOR + offset + 4 * i];
  128. tc_bus[slot].name[i] =
  129. module[TC_MODULE + offset + 4 * i];
  130. }
  131. tc_bus[slot].firmware[8] = 0;
  132. tc_bus[slot].vendor[8] = 0;
  133. tc_bus[slot].name[8] = 0;
  134. /*
  135. * Looks unneccesary, but we may change
  136. * TC? in the future
  137. */
  138. switch (slot) {
  139. case 0:
  140. tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC0];
  141. break;
  142. case 1:
  143. tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC1];
  144. break;
  145. case 2:
  146. tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC2];
  147. break;
  148. /*
  149. * Yuck! DS5000/200 onboard devices
  150. */
  151. case 5:
  152. tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC5];
  153. break;
  154. case 6:
  155. tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC6];
  156. break;
  157. default:
  158. tc_bus[slot].interrupt = -1;
  159. break;
  160. }
  161. iounmap(module);
  162. }
  163. }
  164. /*
  165. * the main entry
  166. */
  167. static int __init tc_init(void)
  168. {
  169. int tc_clock;
  170. int i;
  171. unsigned long slot0addr;
  172. unsigned long slot_size;
  173. if (!TURBOCHANNEL)
  174. return 0;
  175. for (i = 0; i < MAX_SLOT; i++) {
  176. tc_bus[i].base_addr = 0;
  177. tc_bus[i].name[0] = 0;
  178. tc_bus[i].vendor[0] = 0;
  179. tc_bus[i].firmware[0] = 0;
  180. tc_bus[i].interrupt = -1;
  181. tc_bus[i].flags = FREE;
  182. }
  183. info = rex_gettcinfo();
  184. slot0addr = CPHYSADDR((long)rex_slot_address(0));
  185. switch (mips_machtype) {
  186. case MACH_DS5000_200:
  187. num_tcslots = 7;
  188. break;
  189. case MACH_DS5000_1XX:
  190. case MACH_DS5000_2X0:
  191. case MACH_DS5900:
  192. num_tcslots = 3;
  193. break;
  194. case MACH_DS5000_XX:
  195. default:
  196. num_tcslots = 2;
  197. break;
  198. }
  199. tc_clock = 10000 / info->clk_period;
  200. if (info->slot_size && slot0addr) {
  201. pr_info("TURBOchannel rev. %d at %d.%d MHz (with%s parity)\n",
  202. info->revision, tc_clock / 10, tc_clock % 10,
  203. info->parity ? "" : "out");
  204. slot_size = info->slot_size << 20;
  205. tc_probe(slot0addr, slot_size, num_tcslots);
  206. for (i = 0; i < num_tcslots; i++) {
  207. if (!tc_bus[i].base_addr)
  208. continue;
  209. pr_info(" slot %d: %s %s %s\n", i, tc_bus[i].vendor,
  210. tc_bus[i].name, tc_bus[i].firmware);
  211. }
  212. }
  213. return 0;
  214. }
  215. subsys_initcall(tc_init);
  216. EXPORT_SYMBOL(search_tc_card);
  217. EXPORT_SYMBOL(claim_tc_card);
  218. EXPORT_SYMBOL(release_tc_card);
  219. EXPORT_SYMBOL(get_tc_base_addr);
  220. EXPORT_SYMBOL(get_tc_irq_nr);
  221. EXPORT_SYMBOL(get_tc_speed);