devices.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* devices.c: Initial scan of the prom device tree for important
  2. * Sparc device nodes which we need to find.
  3. *
  4. * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  5. */
  6. #include <linux/config.h>
  7. #include <linux/kernel.h>
  8. #include <linux/threads.h>
  9. #include <linux/init.h>
  10. #include <linux/ioport.h>
  11. #include <linux/string.h>
  12. #include <linux/spinlock.h>
  13. #include <linux/errno.h>
  14. #include <asm/page.h>
  15. #include <asm/oplib.h>
  16. #include <asm/system.h>
  17. #include <asm/smp.h>
  18. #include <asm/spitfire.h>
  19. #include <asm/timer.h>
  20. #include <asm/cpudata.h>
  21. /* Used to synchronize acceses to NatSemi SUPER I/O chip configure
  22. * operations in asm/ns87303.h
  23. */
  24. DEFINE_SPINLOCK(ns87303_lock);
  25. extern void cpu_probe(void);
  26. extern void central_probe(void);
  27. static const char *cpu_mid_prop(void)
  28. {
  29. if (tlb_type == spitfire)
  30. return "upa-portid";
  31. return "portid";
  32. }
  33. static int get_cpu_mid(int prom_node)
  34. {
  35. if (tlb_type == hypervisor) {
  36. struct linux_prom64_registers reg;
  37. if (prom_getproplen(prom_node, "cpuid") == 4)
  38. return prom_getintdefault(prom_node, "cpuid", 0);
  39. prom_getproperty(prom_node, "reg", (char *) &reg, sizeof(reg));
  40. return (reg.phys_addr >> 32) & 0x0fffffffUL;
  41. } else {
  42. const char *prop_name = cpu_mid_prop();
  43. return prom_getintdefault(prom_node, prop_name, 0);
  44. }
  45. }
  46. static int check_cpu_node(int nd, int *cur_inst,
  47. int (*compare)(int, int, void *), void *compare_arg,
  48. int *prom_node, int *mid)
  49. {
  50. char node_str[128];
  51. prom_getstring(nd, "device_type", node_str, sizeof(node_str));
  52. if (strcmp(node_str, "cpu"))
  53. return -ENODEV;
  54. if (!compare(nd, *cur_inst, compare_arg)) {
  55. if (prom_node)
  56. *prom_node = nd;
  57. if (mid)
  58. *mid = get_cpu_mid(nd);
  59. return 0;
  60. }
  61. (*cur_inst)++;
  62. return -ENODEV;
  63. }
  64. static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
  65. int *prom_node, int *mid)
  66. {
  67. int nd, cur_inst, err;
  68. nd = prom_root_node;
  69. cur_inst = 0;
  70. err = check_cpu_node(nd, &cur_inst,
  71. compare, compare_arg,
  72. prom_node, mid);
  73. if (err == 0)
  74. return 0;
  75. nd = prom_getchild(nd);
  76. while ((nd = prom_getsibling(nd)) != 0) {
  77. err = check_cpu_node(nd, &cur_inst,
  78. compare, compare_arg,
  79. prom_node, mid);
  80. if (err == 0)
  81. return 0;
  82. }
  83. return -ENODEV;
  84. }
  85. static int cpu_instance_compare(int nd, int instance, void *_arg)
  86. {
  87. int desired_instance = (int) (long) _arg;
  88. if (instance == desired_instance)
  89. return 0;
  90. return -ENODEV;
  91. }
  92. int cpu_find_by_instance(int instance, int *prom_node, int *mid)
  93. {
  94. return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
  95. prom_node, mid);
  96. }
  97. static int cpu_mid_compare(int nd, int instance, void *_arg)
  98. {
  99. int desired_mid = (int) (long) _arg;
  100. int this_mid;
  101. this_mid = get_cpu_mid(nd);
  102. if (this_mid == desired_mid)
  103. return 0;
  104. return -ENODEV;
  105. }
  106. int cpu_find_by_mid(int mid, int *prom_node)
  107. {
  108. return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
  109. prom_node, NULL);
  110. }
  111. void __init device_scan(void)
  112. {
  113. /* FIX ME FAST... -DaveM */
  114. ioport_resource.end = 0xffffffffffffffffUL;
  115. prom_printf("Booting Linux...\n");
  116. #ifndef CONFIG_SMP
  117. {
  118. int err, cpu_node;
  119. err = cpu_find_by_instance(0, &cpu_node, NULL);
  120. if (err) {
  121. prom_printf("No cpu nodes, cannot continue\n");
  122. prom_halt();
  123. }
  124. cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
  125. "clock-frequency",
  126. 0);
  127. cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
  128. "dcache-size",
  129. 16 * 1024);
  130. cpu_data(0).dcache_line_size =
  131. prom_getintdefault(cpu_node, "dcache-line-size", 32);
  132. cpu_data(0).icache_size = prom_getintdefault(cpu_node,
  133. "icache-size",
  134. 16 * 1024);
  135. cpu_data(0).icache_line_size =
  136. prom_getintdefault(cpu_node, "icache-line-size", 32);
  137. cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
  138. "ecache-size",
  139. 4 * 1024 * 1024);
  140. cpu_data(0).ecache_line_size =
  141. prom_getintdefault(cpu_node, "ecache-line-size", 64);
  142. printk("CPU[0]: Caches "
  143. "D[sz(%d):line_sz(%d)] "
  144. "I[sz(%d):line_sz(%d)] "
  145. "E[sz(%d):line_sz(%d)]\n",
  146. cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
  147. cpu_data(0).icache_size, cpu_data(0).icache_line_size,
  148. cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
  149. }
  150. #endif
  151. central_probe();
  152. cpu_probe();
  153. }