tc.c 5.4 KB

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