devices.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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 (strcmp(dp->type, "cpu"))
  59. return -ENODEV;
  60. if (!compare(dp, *cur_inst, compare_arg)) {
  61. if (dev_node)
  62. *dev_node = dp;
  63. if (mid)
  64. *mid = get_cpu_mid(dp);
  65. return 0;
  66. }
  67. (*cur_inst)++;
  68. return -ENODEV;
  69. }
  70. static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
  71. void *compare_arg,
  72. struct device_node **dev_node, int *mid)
  73. {
  74. struct device_node *dp;
  75. int cur_inst;
  76. cur_inst = 0;
  77. for_each_node_by_type(dp, "cpu") {
  78. int err = check_cpu_node(dp, &cur_inst,
  79. compare, compare_arg,
  80. dev_node, mid);
  81. if (err == 0)
  82. return 0;
  83. }
  84. return -ENODEV;
  85. }
  86. static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
  87. {
  88. int desired_instance = (int) (long) _arg;
  89. if (instance == desired_instance)
  90. return 0;
  91. return -ENODEV;
  92. }
  93. int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
  94. {
  95. return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
  96. dev_node, mid);
  97. }
  98. static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
  99. {
  100. int desired_mid = (int) (long) _arg;
  101. int this_mid;
  102. this_mid = get_cpu_mid(dp);
  103. if (this_mid == desired_mid)
  104. return 0;
  105. return -ENODEV;
  106. }
  107. int cpu_find_by_mid(int mid, struct device_node **dev_node)
  108. {
  109. return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
  110. dev_node, NULL);
  111. }
  112. void __init device_scan(void)
  113. {
  114. /* FIX ME FAST... -DaveM */
  115. ioport_resource.end = 0xffffffffffffffffUL;
  116. prom_printf("Booting Linux...\n");
  117. #ifndef CONFIG_SMP
  118. {
  119. struct device_node *dp;
  120. int err, def;
  121. err = cpu_find_by_instance(0, &dp, NULL);
  122. if (err) {
  123. prom_printf("No cpu nodes, cannot continue\n");
  124. prom_halt();
  125. }
  126. cpu_data(0).clock_tick =
  127. of_getintprop_default(dp, "clock-frequency", 0);
  128. def = ((tlb_type == hypervisor) ?
  129. (8 * 1024) :
  130. (16 * 1024));
  131. cpu_data(0).dcache_size = of_getintprop_default(dp,
  132. "dcache-size",
  133. def);
  134. def = 32;
  135. cpu_data(0).dcache_line_size =
  136. of_getintprop_default(dp, "dcache-line-size", def);
  137. def = 16 * 1024;
  138. cpu_data(0).icache_size = of_getintprop_default(dp,
  139. "icache-size",
  140. def);
  141. def = 32;
  142. cpu_data(0).icache_line_size =
  143. of_getintprop_default(dp, "icache-line-size", def);
  144. def = ((tlb_type == hypervisor) ?
  145. (3 * 1024 * 1024) :
  146. (4 * 1024 * 1024));
  147. cpu_data(0).ecache_size = of_getintprop_default(dp,
  148. "ecache-size",
  149. def);
  150. def = 64;
  151. cpu_data(0).ecache_line_size =
  152. of_getintprop_default(dp, "ecache-line-size", def);
  153. printk("CPU[0]: Caches "
  154. "D[sz(%d):line_sz(%d)] "
  155. "I[sz(%d):line_sz(%d)] "
  156. "E[sz(%d):line_sz(%d)]\n",
  157. cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
  158. cpu_data(0).icache_size, cpu_data(0).icache_line_size,
  159. cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
  160. }
  161. #endif
  162. central_probe();
  163. cpu_probe();
  164. }