devices.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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 char *cpu_mid_prop(void)
  28. {
  29. if (tlb_type == spitfire)
  30. return "upa-portid";
  31. return "portid";
  32. }
  33. static int check_cpu_node(int nd, int *cur_inst,
  34. int (*compare)(int, int, void *), void *compare_arg,
  35. int *prom_node, int *mid)
  36. {
  37. char node_str[128];
  38. prom_getstring(nd, "device_type", node_str, sizeof(node_str));
  39. if (strcmp(node_str, "cpu"))
  40. return -ENODEV;
  41. if (!compare(nd, *cur_inst, compare_arg)) {
  42. if (prom_node)
  43. *prom_node = nd;
  44. if (mid)
  45. *mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
  46. return 0;
  47. }
  48. (*cur_inst)++;
  49. return -ENODEV;
  50. }
  51. static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
  52. int *prom_node, int *mid)
  53. {
  54. int nd, cur_inst, err;
  55. nd = prom_root_node;
  56. cur_inst = 0;
  57. err = check_cpu_node(nd, &cur_inst,
  58. compare, compare_arg,
  59. prom_node, mid);
  60. if (err == 0)
  61. return 0;
  62. nd = prom_getchild(nd);
  63. while ((nd = prom_getsibling(nd)) != 0) {
  64. err = check_cpu_node(nd, &cur_inst,
  65. compare, compare_arg,
  66. prom_node, mid);
  67. if (err == 0)
  68. return 0;
  69. }
  70. return -ENODEV;
  71. }
  72. static int cpu_instance_compare(int nd, int instance, void *_arg)
  73. {
  74. int desired_instance = (int) (long) _arg;
  75. if (instance == desired_instance)
  76. return 0;
  77. return -ENODEV;
  78. }
  79. int cpu_find_by_instance(int instance, int *prom_node, int *mid)
  80. {
  81. return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
  82. prom_node, mid);
  83. }
  84. static int cpu_mid_compare(int nd, int instance, void *_arg)
  85. {
  86. int desired_mid = (int) (long) _arg;
  87. int this_mid;
  88. this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
  89. if (this_mid == desired_mid)
  90. return 0;
  91. return -ENODEV;
  92. }
  93. int cpu_find_by_mid(int mid, int *prom_node)
  94. {
  95. return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
  96. prom_node, NULL);
  97. }
  98. void __init device_scan(void)
  99. {
  100. /* FIX ME FAST... -DaveM */
  101. ioport_resource.end = 0xffffffffffffffffUL;
  102. prom_printf("Booting Linux...\n");
  103. #ifndef CONFIG_SMP
  104. {
  105. int err, cpu_node;
  106. err = cpu_find_by_instance(0, &cpu_node, NULL);
  107. if (err) {
  108. prom_printf("No cpu nodes, cannot continue\n");
  109. prom_halt();
  110. }
  111. cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
  112. "clock-frequency",
  113. 0);
  114. }
  115. #endif
  116. central_probe();
  117. cpu_probe();
  118. }