devices.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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/kernel.h>
  7. #include <linux/threads.h>
  8. #include <linux/init.h>
  9. #include <linux/ioport.h>
  10. #include <linux/string.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/errno.h>
  13. #include <linux/bootmem.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(struct device_node *dp)
  34. {
  35. struct property *prop;
  36. if (tlb_type == hypervisor) {
  37. struct linux_prom64_registers *reg;
  38. int len;
  39. prop = of_find_property(dp, "cpuid", &len);
  40. if (prop && len == 4)
  41. return *(int *) prop->value;
  42. prop = of_find_property(dp, "reg", NULL);
  43. reg = prop->value;
  44. return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
  45. } else {
  46. const char *prop_name = cpu_mid_prop();
  47. prop = of_find_property(dp, prop_name, NULL);
  48. if (prop)
  49. return *(int *) prop->value;
  50. return 0;
  51. }
  52. }
  53. static int check_cpu_node(struct device_node *dp, int *cur_inst,
  54. int (*compare)(struct device_node *, int, void *),
  55. void *compare_arg,
  56. struct device_node **dev_node, int *mid)
  57. {
  58. if (!compare(dp, *cur_inst, compare_arg)) {
  59. if (dev_node)
  60. *dev_node = dp;
  61. if (mid)
  62. *mid = get_cpu_mid(dp);
  63. return 0;
  64. }
  65. (*cur_inst)++;
  66. return -ENODEV;
  67. }
  68. static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
  69. void *compare_arg,
  70. struct device_node **dev_node, int *mid)
  71. {
  72. struct device_node *dp;
  73. int cur_inst;
  74. cur_inst = 0;
  75. for_each_node_by_type(dp, "cpu") {
  76. int err = check_cpu_node(dp, &cur_inst,
  77. compare, compare_arg,
  78. dev_node, mid);
  79. if (err == 0)
  80. return 0;
  81. }
  82. return -ENODEV;
  83. }
  84. static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
  85. {
  86. int desired_instance = (int) (long) _arg;
  87. if (instance == desired_instance)
  88. return 0;
  89. return -ENODEV;
  90. }
  91. int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
  92. {
  93. return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
  94. dev_node, mid);
  95. }
  96. static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
  97. {
  98. int desired_mid = (int) (long) _arg;
  99. int this_mid;
  100. this_mid = get_cpu_mid(dp);
  101. if (this_mid == desired_mid)
  102. return 0;
  103. return -ENODEV;
  104. }
  105. int cpu_find_by_mid(int mid, struct device_node **dev_node)
  106. {
  107. return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
  108. dev_node, NULL);
  109. }
  110. void __init device_scan(void)
  111. {
  112. /* FIX ME FAST... -DaveM */
  113. ioport_resource.end = 0xffffffffffffffffUL;
  114. prom_printf("Booting Linux...\n");
  115. #ifndef CONFIG_SMP
  116. {
  117. struct device_node *dp;
  118. int err, def;
  119. err = cpu_find_by_instance(0, &dp, NULL);
  120. if (err) {
  121. prom_printf("No cpu nodes, cannot continue\n");
  122. prom_halt();
  123. }
  124. cpu_data(0).clock_tick =
  125. of_getintprop_default(dp, "clock-frequency", 0);
  126. def = ((tlb_type == hypervisor) ?
  127. (8 * 1024) :
  128. (16 * 1024));
  129. cpu_data(0).dcache_size = of_getintprop_default(dp,
  130. "dcache-size",
  131. def);
  132. def = 32;
  133. cpu_data(0).dcache_line_size =
  134. of_getintprop_default(dp, "dcache-line-size", def);
  135. def = 16 * 1024;
  136. cpu_data(0).icache_size = of_getintprop_default(dp,
  137. "icache-size",
  138. def);
  139. def = 32;
  140. cpu_data(0).icache_line_size =
  141. of_getintprop_default(dp, "icache-line-size", def);
  142. def = ((tlb_type == hypervisor) ?
  143. (3 * 1024 * 1024) :
  144. (4 * 1024 * 1024));
  145. cpu_data(0).ecache_size = of_getintprop_default(dp,
  146. "ecache-size",
  147. def);
  148. def = 64;
  149. cpu_data(0).ecache_line_size =
  150. of_getintprop_default(dp, "ecache-line-size", def);
  151. printk("CPU[0]: Caches "
  152. "D[sz(%d):line_sz(%d)] "
  153. "I[sz(%d):line_sz(%d)] "
  154. "E[sz(%d):line_sz(%d)]\n",
  155. cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
  156. cpu_data(0).icache_size, cpu_data(0).icache_line_size,
  157. cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
  158. }
  159. #endif
  160. central_probe();
  161. cpu_probe();
  162. }